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 381fbe4564SMatthias Ringwald #define __BTSTACK_FILE__ "main.c" 391fbe4564SMatthias Ringwald 401fbe4564SMatthias Ringwald // ***************************************************************************** 411fbe4564SMatthias Ringwald // 421fbe4564SMatthias Ringwald // minimal setup for HCI code 431fbe4564SMatthias Ringwald // 441fbe4564SMatthias Ringwald // ***************************************************************************** 451fbe4564SMatthias Ringwald 461fbe4564SMatthias Ringwald #include <stdint.h> 471fbe4564SMatthias Ringwald #include <stdio.h> 481fbe4564SMatthias Ringwald #include <stdlib.h> 491fbe4564SMatthias Ringwald #include <string.h> 501fbe4564SMatthias Ringwald #include <signal.h> 511fbe4564SMatthias Ringwald 521fbe4564SMatthias Ringwald #include "btstack_config.h" 531fbe4564SMatthias Ringwald 541fbe4564SMatthias Ringwald #include "btstack_debug.h" 551fbe4564SMatthias Ringwald #include "btstack_event.h" 561fbe4564SMatthias Ringwald #include "btstack_link_key_db_fs.h" 571fbe4564SMatthias Ringwald #include "btstack_memory.h" 581fbe4564SMatthias Ringwald #include "btstack_run_loop.h" 591fbe4564SMatthias Ringwald #include "btstack_run_loop_posix.h" 601fbe4564SMatthias Ringwald #include "bluetooth_company_id.h" 611fbe4564SMatthias Ringwald #include "hci.h" 621fbe4564SMatthias Ringwald #include "hci_dump.h" 63*31437b52SMatthias Ringwald #include "hci_dump_posix_fs.h" 641fbe4564SMatthias Ringwald #include "btstack_stdin.h" 651fbe4564SMatthias Ringwald #include "btstack_tlv.h" 661fbe4564SMatthias Ringwald #include "btstack_tlv_posix.h" 671fbe4564SMatthias Ringwald 681fbe4564SMatthias Ringwald int is_bcm; 691fbe4564SMatthias Ringwald 701fbe4564SMatthias Ringwald #define TLV_DB_PATH_PREFIX "/tmp/btstack_" 711fbe4564SMatthias Ringwald #define TLV_DB_PATH_POSTFIX ".tlv" 721fbe4564SMatthias Ringwald static char tlv_db_path[100]; 731fbe4564SMatthias Ringwald static const btstack_tlv_t * tlv_impl; 741fbe4564SMatthias Ringwald static btstack_tlv_posix_t tlv_context; 751fbe4564SMatthias Ringwald static bd_addr_t local_addr; 761fbe4564SMatthias Ringwald 771fbe4564SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 781fbe4564SMatthias Ringwald static void local_version_information_handler(uint8_t * packet); 791fbe4564SMatthias Ringwald 801fbe4564SMatthias Ringwald static hci_transport_config_uart_t config = { 811fbe4564SMatthias Ringwald HCI_TRANSPORT_CONFIG_UART, 821fbe4564SMatthias Ringwald 115200, 831fbe4564SMatthias Ringwald 0, // main baudrate 841fbe4564SMatthias Ringwald 0, // flow control 851fbe4564SMatthias Ringwald NULL, 861fbe4564SMatthias Ringwald }; 871fbe4564SMatthias Ringwald 881fbe4564SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 891fbe4564SMatthias Ringwald 901fbe4564SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 91df71a9a4SMatthias Ringwald UNUSED(channel); 92df71a9a4SMatthias Ringwald UNUSED(size); 93df71a9a4SMatthias Ringwald 941fbe4564SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 95df71a9a4SMatthias Ringwald 961fbe4564SMatthias Ringwald switch (hci_event_packet_get_type(packet)){ 971fbe4564SMatthias Ringwald case BTSTACK_EVENT_STATE: 981fbe4564SMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 991fbe4564SMatthias Ringwald gap_local_bd_addr(local_addr); 1001fbe4564SMatthias Ringwald printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); 1011fbe4564SMatthias Ringwald strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); 1021fbe4564SMatthias Ringwald strcat(tlv_db_path, bd_addr_to_str(local_addr)); 1031fbe4564SMatthias Ringwald strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); 1041fbe4564SMatthias Ringwald tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); 1051fbe4564SMatthias Ringwald btstack_tlv_set_instance(tlv_impl, &tlv_context); 1061fbe4564SMatthias Ringwald break; 1071fbe4564SMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 1081fbe4564SMatthias Ringwald if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ 1091fbe4564SMatthias Ringwald local_version_information_handler(packet); 1101fbe4564SMatthias Ringwald } 1111fbe4564SMatthias Ringwald break; 1121fbe4564SMatthias Ringwald default: 1131fbe4564SMatthias Ringwald break; 1141fbe4564SMatthias Ringwald } 1151fbe4564SMatthias Ringwald } 1161fbe4564SMatthias Ringwald 1171fbe4564SMatthias Ringwald static void sigint_handler(int param){ 1181fbe4564SMatthias Ringwald UNUSED(param); 1191fbe4564SMatthias Ringwald 1201fbe4564SMatthias Ringwald printf("CTRL-C - SIGINT received, shutting down..\n"); 1211fbe4564SMatthias Ringwald log_info("sigint_handler: shutting down"); 1221fbe4564SMatthias Ringwald 1231fbe4564SMatthias Ringwald // reset anyway 1241fbe4564SMatthias Ringwald btstack_stdin_reset(); 1251fbe4564SMatthias Ringwald 1261fbe4564SMatthias Ringwald // power down 1271fbe4564SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 1281fbe4564SMatthias Ringwald hci_close(); 1291fbe4564SMatthias Ringwald log_info("Good bye, see you.\n"); 1301fbe4564SMatthias Ringwald exit(0); 1311fbe4564SMatthias Ringwald } 1321fbe4564SMatthias Ringwald 1331fbe4564SMatthias Ringwald static void local_version_information_handler(uint8_t * packet){ 1341fbe4564SMatthias Ringwald printf("Local version information:\n"); 1351fbe4564SMatthias Ringwald uint16_t hci_version = packet[6]; 1361fbe4564SMatthias Ringwald uint16_t hci_revision = little_endian_read_16(packet, 7); 1371fbe4564SMatthias Ringwald uint16_t lmp_version = packet[9]; 1381fbe4564SMatthias Ringwald uint16_t manufacturer = little_endian_read_16(packet, 10); 1391fbe4564SMatthias Ringwald uint16_t lmp_subversion = little_endian_read_16(packet, 12); 1401fbe4564SMatthias Ringwald printf("- HCI Version 0x%04x\n", hci_version); 1411fbe4564SMatthias Ringwald printf("- HCI Revision 0x%04x\n", hci_revision); 1421fbe4564SMatthias Ringwald printf("- LMP Version 0x%04x\n", lmp_version); 1431fbe4564SMatthias Ringwald printf("- LMP Subversion 0x%04x\n", lmp_subversion); 1441fbe4564SMatthias Ringwald printf("- Manufacturer 0x%04x\n", manufacturer); 1451fbe4564SMatthias Ringwald } 1461fbe4564SMatthias Ringwald 1471fbe4564SMatthias Ringwald #define USB_MAX_PATH_LEN 7 1481fbe4564SMatthias Ringwald int main(int argc, const char * argv[]){ 1491fbe4564SMatthias Ringwald 1501fbe4564SMatthias Ringwald /// GET STARTED with BTstack /// 1511fbe4564SMatthias Ringwald btstack_memory_init(); 1521fbe4564SMatthias Ringwald btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 1531fbe4564SMatthias Ringwald 1541fbe4564SMatthias Ringwald char log_path[100]; 1551fbe4564SMatthias Ringwald strcpy(log_path, "/tmp/hci_dump"); 1561fbe4564SMatthias Ringwald 1571fbe4564SMatthias Ringwald // check for -d pty path 1581fbe4564SMatthias Ringwald if (argc >= 3 && strcmp(argv[1], "-d") == 0){ 1591fbe4564SMatthias Ringwald config.device_name = argv[2]; 1601fbe4564SMatthias Ringwald argc -= 2; 1611fbe4564SMatthias Ringwald memmove(&argv[0], &argv[2], argc * sizeof(char *)); 1621fbe4564SMatthias Ringwald 1631fbe4564SMatthias Ringwald printf("Specified PTY: %s\n", config.device_name); 1641fbe4564SMatthias Ringwald 1651fbe4564SMatthias Ringwald // base logger output file on device_name 1661fbe4564SMatthias Ringwald const char * src = config.device_name; 1671fbe4564SMatthias Ringwald char * dst = &log_path[strlen(log_path)]; 1681fbe4564SMatthias Ringwald while (*src){ 1691fbe4564SMatthias Ringwald if (*src == '/'){ 1701fbe4564SMatthias Ringwald *dst++ = '_'; 1711fbe4564SMatthias Ringwald } else { 1721fbe4564SMatthias Ringwald *dst++ = *src; 1731fbe4564SMatthias Ringwald } 1741fbe4564SMatthias Ringwald src++; 1751fbe4564SMatthias Ringwald } 1761fbe4564SMatthias Ringwald *dst = 0; 1771fbe4564SMatthias Ringwald } 1781fbe4564SMatthias Ringwald 1791fbe4564SMatthias Ringwald // check for -u usb path 1801fbe4564SMatthias Ringwald uint8_t usb_path[USB_MAX_PATH_LEN]; 1811fbe4564SMatthias Ringwald int usb_path_len = 0; 1821fbe4564SMatthias Ringwald if (argc >= 3 && strcmp(argv[1], "-u") == 0){ 1831fbe4564SMatthias Ringwald // parse command line options for "-u 11:22:33" 1841fbe4564SMatthias Ringwald const char * port_str = argv[2]; 1851fbe4564SMatthias Ringwald printf("Specified USB Path: "); 1861fbe4564SMatthias Ringwald while (1){ 1871fbe4564SMatthias Ringwald char * delimiter; 1881fbe4564SMatthias Ringwald int port = strtol(port_str, &delimiter, 16); 1891fbe4564SMatthias Ringwald usb_path[usb_path_len] = port; 1901fbe4564SMatthias Ringwald usb_path_len++; 1911fbe4564SMatthias Ringwald printf("%02x ", port); 1921fbe4564SMatthias Ringwald if (!delimiter) break; 1931fbe4564SMatthias Ringwald if (*delimiter != ':' && *delimiter != '-') break; 1941fbe4564SMatthias Ringwald port_str = delimiter+1; 1951fbe4564SMatthias Ringwald } 1961fbe4564SMatthias Ringwald printf("\n"); 1971fbe4564SMatthias Ringwald argc -= 2; 1981fbe4564SMatthias Ringwald memmove(&argv[0], &argv[2], argc * sizeof(char *)); 1991fbe4564SMatthias Ringwald 2001fbe4564SMatthias Ringwald // base logger output file on usb path 2011fbe4564SMatthias Ringwald if (usb_path_len){ 2021fbe4564SMatthias Ringwald strcat(log_path, "_"); 2031fbe4564SMatthias Ringwald strcat(log_path, argv[2]); 2041fbe4564SMatthias Ringwald } 2051fbe4564SMatthias Ringwald } 2061fbe4564SMatthias Ringwald 2071fbe4564SMatthias Ringwald // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT 2081fbe4564SMatthias Ringwald strcat(log_path, ".pklg"); 209*31437b52SMatthias Ringwald // log into file using HCI_DUMP_PACKETLOGGER format 210*31437b52SMatthias Ringwald hci_dump_posix_fs_open(log_path, HCI_DUMP_PACKETLOGGER); 211*31437b52SMatthias Ringwald hci_dump_init(hci_dump_posix_fs_get_instance()); 2121fbe4564SMatthias Ringwald printf("Packet Log: %s\n", log_path); 2131fbe4564SMatthias Ringwald 2141fbe4564SMatthias Ringwald // init HCI 2151fbe4564SMatthias Ringwald const hci_transport_t * transport; 2161fbe4564SMatthias Ringwald if (config.device_name){ 2171fbe4564SMatthias Ringwald // PTY 218f8da99a8SMatthias Ringwald const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); 219f8da99a8SMatthias Ringwald transport = hci_transport_h4_instance_for_uart(uart_driver); 2201fbe4564SMatthias Ringwald } else { 2211fbe4564SMatthias Ringwald // libusb 2221fbe4564SMatthias Ringwald if (usb_path_len){ 2231fbe4564SMatthias Ringwald hci_transport_usb_set_path(usb_path_len, usb_path); 2241fbe4564SMatthias Ringwald } 2251fbe4564SMatthias Ringwald transport = hci_transport_usb_instance(); 2261fbe4564SMatthias Ringwald } 2271fbe4564SMatthias Ringwald hci_init(transport, (void*) &config); 2281fbe4564SMatthias Ringwald 2291fbe4564SMatthias Ringwald // inform about BTstack state 2301fbe4564SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 2311fbe4564SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 2321fbe4564SMatthias Ringwald 2331fbe4564SMatthias Ringwald // handle CTRL-c 2341fbe4564SMatthias Ringwald signal(SIGINT, sigint_handler); 2351fbe4564SMatthias Ringwald 2361fbe4564SMatthias Ringwald // setup app 2371fbe4564SMatthias Ringwald btstack_main(argc, argv); 2381fbe4564SMatthias Ringwald 2391fbe4564SMatthias Ringwald // go 2401fbe4564SMatthias Ringwald btstack_run_loop_execute(); 2411fbe4564SMatthias Ringwald 2421fbe4564SMatthias Ringwald return 0; 2431fbe4564SMatthias Ringwald } 244