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