forked from tinygo-org/bluetooth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
adapter_nrf51.go
118 lines (108 loc) · 3.8 KB
/
adapter_nrf51.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//go:build softdevice && s110v8
// +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(uint32_t pc, uint16_t line_number, const uint8_t * p_file_name);
*/
import "C"
import "unsafe"
//export assertHandler
func assertHandler(pc uint32, line_number uint16, p_file_name *byte) {
println("SoftDevice assert")
}
func (a *Adapter) enable() error {
// Enable the SoftDevice.
errCode := C.sd_softdevice_enable(C.NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, C.softdevice_assertion_handler_t(C.assertHandler))
if errCode != 0 {
return Error(errCode)
}
// Enable the BLE stack.
enableParams := C.ble_enable_params_t{
gatts_enable_params: C.ble_gatts_enable_params_t{
attr_tab_size: C.BLE_GATTS_ATTR_TAB_SIZE_DEFAULT,
},
}
errCode = C.sd_ble_enable(&enableParams)
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
DefaultAdapter.connectHandler(Address{}, true)
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.
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
// 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)
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)
default:
if debug {
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE)
}
}
default:
if debug {
println("unknown event:", id)
}
}
}
func (a *Adapter) Address() (MACAddress, error) {
var addr C.ble_gap_addr_t
errCode := C.sd_ble_gap_address_get(&addr)
if errCode != 0 {
return MACAddress{}, Error(errCode)
}
return MACAddress{MAC: addr.addr}, nil
}