Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ smoketest-tinygo:
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=pca10040-s132v6 ./examples/nusserver
@md5sum test.hex
# Both pairing examples link in crypto/ecdh for LE Secure Connections,
# whose P-256 tables need more RAM than the nRF52832 has.
$(TINYGO) build -o test.hex -size=short -target=pca10056-s140v7 ./examples/pairing-justworks
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=microbit-v2-s113v7 ./examples/pairing-justworks
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=pca10056-s140v7 ./examples/pairing-passkey
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=microbit-v2-s113v7 ./examples/pairing-passkey
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=pca10040-s132v6 ./examples/scanner
@md5sum test.hex
$(TINYGO) build -o test.hex -size=short -target=pca10040-s132v6 ./examples/stop-advertisement
Expand Down
49 changes: 45 additions & 4 deletions adapter_nrf528xx-full.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func handleEvent() {
gapEvent := eventBuf.evt.unionfield_gap_evt()
switch id {
case C.BLE_GAP_EVT_CONNECTED:
secOnConnect()
connectEvent := gapEvent.params.unionfield_connected()
device := Device{
Address: Address{makeMACAddress(connectEvent.peer_addr)},
Expand All @@ -50,8 +51,9 @@ func handleEvent() {
}
case C.BLE_GAP_EVT_DISCONNECTED:
if debug {
println("evt: disconnected")
println("evt: disconnected, reason", gapEvent.params.unionfield_disconnected().reason)
}
secOnDisconnect(gapEvent.conn_handle)
// Clean up state for this connection.
for i, cb := range gattcNotificationCallbacks {
if uint16(cb.connectionHandle) == currentConnection.handle.Reg {
Expand Down Expand Up @@ -148,6 +150,42 @@ func handleEvent() {
println("gap timeout: other")
}
}
case C.BLE_GAP_EVT_SEC_PARAMS_REQUEST:
if debug {
println("evt: gap security parameters request")
}
secOnSecParamsRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_SEC_INFO_REQUEST:
if debug {
println("evt: gap security info request")
}
secOnSecInfoRequest(gapEvent.conn_handle, gapEvent.params.unionfield_sec_info_request())
case C.BLE_GAP_EVT_PASSKEY_DISPLAY:
if debug {
println("evt: gap passkey display")
}
secOnPasskeyDisplay(gapEvent.conn_handle, gapEvent.params.unionfield_passkey_display())
case C.BLE_GAP_EVT_AUTH_KEY_REQUEST:
if debug {
println("evt: gap auth key request")
}
secOnAuthKeyRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_LESC_DHKEY_REQUEST:
if debug {
println("evt: gap lesc dhkey request")
}
secOnLESCDHKeyRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_CONN_SEC_UPDATE:
if debug {
connSec := gapEvent.params.unionfield_conn_sec_update().conn_sec
println("evt: gap connection security update, mode", connSec.sec_mode.bitfield_sm(), "level", connSec.sec_mode.bitfield_lv())
}
secOnConnSecUpdate(gapEvent.conn_handle)
case C.BLE_GAP_EVT_AUTH_STATUS:
if debug {
println("evt: gap auth status:", gapEvent.params.unionfield_auth_status().auth_status)
}
secOnAuthStatus(gapEvent.conn_handle, gapEvent.params.unionfield_auth_status())
default:
if debug {
println("unknown GAP event:", id)
Expand All @@ -164,16 +202,19 @@ func handleEvent() {
if handler != nil {
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
}
// The write may have changed a CCCD, which a bonded central
// expects to persist across reconnections.
secSaveSysAttrs(gattsEvent.conn_handle)
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 the connected central is bonded with us, its saved CCCD
// state is restored instead of being initialized.
secOnSysAttrMissing(gattsEvent.conn_handle)
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.
Expand Down
49 changes: 45 additions & 4 deletions adapter_nrf528xx-peripheral.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func handleEvent() {
if debug {
println("evt: connected in peripheral role")
}
secOnConnect()
currentConnection.handle.Reg = uint16(gapEvent.conn_handle)
connectEvent := gapEvent.params.unionfield_connected()
device := Device{
Expand All @@ -36,8 +37,9 @@ func handleEvent() {
DefaultAdapter.connectHandler(device, true)
case C.BLE_GAP_EVT_DISCONNECTED:
if debug {
println("evt: disconnected")
println("evt: disconnected, reason", gapEvent.params.unionfield_disconnected().reason)
}
secOnDisconnect(gapEvent.conn_handle)
currentConnection.handle.Reg = C.BLE_CONN_HANDLE_INVALID
// Auto-restart advertisement if needed.
if defaultAdvertisement.isAdvertising.Get() != 0 {
Expand All @@ -64,6 +66,42 @@ func handleEvent() {
C.sd_ble_gap_phy_update(gapEvent.conn_handle, &phyUpdateResponse)
case C.BLE_GAP_EVT_PHY_UPDATE:
// ignore confirmation of phy successfully updated
case C.BLE_GAP_EVT_SEC_PARAMS_REQUEST:
if debug {
println("evt: gap security parameters request")
}
secOnSecParamsRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_SEC_INFO_REQUEST:
if debug {
println("evt: gap security info request")
}
secOnSecInfoRequest(gapEvent.conn_handle, gapEvent.params.unionfield_sec_info_request())
case C.BLE_GAP_EVT_PASSKEY_DISPLAY:
if debug {
println("evt: gap passkey display")
}
secOnPasskeyDisplay(gapEvent.conn_handle, gapEvent.params.unionfield_passkey_display())
case C.BLE_GAP_EVT_AUTH_KEY_REQUEST:
if debug {
println("evt: gap auth key request")
}
secOnAuthKeyRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_LESC_DHKEY_REQUEST:
if debug {
println("evt: gap lesc dhkey request")
}
secOnLESCDHKeyRequest(gapEvent.conn_handle)
case C.BLE_GAP_EVT_CONN_SEC_UPDATE:
if debug {
connSec := gapEvent.params.unionfield_conn_sec_update().conn_sec
println("evt: gap connection security update, mode", connSec.sec_mode.bitfield_sm(), "level", connSec.sec_mode.bitfield_lv())
}
secOnConnSecUpdate(gapEvent.conn_handle)
case C.BLE_GAP_EVT_AUTH_STATUS:
if debug {
println("evt: gap auth status:", gapEvent.params.unionfield_auth_status().auth_status)
}
secOnAuthStatus(gapEvent.conn_handle, gapEvent.params.unionfield_auth_status())
default:
if debug {
println("unknown GAP event:", id)
Expand All @@ -80,16 +118,19 @@ func handleEvent() {
if handler != nil {
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data)
}
// The write may have changed a CCCD, which a bonded central
// expects to persist across reconnections.
secSaveSysAttrs(gattsEvent.conn_handle)
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 the connected central is bonded with us, its saved CCCD
// state is restored instead of being initialized.
secOnSysAttrMissing(gattsEvent.conn_handle)
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.
Expand Down
34 changes: 31 additions & 3 deletions adapter_sd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import (
)

// #include "ble.h"
// #ifdef NRF51
// #include "nrf_soc.h"
// #else
// #include "nrf_soc.h"
// #ifndef NRF51
// #include "nrf_nvic.h"
// #endif
import "C"
Expand Down Expand Up @@ -64,6 +63,18 @@ var DefaultAdapter = &Adapter{isDefault: true,

var eventBufLen C.uint16_t

// flashOpResult is set from the SWI2 interrupt handler when an asynchronous
// sd_flash_write/sd_flash_page_erase command completes. It is a SoC event,
// which is a separate event queue from the BLE events handled by
// handleEvent, but delivered through the same interrupt (SD_EVT_IRQn is
// SWI2_IRQn). 0 means no result yet, 1 success, 2 error. Consumed by bond
// storage code where available.
var flashOpResult volatile.Register8

// Static because taking the address of a local variable for a C call would
// heap-allocate, which is not allowed in interrupt context.
var socEvtID C.uint32_t

// Enable configures the BLE stack. It must be called before any
// Bluetooth-related calls (unless otherwise indicated).
func (a *Adapter) Enable() error {
Expand All @@ -88,6 +99,23 @@ func (a *Adapter) Enable() error {
}
handleEvent()
}

// Drain pending SoC events. Currently only flash operation
// completion is of interest, but any pending event must still be
// pulled out of the queue or the SoftDevice will stop delivering new
// ones.
for {
errCode := C.sd_evt_get(&socEvtID)
if errCode != 0 {
break
}
switch socEvtID {
case C.NRF_EVT_FLASH_OPERATION_SUCCESS:
flashOpResult.Set(1)
case C.NRF_EVT_FLASH_OPERATION_ERROR:
flashOpResult.Set(2)
}
}
})
intr.Enable()
intr.SetPriority(192)
Expand Down
Loading
Loading