Skip to content

Commit 7384ef4

Browse files
committed
sd: handle system attibutes on reconnect
1 parent 113f5fa commit 7384ef4

File tree

4 files changed

+69
-28
lines changed

4 files changed

+69
-28
lines changed

adapter_nrf51.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ func handleEvent() {
5050
currentConnection.Reg = gapEvent.conn_handle
5151
DefaultAdapter.connectHandler(Address{}, true)
5252
case C.BLE_GAP_EVT_DISCONNECTED:
53+
if debug {
54+
println("evt: disconnected")
55+
}
56+
// Store system attributes data
57+
dataLen := uint16(0)
58+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
59+
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
60+
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
61+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
62+
}
63+
// Clean up state for this connection.
64+
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
65+
// Auto-restart advertisement if needed.
5366
if defaultAdvertisement.isAdvertising.Get() != 0 {
5467
// The advertisement was running but was automatically stopped
5568
// by the connection event.
@@ -59,7 +72,6 @@ func handleEvent() {
5972
// necessary.
6073
defaultAdvertisement.start()
6174
}
62-
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
6375
DefaultAdapter.connectHandler(Address{}, false)
6476
case C.BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
6577
// Respond with the default PPCP connection parameters by passing
@@ -87,15 +99,16 @@ func handleEvent() {
8799
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
88100
}
89101
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
90-
// This event is generated when reading the Generic Attribute
91-
// service. It appears to be necessary for bonded devices.
92-
// From the docs:
93-
// > If the pointer is NULL, the system attribute info is
94-
// > initialized, assuming that the application does not have any
95-
// > previously saved system attribute data for this device.
96-
// Maybe we should look at the error, but as there's not really a
97-
// way to handle it, ignore it.
98-
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
102+
if debug {
103+
println("evt: sys attr missing")
104+
}
105+
// Try and restore system attributes data if we have any (from previous connections)
106+
// Fallback to initialize them from scratch otherwise
107+
if len(DefaultAdapter.systemAttributes) > 0 {
108+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
109+
} else {
110+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
111+
}
99112
default:
100113
if debug {
101114
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE)

adapter_nrf528xx-full.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ func handleEvent() {
4949
if debug {
5050
println("evt: disconnected")
5151
}
52+
// Store system attributes data
53+
dataLen := uint16(0)
54+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
55+
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
56+
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
57+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
58+
}
5259
// Clean up state for this connection.
5360
for i, cb := range gattcNotificationCallbacks {
5461
if cb.connectionHandle == currentConnection.Reg {
@@ -116,15 +123,16 @@ func handleEvent() {
116123
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
117124
}
118125
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
119-
// This event is generated when reading the Generic Attribute
120-
// service. It appears to be necessary for bonded devices.
121-
// From the docs:
122-
// > If the pointer is NULL, the system attribute info is
123-
// > initialized, assuming that the application does not have any
124-
// > previously saved system attribute data for this device.
125-
// Maybe we should look at the error, but as there's not really a
126-
// way to handle it, ignore it.
127-
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
126+
if debug {
127+
println("evt: sys attr missing")
128+
}
129+
// Try and restore system attributes data if we have any (from previous connections)
130+
// Fallback to initialize them from scratch otherwise
131+
if len(DefaultAdapter.systemAttributes) > 0 {
132+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
133+
} else {
134+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
135+
}
128136
case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
129137
// This event is generated by some devices. While we could support
130138
// larger MTUs, this default MTU is supported everywhere.

adapter_nrf528xx-peripheral.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ func handleEvent() {
3838
if debug {
3939
println("evt: disconnected")
4040
}
41+
// Store system attributes data
42+
dataLen := uint16(0)
43+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
44+
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
45+
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
46+
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
47+
}
48+
// Clean up state for this connection.
4149
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
4250
// Auto-restart advertisement if needed.
4351
if defaultAdvertisement.isAdvertising.Get() != 0 {
@@ -71,15 +79,16 @@ func handleEvent() {
7179
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
7280
}
7381
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
74-
// This event is generated when reading the Generic Attribute
75-
// service. It appears to be necessary for bonded devices.
76-
// From the docs:
77-
// > If the pointer is NULL, the system attribute info is
78-
// > initialized, assuming that the application does not have any
79-
// > previously saved system attribute data for this device.
80-
// Maybe we should look at the error, but as there's not really a
81-
// way to handle it, ignore it.
82-
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
82+
if debug {
83+
println("evt: sys attr missing")
84+
}
85+
// Try and restore system attributes data if we have any (from previous connections)
86+
// Fallback to initialize them from scratch otherwise
87+
if len(DefaultAdapter.systemAttributes) > 0 {
88+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
89+
} else {
90+
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
91+
}
8392
case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
8493
// This event is generated by some devices. While we could support
8594
// larger MTUs, this default MTU is supported everywhere.

adapter_sd.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,24 @@ type Adapter struct {
5050
charWriteHandlers []charWriteHandler
5151

5252
connectHandler func(device Address, connected bool)
53+
54+
// System attributes in context of SoftDevice primarily mean Client Characteristic Configuration Descriptors (CCCD).
55+
// It is mandated by Bluetooth specification that CCCD values for a bonded peer should be stored between connections.
56+
//
57+
// Our bluetooth stack stores system attributes on disconnect
58+
// and provides them back to SoftDevice on BLE_GATTS_EVT_SYS_ATTR_MISSING event.
59+
//
60+
// Note: CCCD values can be altered only by the peer, so you cannot change them from the application.
61+
// Treat this data as a blob of unknown format, i.e. store it as is and provide it back as is, without changing it.
62+
systemAttributes []byte
5363
}
5464

5565
// DefaultAdapter is the default adapter on the current system. On Nordic chips,
5666
// it will return the SoftDevice interface.
5767
//
5868
// Make sure to call Enable() before using it to initialize the adapter.
5969
var DefaultAdapter = &Adapter{isDefault: true,
70+
systemAttributes: make([]byte, 64)[:0], // capacity 64, length 0
6071
connectHandler: func(device Address, connected bool) {
6172
return
6273
}}

0 commit comments

Comments
 (0)