gap_le_advertisements.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (C) 2014 BlueKitchen GmbH
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. * 4. Any redistribution, use, or modification is done solely for
  17. * personal benefit and not for any commercial purpose or for
  18. * monetary gain.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
  24. * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * Please inquire about commercial licensing options at
  34. * contact@bluekitchen-gmbh.com
  35. *
  36. */
  37. #define BTSTACK_FILE__ "gap_le_advertisements.c"
  38. // *****************************************************************************
  39. /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper
  40. *
  41. * @text This example shows how to scan and parse advertisements.
  42. *
  43. */
  44. // *****************************************************************************
  45. #include <stdint.h>
  46. #include <inttypes.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include "btstack.h"
  51. static btstack_packet_callback_registration_t hci_event_callback_registration;
  52. /* @section GAP LE setup for receiving advertisements
  53. *
  54. * @text GAP LE advertisements are received as custom HCI events of the
  55. * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
  56. * the HCI packet handler, as shown in Listing GAPLEAdvSetup.
  57. */
  58. /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
  59. static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
  60. static const uint8_t adv_data[] = {
  61. // Flags general discoverable, BR/EDR not supported
  62. 0x02, 0x01, 0x06,
  63. // Name
  64. 0x05, 0x09, 't', 'd', 'e', 's',
  65. // Service Solicitation, 128-bit UUIDs - ANCS (little endian)
  66. 0x11,0x15,0xD0,0x00,0x2D,0x12,0x1E,0x4B,0x0F,0xA4,0x99,0x4E,0xCE,0xB5,0x31,0xF4,0x05,0x79
  67. };
  68. static uint8_t adv_data_len = sizeof(adv_data);
  69. static void gap_le_advertisements_setup(void){
  70. // Active scanning, 100% (scan interval = scan window)
  71. // gap_set_scan_parameters(1,48,48);
  72. // gap_start_scan();
  73. gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
  74. gap_advertisements_enable(1);
  75. hci_event_callback_registration.callback = &packet_handler;
  76. hci_add_event_handler(&hci_event_callback_registration);
  77. }
  78. /* LISTING_END */
  79. /* @section GAP LE Advertising Data Dumper
  80. *
  81. * @text Here, we use the definition of advertising data types and flags as specified in
  82. * [Assigned Numbers GAP](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile)
  83. * and [Supplement to the Bluetooth Core Specification, v4](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282152).
  84. */
  85. /* LISTING_START(GAPLEAdvDataTypesAndFlags): Advertising data types and flags */
  86. static const char * ad_types[] = {
  87. "",
  88. "Flags",
  89. "Incomplete List of 16-bit Service Class UUIDs",
  90. "Complete List of 16-bit Service Class UUIDs",
  91. "Incomplete List of 32-bit Service Class UUIDs",
  92. "Complete List of 32-bit Service Class UUIDs",
  93. "Incomplete List of 128-bit Service Class UUIDs",
  94. "Complete List of 128-bit Service Class UUIDs",
  95. "Shortened Local Name",
  96. "Complete Local Name",
  97. "Tx Power Level",
  98. "",
  99. "",
  100. "Class of Device",
  101. "Simple Pairing Hash C",
  102. "Simple Pairing Randomizer R",
  103. "Device ID",
  104. "Security Manager TK Value",
  105. "Slave Connection Interval Range",
  106. "",
  107. "List of 16-bit Service Solicitation UUIDs",
  108. "List of 128-bit Service Solicitation UUIDs",
  109. "Service Data",
  110. "Public Target Address",
  111. "Random Target Address",
  112. "Appearance",
  113. "Advertising Interval"
  114. };
  115. static const char * flags[] = {
  116. "LE Limited Discoverable Mode",
  117. "LE General Discoverable Mode",
  118. "BR/EDR Not Supported",
  119. "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",
  120. "Simultaneous LE and BR/EDR to Same Device Capable (Host)",
  121. "Reserved",
  122. "Reserved",
  123. "Reserved"
  124. };
  125. /* LISTING_END */
  126. /* @text BTstack offers an iterator for parsing sequence of advertising data (AD) structures,
  127. * see [BLE advertisements parser API](../appendix/apis/#ble-advertisements-parser-api).
  128. * After initializing the iterator, each AD structure is dumped according to its type.
  129. */
  130. /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */
  131. static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
  132. ad_context_t context;
  133. bd_addr_t address;
  134. uint8_t uuid_128[16];
  135. for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
  136. uint8_t data_type = ad_iterator_get_data_type(&context);
  137. uint8_t size = ad_iterator_get_data_len(&context);
  138. const uint8_t * data = ad_iterator_get_data(&context);
  139. if (data_type > 0 && data_type < 0x1B){
  140. printf(" %s: ", ad_types[data_type]);
  141. }
  142. int i;
  143. // Assigned Numbers GAP
  144. switch (data_type){
  145. case BLUETOOTH_DATA_TYPE_FLAGS:
  146. // show only first octet, ignore rest
  147. for (i=0; i<8;i++){
  148. if (data[0] & (1<<i)){
  149. printf("%s; ", flags[i]);
  150. }
  151. }
  152. break;
  153. case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
  154. case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
  155. case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
  156. for (i=0; i<size;i+=2){
  157. printf("%02X ", little_endian_read_16(data, i));
  158. }
  159. break;
  160. case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
  161. case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
  162. case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
  163. for (i=0; i<size;i+=4){
  164. printf("%04"PRIX32, little_endian_read_32(data, i));
  165. }
  166. break;
  167. case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
  168. case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
  169. case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
  170. reverse_128(data, uuid_128);
  171. printf("%s", uuid128_to_str(uuid_128));
  172. break;
  173. case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
  174. case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
  175. for (i=0; i<size;i++){
  176. printf("%c", (char)(data[i]));
  177. }
  178. break;
  179. case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
  180. printf("%d dBm", *(int8_t*)data);
  181. break;
  182. case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
  183. printf("Connection Interval Min = %u ms, Max = %u ms", little_endian_read_16(data, 0) * 5/4, little_endian_read_16(data, 2) * 5/4);
  184. break;
  185. case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
  186. printf_hexdump(data, size);
  187. break;
  188. case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
  189. case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
  190. reverse_bd_addr(data, address);
  191. printf("%s", bd_addr_to_str(address));
  192. break;
  193. case BLUETOOTH_DATA_TYPE_APPEARANCE:
  194. // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
  195. printf("%02X", little_endian_read_16(data, 0) );
  196. break;
  197. case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
  198. printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
  199. break;
  200. case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
  201. printf_hexdump(data, size);
  202. break;
  203. case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data
  204. break;
  205. case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
  206. case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
  207. case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
  208. case BLUETOOTH_DATA_TYPE_DEVICE_ID:
  209. case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
  210. default:
  211. printf("Advertising Data Type 0x%2x not handled yet", data_type);
  212. break;
  213. }
  214. printf("\n");
  215. }
  216. printf("\n");
  217. }
  218. /* LISTING_END */
  219. /* @section HCI packet handler
  220. *
  221. * @text The HCI packet handler has to start the scanning,
  222. * and to handle received advertisements. Advertisements are received
  223. * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
  224. * see Listing GAPLEAdvPacketHandler.
  225. */
  226. /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
  227. static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
  228. UNUSED(channel);
  229. UNUSED(size);
  230. if (packet_type != HCI_EVENT_PACKET) return;
  231. switch (hci_event_packet_get_type(packet)) {
  232. case GAP_EVENT_ADVERTISING_REPORT:{
  233. bd_addr_t address;
  234. gap_event_advertising_report_get_address(packet, address);
  235. uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet);
  236. uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
  237. int8_t rssi = gap_event_advertising_report_get_rssi(packet);
  238. uint8_t length = gap_event_advertising_report_get_data_length(packet);
  239. const uint8_t * data = gap_event_advertising_report_get_data(packet);
  240. printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type,
  241. address_type, bd_addr_to_str(address), rssi, length);
  242. printf_hexdump(data, length);
  243. dump_advertisement_data(data, length);
  244. break;
  245. }
  246. default:
  247. break;
  248. }
  249. }
  250. /* LISTING_END */
  251. int btstack_main(void);
  252. int btstack_main(void)
  253. {
  254. gap_le_advertisements_setup();
  255. // turn on!
  256. hci_power_control(HCI_POWER_ON);
  257. return 0;
  258. }
  259. /* EXAMPLE_END */