1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "main.c" 39 40 // ***************************************************************************** 41 // 42 // minimal setup for HCI code 43 // 44 // ***************************************************************************** 45 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <signal.h> 51 #include <unistd.h> 52 #include <getopt.h> 53 54 #include "btstack_config.h" 55 56 #include "ble/le_device_db_tlv.h" 57 #include "bluetooth_company_id.h" 58 #include "btstack_audio.h" 59 #include "btstack_chipset_bcm.h" 60 #include "btstack_chipset_cc256x.h" 61 #include "btstack_chipset_csr.h" 62 #include "btstack_chipset_em9301.h" 63 #include "btstack_chipset_stlc2500d.h" 64 #include "btstack_chipset_tc3566x.h" 65 #include "btstack_chipset_zephyr.h" 66 #include "btstack_debug.h" 67 #include "btstack_event.h" 68 #include "btstack_memory.h" 69 #include "btstack_run_loop.h" 70 #include "btstack_run_loop_posix.h" 71 #include "btstack_signal.h" 72 #include "btstack_stdin.h" 73 #include "btstack_tlv_posix.h" 74 #include "btstack_uart.h" 75 #include "classic/btstack_link_key_db_tlv.h" 76 #include "hci.h" 77 #include "hci_dump.h" 78 #include "hci_dump_posix_fs.h" 79 #include "hci_transport.h" 80 #include "hci_transport_h4.h" 81 82 83 #define TLV_DB_PATH_PREFIX "/tmp/btstack_" 84 #define TLV_DB_PATH_POSTFIX ".tlv" 85 static char tlv_db_path[100]; 86 static bool tlv_reset; 87 static const btstack_tlv_t * tlv_impl; 88 static btstack_tlv_posix_t tlv_context; 89 static bd_addr_t static_address; 90 91 // random MAC address for the device, used if nothing else is available 92 static bd_addr_t random_address = { 0xC1, 0x01, 0x01, 0x01, 0x01, 0x01 }; 93 94 static int is_bcm; 95 // shutdown 96 static bool shutdown_triggered; 97 98 int btstack_main(int argc, const char * argv[]); 99 static void local_version_information_handler(uint8_t * packet); 100 101 static hci_transport_config_uart_t config = { 102 HCI_TRANSPORT_CONFIG_UART, 103 115200, 104 0, // main baudrate 105 1, // flow control 106 NULL, 107 }; 108 109 static btstack_packet_callback_registration_t hci_event_callback_registration; 110 111 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 112 static bd_addr_t local_addr; 113 const uint8_t *params; 114 if (packet_type != HCI_EVENT_PACKET) return; 115 switch (hci_event_packet_get_type(packet)){ 116 case BTSTACK_EVENT_STATE: 117 switch(btstack_event_state_get_state(packet)){ 118 case HCI_STATE_WORKING: 119 gap_local_bd_addr(local_addr); 120 if( btstack_is_null_bd_addr(local_addr) && !btstack_is_null_bd_addr(static_address) ) { 121 memcpy(local_addr, static_address, sizeof(bd_addr_t)); 122 } else if( btstack_is_null_bd_addr(local_addr) && btstack_is_null_bd_addr(static_address) ) { 123 memcpy(local_addr, random_address, sizeof(bd_addr_t)); 124 gap_random_address_set(local_addr); 125 } 126 127 printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); 128 btstack_strcpy(tlv_db_path, sizeof(tlv_db_path), TLV_DB_PATH_PREFIX); 129 btstack_strcat(tlv_db_path, sizeof(tlv_db_path), bd_addr_to_str_with_delimiter(local_addr, '-')); 130 btstack_strcat(tlv_db_path, sizeof(tlv_db_path), TLV_DB_PATH_POSTFIX); 131 printf("TLV path: %s", tlv_db_path); 132 if (tlv_reset){ 133 int rc = unlink(tlv_db_path); 134 if (rc == 0) { 135 printf(", reset ok"); 136 } else { 137 printf(", reset failed with result = %d", rc); 138 } 139 } 140 printf("\n"); 141 tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); 142 btstack_tlv_set_instance(tlv_impl, &tlv_context); 143 #ifdef ENABLE_CLASSIC 144 hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); 145 #endif 146 #ifdef ENABLE_BLE 147 le_device_db_tlv_configure(tlv_impl, &tlv_context); 148 #endif 149 break; 150 case HCI_STATE_OFF: 151 btstack_tlv_posix_deinit(&tlv_context); 152 if (!shutdown_triggered) break; 153 // reset stdin 154 btstack_stdin_reset(); 155 log_info("Good bye, see you.\n"); 156 exit(0); 157 break; 158 default: 159 break; 160 } 161 break; 162 case HCI_EVENT_COMMAND_COMPLETE: 163 switch (hci_event_command_complete_get_command_opcode(packet)){ 164 case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: 165 local_version_information_handler(packet); 166 break; 167 case HCI_OPCODE_HCI_ZEPHYR_READ_STATIC_ADDRESS: 168 log_info("Zephyr read static address available"); 169 params = hci_event_command_complete_get_return_parameters(packet); 170 if(params[0] != 0) 171 break; 172 if(size < 13) 173 break; 174 reverse_48(¶ms[2], static_address); 175 gap_random_address_set(static_address); 176 break; 177 case HCI_OPCODE_HCI_READ_LOCAL_NAME: 178 params = hci_event_command_complete_get_return_parameters(packet); 179 if(params[0] != 0) 180 break; 181 // terminate, name 248 chars 182 packet[6+248] = 0; 183 printf("Local name: %s\n", &packet[6]); 184 if (is_bcm){ 185 btstack_chipset_bcm_set_device_name((const char *)&packet[6]); 186 } 187 break; 188 default: 189 break; 190 } 191 break; 192 193 default: 194 break; 195 } 196 } 197 198 static void trigger_shutdown(void){ 199 printf("CTRL-C - SIGINT received, shutting down..\n"); 200 log_info("sigint_handler: shutting down"); 201 shutdown_triggered = true; 202 hci_power_control(HCI_POWER_OFF); 203 btstack_stdin_reset(); 204 } 205 206 static int led_state = 0; 207 void hal_led_toggle(void){ 208 led_state = 1 - led_state; 209 printf("LED State %u\n", led_state); 210 } 211 static void use_fast_uart(void){ 212 printf("Using 921600 baud.\n"); 213 config.baudrate_main = 921600; 214 } 215 216 static void local_version_information_handler(uint8_t * packet){ 217 printf("Local version information:\n"); 218 uint16_t hci_version = packet[6]; 219 uint16_t hci_revision = little_endian_read_16(packet, 7); 220 uint16_t lmp_version = packet[9]; 221 uint16_t manufacturer = little_endian_read_16(packet, 10); 222 uint16_t lmp_subversion = little_endian_read_16(packet, 12); 223 printf("- HCI Version 0x%04x\n", hci_version); 224 printf("- HCI Revision 0x%04x\n", hci_revision); 225 printf("- LMP Version 0x%04x\n", lmp_version); 226 printf("- LMP Subversion 0x%04x\n", lmp_subversion); 227 printf("- Manufacturer 0x%04x\n", manufacturer); 228 switch (manufacturer){ 229 case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: 230 printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); 231 use_fast_uart(); 232 hci_set_chipset(btstack_chipset_csr_instance()); 233 break; 234 case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: 235 printf("Texas Instruments - CC256x compatible chipset.\n"); 236 if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ 237 printf("Error: LMP Subversion does not match initscript! "); 238 printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); 239 printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n"); 240 exit(10); 241 } 242 use_fast_uart(); 243 hci_set_chipset(btstack_chipset_cc256x_instance()); 244 #ifdef ENABLE_EHCILL 245 printf("eHCILL enabled.\n"); 246 #else 247 printf("eHCILL disable.\n"); 248 #endif 249 250 break; 251 case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: 252 printf("Broadcom/Cypress - using BCM driver.\n"); 253 hci_set_chipset(btstack_chipset_bcm_instance()); 254 use_fast_uart(); 255 is_bcm = 1; 256 break; 257 case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS: 258 printf("ST Microelectronics - using STLC2500d driver.\n"); 259 use_fast_uart(); 260 hci_set_chipset(btstack_chipset_stlc2500d_instance()); 261 break; 262 case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA: 263 printf("EM Microelectronics - using EM9301 driver.\n"); 264 hci_set_chipset(btstack_chipset_em9301_instance()); 265 use_fast_uart(); 266 break; 267 case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA: 268 printf("Nordic Semiconductor nRF5 chipset.\n"); 269 hci_set_chipset(btstack_chipset_zephyr_instance()); 270 break; 271 case BLUETOOTH_COMPANY_ID_THE_LINUX_FOUNDATION: 272 printf("Linux Foundation - assuming Zephyr running on Nordic chipset.\n"); 273 hci_set_chipset(btstack_chipset_zephyr_instance()); 274 break; 275 case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP: 276 printf("Toshiba - using TC3566x driver.\n"); 277 hci_set_chipset(btstack_chipset_tc3566x_instance()); 278 use_fast_uart(); 279 break; 280 case BLUETOOTH_COMPANY_ID_PACKETCRAFT_INC: 281 printf("PacketCraft HCI Controller\n"); 282 hci_set_chipset(btstack_chipset_zephyr_instance()); 283 break; 284 default: 285 printf("Unknown manufacturer / manufacturer not supported yet.\n"); 286 break; 287 } 288 } 289 290 static char short_options[] = "hu:l:rb:"; 291 292 static struct option long_options[] = { 293 {"help", no_argument, NULL, 'h'}, 294 {"logfile", required_argument, NULL, 'l'}, 295 {"reset-tlv", no_argument, NULL, 'r'}, 296 {"tty", required_argument, NULL, 'u'}, 297 {"bd-addr", required_argument, NULL, 'b'}, 298 {0, 0, 0, 0} 299 }; 300 301 static char *help_options[] = { 302 "print (this) help.", 303 "set file to store debug output and HCI trace.", 304 "reset bonding information stored in TLV.", 305 "set path to Bluetooth Controller.", 306 "set random static Bluetooth address for nRF5340 with PacketCraft Controller.", 307 }; 308 309 static char *option_arg_name[] = { 310 "", 311 "LOGFILE", 312 "", 313 "TTY", 314 "BD_ADDR", 315 }; 316 317 static void usage(const char *name){ 318 unsigned int i; 319 printf( "usage:\n\t%s [options]\n", name ); 320 printf("valid options:\n"); 321 for( i=0; long_options[i].name != 0; i++) { 322 printf("--%-10s| -%c %-10s\t\t%s\n", long_options[i].name, long_options[i].val, option_arg_name[i], help_options[i] ); 323 } 324 } 325 326 int main(int argc, const char * argv[]){ 327 328 const char * log_file_path = NULL; 329 330 // set default device path 331 config.device_name = "/dev/tty.usbmodemEF437DF524C51"; 332 333 // parse command line parameters 334 while(true){ 335 int c = getopt_long( argc, (char* const *)argv, short_options, long_options, NULL ); 336 if (c < 0) { 337 break; 338 } 339 if (c == '?'){ 340 break; 341 } 342 switch (c) { 343 case 'u': 344 config.device_name = optarg; 345 break; 346 case 'l': 347 log_file_path = optarg; 348 break; 349 case 'r': 350 tlv_reset = true; 351 break; 352 case 'b': 353 sscanf_bd_addr(optarg, random_address); 354 break; 355 case 'h': 356 default: 357 usage(argv[0]); 358 return EXIT_FAILURE; 359 } 360 } 361 /// GET STARTED with BTstack /// 362 btstack_memory_init(); 363 btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 364 365 // log into file using HCI_DUMP_PACKETLOGGER format 366 if (log_file_path == NULL){ 367 log_file_path = "/tmp/hci_dump.pklg"; 368 } 369 hci_dump_posix_fs_open(log_file_path, HCI_DUMP_PACKETLOGGER); 370 const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); 371 hci_dump_init(hci_dump_impl); 372 printf("Packet Log: %s\n", log_file_path); 373 374 printf("H4 device: %s\n", config.device_name); 375 376 // init HCI 377 const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); 378 const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); 379 hci_init(transport, (void*) &config); 380 381 #ifdef HAVE_PORTAUDIO 382 btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance()); 383 btstack_audio_source_set_instance(btstack_audio_portaudio_source_get_instance()); 384 #endif 385 386 // set BD_ADDR for CSR without Flash/unique address 387 // bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; 388 // btstack_chipset_csr_set_bd_addr(own_address); 389 390 // inform about BTstack state 391 hci_event_callback_registration.callback = &packet_handler; 392 hci_add_event_handler(&hci_event_callback_registration); 393 394 // register callback for CTRL-c 395 btstack_signal_register_callback(SIGINT, &trigger_shutdown); 396 397 // setup app 398 btstack_main(argc, argv); 399 400 // go 401 btstack_run_loop_execute(); 402 403 btstack_stdin_reset(); 404 return 0; 405 } 406