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 <inttypes.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 54 #include "btstack.h" 55 56 static btstack_packet_callback_registration_t hci_event_callback_registration; 57 58 /* @section GAP LE setup for receiving advertisements 59 * 60 * @text GAP LE advertisements are received as custom HCI events of the 61 * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register 62 * the HCI packet handler, as shown in Listing GAPLEAdvSetup. 63 */ 64 65 /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */ 66 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 67 68 static void gap_le_advertisements_setup(void){ 69 hci_event_callback_registration.callback = &packet_handler; 70 hci_add_event_handler(&hci_event_callback_registration); 71 72 // Active scanning, 100% (scan interval = scan window) 73 gap_set_scan_parameters(1,48,48); 74 } 75 76 /* LISTING_END */ 77 78 /* @section GAP LE Advertising Data Dumper 79 * 80 * @text Here, we use the definition of advertising data types and flags as specified in 81 * [Assigned Numbers GAP](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile) 82 * and [Supplement to the Bluetooth Core Specification, v4](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282152). 83 */ 84 85 /* LISTING_START(GAPLEAdvDataTypesAndFlags): Advertising data types and flags */ 86 static 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 116 static char * flags[] = { 117 "LE Limited Discoverable Mode", 118 "LE General Discoverable Mode", 119 "BR/EDR Not Supported", 120 "Simultaneous LE and BR/EDR to Same Device Capable (Controller)", 121 "Simultaneous LE and BR/EDR to Same Device Capable (Host)", 122 "Reserved", 123 "Reserved", 124 "Reserved" 125 }; 126 /* LISTING_END */ 127 128 /* @text BTstack offers an iterator for parsing sequence of advertising data (AD) structures, 129 * see [BLE advertisements parser API](../appendix/apis/#ble-advertisements-parser-api). 130 * After initializing the iterator, each AD structure is dumped according to its type. 131 */ 132 133 /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */ 134 static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){ 135 ad_context_t context; 136 bd_addr_t address; 137 uint8_t uuid_128[16]; 138 for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ 139 uint8_t data_type = ad_iterator_get_data_type(&context); 140 uint8_t size = ad_iterator_get_data_len(&context); 141 const uint8_t * data = ad_iterator_get_data(&context); 142 143 if (data_type > 0 && data_type < 0x1B){ 144 printf(" %s: ", ad_types[data_type]); 145 } 146 int i; 147 // Assigned Numbers GAP 148 149 switch (data_type){ 150 case BLUETOOTH_DATA_TYPE_FLAGS: 151 // show only first octet, ignore rest 152 for (i=0; i<8;i++){ 153 if (data[0] & (1<<i)){ 154 printf("%s; ", flags[i]); 155 } 156 157 } 158 break; 159 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 160 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 161 case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 162 for (i=0; i<size;i+=2){ 163 printf("%02X ", little_endian_read_16(data, i)); 164 } 165 break; 166 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 167 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 168 case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 169 for (i=0; i<size;i+=4){ 170 printf("%04"PRIX32, little_endian_read_32(data, i)); 171 } 172 break; 173 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 174 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 175 case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 176 reverse_128(data, uuid_128); 177 printf("%s", uuid128_to_str(uuid_128)); 178 break; 179 case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME: 180 case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME: 181 for (i=0; i<size;i++){ 182 printf("%c", (char)(data[i])); 183 } 184 break; 185 case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL: 186 printf("%d dBm", *(int8_t*)data); 187 break; 188 case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE: 189 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); 190 break; 191 case BLUETOOTH_DATA_TYPE_SERVICE_DATA: 192 printf_hexdump(data, size); 193 break; 194 case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS: 195 case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS: 196 reverse_bd_addr(data, address); 197 printf("%s", bd_addr_to_str(address)); 198 break; 199 case BLUETOOTH_DATA_TYPE_APPEARANCE: 200 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml 201 printf("%02X", little_endian_read_16(data, 0) ); 202 break; 203 case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL: 204 printf("%u ms", little_endian_read_16(data, 0) * 5/8 ); 205 break; 206 case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA: 207 printf_hexdump(data, size); 208 break; 209 case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data 210 break; 211 case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE: 212 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C: 213 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R: 214 case BLUETOOTH_DATA_TYPE_DEVICE_ID: 215 case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 216 default: 217 printf("Advertising Data Type 0x%2x not handled yet", data_type); 218 break; 219 } 220 printf("\n"); 221 } 222 printf("\n"); 223 } 224 /* LISTING_END */ 225 226 /* @section HCI packet handler 227 * 228 * @text The HCI packet handler has to start the scanning, 229 * and to handle received advertisements. Advertisements are received 230 * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type, 231 * see Listing GAPLEAdvPacketHandler. 232 */ 233 234 /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */ 235 236 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 237 UNUSED(channel); 238 UNUSED(size); 239 240 if (packet_type != HCI_EVENT_PACKET) return; 241 242 switch (hci_event_packet_get_type(packet)) { 243 case BTSTACK_EVENT_STATE: 244 // BTstack activated, get started 245 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 246 printf("Start scaning!\n"); 247 gap_set_scan_parameters(0,0x0030, 0x0030); 248 gap_start_scan(); 249 } 250 break; 251 case GAP_EVENT_ADVERTISING_REPORT:{ 252 bd_addr_t address; 253 gap_event_advertising_report_get_address(packet, address); 254 uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet); 255 uint8_t address_type = gap_event_advertising_report_get_address_type(packet); 256 int8_t rssi = gap_event_advertising_report_get_rssi(packet); 257 uint8_t length = gap_event_advertising_report_get_data_length(packet); 258 const uint8_t * data = gap_event_advertising_report_get_data(packet); 259 260 printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type, 261 address_type, bd_addr_to_str(address), rssi, length); 262 printf_hexdump(data, length); 263 dump_advertisement_data(data, length); 264 break; 265 } 266 default: 267 break; 268 } 269 } 270 /* LISTING_END */ 271 272 int btstack_main(void); 273 int btstack_main(void) 274 { 275 gap_le_advertisements_setup(); 276 277 // turn on! 278 hci_power_control(HCI_POWER_ON); 279 280 return 0; 281 } 282 283 /* EXAMPLE_END */