f91f73ede2
The nrf51822 chip is still widely available, for example in the BBC micro:bit. Therefore it's a good idea to support it too. Unfortunately, Nordic decided to change the API in some significant ways so many parts are not compatible between S110 for nrf51 and the other nrf52* SoftDevices.
131 lines
4.3 KiB
Go
131 lines
4.3 KiB
Go
// +build softdevice,!s110v8
|
|
|
|
package bluetooth
|
|
|
|
/*
|
|
// Define SoftDevice functions as regular function declarations (not inline
|
|
// static functions).
|
|
#define SVCALL_AS_NORMAL_FUNCTION
|
|
|
|
#include "nrf_sdm.h"
|
|
#include "ble.h"
|
|
#include "ble_gap.h"
|
|
|
|
void assertHandler(void);
|
|
*/
|
|
import "C"
|
|
|
|
import "unsafe"
|
|
|
|
//export assertHandler
|
|
func assertHandler() {
|
|
println("SoftDevice assert")
|
|
}
|
|
|
|
var clockConfig C.nrf_clock_lf_cfg_t = C.nrf_clock_lf_cfg_t{
|
|
source: C.NRF_CLOCK_LF_SRC_SYNTH,
|
|
rc_ctiv: 0,
|
|
rc_temp_ctiv: 0,
|
|
accuracy: 0,
|
|
}
|
|
|
|
func (a *Adapter) enable() error {
|
|
// Enable the SoftDevice.
|
|
errCode := C.sd_softdevice_enable(&clockConfig, C.nrf_fault_handler_t(C.assertHandler))
|
|
if errCode != 0 {
|
|
return Error(errCode)
|
|
}
|
|
|
|
// Enable the BLE stack.
|
|
appRAMBase := uint32(0x200039c0)
|
|
errCode = C.sd_ble_enable(&appRAMBase)
|
|
return makeError(errCode)
|
|
}
|
|
|
|
func handleEvent() {
|
|
id := eventBuf.header.evt_id
|
|
switch {
|
|
case id >= C.BLE_GAP_EVT_BASE && id <= C.BLE_GAP_EVT_LAST:
|
|
gapEvent := eventBuf.evt.unionfield_gap_evt()
|
|
switch id {
|
|
case C.BLE_GAP_EVT_CONNECTED:
|
|
handler := defaultAdapter.handler
|
|
if handler != nil {
|
|
handler(&ConnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}})
|
|
}
|
|
case C.BLE_GAP_EVT_DISCONNECTED:
|
|
handler := defaultAdapter.handler
|
|
if handler != nil {
|
|
handler(&DisconnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}})
|
|
}
|
|
case C.BLE_GAP_EVT_ADV_REPORT:
|
|
advReport := gapEvent.params.unionfield_adv_report()
|
|
if debug && &scanReportBuffer.data[0] != advReport.data.p_data {
|
|
// Sanity check.
|
|
panic("scanReportBuffer != advReport.p_data")
|
|
}
|
|
// Prepare the globalScanResult, which will be passed to the
|
|
// callback.
|
|
scanReportBuffer.len = byte(advReport.data.len)
|
|
globalScanResult.RSSI = int16(advReport.rssi)
|
|
globalScanResult.Address = advReport.peer_addr.addr
|
|
globalScanResult.AdvertisementPayload = &scanReportBuffer
|
|
// Signal to the main thread that there was a scan report.
|
|
// Scanning will be resumed (from the main thread) once the scan
|
|
// report has been processed.
|
|
gotScanReport.Set(1)
|
|
case C.BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
|
|
// Respond with the default PPCP connection parameters by passing
|
|
// nil:
|
|
// > If NULL is provided on a peripheral role, the parameters in the
|
|
// > PPCP characteristic of the GAP service will be used instead. If
|
|
// > NULL is provided on a central role and in response to a
|
|
// > BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request
|
|
// > will be rejected
|
|
C.sd_ble_gap_conn_param_update(gapEvent.conn_handle, nil)
|
|
case C.BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
|
|
// We need to respond with sd_ble_gap_data_length_update. Setting
|
|
// both parameters to nil will make sure we send the default values.
|
|
C.sd_ble_gap_data_length_update(gapEvent.conn_handle, nil, nil)
|
|
default:
|
|
if debug {
|
|
println("unknown GAP event:", id)
|
|
}
|
|
}
|
|
case id >= C.BLE_GATTS_EVT_BASE && id <= C.BLE_GATTS_EVT_LAST:
|
|
gattsEvent := eventBuf.evt.unionfield_gatts_evt()
|
|
switch id {
|
|
case C.BLE_GATTS_EVT_WRITE:
|
|
writeEvent := gattsEvent.params.unionfield_write()
|
|
len := writeEvent.len - writeEvent.offset
|
|
data := (*[255]byte)(unsafe.Pointer(&writeEvent.data[0]))[:len:len]
|
|
handler := defaultAdapter.getCharWriteHandler(writeEvent.handle)
|
|
if handler != nil {
|
|
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)
|
|
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.
|
|
C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.BLE_GATT_ATT_MTU_DEFAULT)
|
|
default:
|
|
if debug {
|
|
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE)
|
|
}
|
|
}
|
|
default:
|
|
if debug {
|
|
println("unknown event:", id)
|
|
}
|
|
}
|
|
}
|