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 #define BTSTACK_FILE__ "gap_le_advertisements.c" 39 40 41 // ***************************************************************************** 42 /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper 43 * 44 * @text This example shows how to scan and parse advertisements. 45 * 46 */ 47 // ***************************************************************************** 48 49 50 #include <stdint.h> 51 #include <inttypes.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 56 #include "btstack.h" 57 58 static btstack_packet_callback_registration_t hci_event_callback_registration; 59 60 #define NUM_NODES 2 61 62 static const char * nodes_string[NUM_NODES] = { 63 "5C:F3:70:60:7B:87", 64 "00:1B:DC:07:32:EF", 65 }; 66 static bd_addr_t nodes_addr[NUM_NODES]; 67 68 /* @section GAP LE setup for receiving advertisements 69 * 70 * @text GAP LE advertisements are received as custom HCI events of the 71 * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register 72 * the HCI packet handler, as shown in Listing GAPLEAdvSetup. 73 */ 74 75 static char * ad_types[] = { 76 "", 77 "Flags", 78 "Incomplete List of 16-bit Service Class UUIDs", 79 "Complete List of 16-bit Service Class UUIDs", 80 "Incomplete List of 32-bit Service Class UUIDs", 81 "Complete List of 32-bit Service Class UUIDs", 82 "Incomplete List of 128-bit Service Class UUIDs", 83 "Complete List of 128-bit Service Class UUIDs", 84 "Shortened Local Name", 85 "Complete Local Name", 86 "Tx Power Level", 87 "", 88 "", 89 "Class of Device", 90 "Simple Pairing Hash C", 91 "Simple Pairing Randomizer R", 92 "Device ID", 93 "Security Manager TK Value", 94 "Slave Connection Interval Range", 95 "", 96 "List of 16-bit Service Solicitation UUIDs", 97 "List of 128-bit Service Solicitation UUIDs", 98 "Service Data", 99 "Public Target Address", 100 "Random Target Address", 101 "Appearance", 102 "Advertising Interval" 103 }; 104 105 static char * flags[] = { 106 "LE Limited Discoverable Mode", 107 "LE General Discoverable Mode", 108 "BR/EDR Not Supported", 109 "Simultaneous LE and BR/EDR to Same Device Capable (Controller)", 110 "Simultaneous LE and BR/EDR to Same Device Capable (Host)", 111 "Reserved", 112 "Reserved", 113 "Reserved" 114 }; 115 116 /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */ 117 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 118 119 static void sniffer_setup(void){ 120 hci_event_callback_registration.callback = &packet_handler; 121 hci_add_event_handler(&hci_event_callback_registration); 122 // Active scanning, 100% (scan interval = scan window) 123 gap_set_scan_parameters(1,48,48); 124 // 125 int i; 126 for (i=0;i<NUM_NODES;i++){ 127 sscanf_bd_addr(nodes_string[i], nodes_addr[i]); 128 printf("Listening for %s\n", bd_addr_to_str(nodes_addr[i])); 129 } 130 } 131 132 static int addr_from_list(bd_addr_t addr){ 133 int i; 134 for (i=0;i<NUM_NODES;i++){ 135 if (memcmp(addr, nodes_addr[i], 6) == 0) return 1; 136 } 137 return 0; 138 } 139 140 /* LISTING_END */ 141 142 143 /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */ 144 static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){ 145 ad_context_t context; 146 bd_addr_t address; 147 uint8_t uuid_128[16]; 148 for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ 149 uint8_t data_type = ad_iterator_get_data_type(&context); 150 uint8_t size = ad_iterator_get_data_len(&context); 151 const uint8_t * data = ad_iterator_get_data(&context); 152 153 if (data_type > 0 && data_type < 0x1B){ 154 printf(" %s: ", ad_types[data_type]); 155 } 156 int i; 157 // Assigned Numbers GAP 158 159 switch (data_type){ 160 case BLUETOOTH_DATA_TYPE_FLAGS: 161 // show only first octet, ignore rest 162 for (i=0; i<8;i++){ 163 if (data[0] & (1<<i)){ 164 printf("%s; ", flags[i]); 165 } 166 167 } 168 break; 169 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 170 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 171 case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 172 for (i=0; i<size;i+=2){ 173 printf("%02X ", little_endian_read_16(data, i)); 174 } 175 break; 176 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 177 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 178 case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 179 for (i=0; i<size;i+=4){ 180 printf("%04"PRIX32, little_endian_read_32(data, i)); 181 } 182 break; 183 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 184 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 185 case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 186 reverse_128(data, uuid_128); 187 printf("%s", uuid128_to_str(uuid_128)); 188 break; 189 case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME: 190 case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME: 191 for (i=0; i<size;i++){ 192 printf("%c", (char)(data[i])); 193 } 194 break; 195 case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL: 196 printf("%d dBm", *(int8_t*)data); 197 break; 198 case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE: 199 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); 200 break; 201 case BLUETOOTH_DATA_TYPE_SERVICE_DATA: 202 printf_hexdump(data, size); 203 break; 204 case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS: 205 case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS: 206 reverse_bd_addr(data, address); 207 printf("%s", bd_addr_to_str(address)); 208 break; 209 case BLUETOOTH_DATA_TYPE_APPEARANCE: 210 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml 211 printf("%02X", little_endian_read_16(data, 0) ); 212 break; 213 case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL: 214 printf("%u ms", little_endian_read_16(data, 0) * 5/8 ); 215 break; 216 case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA: 217 printf_hexdump(data, size); 218 break; 219 case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data 220 break; 221 case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE: 222 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C: 223 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R: 224 case BLUETOOTH_DATA_TYPE_DEVICE_ID: 225 case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 226 default: 227 printf("Advertising Data Type 0x%2x not handled yet", data_type); 228 break; 229 } 230 printf("\n"); 231 } 232 printf("\n"); 233 } 234 /* LISTING_END */ 235 236 /* @section HCI packet handler 237 * 238 * @text The HCI packet handler has to start the scanning, 239 * and to handle received advertisements. Advertisements are received 240 * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type, 241 * see Listing GAPLEAdvPacketHandler. 242 */ 243 244 /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */ 245 246 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 247 UNUSED(channel); 248 UNUSED(size); 249 250 if (packet_type != HCI_EVENT_PACKET) return; 251 252 switch (hci_event_packet_get_type(packet)) { 253 case BTSTACK_EVENT_STATE: 254 // BTstack activated, get started 255 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 256 printf("Start scaning!\n"); 257 gap_set_scan_parameters(0,0x0030, 0x0030); 258 gap_start_scan(); 259 } 260 break; 261 case GAP_EVENT_ADVERTISING_REPORT:{ 262 bd_addr_t address; 263 gap_event_advertising_report_get_address(packet, address); 264 // check if in list 265 if (!addr_from_list(address)) break; 266 267 uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet); 268 uint8_t address_type = gap_event_advertising_report_get_address_type(packet); 269 int8_t rssi = gap_event_advertising_report_get_rssi(packet); 270 uint8_t length = gap_event_advertising_report_get_data_length(packet); 271 const uint8_t * data = gap_event_advertising_report_get_data(packet); 272 273 printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type, 274 address_type, bd_addr_to_str(address), rssi, length); 275 printf_hexdump(data, length); 276 dump_advertisement_data(data, length); 277 break; 278 } 279 default: 280 break; 281 } 282 } 283 /* LISTING_END */ 284 285 int btstack_main(void); 286 int btstack_main(void) 287 { 288 sniffer_setup(); 289 290 // turn on! 291 hci_power_control(HCI_POWER_ON); 292 293 return 0; 294 } 295 296 /* EXAMPLE_END */ 297