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__ "main.c" 39*1fbe4564SMatthias Ringwald 40*1fbe4564SMatthias Ringwald // ***************************************************************************** 41*1fbe4564SMatthias Ringwald // 42*1fbe4564SMatthias Ringwald // minimal setup for HCI code 43*1fbe4564SMatthias Ringwald // 44*1fbe4564SMatthias Ringwald // ***************************************************************************** 45*1fbe4564SMatthias Ringwald 46*1fbe4564SMatthias Ringwald #include <stdint.h> 47*1fbe4564SMatthias Ringwald #include <stdio.h> 48*1fbe4564SMatthias Ringwald #include <stdlib.h> 49*1fbe4564SMatthias Ringwald #include <string.h> 50*1fbe4564SMatthias Ringwald #include <signal.h> 51*1fbe4564SMatthias Ringwald 52*1fbe4564SMatthias Ringwald #include "btstack_config.h" 53*1fbe4564SMatthias Ringwald 54*1fbe4564SMatthias Ringwald #include "btstack_debug.h" 55*1fbe4564SMatthias Ringwald #include "btstack_event.h" 56*1fbe4564SMatthias Ringwald #include "btstack_link_key_db_fs.h" 57*1fbe4564SMatthias Ringwald #include "btstack_memory.h" 58*1fbe4564SMatthias Ringwald #include "btstack_run_loop.h" 59*1fbe4564SMatthias Ringwald #include "btstack_run_loop_posix.h" 60*1fbe4564SMatthias Ringwald #include "bluetooth_company_id.h" 61*1fbe4564SMatthias Ringwald #include "hci.h" 62*1fbe4564SMatthias Ringwald #include "hci_dump.h" 63*1fbe4564SMatthias Ringwald #include "btstack_stdin.h" 64*1fbe4564SMatthias Ringwald #include "btstack_tlv.h" 65*1fbe4564SMatthias Ringwald #include "btstack_tlv_posix.h" 66*1fbe4564SMatthias Ringwald 67*1fbe4564SMatthias Ringwald int is_bcm; 68*1fbe4564SMatthias Ringwald 69*1fbe4564SMatthias Ringwald #define TLV_DB_PATH_PREFIX "/tmp/btstack_" 70*1fbe4564SMatthias Ringwald #define TLV_DB_PATH_POSTFIX ".tlv" 71*1fbe4564SMatthias Ringwald static char tlv_db_path[100]; 72*1fbe4564SMatthias Ringwald static const btstack_tlv_t * tlv_impl; 73*1fbe4564SMatthias Ringwald static btstack_tlv_posix_t tlv_context; 74*1fbe4564SMatthias Ringwald static bd_addr_t local_addr; 75*1fbe4564SMatthias Ringwald 76*1fbe4564SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 77*1fbe4564SMatthias Ringwald static void local_version_information_handler(uint8_t * packet); 78*1fbe4564SMatthias Ringwald 79*1fbe4564SMatthias Ringwald static hci_transport_config_uart_t config = { 80*1fbe4564SMatthias Ringwald HCI_TRANSPORT_CONFIG_UART, 81*1fbe4564SMatthias Ringwald 115200, 82*1fbe4564SMatthias Ringwald 0, // main baudrate 83*1fbe4564SMatthias Ringwald 0, // flow control 84*1fbe4564SMatthias Ringwald NULL, 85*1fbe4564SMatthias Ringwald }; 86*1fbe4564SMatthias Ringwald 87*1fbe4564SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 88*1fbe4564SMatthias Ringwald 89*1fbe4564SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 90*1fbe4564SMatthias Ringwald bd_addr_t addr; 91*1fbe4564SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 92*1fbe4564SMatthias Ringwald switch (hci_event_packet_get_type(packet)){ 93*1fbe4564SMatthias Ringwald case BTSTACK_EVENT_STATE: 94*1fbe4564SMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 95*1fbe4564SMatthias Ringwald gap_local_bd_addr(local_addr); 96*1fbe4564SMatthias Ringwald printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); 97*1fbe4564SMatthias Ringwald strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); 98*1fbe4564SMatthias Ringwald strcat(tlv_db_path, bd_addr_to_str(local_addr)); 99*1fbe4564SMatthias Ringwald strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); 100*1fbe4564SMatthias Ringwald tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); 101*1fbe4564SMatthias Ringwald btstack_tlv_set_instance(tlv_impl, &tlv_context); 102*1fbe4564SMatthias Ringwald break; 103*1fbe4564SMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 104*1fbe4564SMatthias Ringwald if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ 105*1fbe4564SMatthias Ringwald local_version_information_handler(packet); 106*1fbe4564SMatthias Ringwald } 107*1fbe4564SMatthias Ringwald break; 108*1fbe4564SMatthias Ringwald default: 109*1fbe4564SMatthias Ringwald break; 110*1fbe4564SMatthias Ringwald } 111*1fbe4564SMatthias Ringwald } 112*1fbe4564SMatthias Ringwald 113*1fbe4564SMatthias Ringwald static void sigint_handler(int param){ 114*1fbe4564SMatthias Ringwald UNUSED(param); 115*1fbe4564SMatthias Ringwald 116*1fbe4564SMatthias Ringwald printf("CTRL-C - SIGINT received, shutting down..\n"); 117*1fbe4564SMatthias Ringwald log_info("sigint_handler: shutting down"); 118*1fbe4564SMatthias Ringwald 119*1fbe4564SMatthias Ringwald // reset anyway 120*1fbe4564SMatthias Ringwald btstack_stdin_reset(); 121*1fbe4564SMatthias Ringwald 122*1fbe4564SMatthias Ringwald // power down 123*1fbe4564SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 124*1fbe4564SMatthias Ringwald hci_close(); 125*1fbe4564SMatthias Ringwald log_info("Good bye, see you.\n"); 126*1fbe4564SMatthias Ringwald exit(0); 127*1fbe4564SMatthias Ringwald } 128*1fbe4564SMatthias Ringwald 129*1fbe4564SMatthias Ringwald static int led_state = 0; 130*1fbe4564SMatthias Ringwald void hal_led_toggle(void){ 131*1fbe4564SMatthias Ringwald led_state = 1 - led_state; 132*1fbe4564SMatthias Ringwald printf("LED State %u\n", led_state); 133*1fbe4564SMatthias Ringwald } 134*1fbe4564SMatthias Ringwald 135*1fbe4564SMatthias Ringwald static void local_version_information_handler(uint8_t * packet){ 136*1fbe4564SMatthias Ringwald printf("Local version information:\n"); 137*1fbe4564SMatthias Ringwald uint16_t hci_version = packet[6]; 138*1fbe4564SMatthias Ringwald uint16_t hci_revision = little_endian_read_16(packet, 7); 139*1fbe4564SMatthias Ringwald uint16_t lmp_version = packet[9]; 140*1fbe4564SMatthias Ringwald uint16_t manufacturer = little_endian_read_16(packet, 10); 141*1fbe4564SMatthias Ringwald uint16_t lmp_subversion = little_endian_read_16(packet, 12); 142*1fbe4564SMatthias Ringwald printf("- HCI Version 0x%04x\n", hci_version); 143*1fbe4564SMatthias Ringwald printf("- HCI Revision 0x%04x\n", hci_revision); 144*1fbe4564SMatthias Ringwald printf("- LMP Version 0x%04x\n", lmp_version); 145*1fbe4564SMatthias Ringwald printf("- LMP Subversion 0x%04x\n", lmp_subversion); 146*1fbe4564SMatthias Ringwald printf("- Manufacturer 0x%04x\n", manufacturer); 147*1fbe4564SMatthias Ringwald } 148*1fbe4564SMatthias Ringwald 149*1fbe4564SMatthias Ringwald #define USB_MAX_PATH_LEN 7 150*1fbe4564SMatthias Ringwald int main(int argc, const char * argv[]){ 151*1fbe4564SMatthias Ringwald 152*1fbe4564SMatthias Ringwald /// GET STARTED with BTstack /// 153*1fbe4564SMatthias Ringwald btstack_memory_init(); 154*1fbe4564SMatthias Ringwald btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 155*1fbe4564SMatthias Ringwald 156*1fbe4564SMatthias Ringwald char log_path[100]; 157*1fbe4564SMatthias Ringwald strcpy(log_path, "/tmp/hci_dump"); 158*1fbe4564SMatthias Ringwald 159*1fbe4564SMatthias Ringwald // check for -d pty path 160*1fbe4564SMatthias Ringwald if (argc >= 3 && strcmp(argv[1], "-d") == 0){ 161*1fbe4564SMatthias Ringwald config.device_name = argv[2]; 162*1fbe4564SMatthias Ringwald argc -= 2; 163*1fbe4564SMatthias Ringwald memmove(&argv[0], &argv[2], argc * sizeof(char *)); 164*1fbe4564SMatthias Ringwald 165*1fbe4564SMatthias Ringwald printf("Specified PTY: %s\n", config.device_name); 166*1fbe4564SMatthias Ringwald 167*1fbe4564SMatthias Ringwald // base logger output file on device_name 168*1fbe4564SMatthias Ringwald const char * src = config.device_name; 169*1fbe4564SMatthias Ringwald char * dst = &log_path[strlen(log_path)]; 170*1fbe4564SMatthias Ringwald while (*src){ 171*1fbe4564SMatthias Ringwald if (*src == '/'){ 172*1fbe4564SMatthias Ringwald *dst++ = '_'; 173*1fbe4564SMatthias Ringwald } else { 174*1fbe4564SMatthias Ringwald *dst++ = *src; 175*1fbe4564SMatthias Ringwald } 176*1fbe4564SMatthias Ringwald src++; 177*1fbe4564SMatthias Ringwald } 178*1fbe4564SMatthias Ringwald *dst = 0; 179*1fbe4564SMatthias Ringwald } 180*1fbe4564SMatthias Ringwald 181*1fbe4564SMatthias Ringwald // check for -u usb path 182*1fbe4564SMatthias Ringwald uint8_t usb_path[USB_MAX_PATH_LEN]; 183*1fbe4564SMatthias Ringwald int usb_path_len = 0; 184*1fbe4564SMatthias Ringwald if (argc >= 3 && strcmp(argv[1], "-u") == 0){ 185*1fbe4564SMatthias Ringwald // parse command line options for "-u 11:22:33" 186*1fbe4564SMatthias Ringwald const char * port_str = argv[2]; 187*1fbe4564SMatthias Ringwald printf("Specified USB Path: "); 188*1fbe4564SMatthias Ringwald while (1){ 189*1fbe4564SMatthias Ringwald char * delimiter; 190*1fbe4564SMatthias Ringwald int port = strtol(port_str, &delimiter, 16); 191*1fbe4564SMatthias Ringwald usb_path[usb_path_len] = port; 192*1fbe4564SMatthias Ringwald usb_path_len++; 193*1fbe4564SMatthias Ringwald printf("%02x ", port); 194*1fbe4564SMatthias Ringwald if (!delimiter) break; 195*1fbe4564SMatthias Ringwald if (*delimiter != ':' && *delimiter != '-') break; 196*1fbe4564SMatthias Ringwald port_str = delimiter+1; 197*1fbe4564SMatthias Ringwald } 198*1fbe4564SMatthias Ringwald printf("\n"); 199*1fbe4564SMatthias Ringwald argc -= 2; 200*1fbe4564SMatthias Ringwald memmove(&argv[0], &argv[2], argc * sizeof(char *)); 201*1fbe4564SMatthias Ringwald 202*1fbe4564SMatthias Ringwald // base logger output file on usb path 203*1fbe4564SMatthias Ringwald if (usb_path_len){ 204*1fbe4564SMatthias Ringwald strcat(log_path, "_"); 205*1fbe4564SMatthias Ringwald strcat(log_path, argv[2]); 206*1fbe4564SMatthias Ringwald } 207*1fbe4564SMatthias Ringwald } 208*1fbe4564SMatthias Ringwald 209*1fbe4564SMatthias Ringwald // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT 210*1fbe4564SMatthias Ringwald strcat(log_path, ".pklg"); 211*1fbe4564SMatthias Ringwald printf("Packet Log: %s\n", log_path); 212*1fbe4564SMatthias Ringwald hci_dump_open(log_path, HCI_DUMP_PACKETLOGGER); 213*1fbe4564SMatthias Ringwald 214*1fbe4564SMatthias Ringwald // init HCI 215*1fbe4564SMatthias Ringwald const hci_transport_t * transport; 216*1fbe4564SMatthias Ringwald if (config.device_name){ 217*1fbe4564SMatthias Ringwald // PTY 218*1fbe4564SMatthias Ringwald const btstack_uart_block_t * uart_driver = btstack_uart_block_posix_instance(); 219*1fbe4564SMatthias Ringwald transport = hci_transport_h4_instance(uart_driver); 220*1fbe4564SMatthias Ringwald } else { 221*1fbe4564SMatthias Ringwald // libusb 222*1fbe4564SMatthias Ringwald if (usb_path_len){ 223*1fbe4564SMatthias Ringwald hci_transport_usb_set_path(usb_path_len, usb_path); 224*1fbe4564SMatthias Ringwald } 225*1fbe4564SMatthias Ringwald transport = hci_transport_usb_instance(); 226*1fbe4564SMatthias Ringwald } 227*1fbe4564SMatthias Ringwald hci_init(transport, (void*) &config); 228*1fbe4564SMatthias Ringwald 229*1fbe4564SMatthias Ringwald // inform about BTstack state 230*1fbe4564SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 231*1fbe4564SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 232*1fbe4564SMatthias Ringwald 233*1fbe4564SMatthias Ringwald // handle CTRL-c 234*1fbe4564SMatthias Ringwald signal(SIGINT, sigint_handler); 235*1fbe4564SMatthias Ringwald 236*1fbe4564SMatthias Ringwald // setup app 237*1fbe4564SMatthias Ringwald btstack_main(argc, argv); 238*1fbe4564SMatthias Ringwald 239*1fbe4564SMatthias Ringwald // go 240*1fbe4564SMatthias Ringwald btstack_run_loop_execute(); 241*1fbe4564SMatthias Ringwald 242*1fbe4564SMatthias Ringwald return 0; 243*1fbe4564SMatthias Ringwald } 244