d07cf38d66
This is necessary when connecting to a device when using the SoftDevice. The information is not set on Linux and Windows and is ignored on those platform when connecting.
135 lines
4.7 KiB
Go
135 lines
4.7 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:
|
|
currentConnection.Reg = gapEvent.conn_handle
|
|
case C.BLE_GAP_EVT_DISCONNECTED:
|
|
if defaultAdvertisement.isAdvertising.Get() != 0 {
|
|
// The advertisement was running but was automatically stopped
|
|
// by the connection event.
|
|
// Note that it cannot be restarted during connect like this,
|
|
// because it would need to be reconfigured as a non-connectable
|
|
// advertisement. That's left as a future addition, if
|
|
// necessary.
|
|
C.sd_ble_gap_adv_start(defaultAdvertisement.handle, C.BLE_CONN_CFG_TAG_DEFAULT)
|
|
}
|
|
currentConnection.Reg = C.BLE_CONN_HANDLE_INVALID
|
|
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.MAC = advReport.peer_addr.addr
|
|
globalScanResult.Address.IsRandom = advReport.peer_addr.bitfield_addr_type() != 0
|
|
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)
|
|
}
|
|
}
|
|
}
|