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