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