xref: /btstack/test/mesh/sniffer.c (revision bc6a318f2177319997f3b7da7b6f161b4ec94fed)
11fbe4564SMatthias Ringwald /*
21fbe4564SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
31fbe4564SMatthias Ringwald  *
41fbe4564SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
51fbe4564SMatthias Ringwald  * modification, are permitted provided that the following conditions
61fbe4564SMatthias Ringwald  * are met:
71fbe4564SMatthias Ringwald  *
81fbe4564SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
91fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
101fbe4564SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
111fbe4564SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
121fbe4564SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
131fbe4564SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
141fbe4564SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
151fbe4564SMatthias Ringwald  *    from this software without specific prior written permission.
161fbe4564SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
171fbe4564SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
181fbe4564SMatthias Ringwald  *    monetary gain.
191fbe4564SMatthias Ringwald  *
201fbe4564SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211fbe4564SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221fbe4564SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
231fbe4564SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
241fbe4564SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251fbe4564SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261fbe4564SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271fbe4564SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281fbe4564SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291fbe4564SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301fbe4564SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311fbe4564SMatthias Ringwald  * SUCH DAMAGE.
321fbe4564SMatthias Ringwald  *
331fbe4564SMatthias Ringwald  * Please inquire about commercial licensing options at
341fbe4564SMatthias Ringwald  * [email protected]
351fbe4564SMatthias Ringwald  *
361fbe4564SMatthias Ringwald  */
371fbe4564SMatthias Ringwald 
38*bc6a318fSMatthias Ringwald #define BTSTACK_FILE__ "gap_le_advertisements.c"
391fbe4564SMatthias Ringwald 
401fbe4564SMatthias Ringwald 
411fbe4564SMatthias Ringwald // *****************************************************************************
421fbe4564SMatthias Ringwald /* EXAMPLE_START(gap_le_advertisements): GAP LE Advertisements Dumper
431fbe4564SMatthias Ringwald  *
441fbe4564SMatthias Ringwald  * @text This example shows how to scan and parse advertisements.
451fbe4564SMatthias Ringwald  *
461fbe4564SMatthias Ringwald  */
471fbe4564SMatthias Ringwald  // *****************************************************************************
481fbe4564SMatthias Ringwald 
491fbe4564SMatthias Ringwald 
501fbe4564SMatthias Ringwald #include <stdint.h>
511fbe4564SMatthias Ringwald #include <inttypes.h>
521fbe4564SMatthias Ringwald #include <stdio.h>
531fbe4564SMatthias Ringwald #include <stdlib.h>
541fbe4564SMatthias Ringwald #include <string.h>
551fbe4564SMatthias Ringwald 
561fbe4564SMatthias Ringwald #include "btstack.h"
571fbe4564SMatthias Ringwald 
581fbe4564SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
591fbe4564SMatthias Ringwald 
601fbe4564SMatthias Ringwald #define NUM_NODES 2
611fbe4564SMatthias Ringwald 
621fbe4564SMatthias Ringwald static const char * nodes_string[NUM_NODES] = {
631fbe4564SMatthias Ringwald     "5C:F3:70:60:7B:87",
641fbe4564SMatthias Ringwald     "00:1B:DC:07:32:EF",
651fbe4564SMatthias Ringwald };
661fbe4564SMatthias Ringwald static bd_addr_t nodes_addr[NUM_NODES];
671fbe4564SMatthias Ringwald 
681fbe4564SMatthias Ringwald /* @section GAP LE setup for receiving advertisements
691fbe4564SMatthias Ringwald  *
701fbe4564SMatthias Ringwald  * @text GAP LE advertisements are received as custom HCI events of the
711fbe4564SMatthias Ringwald  * GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
721fbe4564SMatthias Ringwald  * the HCI packet handler, as shown in Listing GAPLEAdvSetup.
731fbe4564SMatthias Ringwald  */
741fbe4564SMatthias Ringwald 
751fbe4564SMatthias Ringwald static char * ad_types[] = {
761fbe4564SMatthias Ringwald     "",
771fbe4564SMatthias Ringwald     "Flags",
781fbe4564SMatthias Ringwald     "Incomplete List of 16-bit Service Class UUIDs",
791fbe4564SMatthias Ringwald     "Complete List of 16-bit Service Class UUIDs",
801fbe4564SMatthias Ringwald     "Incomplete List of 32-bit Service Class UUIDs",
811fbe4564SMatthias Ringwald     "Complete List of 32-bit Service Class UUIDs",
821fbe4564SMatthias Ringwald     "Incomplete List of 128-bit Service Class UUIDs",
831fbe4564SMatthias Ringwald     "Complete List of 128-bit Service Class UUIDs",
841fbe4564SMatthias Ringwald     "Shortened Local Name",
851fbe4564SMatthias Ringwald     "Complete Local Name",
861fbe4564SMatthias Ringwald     "Tx Power Level",
871fbe4564SMatthias Ringwald     "",
881fbe4564SMatthias Ringwald     "",
891fbe4564SMatthias Ringwald     "Class of Device",
901fbe4564SMatthias Ringwald     "Simple Pairing Hash C",
911fbe4564SMatthias Ringwald     "Simple Pairing Randomizer R",
921fbe4564SMatthias Ringwald     "Device ID",
931fbe4564SMatthias Ringwald     "Security Manager TK Value",
941fbe4564SMatthias Ringwald     "Slave Connection Interval Range",
951fbe4564SMatthias Ringwald     "",
961fbe4564SMatthias Ringwald     "List of 16-bit Service Solicitation UUIDs",
971fbe4564SMatthias Ringwald     "List of 128-bit Service Solicitation UUIDs",
981fbe4564SMatthias Ringwald     "Service Data",
991fbe4564SMatthias Ringwald     "Public Target Address",
1001fbe4564SMatthias Ringwald     "Random Target Address",
1011fbe4564SMatthias Ringwald     "Appearance",
1021fbe4564SMatthias Ringwald     "Advertising Interval"
1031fbe4564SMatthias Ringwald };
1041fbe4564SMatthias Ringwald 
1051fbe4564SMatthias Ringwald static char * flags[] = {
1061fbe4564SMatthias Ringwald     "LE Limited Discoverable Mode",
1071fbe4564SMatthias Ringwald     "LE General Discoverable Mode",
1081fbe4564SMatthias Ringwald     "BR/EDR Not Supported",
1091fbe4564SMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",
1101fbe4564SMatthias Ringwald     "Simultaneous LE and BR/EDR to Same Device Capable (Host)",
1111fbe4564SMatthias Ringwald     "Reserved",
1121fbe4564SMatthias Ringwald     "Reserved",
1131fbe4564SMatthias Ringwald     "Reserved"
1141fbe4564SMatthias Ringwald };
1151fbe4564SMatthias Ringwald 
1161fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
1171fbe4564SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
1181fbe4564SMatthias Ringwald 
sniffer_setup(void)1191fbe4564SMatthias Ringwald static void sniffer_setup(void){
1201fbe4564SMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
1211fbe4564SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
1221fbe4564SMatthias Ringwald     // Active scanning, 100% (scan interval = scan window)
1231fbe4564SMatthias Ringwald     gap_set_scan_parameters(1,48,48);
1241fbe4564SMatthias Ringwald     //
1251fbe4564SMatthias Ringwald     int i;
1261fbe4564SMatthias Ringwald     for (i=0;i<NUM_NODES;i++){
1271fbe4564SMatthias Ringwald         sscanf_bd_addr(nodes_string[i], nodes_addr[i]);
1281fbe4564SMatthias Ringwald         printf("Listening for %s\n", bd_addr_to_str(nodes_addr[i]));
1291fbe4564SMatthias Ringwald     }
1301fbe4564SMatthias Ringwald }
1311fbe4564SMatthias Ringwald 
addr_from_list(bd_addr_t addr)1321fbe4564SMatthias Ringwald static int addr_from_list(bd_addr_t addr){
1331fbe4564SMatthias Ringwald     int i;
1341fbe4564SMatthias Ringwald     for (i=0;i<NUM_NODES;i++){
1351fbe4564SMatthias Ringwald         if (memcmp(addr, nodes_addr[i], 6) == 0) return 1;
1361fbe4564SMatthias Ringwald     }
1371fbe4564SMatthias Ringwald     return 0;
1381fbe4564SMatthias Ringwald }
1391fbe4564SMatthias Ringwald 
1401fbe4564SMatthias Ringwald /* LISTING_END */
1411fbe4564SMatthias Ringwald 
1421fbe4564SMatthias Ringwald 
1431fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */
dump_advertisement_data(const uint8_t * adv_data,uint8_t adv_size)1441fbe4564SMatthias Ringwald static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
1451fbe4564SMatthias Ringwald     ad_context_t context;
1461fbe4564SMatthias Ringwald     bd_addr_t address;
1471fbe4564SMatthias Ringwald     uint8_t uuid_128[16];
1481fbe4564SMatthias Ringwald     for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
1491fbe4564SMatthias Ringwald         uint8_t data_type    = ad_iterator_get_data_type(&context);
1501fbe4564SMatthias Ringwald         uint8_t size         = ad_iterator_get_data_len(&context);
1511fbe4564SMatthias Ringwald         const uint8_t * data = ad_iterator_get_data(&context);
1521fbe4564SMatthias Ringwald 
1531fbe4564SMatthias Ringwald         if (data_type > 0 && data_type < 0x1B){
1541fbe4564SMatthias Ringwald             printf("    %s: ", ad_types[data_type]);
1551fbe4564SMatthias Ringwald         }
1561fbe4564SMatthias Ringwald         int i;
1571fbe4564SMatthias Ringwald         // Assigned Numbers GAP
1581fbe4564SMatthias Ringwald 
1591fbe4564SMatthias Ringwald         switch (data_type){
1601fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_FLAGS:
1611fbe4564SMatthias Ringwald                 // show only first octet, ignore rest
1621fbe4564SMatthias Ringwald                 for (i=0; i<8;i++){
1631fbe4564SMatthias Ringwald                     if (data[0] & (1<<i)){
1641fbe4564SMatthias Ringwald                         printf("%s; ", flags[i]);
1651fbe4564SMatthias Ringwald                     }
1661fbe4564SMatthias Ringwald 
1671fbe4564SMatthias Ringwald                 }
1681fbe4564SMatthias Ringwald                 break;
1691fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
1701fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
1711fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
1721fbe4564SMatthias Ringwald                 for (i=0; i<size;i+=2){
1731fbe4564SMatthias Ringwald                     printf("%02X ", little_endian_read_16(data, i));
1741fbe4564SMatthias Ringwald                 }
1751fbe4564SMatthias Ringwald                 break;
1761fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
1771fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
1781fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
1791fbe4564SMatthias Ringwald                 for (i=0; i<size;i+=4){
1801fbe4564SMatthias Ringwald                     printf("%04"PRIX32, little_endian_read_32(data, i));
1811fbe4564SMatthias Ringwald                 }
1821fbe4564SMatthias Ringwald                 break;
1831fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
1841fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
1851fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
1861fbe4564SMatthias Ringwald                 reverse_128(data, uuid_128);
1871fbe4564SMatthias Ringwald                 printf("%s", uuid128_to_str(uuid_128));
1881fbe4564SMatthias Ringwald                 break;
1891fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
1901fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
1911fbe4564SMatthias Ringwald                 for (i=0; i<size;i++){
1921fbe4564SMatthias Ringwald                     printf("%c", (char)(data[i]));
1931fbe4564SMatthias Ringwald                 }
1941fbe4564SMatthias Ringwald                 break;
1951fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
1961fbe4564SMatthias Ringwald                 printf("%d dBm", *(int8_t*)data);
1971fbe4564SMatthias Ringwald                 break;
1981fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
1991fbe4564SMatthias 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);
2001fbe4564SMatthias Ringwald                 break;
2011fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
2021fbe4564SMatthias Ringwald                 printf_hexdump(data, size);
2031fbe4564SMatthias Ringwald                 break;
2041fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
2051fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
2061fbe4564SMatthias Ringwald                 reverse_bd_addr(data, address);
2071fbe4564SMatthias Ringwald                 printf("%s", bd_addr_to_str(address));
2081fbe4564SMatthias Ringwald                 break;
2091fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_APPEARANCE:
2101fbe4564SMatthias Ringwald                 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
2111fbe4564SMatthias Ringwald                 printf("%02X", little_endian_read_16(data, 0) );
2121fbe4564SMatthias Ringwald                 break;
2131fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
2141fbe4564SMatthias Ringwald                 printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
2151fbe4564SMatthias Ringwald                 break;
2161fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
2171fbe4564SMatthias Ringwald                 printf_hexdump(data, size);
2181fbe4564SMatthias Ringwald                 break;
2191fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data
2201fbe4564SMatthias Ringwald                 break;
2211fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
2221fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
2231fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
2241fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_DEVICE_ID:
2251fbe4564SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
2261fbe4564SMatthias Ringwald             default:
2271fbe4564SMatthias Ringwald                 printf("Advertising Data Type 0x%2x not handled yet", data_type);
2281fbe4564SMatthias Ringwald                 break;
2291fbe4564SMatthias Ringwald         }
2301fbe4564SMatthias Ringwald         printf("\n");
2311fbe4564SMatthias Ringwald     }
2321fbe4564SMatthias Ringwald     printf("\n");
2331fbe4564SMatthias Ringwald }
2341fbe4564SMatthias Ringwald /* LISTING_END */
2351fbe4564SMatthias Ringwald 
2361fbe4564SMatthias Ringwald /* @section HCI packet handler
2371fbe4564SMatthias Ringwald  *
2381fbe4564SMatthias Ringwald  * @text The HCI packet handler has to start the scanning,
2391fbe4564SMatthias Ringwald  * and to handle received advertisements. Advertisements are received
2401fbe4564SMatthias Ringwald  * as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
2411fbe4564SMatthias Ringwald  * see Listing GAPLEAdvPacketHandler.
2421fbe4564SMatthias Ringwald  */
2431fbe4564SMatthias Ringwald 
2441fbe4564SMatthias Ringwald /* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
2451fbe4564SMatthias Ringwald 
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)2461fbe4564SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
2471fbe4564SMatthias Ringwald     UNUSED(channel);
2481fbe4564SMatthias Ringwald     UNUSED(size);
2491fbe4564SMatthias Ringwald 
2501fbe4564SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
2511fbe4564SMatthias Ringwald 
2521fbe4564SMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
2531fbe4564SMatthias Ringwald         case BTSTACK_EVENT_STATE:
2541fbe4564SMatthias Ringwald             // BTstack activated, get started
2551fbe4564SMatthias Ringwald             if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
2561fbe4564SMatthias Ringwald                 printf("Start scaning!\n");
2571fbe4564SMatthias Ringwald                 gap_set_scan_parameters(0,0x0030, 0x0030);
2581fbe4564SMatthias Ringwald                 gap_start_scan();
2591fbe4564SMatthias Ringwald             }
2601fbe4564SMatthias Ringwald             break;
2611fbe4564SMatthias Ringwald         case GAP_EVENT_ADVERTISING_REPORT:{
2621fbe4564SMatthias Ringwald             bd_addr_t address;
2631fbe4564SMatthias Ringwald             gap_event_advertising_report_get_address(packet, address);
2641fbe4564SMatthias Ringwald             // check if in list
2651fbe4564SMatthias Ringwald             if (!addr_from_list(address)) break;
2661fbe4564SMatthias Ringwald 
2671fbe4564SMatthias Ringwald             uint8_t event_type = gap_event_advertising_report_get_advertising_event_type(packet);
2681fbe4564SMatthias Ringwald             uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
2691fbe4564SMatthias Ringwald             int8_t rssi = gap_event_advertising_report_get_rssi(packet);
2701fbe4564SMatthias Ringwald             uint8_t length = gap_event_advertising_report_get_data_length(packet);
2711fbe4564SMatthias Ringwald             const uint8_t * data = gap_event_advertising_report_get_data(packet);
2721fbe4564SMatthias Ringwald 
2731fbe4564SMatthias Ringwald             printf("Advertisement event: evt-type %u, addr-type %u, addr %s, rssi %d, data[%u] ", event_type,
2741fbe4564SMatthias Ringwald                address_type, bd_addr_to_str(address), rssi, length);
2751fbe4564SMatthias Ringwald             printf_hexdump(data, length);
2761fbe4564SMatthias Ringwald             dump_advertisement_data(data, length);
2771fbe4564SMatthias Ringwald             break;
2781fbe4564SMatthias Ringwald         }
2791fbe4564SMatthias Ringwald         default:
2801fbe4564SMatthias Ringwald             break;
2811fbe4564SMatthias Ringwald     }
2821fbe4564SMatthias Ringwald }
2831fbe4564SMatthias Ringwald /* LISTING_END */
2841fbe4564SMatthias Ringwald 
2851fbe4564SMatthias Ringwald int btstack_main(void);
btstack_main(void)2861fbe4564SMatthias Ringwald int btstack_main(void)
2871fbe4564SMatthias Ringwald {
2881fbe4564SMatthias Ringwald     sniffer_setup();
2891fbe4564SMatthias Ringwald 
2901fbe4564SMatthias Ringwald     // turn on!
2911fbe4564SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
2921fbe4564SMatthias Ringwald 
2931fbe4564SMatthias Ringwald     return 0;
2941fbe4564SMatthias Ringwald }
2951fbe4564SMatthias Ringwald 
2961fbe4564SMatthias Ringwald /* EXAMPLE_END */
297