sd: handle system attibutes on reconnect
This commit is contained in:
parent
113f5fa503
commit
7384ef4c56
4 changed files with 69 additions and 28 deletions
|
@ -50,6 +50,19 @@ func handleEvent() {
|
|||
currentConnection.Reg = gapEvent.conn_handle
|
||||
DefaultAdapter.connectHandler(Address{}, true)
|
||||
case C.BLE_GAP_EVT_DISCONNECTED:
|
||||
if debug {
|
||||
println("evt: disconnected")
|
||||
}
|
||||
// Store system attributes data
|
||||
dataLen := uint16(0)
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
|
||||
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
|
||||
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
|
||||
}
|
||||
// Clean up state for this connection.
|
||||
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
|
||||
// Auto-restart advertisement if needed.
|
||||
if defaultAdvertisement.isAdvertising.Get() != 0 {
|
||||
// The advertisement was running but was automatically stopped
|
||||
// by the connection event.
|
||||
|
@ -59,7 +72,6 @@ func handleEvent() {
|
|||
// necessary.
|
||||
defaultAdvertisement.start()
|
||||
}
|
||||
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
|
||||
DefaultAdapter.connectHandler(Address{}, false)
|
||||
case C.BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
|
||||
// Respond with the default PPCP connection parameters by passing
|
||||
|
@ -87,15 +99,16 @@ func handleEvent() {
|
|||
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
|
||||
}
|
||||
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
// This event is generated when reading the Generic Attribute
|
||||
// service. It appears to be necessary for bonded devices.
|
||||
// From the docs:
|
||||
// > If the pointer is NULL, the system attribute info is
|
||||
// > initialized, assuming that the application does not have any
|
||||
// > previously saved system attribute data for this device.
|
||||
// Maybe we should look at the error, but as there's not really a
|
||||
// way to handle it, ignore it.
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
if debug {
|
||||
println("evt: sys attr missing")
|
||||
}
|
||||
// Try and restore system attributes data if we have any (from previous connections)
|
||||
// Fallback to initialize them from scratch otherwise
|
||||
if len(DefaultAdapter.systemAttributes) > 0 {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
|
||||
} else {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
}
|
||||
default:
|
||||
if debug {
|
||||
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE)
|
||||
|
|
|
@ -49,6 +49,13 @@ func handleEvent() {
|
|||
if debug {
|
||||
println("evt: disconnected")
|
||||
}
|
||||
// Store system attributes data
|
||||
dataLen := uint16(0)
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
|
||||
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
|
||||
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
|
||||
}
|
||||
// Clean up state for this connection.
|
||||
for i, cb := range gattcNotificationCallbacks {
|
||||
if cb.connectionHandle == currentConnection.Reg {
|
||||
|
@ -116,15 +123,16 @@ func handleEvent() {
|
|||
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
|
||||
}
|
||||
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
// This event is generated when reading the Generic Attribute
|
||||
// service. It appears to be necessary for bonded devices.
|
||||
// From the docs:
|
||||
// > If the pointer is NULL, the system attribute info is
|
||||
// > initialized, assuming that the application does not have any
|
||||
// > previously saved system attribute data for this device.
|
||||
// Maybe we should look at the error, but as there's not really a
|
||||
// way to handle it, ignore it.
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
if debug {
|
||||
println("evt: sys attr missing")
|
||||
}
|
||||
// Try and restore system attributes data if we have any (from previous connections)
|
||||
// Fallback to initialize them from scratch otherwise
|
||||
if len(DefaultAdapter.systemAttributes) > 0 {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
|
||||
} else {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
}
|
||||
case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
|
||||
// This event is generated by some devices. While we could support
|
||||
// larger MTUs, this default MTU is supported everywhere.
|
||||
|
|
|
@ -38,6 +38,14 @@ func handleEvent() {
|
|||
if debug {
|
||||
println("evt: disconnected")
|
||||
}
|
||||
// Store system attributes data
|
||||
dataLen := uint16(0)
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, nil, &dataLen, 0) // get data length
|
||||
if int(dataLen) <= cap(DefaultAdapter.systemAttributes) { // we can not allocate here, so ensure at least data fits the buffer
|
||||
DefaultAdapter.systemAttributes = DefaultAdapter.systemAttributes[:dataLen]
|
||||
C.sd_ble_gatts_sys_attr_get(gapEvent.conn_handle, &DefaultAdapter.systemAttributes[0], &dataLen, 0)
|
||||
}
|
||||
// Clean up state for this connection.
|
||||
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
|
||||
// Auto-restart advertisement if needed.
|
||||
if defaultAdvertisement.isAdvertising.Get() != 0 {
|
||||
|
@ -71,15 +79,16 @@ func handleEvent() {
|
|||
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
|
||||
}
|
||||
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
// This event is generated when reading the Generic Attribute
|
||||
// service. It appears to be necessary for bonded devices.
|
||||
// From the docs:
|
||||
// > If the pointer is NULL, the system attribute info is
|
||||
// > initialized, assuming that the application does not have any
|
||||
// > previously saved system attribute data for this device.
|
||||
// Maybe we should look at the error, but as there's not really a
|
||||
// way to handle it, ignore it.
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
if debug {
|
||||
println("evt: sys attr missing")
|
||||
}
|
||||
// Try and restore system attributes data if we have any (from previous connections)
|
||||
// Fallback to initialize them from scratch otherwise
|
||||
if len(DefaultAdapter.systemAttributes) > 0 {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, &DefaultAdapter.systemAttributes[0], uint16(len(DefaultAdapter.systemAttributes)), 0)
|
||||
} else {
|
||||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0)
|
||||
}
|
||||
case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
|
||||
// This event is generated by some devices. While we could support
|
||||
// larger MTUs, this default MTU is supported everywhere.
|
||||
|
|
|
@ -50,6 +50,16 @@ type Adapter struct {
|
|||
charWriteHandlers []charWriteHandler
|
||||
|
||||
connectHandler func(device Address, connected bool)
|
||||
|
||||
// System attributes in context of SoftDevice primarily mean Client Characteristic Configuration Descriptors (CCCD).
|
||||
// It is mandated by Bluetooth specification that CCCD values for a bonded peer should be stored between connections.
|
||||
//
|
||||
// Our bluetooth stack stores system attributes on disconnect
|
||||
// and provides them back to SoftDevice on BLE_GATTS_EVT_SYS_ATTR_MISSING event.
|
||||
//
|
||||
// Note: CCCD values can be altered only by the peer, so you cannot change them from the application.
|
||||
// Treat this data as a blob of unknown format, i.e. store it as is and provide it back as is, without changing it.
|
||||
systemAttributes []byte
|
||||
}
|
||||
|
||||
// DefaultAdapter is the default adapter on the current system. On Nordic chips,
|
||||
|
@ -57,6 +67,7 @@ type Adapter struct {
|
|||
//
|
||||
// Make sure to call Enable() before using it to initialize the adapter.
|
||||
var DefaultAdapter = &Adapter{isDefault: true,
|
||||
systemAttributes: make([]byte, 64)[:0], // capacity 64, length 0
|
||||
connectHandler: func(device Address, connected bool) {
|
||||
return
|
||||
}}
|
||||
|
|
Loading…
Reference in a new issue