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 // Active scanning, 100% (scan interval = scan window) 72 gap_set_scan_parameters(1,48,48); 73 } 74 75 /* LISTING_END */ 76 77 /* @section GAP LE Advertising Data Dumper 78 * 79 * @text Here, we use the definition of advertising data types and flags as specified in 80 * [Assigned Numbers GAP](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile) 81 * and [Supplement to the Bluetooth Core Specification, v4](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282152). 82 */ 83 84 /* LISTING_START(GAPLEAdvDataTypesAndFlags): Advertising data types and flags */ 85 static char * ad_types[] = { 86 "", 87 "Flags", 88 "Incomplete List of 16-bit Service Class UUIDs", 89 "Complete List of 16-bit Service Class UUIDs", 90 "Incomplete List of 32-bit Service Class UUIDs", 91 "Complete List of 32-bit Service Class UUIDs", 92 "Incomplete List of 128-bit Service Class UUIDs", 93 "Complete List of 128-bit Service Class UUIDs", 94 "Shortened Local Name", 95 "Complete Local Name", 96 "Tx Power Level", 97 "", 98 "", 99 "Class of Device", 100 "Simple Pairing Hash C", 101 "Simple Pairing Randomizer R", 102 "Device ID", 103 "Security Manager TK Value", 104 "Slave Connection Interval Range", 105 "", 106 "List of 16-bit Service Solicitation UUIDs", 107 "List of 128-bit Service Solicitation UUIDs", 108 "Service Data", 109 "Public Target Address", 110 "Random Target Address", 111 "Appearance", 112 "Advertising Interval" 113 }; 114 115 static 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 127 /* @text BTstack offers an iterator for parsing sequence of advertising data (AD) structures, 128 * see [BLE advertisements parser API](../appendix/apis/#ble-advertisements-parser-api). 129 * After initializing the iterator, each AD structure is dumped according to its type. 130 */ 131 132 /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */ 133 static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){ 134 ad_context_t context; 135 bd_addr_t address; 136 uint8_t uuid_128[16]; 137 for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ 138 uint8_t data_type = ad_iterator_get_data_type(&context); 139 uint8_t size = ad_iterator_get_data_len(&context); 140 const uint8_t * data = ad_iterator_get_data(&context); 141 142 if (data_type > 0 && data_type < 0x1B){ 143 printf(" %s: ", ad_types[data_type]); 144 } 145 int i; 146 // Assigned Numbers GAP 147 148 switch (data_type){ 149 case BLUETOOTH_DATA_TYPE_FLAGS: 150 // show only first octet, ignore rest 151 for (i=0; i<8;i++){ 152 if (data[0] & (1<<i)){ 153 printf("%s; ", flags[i]); 154 } 155 156 } 157 break; 158 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 159 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 160 case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 161 for (i=0; i<size;i+=2){ 162 printf("%02X ", little_endian_read_16(data, i)); 163 } 164 break; 165 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 166 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 167 case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 168 for (i=0; i<size;i+=4){ 169 printf("%04"PRIX32, little_endian_read_32(data, i)); 170 } 171 break; 172 case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 173 case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 174 case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 175 reverse_128(data, uuid_128); 176 printf("%s", uuid128_to_str(uuid_128)); 177 break; 178 case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME: 179 case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME: 180 for (i=0; i<size;i++){ 181 printf("%c", (char)(data[i])); 182 } 183 break; 184 case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL: 185 printf("%d dBm", *(int8_t*)data); 186 break; 187 case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE: 188 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); 189 break; 190 case BLUETOOTH_DATA_TYPE_SERVICE_DATA: 191 printf_hexdump(data, size); 192 break; 193 case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS: 194 case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS: 195 reverse_bd_addr(data, address); 196 printf("%s", bd_addr_to_str(address)); 197 break; 198 case BLUETOOTH_DATA_TYPE_APPEARANCE: 199 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml 200 printf("%02X", little_endian_read_16(data, 0) ); 201 break; 202 case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL: 203 printf("%u ms", little_endian_read_16(data, 0) * 5/8 ); 204 break; 205 case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA: 206 printf_hexdump(data, size); 207 break; 208 case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data 209 break; 210 case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE: 211 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C: 212 case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R: 213 case BLUETOOTH_DATA_TYPE_DEVICE_ID: 214 case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 215 default: 216 printf("Advertising Data Type 0x%2x not handled yet", data_type); 217 break; 218 } 219 printf("\n"); 220 } 221 printf("\n"); 222 } 223 /* LISTING_END */ 224 225 /* @section HCI packet handler 226 * 227 * @text The HCI packet handler has to start the scanning, 228 * and to handle received advertisements. Advertisements are received 229 * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type, 230 * see Listing GAPLEAdvPacketHandler. 231 */ 232 233 /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */ 234 235 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 236 UNUSED(channel); 237 UNUSED(size); 238 239 if (packet_type != HCI_EVENT_PACKET) return; 240 241 switch (hci_event_packet_get_type(packet)) { 242 case BTSTACK_EVENT_STATE: 243 // BTstack activated, get started 244 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 245 printf("Start scaning!\n"); 246 gap_set_scan_parameters(0,0x0030, 0x0030); 247 gap_start_scan(); 248 } 249 break; 250 case GAP_EVENT_ADVERTISING_REPORT:{ 251 bd_addr_t address; 252 gap_event_advertising_report_get_address(packet, address); 253 uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet); 254 uint8_t address_type = gap_event_advertising_report_get_address_type(packet); 255 int8_t rssi = gap_event_advertising_report_get_rssi(packet); 256 uint8_t length = gap_event_advertising_report_get_data_length(packet); 257 const uint8_t * data = gap_event_advertising_report_get_data(packet); 258 259 printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type, 260 address_type, bd_addr_to_str(address), rssi, length); 261 printf_hexdump(data, length); 262 dump_advertisement_data(data, length); 263 break; 264 } 265 default: 266 break; 267 } 268 } 269 /* LISTING_END */ 270 271 int btstack_main(void); 272 int btstack_main(void) 273 { 274 gap_le_advertisements_setup(); 275 276 // turn on! 277 hci_power_control(HCI_POWER_ON); 278 279 return 0; 280 } 281 282 /* EXAMPLE_END */