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 * [email protected] 35 * 36 */ 37 38 39 // ***************************************************************************** 40 /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper 41 * 42 * @text This example shows how to scan and parse advertisements. 43 * 44 */ 45 // ***************************************************************************** 46 47 48 #include <stdint.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 53 #include "btstack.h" 54 55 static btstack_packet_callback_registration_t hci_event_callback_registration; 56 57 /* @section GAP LE setup for receiving advertisements 58 * 59 * @text GAP LE advertisements are received as custom HCI events of the 60 * GAP_LE_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register 61 * the HCI packet handler, as shown in Listing GAPLEAdvSetup. 62 */ 63 64 /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */ 65 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 66 67 static void gap_le_advertisements_setup(void){ 68 hci_event_callback_registration.callback = &packet_handler; 69 hci_add_event_handler(&hci_event_callback_registration); 70 } 71 72 /* LISTING_END */ 73 74 /* @section GAP LE Advertising Data Dumper 75 * 76 * @text Here, we use the definition of advertising data types and flags as specified in 77 * [Assigned Numbers GAP](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile) 78 * and [Supplement to the Bluetooth Core Specification, v4](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282152). 79 */ 80 81 /* LISTING_START(GAPLEAdvDataTypesAndFlags): Advertising data types and flags */ 82 static char * ad_types[] = { 83 "", 84 "Flags", 85 "Incomplete List of 16-bit Service Class UUIDs", 86 "Complete List of 16-bit Service Class UUIDs", 87 "Incomplete List of 32-bit Service Class UUIDs", 88 "Complete List of 32-bit Service Class UUIDs", 89 "Incomplete List of 128-bit Service Class UUIDs", 90 "Complete List of 128-bit Service Class UUIDs", 91 "Shortened Local Name", 92 "Complete Local Name", 93 "Tx Power Level", 94 "", 95 "", 96 "Class of Device", 97 "Simple Pairing Hash C", 98 "Simple Pairing Randomizer R", 99 "Device ID", 100 "Security Manager TK Value", 101 "Slave Connection Interval Range", 102 "", 103 "List of 16-bit Service Solicitation UUIDs", 104 "List of 128-bit Service Solicitation UUIDs", 105 "Service Data", 106 "Public Target Address", 107 "Random Target Address", 108 "Appearance", 109 "Advertising Interval" 110 }; 111 112 static char * flags[] = { 113 "LE Limited Discoverable Mode", 114 "LE General Discoverable Mode", 115 "BR/EDR Not Supported", 116 "Simultaneous LE and BR/EDR to Same Device Capable (Controller)", 117 "Simultaneous LE and BR/EDR to Same Device Capable (Host)", 118 "Reserved", 119 "Reserved", 120 "Reserved" 121 }; 122 /* LISTING_END */ 123 124 /* @text BTstack offers an iterator for parsing sequence of advertising data (AD) structures, 125 * see [BLE advertisements parser API](../appendix/apis/#ble-advertisements-parser-api). 126 * After initializing the iterator, each AD structure is dumped according to its type. 127 */ 128 129 /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */ 130 static void dump_advertisement_data(uint8_t * adv_data, uint8_t adv_size){ 131 ad_context_t context; 132 bd_addr_t address; 133 uint8_t uuid_128[16]; 134 for (ad_iterator_init(&context, adv_size, adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ 135 uint8_t data_type = ad_iterator_get_data_type(&context); 136 uint8_t size = ad_iterator_get_data_len(&context); 137 uint8_t * data = ad_iterator_get_data(&context); 138 139 if (data_type > 0 && data_type < 0x1B){ 140 printf(" %s: ", ad_types[data_type]); 141 } 142 int i; 143 // Assigned Numbers GAP 144 145 switch (data_type){ 146 case 0x01: // Flags 147 // show only first octet, ignore rest 148 for (i=0; i<8;i++){ 149 if (data[0] & (1<<i)){ 150 printf("%s; ", flags[i]); 151 } 152 153 } 154 break; 155 case 0x02: // Incomplete List of 16-bit Service Class UUIDs 156 case 0x03: // Complete List of 16-bit Service Class UUIDs 157 case 0x14: // List of 16-bit Service Solicitation UUIDs 158 for (i=0; i<size;i+=2){ 159 printf("%02X ", little_endian_read_16(data, i)); 160 } 161 break; 162 case 0x04: // Incomplete List of 32-bit Service Class UUIDs 163 case 0x05: // Complete List of 32-bit Service Class UUIDs 164 for (i=0; i<size;i+=4){ 165 printf("%04X ", little_endian_read_32(data, i)); 166 } 167 break; 168 case 0x06: // Incomplete List of 128-bit Service Class UUIDs 169 case 0x07: // Complete List of 128-bit Service Class UUIDs 170 case 0x15: // List of 128-bit Service Solicitation UUIDs 171 reverse_128(data, uuid_128); 172 printf("%s", uuid128_to_str(uuid_128)); 173 break; 174 case 0x08: // Shortened Local Name 175 case 0x09: // Complete Local Name 176 for (i=0; i<size;i++){ 177 printf("%c", (char)(data[i])); 178 } 179 break; 180 case 0x0A: // Tx Power Level 181 printf("%d dBm", *(int8_t*)data); 182 break; 183 case 0x12: // Slave Connection Interval Range 184 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); 185 break; 186 case 0x16: // Service Data 187 printf_hexdump(data, size); 188 break; 189 case 0x17: // Public Target Address 190 case 0x18: // Random Target Address 191 reverse_bd_addr(data, address); 192 printf("%s", bd_addr_to_str(address)); 193 break; 194 case 0x19: // Appearance 195 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml 196 printf("%02X", little_endian_read_16(data, 0) ); 197 break; 198 case 0x1A: // Advertising Interval 199 printf("%u ms", little_endian_read_16(data, 0) * 5/8 ); 200 break; 201 case 0x3D: // 3D Information Data 202 printf_hexdump(data, size); 203 break; 204 case 0xFF: // Manufacturer Specific Data 205 break; 206 case 0x0D: // Class of Device (3B) 207 case 0x0E: // Simple Pairing Hash C (16B) 208 case 0x0F: // Simple Pairing Randomizer R (16B) 209 case 0x10: // Device ID 210 case 0x11: // Security Manager TK Value (16B) 211 default: 212 printf("Unknown Advertising Data Type"); 213 break; 214 } 215 printf("\n"); 216 } 217 printf("\n"); 218 } 219 /* LISTING_END */ 220 221 /* @section HCI packet handler 222 * 223 * @text The HCI packet handler has to start the scanning, 224 * and to handle received advertisements. Advertisements are received 225 * as HCI event packets of the GAP_LE_EVENT_ADVERTISING_REPORT type, 226 * see Listing GAPLEAdvPacketHandler. 227 */ 228 229 /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */ 230 231 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 232 if (packet_type != HCI_EVENT_PACKET) return; 233 234 switch (hci_event_packet_get_type(packet)) { 235 case BTSTACK_EVENT_STATE: 236 // BTstack activated, get started 237 if (packet[2] == HCI_STATE_WORKING) { 238 printf("BTstack activated, start scaning!\n"); 239 gap_set_scan_parameters(0,0x0030, 0x0030); 240 gap_start_scan(); 241 } 242 break; 243 case GAP_LE_EVENT_ADVERTISING_REPORT:{ 244 int pos = 2; 245 uint8_t event_type = packet[pos++]; 246 uint8_t address_type = packet[pos++]; 247 bd_addr_t address; 248 reverse_bd_addr(&packet[pos], address); 249 pos += 6; 250 uint8_t rssi = packet[pos++]; 251 uint8_t length = packet[pos++]; 252 uint8_t * data = &packet[pos]; 253 254 printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %u, data[%u] ", event_type, 255 address_type, bd_addr_to_str(address), rssi, length); 256 printf_hexdump(data, length); 257 dump_advertisement_data(data, length); 258 break; 259 } 260 default: 261 break; 262 } 263 } 264 /* LISTING_END */ 265 266 int btstack_main(void); 267 int btstack_main(void) 268 { 269 gap_le_advertisements_setup(); 270 271 // turn on! 272 hci_power_control(HCI_POWER_ON); 273 274 return 0; 275 } 276 277 /* EXAMPLE_END */