xref: /btstack/test/mesh/sniffer.c (revision 1fbe4564be530ba975f4cd70443a76f0afda5276)
1*1fbe4564SMatthias Ringwald /*
2*1fbe4564SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*1fbe4564SMatthias Ringwald  *
4*1fbe4564SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*1fbe4564SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*1fbe4564SMatthias Ringwald  * are met:
7*1fbe4564SMatthias Ringwald  *
8*1fbe4564SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*1fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*1fbe4564SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*1fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*1fbe4564SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*1fbe4564SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*1fbe4564SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*1fbe4564SMatthias Ringwald  *    from this software without specific prior written permission.
16*1fbe4564SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*1fbe4564SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*1fbe4564SMatthias Ringwald  *    monetary gain.
19*1fbe4564SMatthias Ringwald  *
20*1fbe4564SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*1fbe4564SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1fbe4564SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*1fbe4564SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*1fbe4564SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*1fbe4564SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*1fbe4564SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*1fbe4564SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*1fbe4564SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*1fbe4564SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*1fbe4564SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*1fbe4564SMatthias Ringwald  * SUCH DAMAGE.
32*1fbe4564SMatthias Ringwald  *
33*1fbe4564SMatthias Ringwald  * Please inquire about commercial licensing options at
34*1fbe4564SMatthias Ringwald  * [email protected]
35*1fbe4564SMatthias Ringwald  *
36*1fbe4564SMatthias Ringwald  */
37*1fbe4564SMatthias Ringwald 
38*1fbe4564SMatthias Ringwald #define __BTSTACK_FILE__ "gap_le_advertisements.c"
39*1fbe4564SMatthias Ringwald 
40*1fbe4564SMatthias Ringwald 
41*1fbe4564SMatthias Ringwald // *****************************************************************************
42*1fbe4564SMatthias Ringwald /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper
43*1fbe4564SMatthias Ringwald  *
44*1fbe4564SMatthias Ringwald  * @text This example shows how to scan and parse advertisements.
45*1fbe4564SMatthias Ringwald  *
46*1fbe4564SMatthias Ringwald  */
47*1fbe4564SMatthias Ringwald  // *****************************************************************************
48*1fbe4564SMatthias Ringwald 
49*1fbe4564SMatthias Ringwald 
50*1fbe4564SMatthias Ringwald #include <stdint.h>
51*1fbe4564SMatthias Ringwald #include <inttypes.h>
52*1fbe4564SMatthias Ringwald #include <stdio.h>
53*1fbe4564SMatthias Ringwald #include <stdlib.h>
54*1fbe4564SMatthias Ringwald #include <string.h>
55*1fbe4564SMatthias Ringwald 
56*1fbe4564SMatthias Ringwald #include "btstack.h"
57*1fbe4564SMatthias Ringwald 
58*1fbe4564SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
59*1fbe4564SMatthias Ringwald 
60*1fbe4564SMatthias Ringwald #define NUM_NODES 2
61*1fbe4564SMatthias Ringwald 
62*1fbe4564SMatthias Ringwald static const char * nodes_string[NUM_NODES] = {
63*1fbe4564SMatthias Ringwald     "5C:F3:70:60:7B:87",
64*1fbe4564SMatthias Ringwald     "00:1B:DC:07:32:EF",
65*1fbe4564SMatthias Ringwald };
66*1fbe4564SMatthias Ringwald static bd_addr_t nodes_addr[NUM_NODES];
67*1fbe4564SMatthias Ringwald 
68*1fbe4564SMatthias Ringwald /* @section GAP LE setup for receiving advertisements
69*1fbe4564SMatthias Ringwald  *
70*1fbe4564SMatthias Ringwald  * @text GAP LE advertisements are received as custom HCI events of the
71*1fbe4564SMatthias Ringwald  * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
72*1fbe4564SMatthias Ringwald  * the HCI packet handler, as shown in Listing GAPLEAdvSetup.
73*1fbe4564SMatthias Ringwald  */
74*1fbe4564SMatthias Ringwald 
75*1fbe4564SMatthias Ringwald static char * ad_types[] = {
76*1fbe4564SMatthias Ringwald     "",
77*1fbe4564SMatthias Ringwald     "Flags",
78*1fbe4564SMatthias Ringwald     "Incomplete List of 16-bit Service Class UUIDs",
79*1fbe4564SMatthias Ringwald     "Complete List of 16-bit Service Class UUIDs",
80*1fbe4564SMatthias Ringwald     "Incomplete List of 32-bit Service Class UUIDs",
81*1fbe4564SMatthias Ringwald     "Complete List of 32-bit Service Class UUIDs",
82*1fbe4564SMatthias Ringwald     "Incomplete List of 128-bit Service Class UUIDs",
83*1fbe4564SMatthias Ringwald     "Complete List of 128-bit Service Class UUIDs",
84*1fbe4564SMatthias Ringwald     "Shortened Local Name",
85*1fbe4564SMatthias Ringwald     "Complete Local Name",
86*1fbe4564SMatthias Ringwald     "Tx Power Level",
87*1fbe4564SMatthias Ringwald     "",
88*1fbe4564SMatthias Ringwald     "",
89*1fbe4564SMatthias Ringwald     "Class of Device",
90*1fbe4564SMatthias Ringwald     "Simple Pairing Hash C",
91*1fbe4564SMatthias Ringwald     "Simple Pairing Randomizer R",
92*1fbe4564SMatthias Ringwald     "Device ID",
93*1fbe4564SMatthias Ringwald     "Security Manager TK Value",
94*1fbe4564SMatthias Ringwald     "Slave Connection Interval Range",
95*1fbe4564SMatthias Ringwald     "",
96*1fbe4564SMatthias Ringwald     "List of 16-bit Service Solicitation UUIDs",
97*1fbe4564SMatthias Ringwald     "List of 128-bit Service Solicitation UUIDs",
98*1fbe4564SMatthias Ringwald     "Service Data",
99*1fbe4564SMatthias Ringwald     "Public Target Address",
100*1fbe4564SMatthias Ringwald     "Random Target Address",
101*1fbe4564SMatthias Ringwald     "Appearance",
102*1fbe4564SMatthias Ringwald     "Advertising Interval"
103*1fbe4564SMatthias Ringwald };
104*1fbe4564SMatthias Ringwald 
105*1fbe4564SMatthias Ringwald static char * flags[] = {
106*1fbe4564SMatthias Ringwald     "LE Limited Discoverable Mode",
107*1fbe4564SMatthias Ringwald     "LE General Discoverable Mode",
108*1fbe4564SMatthias Ringwald     "BR/EDR Not Supported",
109*1fbe4564SMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",
110*1fbe4564SMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Host)",
111*1fbe4564SMatthias Ringwald     "Reserved",
112*1fbe4564SMatthias Ringwald     "Reserved",
113*1fbe4564SMatthias Ringwald     "Reserved"
114*1fbe4564SMatthias Ringwald };
115*1fbe4564SMatthias Ringwald 
116*1fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
117*1fbe4564SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
118*1fbe4564SMatthias Ringwald 
119*1fbe4564SMatthias Ringwald static void sniffer_setup(void){
120*1fbe4564SMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
121*1fbe4564SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
122*1fbe4564SMatthias Ringwald     // Active scanning, 100% (scan interval = scan window)
123*1fbe4564SMatthias Ringwald     gap_set_scan_parameters(1,48,48);
124*1fbe4564SMatthias Ringwald     //
125*1fbe4564SMatthias Ringwald     int i;
126*1fbe4564SMatthias Ringwald     for (i=0;i<NUM_NODES;i++){
127*1fbe4564SMatthias Ringwald         sscanf_bd_addr(nodes_string[i], nodes_addr[i]);
128*1fbe4564SMatthias Ringwald         printf("Listening for %s\n", bd_addr_to_str(nodes_addr[i]));
129*1fbe4564SMatthias Ringwald     }
130*1fbe4564SMatthias Ringwald }
131*1fbe4564SMatthias Ringwald 
132*1fbe4564SMatthias Ringwald static int addr_from_list(bd_addr_t addr){
133*1fbe4564SMatthias Ringwald     int i;
134*1fbe4564SMatthias Ringwald     for (i=0;i<NUM_NODES;i++){
135*1fbe4564SMatthias Ringwald         if (memcmp(addr, nodes_addr[i], 6) == 0) return 1;
136*1fbe4564SMatthias Ringwald     }
137*1fbe4564SMatthias Ringwald     return 0;
138*1fbe4564SMatthias Ringwald }
139*1fbe4564SMatthias Ringwald 
140*1fbe4564SMatthias Ringwald /* LISTING_END */
141*1fbe4564SMatthias Ringwald 
142*1fbe4564SMatthias Ringwald 
143*1fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */
144*1fbe4564SMatthias Ringwald static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
145*1fbe4564SMatthias Ringwald     ad_context_t context;
146*1fbe4564SMatthias Ringwald     bd_addr_t address;
147*1fbe4564SMatthias Ringwald     uint8_t uuid_128[16];
148*1fbe4564SMatthias Ringwald     for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
149*1fbe4564SMatthias Ringwald         uint8_t data_type    = ad_iterator_get_data_type(&context);
150*1fbe4564SMatthias Ringwald         uint8_t size         = ad_iterator_get_data_len(&context);
151*1fbe4564SMatthias Ringwald         const uint8_t * data = ad_iterator_get_data(&context);
152*1fbe4564SMatthias Ringwald 
153*1fbe4564SMatthias Ringwald         if (data_type > 0 && data_type < 0x1B){
154*1fbe4564SMatthias Ringwald             printf("    %s: ", ad_types[data_type]);
155*1fbe4564SMatthias Ringwald         }
156*1fbe4564SMatthias Ringwald         int i;
157*1fbe4564SMatthias Ringwald         // Assigned Numbers GAP
158*1fbe4564SMatthias Ringwald 
159*1fbe4564SMatthias Ringwald         switch (data_type){
160*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_FLAGS:
161*1fbe4564SMatthias Ringwald                 // show only first octet, ignore rest
162*1fbe4564SMatthias Ringwald                 for (i=0; i<8;i++){
163*1fbe4564SMatthias Ringwald                     if (data[0] & (1<<i)){
164*1fbe4564SMatthias Ringwald                         printf("%s; ", flags[i]);
165*1fbe4564SMatthias Ringwald                     }
166*1fbe4564SMatthias Ringwald 
167*1fbe4564SMatthias Ringwald                 }
168*1fbe4564SMatthias Ringwald                 break;
169*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
170*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
171*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
172*1fbe4564SMatthias Ringwald                 for (i=0; i<size;i+=2){
173*1fbe4564SMatthias Ringwald                     printf("%02X ", little_endian_read_16(data, i));
174*1fbe4564SMatthias Ringwald                 }
175*1fbe4564SMatthias Ringwald                 break;
176*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
177*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
178*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
179*1fbe4564SMatthias Ringwald                 for (i=0; i<size;i+=4){
180*1fbe4564SMatthias Ringwald                     printf("%04"PRIX32, little_endian_read_32(data, i));
181*1fbe4564SMatthias Ringwald                 }
182*1fbe4564SMatthias Ringwald                 break;
183*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
184*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
185*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
186*1fbe4564SMatthias Ringwald                 reverse_128(data, uuid_128);
187*1fbe4564SMatthias Ringwald                 printf("%s", uuid128_to_str(uuid_128));
188*1fbe4564SMatthias Ringwald                 break;
189*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
190*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
191*1fbe4564SMatthias Ringwald                 for (i=0; i<size;i++){
192*1fbe4564SMatthias Ringwald                     printf("%c", (char)(data[i]));
193*1fbe4564SMatthias Ringwald                 }
194*1fbe4564SMatthias Ringwald                 break;
195*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
196*1fbe4564SMatthias Ringwald                 printf("%d dBm", *(int8_t*)data);
197*1fbe4564SMatthias Ringwald                 break;
198*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
199*1fbe4564SMatthias Ringwald                 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*1fbe4564SMatthias Ringwald                 break;
201*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
202*1fbe4564SMatthias Ringwald                 printf_hexdump(data, size);
203*1fbe4564SMatthias Ringwald                 break;
204*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
205*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
206*1fbe4564SMatthias Ringwald                 reverse_bd_addr(data, address);
207*1fbe4564SMatthias Ringwald                 printf("%s", bd_addr_to_str(address));
208*1fbe4564SMatthias Ringwald                 break;
209*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_APPEARANCE:
210*1fbe4564SMatthias Ringwald                 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
211*1fbe4564SMatthias Ringwald                 printf("%02X", little_endian_read_16(data, 0) );
212*1fbe4564SMatthias Ringwald                 break;
213*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
214*1fbe4564SMatthias Ringwald                 printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
215*1fbe4564SMatthias Ringwald                 break;
216*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
217*1fbe4564SMatthias Ringwald                 printf_hexdump(data, size);
218*1fbe4564SMatthias Ringwald                 break;
219*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data
220*1fbe4564SMatthias Ringwald                 break;
221*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
222*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
223*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
224*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_DEVICE_ID:
225*1fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
226*1fbe4564SMatthias Ringwald             default:
227*1fbe4564SMatthias Ringwald                 printf("Advertising Data Type 0x%2x not handled yet", data_type);
228*1fbe4564SMatthias Ringwald                 break;
229*1fbe4564SMatthias Ringwald         }
230*1fbe4564SMatthias Ringwald         printf("\n");
231*1fbe4564SMatthias Ringwald     }
232*1fbe4564SMatthias Ringwald     printf("\n");
233*1fbe4564SMatthias Ringwald }
234*1fbe4564SMatthias Ringwald /* LISTING_END */
235*1fbe4564SMatthias Ringwald 
236*1fbe4564SMatthias Ringwald /* @section HCI packet handler
237*1fbe4564SMatthias Ringwald  *
238*1fbe4564SMatthias Ringwald  * @text The HCI packet handler has to start the scanning,
239*1fbe4564SMatthias Ringwald  * and to handle received advertisements. Advertisements are received
240*1fbe4564SMatthias Ringwald  * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
241*1fbe4564SMatthias Ringwald  * see Listing GAPLEAdvPacketHandler.
242*1fbe4564SMatthias Ringwald  */
243*1fbe4564SMatthias Ringwald 
244*1fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
245*1fbe4564SMatthias Ringwald 
246*1fbe4564SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
247*1fbe4564SMatthias Ringwald     UNUSED(channel);
248*1fbe4564SMatthias Ringwald     UNUSED(size);
249*1fbe4564SMatthias Ringwald 
250*1fbe4564SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
251*1fbe4564SMatthias Ringwald 
252*1fbe4564SMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
253*1fbe4564SMatthias Ringwald         case BTSTACK_EVENT_STATE:
254*1fbe4564SMatthias Ringwald             // BTstack activated, get started
255*1fbe4564SMatthias Ringwald             if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
256*1fbe4564SMatthias Ringwald                 printf("Start scaning!\n");
257*1fbe4564SMatthias Ringwald                 gap_set_scan_parameters(0,0x0030, 0x0030);
258*1fbe4564SMatthias Ringwald                 gap_start_scan();
259*1fbe4564SMatthias Ringwald             }
260*1fbe4564SMatthias Ringwald             break;
261*1fbe4564SMatthias Ringwald         case GAP_EVENT_ADVERTISING_REPORT:{
262*1fbe4564SMatthias Ringwald             bd_addr_t address;
263*1fbe4564SMatthias Ringwald             gap_event_advertising_report_get_address(packet, address);
264*1fbe4564SMatthias Ringwald             // check if in list
265*1fbe4564SMatthias Ringwald             if (!addr_from_list(address)) break;
266*1fbe4564SMatthias Ringwald 
267*1fbe4564SMatthias Ringwald             uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet);
268*1fbe4564SMatthias Ringwald             uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
269*1fbe4564SMatthias Ringwald             int8_t rssi = gap_event_advertising_report_get_rssi(packet);
270*1fbe4564SMatthias Ringwald             uint8_t length = gap_event_advertising_report_get_data_length(packet);
271*1fbe4564SMatthias Ringwald             const uint8_t * data = gap_event_advertising_report_get_data(packet);
272*1fbe4564SMatthias Ringwald 
273*1fbe4564SMatthias Ringwald             printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type,
274*1fbe4564SMatthias Ringwald                address_type, bd_addr_to_str(address), rssi, length);
275*1fbe4564SMatthias Ringwald             printf_hexdump(data, length);
276*1fbe4564SMatthias Ringwald             dump_advertisement_data(data, length);
277*1fbe4564SMatthias Ringwald             break;
278*1fbe4564SMatthias Ringwald         }
279*1fbe4564SMatthias Ringwald         default:
280*1fbe4564SMatthias Ringwald             break;
281*1fbe4564SMatthias Ringwald     }
282*1fbe4564SMatthias Ringwald }
283*1fbe4564SMatthias Ringwald /* LISTING_END */
284*1fbe4564SMatthias Ringwald 
285*1fbe4564SMatthias Ringwald int btstack_main(void);
286*1fbe4564SMatthias Ringwald int btstack_main(void)
287*1fbe4564SMatthias Ringwald {
288*1fbe4564SMatthias Ringwald     sniffer_setup();
289*1fbe4564SMatthias Ringwald 
290*1fbe4564SMatthias Ringwald     // turn on!
291*1fbe4564SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
292*1fbe4564SMatthias Ringwald 
293*1fbe4564SMatthias Ringwald     return 0;
294*1fbe4564SMatthias Ringwald }
295*1fbe4564SMatthias Ringwald 
296*1fbe4564SMatthias Ringwald /* EXAMPLE_END */
297