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