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 } 204 205 static int led_state = 0; 206 void hal_led_toggle(void){ 207 led_state = 1 - led_state; 208 printf("LED State %u\n", led_state); 209 } 210 static void use_fast_uart(void){ 211 printf("Using 921600 baud.\n"); 212 config.baudrate_main = 921600; 213 } 214 215 static void local_version_information_handler(uint8_t * packet){ 216 printf("Local version information:\n"); 217 uint16_t hci_version = packet[6]; 218 uint16_t hci_revision = little_endian_read_16(packet, 7); 219 uint16_t lmp_version = packet[9]; 220 uint16_t manufacturer = little_endian_read_16(packet, 10); 221 uint16_t lmp_subversion = little_endian_read_16(packet, 12); 222 printf("- HCI Version 0x%04x\n", hci_version); 223 printf("- HCI Revision 0x%04x\n", hci_revision); 224 printf("- LMP Version 0x%04x\n", lmp_version); 225 printf("- LMP Subversion 0x%04x\n", lmp_subversion); 226 printf("- Manufacturer 0x%04x\n", manufacturer); 227 switch (manufacturer){ 228 case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: 229 printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); 230 use_fast_uart(); 231 hci_set_chipset(btstack_chipset_csr_instance()); 232 break; 233 case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: 234 printf("Texas Instruments - CC256x compatible chipset.\n"); 235 if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ 236 printf("Error: LMP Subversion does not match initscript! "); 237 printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); 238 printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n"); 239 exit(10); 240 } 241 use_fast_uart(); 242 hci_set_chipset(btstack_chipset_cc256x_instance()); 243 #ifdef ENABLE_EHCILL 244 printf("eHCILL enabled.\n"); 245 #else 246 printf("eHCILL disable.\n"); 247 #endif 248 249 break; 250 case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: 251 printf("Broadcom/Cypress - using BCM driver.\n"); 252 hci_set_chipset(btstack_chipset_bcm_instance()); 253 use_fast_uart(); 254 is_bcm = 1; 255 break; 256 case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS: 257 printf("ST Microelectronics - using STLC2500d driver.\n"); 258 use_fast_uart(); 259 hci_set_chipset(btstack_chipset_stlc2500d_instance()); 260 break; 261 case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA: 262 printf("EM Microelectronics - using EM9301 driver.\n"); 263 hci_set_chipset(btstack_chipset_em9301_instance()); 264 use_fast_uart(); 265 break; 266 case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA: 267 printf("Nordic Semiconductor nRF5 chipset.\n"); 268 hci_set_chipset(btstack_chipset_zephyr_instance()); 269 break; 270 case BLUETOOTH_COMPANY_ID_THE_LINUX_FOUNDATION: 271 printf("Linux Foundation - assuming Zephyr running on Nordic chipset.\n"); 272 hci_set_chipset(btstack_chipset_zephyr_instance()); 273 break; 274 case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP: 275 printf("Toshiba - using TC3566x driver.\n"); 276 hci_set_chipset(btstack_chipset_tc3566x_instance()); 277 use_fast_uart(); 278 break; 279 case BLUETOOTH_COMPANY_ID_PACKETCRAFT_INC: 280 printf("PacketCraft HCI Controller\n"); 281 hci_set_chipset(btstack_chipset_zephyr_instance()); 282 break; 283 default: 284 printf("Unknown manufacturer / manufacturer not supported yet.\n"); 285 break; 286 } 287 } 288 289 static char short_options[] = "hu:l:rb:"; 290 291 static struct option long_options[] = { 292 {"help", no_argument, NULL, 'h'}, 293 {"logfile", required_argument, NULL, 'l'}, 294 {"reset-tlv", no_argument, NULL, 'r'}, 295 {"tty", required_argument, NULL, 'u'}, 296 {"bd-addr", required_argument, NULL, 'b'}, 297 {0, 0, 0, 0} 298 }; 299 300 static char *help_options[] = { 301 "print (this) help.", 302 "set file to store debug output and HCI trace.", 303 "reset bonding information stored in TLV.", 304 "set path to Bluetooth Controller.", 305 "set random static Bluetooth address for nRF5340 with PacketCraft Controller.", 306 }; 307 308 static char *option_arg_name[] = { 309 "", 310 "LOGFILE", 311 "", 312 "TTY", 313 "BD_ADDR", 314 }; 315 316 static void usage(const char *name){ 317 unsigned int i; 318 printf( "usage:\n\t%s [options]\n", name ); 319 printf("valid options:\n"); 320 for( i=0; long_options[i].name != 0; i++) { 321 printf("--%-10s| -%c %-10s\t\t%s\n", long_options[i].name, long_options[i].val, option_arg_name[i], help_options[i] ); 322 } 323 } 324 325 int main(int argc, const char * argv[]){ 326 327 const char * log_file_path = NULL; 328 329 // set default device path 330 config.device_name = "/dev/tty.usbmodemEF437DF524C51"; 331 332 // parse command line parameters 333 while(true){ 334 int c = getopt_long( argc, (char* const *)argv, short_options, long_options, NULL ); 335 if (c < 0) { 336 break; 337 } 338 if (c == '?'){ 339 break; 340 } 341 switch (c) { 342 case 'u': 343 config.device_name = optarg; 344 break; 345 case 'l': 346 log_file_path = optarg; 347 break; 348 case 'r': 349 tlv_reset = true; 350 break; 351 case 'b': 352 sscanf_bd_addr(optarg, random_address); 353 break; 354 case 'h': 355 default: 356 usage(argv[0]); 357 return EXIT_FAILURE; 358 } 359 } 360 /// GET STARTED with BTstack /// 361 btstack_memory_init(); 362 btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 363 364 // log into file using HCI_DUMP_PACKETLOGGER format 365 if (log_file_path == NULL){ 366 log_file_path = "/tmp/hci_dump.pklg"; 367 } 368 hci_dump_posix_fs_open(log_file_path, HCI_DUMP_PACKETLOGGER); 369 const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); 370 hci_dump_init(hci_dump_impl); 371 printf("Packet Log: %s\n", log_file_path); 372 373 printf("H4 device: %s\n", config.device_name); 374 375 // init HCI 376 const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); 377 const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); 378 hci_init(transport, (void*) &config); 379 380 #ifdef HAVE_PORTAUDIO 381 btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance()); 382 btstack_audio_source_set_instance(btstack_audio_portaudio_source_get_instance()); 383 #endif 384 385 // set BD_ADDR for CSR without Flash/unique address 386 // bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; 387 // btstack_chipset_csr_set_bd_addr(own_address); 388 389 // inform about BTstack state 390 hci_event_callback_registration.callback = &packet_handler; 391 hci_add_event_handler(&hci_event_callback_registration); 392 393 // register callback for CTRL-c 394 btstack_signal_register_callback(SIGINT, &trigger_shutdown); 395 396 // setup app 397 btstack_main(argc, argv); 398 399 // go 400 btstack_run_loop_execute(); 401 402 return 0; 403 } 404