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