xref: /btstack/port/arduino/BTstack.cpp (revision cf26c8fbbf161f7e5ee9327de39264752c730a34)
1 /**
2  * Arduino Wrapper for BTstack
3  */
4 
5 #include <Arduino.h>
6 #include <SPI.h>
7 
8 #ifdef __AVR__
9 #include <avr/wdt.h>
10 #endif
11 
12 #if __arm__
13 #include <Reset.h>  // also provides NVIC_SystemReset
14 #endif
15 
16 #include "BTstack.h"
17 
18 #include "btstack_memory.h"
19 #include "hal_tick.h"
20 #include "hal_cpu.h"
21 #include "hci_cmd.h"
22 #include "btstack_util.h"
23 #include "btstack_run_loop.h"
24 #include "btstack_run_loop_embedded.h"
25 #include "classic/sdp_util.h"
26 #include "hci_transport.h"
27 #include "hci_transport_h4.h"
28 
29 #include "ad_parser.h"
30 #include "btstack_chipset_em9301.h"
31 #include "btstack_debug.h"
32 #include "gap.h"
33 #include "hci.h"
34 #include "hci_dump.h"
35 #include "hci_dump_embedded_stdout.h"
36 #include "l2cap.h"
37 #include "ble/att_db.h"
38 #include "ble/att_server.h"
39 #include "ble/att_db_util.h"
40 #include "ble/le_device_db.h"
41 #include "ble/sm.h"
42 
43 // Pin 13 has an LED connected on most Arduino boards.
44 #define PIN_LED 13
45 
46 // prototypes
47 extern "C" void hal_uart_dma_process(void);
48 
49 enum {
50     SET_ADVERTISEMENT_PARAMS  = 1 << 0,
51     SET_ADVERTISEMENT_DATA    = 1 << 1,
52     SET_ADVERTISEMENT_ENABLED = 1 << 2,
53 };
54 
55 typedef enum gattAction {
56     gattActionWrite,
57     gattActionSubscribe,
58     gattActionUnsubscribe,
59     gattActionServiceQuery,
60     gattActionCharacteristicQuery,
61     gattActionRead,
62 } gattAction_t;
63 
64 static gattAction_t gattAction;
65 
66 // btstack state
67 static int btstack_state;
68 
69 static const uint8_t iBeaconAdvertisement01[] = { 0x02, 0x01 };
70 static const uint8_t iBeaconAdvertisement38[] = { 0x1a, 0xff, 0x4c, 0x00, 0x02, 0x15 };
71 static uint8_t   adv_data[31];
72 static uint16_t  adv_data_len = 0;
73 static uint16_t gatt_client_id;
74 static int gatt_is_characteristics_query;
75 
76 static uint16_t le_peripheral_todos = 0;
77 static bool have_custom_addr;
78 static bd_addr_t public_bd_addr;
79 
80 static btstack_timer_source_t connection_timer;
81 
82 static void (*bleAdvertismentCallback)(BLEAdvertisement * bleAdvertisement) = NULL;
83 static void (*bleDeviceConnectedCallback)(BLEStatus status, BLEDevice * device)= NULL;
84 static void (*bleDeviceDisconnectedCallback)(BLEDevice * device) = NULL;
85 static void (*gattServiceDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLEService * bleService) = NULL;
86 static void (*gattCharacteristicDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic) = NULL;
87 static void (*gattCharacteristicNotificationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL;
88 static void (*gattCharacteristicIndicationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL;
89 static void (*gattCharacteristicReadCallback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length) = NULL;
90 static void (*gattCharacteristicWrittenCallback)(BLEStatus status, BLEDevice * device) = NULL;
91 static void (*gattCharacteristicSubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
92 static void (*gattCharacteristicUnsubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
93 
94 
95 // retarget printf to Serial
96 #ifdef ENERGIA
97 extern "C" int putchar(int c) {
98     Serial.write((uint8_t)c);
99     return c;
100 }
101 #else
102 #ifdef __AVR__
103 static FILE uartout = {0} ;
104 static int uart_putchar (char c, FILE *stream) {
105     Serial.write(c);
106     return 0;
107 }
108 #endif
109 // added for Arduino Zero. Arduino Due already has tis own _write(..) implementation
110 // in  /Users/mringwal/Library/Arduino15/packages/arduino/hardware/sam/1.6.4/cores/arduino/syscalls_sam3.c
111 #if defined(__SAMD21G18A__)
112 // #ifdef __arm__
113 extern "C" int _write(int file, char *ptr, int len){
114     int i;
115     for (i = 0; i < len; i++) {
116         if (ptr[i] == '\n') {
117             Serial.write((uint8_t)'\r');
118         }
119         Serial.write((uint8_t)ptr[i]);
120     }
121     return i;
122 }
123 #endif
124 #endif
125 
126 // HAL CPU Implementation
127 extern "C" void hal_cpu_disable_irqs(void){ }
128 extern "C" void hal_cpu_enable_irqs(void) { }
129 extern "C" void hal_cpu_enable_irqs_and_sleep(void) { }
130 
131 //
132 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
133 
134     bd_addr_t addr;
135     hci_con_handle_t con_handle;
136 
137     switch (packet_type) {
138 
139         case HCI_EVENT_PACKET:
140             switch (packet[0]) {
141 
142                 case BTSTACK_EVENT_STATE:
143                     btstack_state = packet[2];
144                     // bt stack activated, get started
145                     if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
146                         le_peripheral_todos |= SET_ADVERTISEMENT_PARAMS
147                                             | SET_ADVERTISEMENT_DATA
148                                             | SET_ADVERTISEMENT_ENABLED;
149                     }
150                     break;
151 
152                 case HCI_EVENT_DISCONNECTION_COMPLETE:
153                     if (bleDeviceDisconnectedCallback) {
154                         con_handle = little_endian_read_16(packet, 3);
155                         BLEDevice device(con_handle);
156                         (*bleDeviceDisconnectedCallback)(&device);
157                     }
158                     le_peripheral_todos |= SET_ADVERTISEMENT_ENABLED;
159                     break;
160 
161                 case GAP_EVENT_ADVERTISING_REPORT: {
162                     if (bleAdvertismentCallback) {
163                         BLEAdvertisement advertisement(packet);
164                         (*bleAdvertismentCallback)(&advertisement);
165                     }
166                     break;
167                 }
168 
169                 case HCI_EVENT_COMMAND_COMPLETE:
170                     if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) {
171                         bt_flip_addr(addr, &packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1]);
172                         printf("Local Address: %s\n", bd_addr_to_str(addr));
173                         break;
174                     }
175                     break;
176 
177                 case HCI_EVENT_LE_META:
178                     switch (packet[2]) {
179                         case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
180                             con_handle = little_endian_read_16(packet, 4);
181                             printf("Connection complete, con_handle 0x%04x\n", con_handle);
182                             btstack_run_loop_remove_timer(&connection_timer);
183                             if (!bleDeviceConnectedCallback) break;
184                             if (packet[3]){
185                                 (*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_ERROR, NULL);
186                             } else {
187                                 BLEDevice device(con_handle);
188                                 (*bleDeviceConnectedCallback)(BLE_STATUS_OK, &device);
189                             }
190                             break;
191                         default:
192                             break;
193                     }
194                     break;
195             }
196     }
197 }
198 
199 static void extract_service(gatt_client_service_t * service, uint8_t * packet){
200     service->start_group_handle = little_endian_read_16(packet, 4);
201     service->end_group_handle   = little_endian_read_16(packet, 6);
202     service->uuid16 = 0;
203     reverse_128(&packet[8], service->uuid128);
204     if (uuid_has_bluetooth_prefix(service->uuid128)){
205         service->uuid16 = big_endian_read_32(service->uuid128, 0);
206     }
207 }
208 
209 static void extract_characteristic(gatt_client_characteristic_t * characteristic, uint8_t * packet){
210     characteristic->start_handle = little_endian_read_16(packet, 4);
211     characteristic->value_handle = little_endian_read_16(packet, 6);
212     characteristic->end_handle =   little_endian_read_16(packet, 8);
213     characteristic->properties =   little_endian_read_16(packet, 10);
214     characteristic->uuid16 = 0;
215     reverse_128(&packet[12], characteristic->uuid128);
216     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
217         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
218     }
219 }
220 
221 static void gatt_client_callback(uint8_t packet_type, uint8_t * packet, uint16_t size){
222 
223     // if (hci) event is not 4-byte aligned, event->handle causes crash
224     // workaround: check event type, assuming GATT event types are contagious
225     if (packet[0] < GATT_EVENT_QUERY_COMPLETE) return;
226     if (packet[0] > GATT_EVENT_MTU) return;
227 
228     hci_con_handle_t con_handle = little_endian_read_16(packet, 2);
229     uint8_t   status;
230     uint8_t * value;
231     uint16_t  value_handle;
232     uint16_t  value_length;
233 
234     BLEDevice device(con_handle);
235     switch(hci_event_packet_get_type(packet)){
236         case GATT_EVENT_SERVICE_QUERY_RESULT:
237             if (gattServiceDiscoveredCallback) {
238                 gatt_client_service_t service;
239                 extract_service(&service, packet);
240                 BLEService bleService(service);
241                 (*gattServiceDiscoveredCallback)(BLE_STATUS_OK, &device, &bleService);
242             }
243             break;
244         case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
245             if (gattCharacteristicDiscoveredCallback){
246                 gatt_client_characteristic_t characteristic;
247                 extract_characteristic(&characteristic, packet);
248                 BLECharacteristic bleCharacteristic(characteristic);
249                (*gattCharacteristicDiscoveredCallback)(BLE_STATUS_OK, &device, &bleCharacteristic);
250             }
251             break;
252         case GATT_EVENT_QUERY_COMPLETE:
253             status = little_endian_read_16(packet, 4);
254             switch (gattAction){
255                 case gattActionWrite:
256                     if (gattCharacteristicWrittenCallback) gattCharacteristicWrittenCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
257                     break;
258                 case gattActionSubscribe:
259                     if (gattCharacteristicSubscribedCallback) gattCharacteristicSubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
260                     break;
261                 case gattActionUnsubscribe:
262                     if (gattCharacteristicUnsubscribedCallback) gattCharacteristicUnsubscribedCallback(status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
263                     break;
264                 case gattActionServiceQuery:
265                     if (gattServiceDiscoveredCallback) gattServiceDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
266                     break;
267                 case gattActionCharacteristicQuery:
268                     if (gattCharacteristicDiscoveredCallback) gattCharacteristicDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
269                     break;
270                 default:
271                     break;
272             };
273             break;
274         case GATT_EVENT_NOTIFICATION:
275             if (gattCharacteristicNotificationCallback) {
276                 value_handle = little_endian_read_16(packet, 4);
277                 value_length = little_endian_read_16(packet, 6);
278                 value = &packet[8];
279                 (*gattCharacteristicNotificationCallback)(&device, value_handle, value, value_length);
280             }
281             break;
282         case GATT_EVENT_INDICATION:
283             if (gattCharacteristicIndicationCallback) {
284                 value_handle = little_endian_read_16(packet, 4);
285                 value_length = little_endian_read_16(packet, 6);
286                 value = &packet[8];
287                 (*gattCharacteristicIndicationCallback)(&device, value_handle, value, value_length);
288             }
289             break;
290         case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
291             if (gattCharacteristicReadCallback) {
292                 value_handle = little_endian_read_16(packet, 4);
293                 value_length = little_endian_read_16(packet, 6);
294                 value = &packet[8];
295                 (*gattCharacteristicReadCallback)(BLE_STATUS_OK, &device, value, value_length);
296             }
297             break;
298         default:
299             break;
300     }
301 }
302 
303 static void connection_timeout_handler(btstack_timer_source_t * timer){
304     // log_info("Cancel outgoing connection");
305     gap_le_connect_cancel();
306     if (!bleDeviceConnectedCallback) return;
307     (*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_TIMEOUT, NULL);  // page timeout 0x04
308 }
309 
310 //
311 
312 static int nibble_for_char(const char c){
313     if ('0' <= c && c <= '9') return c - '0';
314     if ('a' <= c && c <= 'f') return c - 'a' + 10;
315     if ('A' <= c && c <= 'F') return c - 'A' + 10;
316     return 0;
317 }
318 
319 /// UUID class
320 UUID::UUID(void){
321     memset(uuid, 0, 16);
322 }
323 
324 UUID::UUID(const uint8_t uuid[16]){
325     memcpy(this->uuid, uuid, 16);
326 }
327 
328 UUID::UUID(const char * uuidStr){
329     memset(uuid, 0, 16);
330     int len = strlen(uuidStr);
331     if (len <= 4){
332         // Handle 4 Bytes HEX
333         uint16_t uuid16;
334         int result = sscanf( (char *) uuidStr, "%x", &uuid16);
335         if (result == 1){
336             uuid_add_bluetooth_prefix(uuid, uuid16);
337         }
338         return;
339     }
340 
341     // quick UUID parser, ignoring dashes
342     int i = 0;
343     int data = 0;
344     int have_nibble = 0;
345     while(*uuidStr && i < 16){
346         const char c = *uuidStr++;
347         if (c == '-') continue;
348         data = data << 4 | nibble_for_char(c);
349         if (!have_nibble) {
350             have_nibble = 1;
351             continue;
352         }
353         uuid[i++] = data;
354         data = 0;
355         have_nibble = 0;
356     }
357 }
358 
359 const uint8_t * UUID::getUuid(void) const {
360     return uuid;
361 }
362 
363 static char uuid16_buffer[5];
364 const char * UUID::getUuidString() const {
365     // TODO: fix uuid_has_bluetooth_prefix call to use const
366     if (uuid_has_bluetooth_prefix((uint8_t*)uuid)){
367         sprintf(uuid16_buffer, "%04x", (uint16_t) big_endian_read_32(uuid, 0));
368         return uuid16_buffer;
369     }  else {
370         // TODO: fix uuid128_to_str
371         return uuid128_to_str((uint8_t*)uuid);
372     }
373 }
374 
375 const char * UUID::getUuid128String() const {
376     return uuid128_to_str((uint8_t*)uuid);
377 }
378 
379 bool UUID::matches(UUID *other)        const {
380     return memcmp(this->uuid, other->uuid, 16) == 0;
381 }
382 
383 
384 // BD_ADDR class
385 BD_ADDR::BD_ADDR(void){
386 }
387 
388 BD_ADDR::BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type ) : address_type(address_type) {
389     // TODO: implement
390     // log_error("BD_ADDR::BD_ADDR(const char *, BD_ADDR_TYPE) not implemented yet!");
391 }
392 
393 BD_ADDR::BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type) : address_type(address_type){
394     memcpy(this->address, address, 6);
395 }
396 
397 const uint8_t * BD_ADDR::getAddress(void){
398     return address;
399 }
400 
401 const char * BD_ADDR::getAddressString(void){
402     return bd_addr_to_str(address);
403 }
404 
405 BD_ADDR_TYPE BD_ADDR::getAddressType(void){
406     return address_type;
407 }
408 
409 
410 BLEAdvertisement::BLEAdvertisement(uint8_t * event_packet) :
411 advertising_event_type(event_packet[2]),
412 rssi(event_packet[10]),
413 data_length(event_packet[11]),
414 iBeacon_UUID(NULL)
415 {
416     bd_addr_t addr;
417     bt_flip_addr(addr, &event_packet[4]);
418     bd_addr = BD_ADDR(addr, (BD_ADDR_TYPE)event_packet[3]);
419     memcpy(data, &event_packet[12], LE_ADVERTISING_DATA_SIZE);
420 }
421 
422 BLEAdvertisement::~BLEAdvertisement(){
423     if (iBeacon_UUID) delete(iBeacon_UUID);
424 }
425 
426 const uint8_t * BLEAdvertisement::getAdvData(void){
427     return data;
428 }
429 
430 BD_ADDR * BLEAdvertisement::getBdAddr(void){
431     return &bd_addr;
432 }
433 
434 int BLEAdvertisement::getRssi(void){
435     return rssi > 127 ? rssi - 256 : rssi;
436 }
437 
438 
439 bool BLEAdvertisement::containsService(UUID * service){
440     return ad_data_contains_uuid128(data_length, data, (uint8_t*) service->getUuid());
441 }
442 
443 bool BLEAdvertisement::nameHasPrefix(const char * name_prefix){
444     ad_context_t context;
445     int name_prefix_len = strlen(name_prefix);
446     for (ad_iterator_init(&context, data_length, data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
447         uint8_t data_type = ad_iterator_get_data_type(&context);
448         uint8_t data_len  = ad_iterator_get_data_len(&context);
449         uint8_t * data    = ad_iterator_get_data(&context);
450         int compare_len = name_prefix_len;
451         switch(data_type){
452             case 8: // shortented local name
453             case 9: // complete local name
454                 if (compare_len > data_len) compare_len = data_len;
455                 if (strncmp(name_prefix, (const char*) data, compare_len) == 0) return true;
456                 break;
457             default:
458                 break;
459         }
460     }
461     return false;
462 };
463 
464 bool BLEAdvertisement::isIBeacon(void){
465     return ((memcmp(iBeaconAdvertisement01,  data,    sizeof(iBeaconAdvertisement01)) == 0)
466       &&    (memcmp(iBeaconAdvertisement38, &data[3], sizeof(iBeaconAdvertisement38)) == 0));
467 }
468 
469 const UUID * BLEAdvertisement::getIBeaconUUID(void){
470     if (!iBeacon_UUID){
471         iBeacon_UUID = new UUID(&data[9]);
472     }
473     return iBeacon_UUID;
474 };
475 uint16_t BLEAdvertisement::getIBeaconMajorID(void){
476     return big_endian_read_16(data, 25);
477 };
478 uint16_t BLEAdvertisement::getIBecaonMinorID(void){
479     return big_endian_read_16(data, 27);
480 };
481 uint8_t BLEAdvertisement::getiBeaconMeasuredPower(void){
482     return data[29];
483 }
484 
485 
486 BLECharacteristic::BLECharacteristic(void){
487 }
488 
489 BLECharacteristic::BLECharacteristic(gatt_client_characteristic_t characteristic)
490 : characteristic(characteristic), uuid(characteristic.uuid128) {
491 }
492 
493 const UUID * BLECharacteristic::getUUID(void){
494     return &uuid;
495 }
496 
497 bool BLECharacteristic::matches(UUID * uuid){
498     return this->uuid.matches(uuid);
499 }
500 
501 bool BLECharacteristic::isValueHandle(uint16_t value_handle){
502     return characteristic.value_handle == value_handle;
503 }
504 
505 const gatt_client_characteristic_t * BLECharacteristic::getCharacteristic(void){
506     return &characteristic;
507 }
508 
509 
510 BLEService::BLEService(void){
511 }
512 
513 BLEService::BLEService(gatt_client_service_t service)
514 : service(service), uuid(service.uuid128){
515 }
516 
517 const UUID * BLEService::getUUID(void){
518     return &uuid;
519 }
520 
521 bool BLEService::matches(UUID * uuid){
522     return this->uuid.matches(uuid);
523 }
524 
525 const gatt_client_service_t * BLEService::getService(void){
526     return &service;
527 }
528 
529 // discovery of services and characteristics
530 BLEDevice::BLEDevice(void){
531 }
532 BLEDevice::BLEDevice(hci_con_handle_t handle)
533 : handle(handle){
534 }
535 uint16_t BLEDevice::getHandle(void){
536     return handle;
537 }
538 int BLEDevice::discoverGATTServices(void){
539     return BTstack.discoverGATTServices(this);
540 }
541 int BLEDevice::discoverCharacteristicsForService(BLEService * service){
542     return BTstack.discoverCharacteristicsForService(this, service);
543 }
544 int BLEDevice::readCharacteristic(BLECharacteristic * characteristic){
545     return BTstack.readCharacteristic(this, characteristic);
546 }
547 int BLEDevice::writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
548     return BTstack.writeCharacteristic(this, characteristic, data, size);
549 }
550 int BLEDevice::writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
551     return BTstack.writeCharacteristicWithoutResponse(this, characteristic, data, size);
552 }
553 int BLEDevice::subscribeForNotifications(BLECharacteristic * characteristic){
554     return BTstack.subscribeForNotifications(this, characteristic);
555 }
556 int BLEDevice::unsubscribeFromNotifications(BLECharacteristic * characteristic){
557     return BTstack.unsubscribeFromNotifications(this, characteristic);
558 }
559 int BLEDevice::subscribeForIndications(BLECharacteristic * characteristic){
560     return BTstack.subscribeForIndications(this, characteristic);
561 }
562 int BLEDevice::unsubscribeFromIndications(BLECharacteristic * characteristic){
563     return BTstack.unsubscribeFromIndications(this, characteristic);
564 }
565 
566 
567 
568 static uint16_t (*gattReadCallback)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size);
569 static int (*gattWriteCallback)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size);
570 
571 // ATT Client Read Callback for Dynamic Data
572 // - if buffer == NULL, don't copy data, just return size of value
573 // - if buffer != NULL, copy data and return number bytes copied
574 // @param offset defines start of attribute value
575 static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
576     if (gattReadCallback){
577         return gattReadCallback(att_handle, buffer, buffer_size);
578     }
579     return 0;
580 }
581 /* LISTING_END */
582 
583 
584 /*
585  * @section ATT Write
586  *
587  * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification
588  * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used
589  * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite.
590  */
591 
592 /* LISTING_START(attWrite): ATT Write */
593 static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
594     if (gattWriteCallback){
595         gattWriteCallback(att_handle, buffer, buffer_size);
596     }
597     return 0;
598 }
599 
600 
601 
602 BTstackManager::BTstackManager(void){
603     // client_packet_handler = NULL;
604     have_custom_addr = false;
605     // reset handler
606     bleAdvertismentCallback = NULL;
607     bleDeviceConnectedCallback = NULL;
608     bleDeviceDisconnectedCallback = NULL;
609     gattServiceDiscoveredCallback = NULL;
610     gattCharacteristicDiscoveredCallback = NULL;
611     gattCharacteristicNotificationCallback = NULL;
612 
613     att_db_util_init();
614 
615     // disable LOG_INFO messages
616     hci_dump_enable_log_level(LOG_LEVEL_INFO, 0);
617 
618 #ifdef __AVR__
619     // configure stdout to go via Serial
620   fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
621   stdout = &uartout;
622 #endif
623 }
624 
625 void BTstackManager::setBLEAdvertisementCallback(void (*callback)(BLEAdvertisement * bleAdvertisement)){
626     bleAdvertismentCallback = callback;
627 }
628 void BTstackManager::setBLEDeviceConnectedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
629     bleDeviceConnectedCallback = callback;
630 }
631 void BTstackManager::setBLEDeviceDisconnectedCallback(void (*callback)(BLEDevice * device)){
632     bleDeviceDisconnectedCallback = callback;
633 }
634 void BTstackManager::setGATTServiceDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLEService * bleService)){
635     gattServiceDiscoveredCallback = callback;
636 }
637 void BTstackManager::setGATTCharacteristicDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic)){
638     gattCharacteristicDiscoveredCallback = callback;
639 }
640 void BTstackManager::setGATTCharacteristicNotificationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)){
641     gattCharacteristicNotificationCallback = callback;
642 }
643 void BTstackManager::setGATTCharacteristicIndicationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)){
644     gattCharacteristicIndicationCallback = callback;
645 }
646 void BTstackManager::setGATTCharacteristicReadCallback(void (*callback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length)){
647     gattCharacteristicReadCallback = callback;
648 }
649 void BTstackManager::setGATTCharacteristicWrittenCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
650     gattCharacteristicWrittenCallback = callback;
651 }
652 void BTstackManager::setGATTCharacteristicSubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
653     gattCharacteristicSubscribedCallback = callback;
654 }
655 void BTstackManager::setGATTCharacteristicUnsubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
656     gattCharacteristicUnsubscribedCallback = callback;
657 }
658 
659 int BTstackManager::discoverGATTServices(BLEDevice * device){
660     gattAction = gattActionServiceQuery;
661     return gatt_client_discover_primary_services(gatt_client_id, device->getHandle());
662 }
663 int BTstackManager::discoverCharacteristicsForService(BLEDevice * device, BLEService * service){
664     gattAction = gattActionCharacteristicQuery;
665     return gatt_client_discover_characteristics_for_service(gatt_client_id, device->getHandle(), (gatt_client_service_t*) service->getService());
666 }
667 int  BTstackManager::readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic){
668     return gatt_client_read_value_of_characteristic(gatt_client_id, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic());
669 }
670 int  BTstackManager::writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
671     gattAction = gattActionWrite;
672     return gatt_client_write_value_of_characteristic(gatt_client_id, device->getHandle(), characteristic->getCharacteristic()->value_handle,
673         size, data);
674 }
675 int  BTstackManager::writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
676     return gatt_client_write_value_of_characteristic_without_response(gatt_client_id, device->getHandle(), characteristic->getCharacteristic()->value_handle,
677          size, data);
678 }
679 int BTstackManager::subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic){
680     gattAction = gattActionSubscribe;
681     return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
682      GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
683 }
684 int BTstackManager::subscribeForIndications(BLEDevice * device, BLECharacteristic * characteristic){
685     gattAction = gattActionSubscribe;
686     return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
687      GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION);
688 }
689 int BTstackManager::unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic){
690     gattAction = gattActionUnsubscribe;
691     return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
692      GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE);
693 }
694 int BTstackManager::unsubscribeFromIndications(BLEDevice * device, BLECharacteristic * characteristic){
695     gattAction = gattActionUnsubscribe;
696     return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (gatt_client_characteristic_t*) characteristic->getCharacteristic(),
697      GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE);
698 }
699 void BTstackManager::bleConnect(BLEAdvertisement * advertisement, int timeout_ms){
700     bleConnect(advertisement->getBdAddr(), timeout_ms);
701 }
702 void BTstackManager::bleConnect(BD_ADDR * address, int timeout_ms){
703     bleConnect(address->getAddressType(), address->getAddress(), timeout_ms);
704 }
705 void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms){
706     // TOOD: implement
707     // log_error("BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) not implemented");
708 }
709 void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms){
710     gap_le_connect((uint8_t*)address, (bd_addr_type_t) address_type);
711     if (!timeout_ms) return;
712     btstack_run_loop_set_timer(&connection_timer, timeout_ms);
713     btstack_run_loop_set_timer_handler(&connection_timer, connection_timeout_handler);
714     btstack_run_loop_add_timer(&connection_timer);
715 }
716 
717 void BTstackManager::bleDisconnect(BLEDevice * device){
718     btstack_run_loop_remove_timer(&connection_timer);
719     gap_disconnect(device->getHandle());
720 }
721 
722 void BTstackManager::setPublicBdAddr(bd_addr_t addr){
723     have_custom_addr = true;
724     memcpy(public_bd_addr, addr ,6);
725 }
726 
727 void bluetooth_hardware_error(uint8_t error){
728     printf("Bluetooth Hardware Error event 0x%02x. Restarting...\n\n\n", error);
729 #ifdef __AVR__
730     wdt_enable(WDTO_15MS);
731     // wait for watchdog to trigger
732 #endif
733 
734 #ifdef __arm__
735     NVIC_SystemReset();
736 #endif
737     while(1);
738 }
739 
740 void BTstackManager::setup(void){
741 
742 #ifdef PIN_LED
743     pinMode(PIN_LED, OUTPUT);
744 #endif
745 
746     printf("BTstackManager::setup()\n");
747 
748 	btstack_memory_init();
749     btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
750 
751 	const hci_transport_t * transport = hci_transport_h4_instance(btstack_uart_block_embedded_instance());
752 	hci_init(transport, NULL);
753     hci_set_chipset(btstack_chipset_em9301_instance());
754 
755     if (have_custom_addr){
756         hci_set_bd_addr(public_bd_addr);
757     }
758 
759     hci_set_hardware_error_callback(&bluetooth_hardware_error);
760 
761     l2cap_init();
762 
763     // setup central device db
764     le_device_db_init();
765 
766     sm_init();
767 
768     att_server_init(att_db_util_get_address(),att_read_callback, att_write_callback);
769     att_server_register_packet_handler(packet_handler);
770 
771     gatt_client_init();
772     gatt_client_id = gatt_client_register_packet_handler(gatt_client_callback);
773 
774     // setup advertisements params
775     uint16_t adv_int_min = 0x0030;
776     uint16_t adv_int_max = 0x0030;
777     uint8_t adv_type = 0;
778     bd_addr_t null_addr;
779     memset(null_addr, 0, 6);
780     gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
781 
782     // setup advertisements data
783     int pos = 0;
784     const uint8_t flags[] = { 0x02, 0x01, 0x02 };
785     memcpy(&adv_data[pos], flags, sizeof(flags));
786     pos += sizeof(flags);
787     char * name = "BTstack LE Shield";
788     adv_data[pos++] = strlen(name) + 1;
789     adv_data[pos++] = 0x09;
790     memcpy(&adv_data[pos], name, strlen(name));
791     pos += strlen(name);
792     adv_data_len = pos;
793     gap_advertisements_set_data(adv_data_len, adv_data);
794 
795     // turn on!
796     btstack_state = 0;
797     hci_power_control(HCI_POWER_ON);
798 
799     // poll until working
800     while (btstack_state != HCI_STATE_WORKING){
801         loop();
802     }
803     printf("--> READY <--\n");
804 }
805 
806 void BTstackManager::enablePacketLogger(void){
807     hci_dump_init(hci_dump_embedded_stdout_get_instance());
808 }
809 
810 void BTstackManager::enableDebugLogger(){
811     // enable LOG_INFO messages
812     hci_dump_enable_log_level(LOG_LEVEL_INFO, 1);
813 }
814 
815 
816 void BTstackManager::loop(void){
817     // process data from/to Bluetooth module
818     hal_uart_dma_process();
819     // BTstack Run Loop
820     btstack_run_loop_embedded_execute_once();
821 }
822 
823 void BTstackManager::bleStartScanning(void){
824     printf("Start scanning\n");
825     gap_le_start_scan();
826 }
827 void BTstackManager::bleStopScanning(void){
828     gap_le_stop_scan();
829 }
830 
831 void BTstackManager::setGATTCharacteristicRead(uint16_t (*cb)(uint16_t characteristic_id, uint8_t * buffer, uint16_t buffer_size)){
832     gattReadCallback = cb;
833 }
834 void BTstackManager::setGATTCharacteristicWrite(int (*cb)(uint16_t characteristic_id, uint8_t *buffer, uint16_t buffer_size)){
835     gattWriteCallback = cb;
836 }
837 void BTstackManager::addGATTService(UUID * uuid){
838     att_db_util_add_service_uuid128((uint8_t*)uuid->getUuid());
839 }
840 uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, const char * text){
841     return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, (uint8_t*)text, strlen(text));
842 }
843 uint16_t BTstackManager::addGATTCharacteristic(UUID * uuid, uint16_t flags, uint8_t * data, uint16_t data_len){
844     return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags, data, data_len);
845 }
846 uint16_t BTstackManager::addGATTCharacteristicDynamic(UUID * uuid, uint16_t flags, uint16_t characteristic_id){
847     return att_db_util_add_characteristic_uuid128((uint8_t*)uuid->getUuid(), flags | ATT_PROPERTY_DYNAMIC, NULL, 0);
848 }
849 void BTstackManager::setAdvData(uint16_t adv_data_len, const uint8_t * adv_data){
850     gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
851 }
852 void BTstackManager::startAdvertising(){
853     gap_advertisements_enable(1);
854 }
855 void BTstackManager::stopAdvertising(){
856     gap_advertisements_enable(0);
857 }
858 void BTstackManager::iBeaconConfigure(UUID * uuid, uint16_t major_id, uint16_t minor_id, uint8_t measured_power){
859     memcpy(adv_data, iBeaconAdvertisement01,  sizeof(iBeaconAdvertisement01));
860     adv_data[2] = 0x06;
861     memcpy(&adv_data[3], iBeaconAdvertisement38, sizeof(iBeaconAdvertisement38));
862     memcpy(&adv_data[9], uuid->getUuid(), 16);
863     big_endian_store_16(adv_data, 25, major_id);
864     big_endian_store_16(adv_data, 27, minor_id);
865     adv_data[29] = measured_power;
866     adv_data_len = 30;
867     gap_advertisements_set_data(adv_data_len, adv_data);
868 }
869 // 02 01 06 1A FF 4C 00 02 15 -- F8 97 17 7B AE E8 47 67 8E CC CC 69 4F D5 FC EE -- 12 67 00 02 00 00
870 // 02 01 06 1a ff 4c 00 02 15 -- FB 0B 57 A2 82 28 44 CD 91 3A 94 A1 22 BA 12 06 -- 00 01 00 02 D1 00
871 
872 
873 BTstackManager BTstack;
874 
875