xref: /btstack/example/gap_le_advertisements.c (revision bfb465b059d2553faf19585e99c5cc1392ab57a4)
1bcf00d8fSMatthias Ringwald /*
2bcf00d8fSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3bcf00d8fSMatthias Ringwald  *
4bcf00d8fSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5bcf00d8fSMatthias Ringwald  * modification, are permitted provided that the following conditions
6bcf00d8fSMatthias Ringwald  * are met:
7bcf00d8fSMatthias Ringwald  *
8bcf00d8fSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9bcf00d8fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10bcf00d8fSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11bcf00d8fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12bcf00d8fSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13bcf00d8fSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14bcf00d8fSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15bcf00d8fSMatthias Ringwald  *    from this software without specific prior written permission.
16bcf00d8fSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17bcf00d8fSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18bcf00d8fSMatthias Ringwald  *    monetary gain.
19bcf00d8fSMatthias Ringwald  *
20bcf00d8fSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21bcf00d8fSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22bcf00d8fSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23bcf00d8fSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24bcf00d8fSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25bcf00d8fSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26bcf00d8fSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27bcf00d8fSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28bcf00d8fSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29bcf00d8fSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30bcf00d8fSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31bcf00d8fSMatthias Ringwald  * SUCH DAMAGE.
32bcf00d8fSMatthias Ringwald  *
33bcf00d8fSMatthias Ringwald  * Please inquire about commercial licensing options at
34bcf00d8fSMatthias Ringwald  * [email protected]
35bcf00d8fSMatthias Ringwald  *
36bcf00d8fSMatthias Ringwald  */
37bcf00d8fSMatthias Ringwald 
38bcf00d8fSMatthias Ringwald 
39bcf00d8fSMatthias Ringwald // *****************************************************************************
40bcf00d8fSMatthias Ringwald /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper
41bcf00d8fSMatthias Ringwald  *
42bcf00d8fSMatthias Ringwald  * @text This example shows how to scan and parse advertisements.
43bcf00d8fSMatthias Ringwald  *
44bcf00d8fSMatthias Ringwald  */
45bcf00d8fSMatthias Ringwald  // *****************************************************************************
46bcf00d8fSMatthias Ringwald 
47bcf00d8fSMatthias Ringwald 
48bcf00d8fSMatthias Ringwald #include <stdint.h>
49de1762f7SMatthias Ringwald #include <inttypes.h>
50bcf00d8fSMatthias Ringwald #include <stdio.h>
51bcf00d8fSMatthias Ringwald #include <stdlib.h>
52bcf00d8fSMatthias Ringwald #include <string.h>
53bcf00d8fSMatthias Ringwald 
540e2df43fSMatthias Ringwald #include "btstack.h"
55bcf00d8fSMatthias Ringwald 
56bcf00d8fSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
57bcf00d8fSMatthias Ringwald 
58bcf00d8fSMatthias Ringwald /* @section GAP LE setup for receiving advertisements
59bcf00d8fSMatthias Ringwald  *
60bcf00d8fSMatthias Ringwald  * @text GAP LE advertisements are received as custom HCI events of the
61045013feSMatthias Ringwald  * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
62bcf00d8fSMatthias Ringwald  * the HCI packet handler, as shown in Listing GAPLEAdvSetup.
63bcf00d8fSMatthias Ringwald  */
64bcf00d8fSMatthias Ringwald 
65bcf00d8fSMatthias Ringwald /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
66bcf00d8fSMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
67bcf00d8fSMatthias Ringwald 
68bcf00d8fSMatthias Ringwald static void gap_le_advertisements_setup(void){
69bcf00d8fSMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
70bcf00d8fSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
71*bfb465b0SMatthias Ringwald 
72*bfb465b0SMatthias Ringwald     // Active scanning, 100% (scan interval = scan window)
73*bfb465b0SMatthias Ringwald     gap_set_scan_parameters(1,48,48);
74bcf00d8fSMatthias Ringwald }
75bcf00d8fSMatthias Ringwald 
76bcf00d8fSMatthias Ringwald /* LISTING_END */
77bcf00d8fSMatthias Ringwald 
78bcf00d8fSMatthias Ringwald /* @section GAP LE Advertising Data Dumper
79bcf00d8fSMatthias Ringwald  *
80bcf00d8fSMatthias Ringwald  * @text Here, we use the definition of advertising data types and flags as specified in
81bcf00d8fSMatthias Ringwald  * [Assigned Numbers GAP](https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile)
82bcf00d8fSMatthias Ringwald  * and [Supplement to the Bluetooth Core Specification, v4](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=282152).
83bcf00d8fSMatthias Ringwald  */
84bcf00d8fSMatthias Ringwald 
85bcf00d8fSMatthias Ringwald /* LISTING_START(GAPLEAdvDataTypesAndFlags): Advertising data types and flags */
86bcf00d8fSMatthias Ringwald static char * ad_types[] = {
87bcf00d8fSMatthias Ringwald     "",
88bcf00d8fSMatthias Ringwald     "Flags",
89bcf00d8fSMatthias Ringwald     "Incomplete List of 16-bit Service Class UUIDs",
90bcf00d8fSMatthias Ringwald     "Complete List of 16-bit Service Class UUIDs",
91bcf00d8fSMatthias Ringwald     "Incomplete List of 32-bit Service Class UUIDs",
92bcf00d8fSMatthias Ringwald     "Complete List of 32-bit Service Class UUIDs",
93bcf00d8fSMatthias Ringwald     "Incomplete List of 128-bit Service Class UUIDs",
94bcf00d8fSMatthias Ringwald     "Complete List of 128-bit Service Class UUIDs",
95bcf00d8fSMatthias Ringwald     "Shortened Local Name",
96bcf00d8fSMatthias Ringwald     "Complete Local Name",
97bcf00d8fSMatthias Ringwald     "Tx Power Level",
98bcf00d8fSMatthias Ringwald     "",
99bcf00d8fSMatthias Ringwald     "",
100bcf00d8fSMatthias Ringwald     "Class of Device",
101bcf00d8fSMatthias Ringwald     "Simple Pairing Hash C",
102bcf00d8fSMatthias Ringwald     "Simple Pairing Randomizer R",
103bcf00d8fSMatthias Ringwald     "Device ID",
104bcf00d8fSMatthias Ringwald     "Security Manager TK Value",
105bcf00d8fSMatthias Ringwald     "Slave Connection Interval Range",
106bcf00d8fSMatthias Ringwald     "",
107bcf00d8fSMatthias Ringwald     "List of 16-bit Service Solicitation UUIDs",
108bcf00d8fSMatthias Ringwald     "List of 128-bit Service Solicitation UUIDs",
109bcf00d8fSMatthias Ringwald     "Service Data",
110bcf00d8fSMatthias Ringwald     "Public Target Address",
111bcf00d8fSMatthias Ringwald     "Random Target Address",
112bcf00d8fSMatthias Ringwald     "Appearance",
113bcf00d8fSMatthias Ringwald     "Advertising Interval"
114bcf00d8fSMatthias Ringwald };
115bcf00d8fSMatthias Ringwald 
116bcf00d8fSMatthias Ringwald static char * flags[] = {
117bcf00d8fSMatthias Ringwald     "LE Limited Discoverable Mode",
118bcf00d8fSMatthias Ringwald     "LE General Discoverable Mode",
119bcf00d8fSMatthias Ringwald     "BR/EDR Not Supported",
120bcf00d8fSMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",
121bcf00d8fSMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Host)",
122bcf00d8fSMatthias Ringwald     "Reserved",
123bcf00d8fSMatthias Ringwald     "Reserved",
124bcf00d8fSMatthias Ringwald     "Reserved"
125bcf00d8fSMatthias Ringwald };
126bcf00d8fSMatthias Ringwald /* LISTING_END */
127bcf00d8fSMatthias Ringwald 
128bcf00d8fSMatthias Ringwald /* @text BTstack offers an iterator for parsing sequence of advertising data (AD) structures,
129bcf00d8fSMatthias Ringwald  * see [BLE advertisements parser API](../appendix/apis/#ble-advertisements-parser-api).
130bcf00d8fSMatthias Ringwald  * After initializing the iterator, each AD structure is dumped according to its type.
131bcf00d8fSMatthias Ringwald  */
132bcf00d8fSMatthias Ringwald 
133bcf00d8fSMatthias Ringwald /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */
1343ee82ab1SMilanka Ringwald static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
135bcf00d8fSMatthias Ringwald     ad_context_t context;
136bcf00d8fSMatthias Ringwald     bd_addr_t address;
137bcf00d8fSMatthias Ringwald     uint8_t uuid_128[16];
1383ee82ab1SMilanka Ringwald     for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
139bcf00d8fSMatthias Ringwald         uint8_t data_type    = ad_iterator_get_data_type(&context);
140bcf00d8fSMatthias Ringwald         uint8_t size         = ad_iterator_get_data_len(&context);
14118a2fc6fSMatthias Ringwald         const uint8_t * data = ad_iterator_get_data(&context);
142bcf00d8fSMatthias Ringwald 
143bcf00d8fSMatthias Ringwald         if (data_type > 0 && data_type < 0x1B){
144bcf00d8fSMatthias Ringwald             printf("    %s: ", ad_types[data_type]);
145bcf00d8fSMatthias Ringwald         }
146bcf00d8fSMatthias Ringwald         int i;
147bcf00d8fSMatthias Ringwald         // Assigned Numbers GAP
148bcf00d8fSMatthias Ringwald 
149bcf00d8fSMatthias Ringwald         switch (data_type){
1501d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_FLAGS:
151bcf00d8fSMatthias Ringwald                 // show only first octet, ignore rest
152bcf00d8fSMatthias Ringwald                 for (i=0; i<8;i++){
153bcf00d8fSMatthias Ringwald                     if (data[0] & (1<<i)){
154bcf00d8fSMatthias Ringwald                         printf("%s; ", flags[i]);
155bcf00d8fSMatthias Ringwald                     }
156bcf00d8fSMatthias Ringwald 
157bcf00d8fSMatthias Ringwald                 }
158bcf00d8fSMatthias Ringwald                 break;
1591d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
1601d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
1611d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
162bcf00d8fSMatthias Ringwald                 for (i=0; i<size;i+=2){
163bcf00d8fSMatthias Ringwald                     printf("%02X ", little_endian_read_16(data, i));
164bcf00d8fSMatthias Ringwald                 }
165bcf00d8fSMatthias Ringwald                 break;
1661d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
1671d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
1681d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
169bcf00d8fSMatthias Ringwald                 for (i=0; i<size;i+=4){
170de1762f7SMatthias Ringwald                     printf("%04"PRIX32, little_endian_read_32(data, i));
171bcf00d8fSMatthias Ringwald                 }
172bcf00d8fSMatthias Ringwald                 break;
1731d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
1741d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
1751d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
176bcf00d8fSMatthias Ringwald                 reverse_128(data, uuid_128);
177bcf00d8fSMatthias Ringwald                 printf("%s", uuid128_to_str(uuid_128));
178bcf00d8fSMatthias Ringwald                 break;
1791d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
1801d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
181bcf00d8fSMatthias Ringwald                 for (i=0; i<size;i++){
182bcf00d8fSMatthias Ringwald                     printf("%c", (char)(data[i]));
183bcf00d8fSMatthias Ringwald                 }
184bcf00d8fSMatthias Ringwald                 break;
1851d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
186bcf00d8fSMatthias Ringwald                 printf("%d dBm", *(int8_t*)data);
187bcf00d8fSMatthias Ringwald                 break;
1881d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
189bcf00d8fSMatthias 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);
190bcf00d8fSMatthias Ringwald                 break;
1911d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
192bcf00d8fSMatthias Ringwald                 printf_hexdump(data, size);
193bcf00d8fSMatthias Ringwald                 break;
1941d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
1951d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
196bcf00d8fSMatthias Ringwald                 reverse_bd_addr(data, address);
197bcf00d8fSMatthias Ringwald                 printf("%s", bd_addr_to_str(address));
198bcf00d8fSMatthias Ringwald                 break;
1991d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_APPEARANCE:
200bcf00d8fSMatthias Ringwald                 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
201bcf00d8fSMatthias Ringwald                 printf("%02X", little_endian_read_16(data, 0) );
202bcf00d8fSMatthias Ringwald                 break;
2031d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
204bcf00d8fSMatthias Ringwald                 printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
205bcf00d8fSMatthias Ringwald                 break;
2061d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
207bcf00d8fSMatthias Ringwald                 printf_hexdump(data, size);
208bcf00d8fSMatthias Ringwald                 break;
2091d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data
210bcf00d8fSMatthias Ringwald                 break;
2111d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
2121d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
2131d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
2141d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_DEVICE_ID:
2151d0cde9dSMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
216bcf00d8fSMatthias Ringwald             default:
2171d0cde9dSMatthias Ringwald                 printf("Advertising Data Type 0x%2x not handled yet", data_type);
218bcf00d8fSMatthias Ringwald                 break;
219bcf00d8fSMatthias Ringwald         }
220bcf00d8fSMatthias Ringwald         printf("\n");
221bcf00d8fSMatthias Ringwald     }
222bcf00d8fSMatthias Ringwald     printf("\n");
223bcf00d8fSMatthias Ringwald }
224bcf00d8fSMatthias Ringwald /* LISTING_END */
225bcf00d8fSMatthias Ringwald 
226bcf00d8fSMatthias Ringwald /* @section HCI packet handler
227bcf00d8fSMatthias Ringwald  *
228bcf00d8fSMatthias Ringwald  * @text The HCI packet handler has to start the scanning,
229bcf00d8fSMatthias Ringwald  * and to handle received advertisements. Advertisements are received
230045013feSMatthias Ringwald  * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
231bcf00d8fSMatthias Ringwald  * see Listing GAPLEAdvPacketHandler.
232bcf00d8fSMatthias Ringwald  */
233bcf00d8fSMatthias Ringwald 
234bcf00d8fSMatthias Ringwald /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
235bcf00d8fSMatthias Ringwald 
236bcf00d8fSMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
2379ec2630cSMatthias Ringwald     UNUSED(channel);
2389ec2630cSMatthias Ringwald     UNUSED(size);
2399ec2630cSMatthias Ringwald 
240bcf00d8fSMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
241bcf00d8fSMatthias Ringwald 
2420e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
243bcf00d8fSMatthias Ringwald         case BTSTACK_EVENT_STATE:
244bcf00d8fSMatthias Ringwald             // BTstack activated, get started
245be7cc9a0SMilanka Ringwald             if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
246d356a6daSMatthias Ringwald                 printf("Start scaning!\n");
247bcf00d8fSMatthias Ringwald                 gap_set_scan_parameters(0,0x0030, 0x0030);
248bcf00d8fSMatthias Ringwald                 gap_start_scan();
249bcf00d8fSMatthias Ringwald             }
250bcf00d8fSMatthias Ringwald             break;
251045013feSMatthias Ringwald         case GAP_EVENT_ADVERTISING_REPORT:{
252bcf00d8fSMatthias Ringwald             bd_addr_t address;
2533ee82ab1SMilanka Ringwald             gap_event_advertising_report_get_address(packet, address);
2543ee82ab1SMilanka Ringwald             uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet);
2553ee82ab1SMilanka Ringwald             uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
2563ee82ab1SMilanka Ringwald             int8_t rssi = gap_event_advertising_report_get_rssi(packet);
2573ee82ab1SMilanka Ringwald             uint8_t length = gap_event_advertising_report_get_data_length(packet);
2583ee82ab1SMilanka Ringwald             const uint8_t * data = gap_event_advertising_report_get_data(packet);
259bcf00d8fSMatthias Ringwald 
26089fd9aefSMatthias Ringwald             printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type,
261bcf00d8fSMatthias Ringwald                address_type, bd_addr_to_str(address), rssi, length);
262bcf00d8fSMatthias Ringwald             printf_hexdump(data, length);
263bcf00d8fSMatthias Ringwald             dump_advertisement_data(data, length);
264bcf00d8fSMatthias Ringwald             break;
265bcf00d8fSMatthias Ringwald         }
266bcf00d8fSMatthias Ringwald         default:
267bcf00d8fSMatthias Ringwald             break;
268bcf00d8fSMatthias Ringwald     }
269bcf00d8fSMatthias Ringwald }
270bcf00d8fSMatthias Ringwald /* LISTING_END */
271bcf00d8fSMatthias Ringwald 
272bcf00d8fSMatthias Ringwald int btstack_main(void);
273bcf00d8fSMatthias Ringwald int btstack_main(void)
274bcf00d8fSMatthias Ringwald {
275bcf00d8fSMatthias Ringwald     gap_le_advertisements_setup();
276bcf00d8fSMatthias Ringwald 
277bcf00d8fSMatthias Ringwald     // turn on!
278bcf00d8fSMatthias Ringwald     hci_power_control(HCI_POWER_ON);
279bcf00d8fSMatthias Ringwald 
280bcf00d8fSMatthias Ringwald     return 0;
281bcf00d8fSMatthias Ringwald }
282bcf00d8fSMatthias Ringwald 
283bcf00d8fSMatthias Ringwald /* EXAMPLE_END */