|
@@ -26,23 +26,22 @@
|
26
|
26
|
#include "util.h"
|
27
|
27
|
#include "ble.h"
|
28
|
28
|
|
|
29
|
+#define BLE_MAX_SCAN_AGE_MS (10 * 1000)
|
|
30
|
+
|
29
|
31
|
enum ble_state {
|
30
|
32
|
TC_OFF = 0,
|
31
|
33
|
TC_IDLE,
|
32
|
|
- TC_W4_SCAN_RESULT,
|
|
34
|
+ TC_W4_SCAN,
|
33
|
35
|
TC_W4_CONNECT,
|
34
|
|
- TC_W4_SERVICE_RESULT,
|
35
|
|
- TC_W4_CHARACTERISTIC_RESULT,
|
36
|
|
- TC_W4_ENABLE_NOTIFICATIONS_COMPLETE,
|
37
|
|
- TC_W4_READY
|
|
36
|
+ TC_READY
|
38
|
37
|
};
|
39
|
38
|
|
40
|
39
|
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
|
40
|
+static hci_con_handle_t connection_handle;
|
|
41
|
+
|
41
|
42
|
static enum ble_state state = TC_OFF;
|
42
|
43
|
static struct ble_scan_result scans[BLE_MAX_SCAN_RESULTS] = {0};
|
43
|
44
|
|
44
|
|
-// TODO scan result entries are not aging out
|
45
|
|
-
|
46
|
45
|
static void hci_add_scan_result(bd_addr_t addr, bd_addr_type_t type, int8_t rssi) {
|
47
|
46
|
int unused = -1;
|
48
|
47
|
|
|
@@ -55,8 +54,9 @@ static void hci_add_scan_result(bd_addr_t addr, bd_addr_type_t type, int8_t rssi
|
55
|
54
|
}
|
56
|
55
|
|
57
|
56
|
if (memcmp(addr, scans[i].addr, sizeof(bd_addr_t)) == 0) {
|
58
|
|
- // already in list, just update time for aging
|
|
57
|
+ // already in list, just update changing values
|
59
|
58
|
scans[i].time = to_ms_since_boot(get_absolute_time());
|
|
59
|
+ scans[i].rssi = rssi;
|
60
|
60
|
return;
|
61
|
61
|
}
|
62
|
62
|
}
|
|
@@ -102,7 +102,7 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
102
|
102
|
UNUSED(channel);
|
103
|
103
|
|
104
|
104
|
if (packet_type != HCI_EVENT_PACKET) {
|
105
|
|
- debug("unexpected packet 0x%02X", packet_type);
|
|
105
|
+ //debug("unexpected packet 0x%02X", packet_type);
|
106
|
106
|
return;
|
107
|
107
|
}
|
108
|
108
|
|
|
@@ -119,16 +119,8 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
119
|
119
|
}
|
120
|
120
|
break;
|
121
|
121
|
|
122
|
|
- case HCI_EVENT_INQUIRY_COMPLETE:
|
123
|
|
- case HCI_EVENT_COMMAND_STATUS:
|
124
|
|
- case HCI_EVENT_REMOTE_HOST_SUPPORTED_FEATURES:
|
125
|
|
- case BTSTACK_EVENT_SCAN_MODE_CHANGED:
|
126
|
|
- case HCI_EVENT_COMMAND_COMPLETE:
|
127
|
|
- case HCI_EVENT_TRANSPORT_PACKET_SENT:
|
128
|
|
- break;
|
129
|
|
-
|
130
|
122
|
case GAP_EVENT_ADVERTISING_REPORT: {
|
131
|
|
- if (state != TC_W4_SCAN_RESULT) {
|
|
123
|
+ if (state != TC_W4_SCAN) {
|
132
|
124
|
debug("scan result in invalid state %d", state);
|
133
|
125
|
return;
|
134
|
126
|
}
|
|
@@ -163,17 +155,9 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
163
|
155
|
hci_scan_result_add_name(addr, data, data_size);
|
164
|
156
|
break;
|
165
|
157
|
|
166
|
|
- case BLUETOOTH_DATA_TYPE_FLAGS:
|
167
|
|
- case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
|
168
|
|
- case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
169
|
|
- case BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID:
|
170
|
|
- case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
|
171
|
|
- case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
|
172
|
|
- break;
|
173
|
|
-
|
174
|
158
|
default:
|
175
|
|
- debug("Unexpected advertisement type 0x%02X from %s", data_type, bd_addr_to_str(addr));
|
176
|
|
- hexdump(data, data_size);
|
|
159
|
+ //debug("Unexpected advertisement type 0x%02X from %s", data_type, bd_addr_to_str(addr));
|
|
160
|
+ //hexdump(data, data_size);
|
177
|
161
|
break;
|
178
|
162
|
}
|
179
|
163
|
}
|
|
@@ -182,22 +166,29 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
182
|
166
|
|
183
|
167
|
case HCI_EVENT_LE_META:
|
184
|
168
|
switch (hci_event_le_meta_get_subevent_code(packet)) {
|
185
|
|
- case HCI_SUBEVENT_LE_ADVERTISING_REPORT:
|
186
|
|
- // handled internally by BTstack
|
187
|
|
- break;
|
188
|
|
-
|
189
|
169
|
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
190
|
|
- debug("connection complete?!");
|
|
170
|
+ if (state != TC_W4_CONNECT) {
|
|
171
|
+ return;
|
|
172
|
+ }
|
|
173
|
+ debug("connection complete");
|
|
174
|
+ connection_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
|
|
175
|
+ state = TC_READY;
|
191
|
176
|
break;
|
192
|
177
|
|
193
|
178
|
default:
|
194
|
|
- debug("unexpected LE meta event 0x%02X", hci_event_le_meta_get_subevent_code(packet));
|
|
179
|
+ //debug("unexpected LE meta event 0x%02X", hci_event_le_meta_get_subevent_code(packet));
|
195
|
180
|
break;
|
196
|
181
|
}
|
197
|
182
|
break;
|
198
|
183
|
|
|
184
|
+ case HCI_EVENT_DISCONNECTION_COMPLETE:
|
|
185
|
+ debug("disconnected");
|
|
186
|
+ connection_handle = HCI_CON_HANDLE_INVALID;
|
|
187
|
+ state = TC_IDLE;
|
|
188
|
+ break;
|
|
189
|
+
|
199
|
190
|
default:
|
200
|
|
- debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
|
|
191
|
+ //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
|
201
|
192
|
break;
|
202
|
193
|
}
|
203
|
194
|
}
|
|
@@ -236,6 +227,11 @@ bool ble_is_ready(void) {
|
236
|
227
|
void ble_scan(enum ble_scan_mode mode) {
|
237
|
228
|
cyw43_thread_enter();
|
238
|
229
|
|
|
230
|
+ if (state == TC_OFF) {
|
|
231
|
+ cyw43_thread_exit();
|
|
232
|
+ return;
|
|
233
|
+ }
|
|
234
|
+
|
239
|
235
|
switch (mode) {
|
240
|
236
|
case BLE_SCAN_OFF:
|
241
|
237
|
debug("stopping BLE scan");
|
|
@@ -245,14 +241,14 @@ void ble_scan(enum ble_scan_mode mode) {
|
245
|
241
|
|
246
|
242
|
case BLE_SCAN_ON:
|
247
|
243
|
debug("starting BLE scan");
|
248
|
|
- state = TC_W4_SCAN_RESULT;
|
|
244
|
+ state = TC_W4_SCAN;
|
249
|
245
|
gap_set_scan_parameters(1, 0x0030, 0x0030);
|
250
|
246
|
gap_start_scan();
|
251
|
247
|
break;
|
252
|
248
|
|
253
|
249
|
case BLE_SCAN_TOGGLE:
|
254
|
250
|
switch (state) {
|
255
|
|
- case TC_W4_SCAN_RESULT:
|
|
251
|
+ case TC_W4_SCAN:
|
256
|
252
|
cyw43_thread_exit();
|
257
|
253
|
ble_scan(0);
|
258
|
254
|
return;
|
|
@@ -283,12 +279,23 @@ int ble_get_scan_results(struct ble_scan_result *buf, uint len) {
|
283
|
279
|
|
284
|
280
|
cyw43_thread_enter();
|
285
|
281
|
|
|
282
|
+ if (state == TC_OFF) {
|
|
283
|
+ cyw43_thread_exit();
|
|
284
|
+ return -1;
|
|
285
|
+ }
|
|
286
|
+
|
286
|
287
|
uint pos = 0;
|
287
|
288
|
for (uint i = 0; i < BLE_MAX_SCAN_RESULTS; i++) {
|
288
|
289
|
if (!scans[i].set) {
|
289
|
290
|
continue;
|
290
|
291
|
}
|
291
|
292
|
|
|
293
|
+ uint32_t diff = to_ms_since_boot(get_absolute_time()) - scans[i].time;
|
|
294
|
+ if (diff >= BLE_MAX_SCAN_AGE_MS) {
|
|
295
|
+ //debug("removing %s due to age", bd_addr_to_str(scans[i].addr));
|
|
296
|
+ scans[i].set = false;
|
|
297
|
+ }
|
|
298
|
+
|
292
|
299
|
memcpy(buf + pos, scans + i, sizeof(struct ble_scan_result));
|
293
|
300
|
pos++;
|
294
|
301
|
|
|
@@ -300,3 +307,42 @@ int ble_get_scan_results(struct ble_scan_result *buf, uint len) {
|
300
|
307
|
cyw43_thread_exit();
|
301
|
308
|
return pos;
|
302
|
309
|
}
|
|
310
|
+
|
|
311
|
+void ble_connect(bd_addr_t addr, bd_addr_type_t type) {
|
|
312
|
+ cyw43_thread_enter();
|
|
313
|
+
|
|
314
|
+ switch (state) {
|
|
315
|
+ case TC_OFF:
|
|
316
|
+ cyw43_thread_exit();
|
|
317
|
+ return;
|
|
318
|
+
|
|
319
|
+ case TC_W4_SCAN:
|
|
320
|
+ cyw43_thread_exit();
|
|
321
|
+ ble_scan(0);
|
|
322
|
+ cyw43_thread_enter();
|
|
323
|
+ break;
|
|
324
|
+
|
|
325
|
+ case TC_READY:
|
|
326
|
+ gap_disconnect(connection_handle);
|
|
327
|
+ break;
|
|
328
|
+
|
|
329
|
+ default:
|
|
330
|
+ break;
|
|
331
|
+ }
|
|
332
|
+
|
|
333
|
+ debug("connecting to %s", bd_addr_to_str(addr));
|
|
334
|
+ state = TC_W4_CONNECT;
|
|
335
|
+ gap_connect(addr, type);
|
|
336
|
+
|
|
337
|
+ cyw43_thread_exit();
|
|
338
|
+}
|
|
339
|
+
|
|
340
|
+void ble_disconnect(void) {
|
|
341
|
+ cyw43_thread_enter();
|
|
342
|
+
|
|
343
|
+ if (state == TC_READY) {
|
|
344
|
+ gap_disconnect(connection_handle);
|
|
345
|
+ }
|
|
346
|
+
|
|
347
|
+ cyw43_thread_exit();
|
|
348
|
+}
|