2022-02-22 13:04:20 +03:00
|
|
|
//go:build softdevice
|
2019-06-02 20:12:36 +03:00
|
|
|
|
|
|
|
package bluetooth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"device/nrf"
|
2019-11-09 15:07:07 +03:00
|
|
|
"errors"
|
2020-05-24 22:23:34 +03:00
|
|
|
"runtime/interrupt"
|
2020-06-03 18:33:32 +03:00
|
|
|
"runtime/volatile"
|
2019-06-02 20:12:36 +03:00
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
2022-04-13 19:02:17 +03:00
|
|
|
// #include "ble.h"
|
|
|
|
// #ifdef NRF51
|
|
|
|
// #include "nrf_soc.h"
|
|
|
|
// #else
|
|
|
|
// #include "nrf_nvic.h"
|
|
|
|
// #endif
|
|
|
|
import "C"
|
|
|
|
|
2019-11-09 15:07:07 +03:00
|
|
|
var (
|
|
|
|
ErrNotDefaultAdapter = errors.New("bluetooth: not the default adapter")
|
|
|
|
)
|
|
|
|
|
2019-06-02 20:12:36 +03:00
|
|
|
var (
|
2019-11-09 14:27:48 +03:00
|
|
|
secModeOpen C.ble_gap_conn_sec_mode_t // No security is needed (aka open link).
|
2019-06-02 20:12:36 +03:00
|
|
|
defaultDeviceName = [6]byte{'T', 'i', 'n', 'y', 'G', 'o'}
|
|
|
|
)
|
|
|
|
|
2020-06-03 18:33:32 +03:00
|
|
|
// There can only be one connection at a time in the default configuration.
|
|
|
|
var currentConnection = volatile.Register16{C.BLE_CONN_HANDLE_INVALID}
|
|
|
|
|
2019-06-02 20:12:36 +03:00
|
|
|
// Globally allocated buffer for incoming SoftDevice events.
|
|
|
|
var eventBuf struct {
|
|
|
|
C.ble_evt_t
|
|
|
|
buf [23]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
secModeOpen.set_bitfield_sm(1)
|
|
|
|
secModeOpen.set_bitfield_lv(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adapter is a dummy adapter: it represents the connection to the (only)
|
|
|
|
// SoftDevice on the chip.
|
|
|
|
type Adapter struct {
|
2019-11-09 15:55:34 +03:00
|
|
|
isDefault bool
|
2020-05-28 00:13:04 +03:00
|
|
|
scanning bool
|
2019-11-09 15:55:34 +03:00
|
|
|
charWriteHandlers []charWriteHandler
|
2020-09-10 18:17:45 +03:00
|
|
|
|
2023-04-25 03:12:05 +03:00
|
|
|
connectHandler func(device Address, connected bool)
|
2019-06-02 20:12:36 +03:00
|
|
|
}
|
|
|
|
|
2020-06-01 14:26:45 +03:00
|
|
|
// DefaultAdapter is the default adapter on the current system. On Nordic chips,
|
|
|
|
// it will return the SoftDevice interface.
|
|
|
|
//
|
|
|
|
// Make sure to call Enable() before using it to initialize the adapter.
|
2020-09-10 18:17:45 +03:00
|
|
|
var DefaultAdapter = &Adapter{isDefault: true,
|
2023-04-25 03:12:05 +03:00
|
|
|
connectHandler: func(device Address, connected bool) {
|
2020-09-10 18:17:45 +03:00
|
|
|
return
|
|
|
|
}}
|
2019-06-02 20:12:36 +03:00
|
|
|
|
2023-04-25 03:04:03 +03:00
|
|
|
var eventBufLen uint16
|
|
|
|
|
2019-06-02 20:12:36 +03:00
|
|
|
// Enable configures the BLE stack. It must be called before any
|
|
|
|
// Bluetooth-related calls (unless otherwise indicated).
|
|
|
|
func (a *Adapter) Enable() error {
|
2019-11-09 15:07:07 +03:00
|
|
|
if !a.isDefault {
|
|
|
|
return ErrNotDefaultAdapter
|
|
|
|
}
|
|
|
|
|
2019-06-02 20:12:36 +03:00
|
|
|
// Enable the IRQ that handles all events.
|
2020-05-24 22:23:34 +03:00
|
|
|
intr := interrupt.New(nrf.IRQ_SWI2, func(interrupt.Interrupt) {
|
|
|
|
for {
|
2023-04-25 03:04:03 +03:00
|
|
|
eventBufLen = uint16(unsafe.Sizeof(eventBuf))
|
2020-05-24 22:23:34 +03:00
|
|
|
errCode := C.sd_ble_evt_get((*uint8)(unsafe.Pointer(&eventBuf)), &eventBufLen)
|
|
|
|
if errCode != 0 {
|
|
|
|
// Possible error conditions:
|
|
|
|
// * NRF_ERROR_NOT_FOUND: no events left, break
|
|
|
|
// * NRF_ERROR_DATA_SIZE: retry with a bigger data buffer
|
|
|
|
// (currently not handled, TODO)
|
|
|
|
// * NRF_ERROR_INVALID_ADDR: pointer is not aligned, should
|
|
|
|
// not happen.
|
|
|
|
// In all cases, it's best to simply stop now.
|
|
|
|
break
|
|
|
|
}
|
|
|
|
handleEvent()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
intr.Enable()
|
|
|
|
intr.SetPriority(192)
|
|
|
|
|
|
|
|
// Do more specific initialization of this SoftDevice (split out for nrf52*
|
|
|
|
// and nrf51 chips because of the different API).
|
|
|
|
err := a.enable()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-06-02 20:12:36 +03:00
|
|
|
}
|
|
|
|
|
2020-05-24 22:23:34 +03:00
|
|
|
errCode := C.sd_ble_gap_device_name_set(&secModeOpen, &defaultDeviceName[0], uint16(len(defaultDeviceName)))
|
2019-06-02 20:12:36 +03:00
|
|
|
if errCode != 0 {
|
|
|
|
return Error(errCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
var gapConnParams C.ble_gap_conn_params_t
|
|
|
|
gapConnParams.min_conn_interval = C.BLE_GAP_CP_MIN_CONN_INTVL_MIN
|
|
|
|
gapConnParams.max_conn_interval = C.BLE_GAP_CP_MIN_CONN_INTVL_MAX
|
|
|
|
gapConnParams.slave_latency = 0
|
|
|
|
gapConnParams.conn_sup_timeout = C.BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE
|
|
|
|
|
|
|
|
errCode = C.sd_ble_gap_ppcp_set(&gapConnParams)
|
2020-05-24 22:23:34 +03:00
|
|
|
return makeError(errCode)
|
2019-06-02 20:12:36 +03:00
|
|
|
}
|
2020-06-11 17:52:04 +03:00
|
|
|
|
|
|
|
// DisableInterrupts must be used instead of disabling interrupts directly, to
|
|
|
|
// play well with the SoftDevice. Restore interrupts to the previous state with
|
|
|
|
// RestoreInterrupts.
|
|
|
|
func DisableInterrupts() uintptr {
|
|
|
|
var is_nested_critical_region uint8
|
|
|
|
C.sd_nvic_critical_region_enter(&is_nested_critical_region)
|
|
|
|
return uintptr(is_nested_critical_region)
|
|
|
|
}
|
|
|
|
|
|
|
|
// RestoreInterrupts restores interrupts to the state before calling
|
|
|
|
// DisableInterrupts. The mask parameter must be the value returned by
|
|
|
|
// DisableInterrupts.
|
|
|
|
func RestoreInterrupts(mask uintptr) {
|
|
|
|
C.sd_nvic_critical_region_exit(uint8(mask))
|
|
|
|
}
|