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 break; 269 case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP: 270 printf("Toshiba - using TC3566x driver.\n"); 271 hci_set_chipset(btstack_chipset_tc3566x_instance()); 272 use_fast_uart(); 273 break; 274 case BLUETOOTH_COMPANY_ID_PACKETCRAFT_INC: 275 printf("PacketCraft HCI Controller\n"); 276 hci_set_chipset(btstack_chipset_zephyr_instance()); 277 break; 278 default: 279 printf("Unknown manufacturer / manufacturer not supported yet.\n"); 280 break; 281 } 282 } 283 284 static char short_options[] = "hu:l:rb:"; 285 286 static struct option long_options[] = { 287 {"help", no_argument, NULL, 'h'}, 288 {"logfile", required_argument, NULL, 'l'}, 289 {"reset-tlv", no_argument, NULL, 'r'}, 290 {"tty", required_argument, NULL, 'u'}, 291 {"bd-addr", required_argument, NULL, 'b'}, 292 {0, 0, 0, 0} 293 }; 294 295 static char *help_options[] = { 296 "print (this) help.", 297 "set file to store debug output and HCI trace.", 298 "reset bonding information stored in TLV.", 299 "set path to Bluetooth Controller.", 300 "set random static Bluetooth address for nRF5340 with PacketCraft Controller.", 301 }; 302 303 static char *option_arg_name[] = { 304 "", 305 "LOGFILE", 306 "", 307 "TTY", 308 "BD_ADDR", 309 }; 310 311 static void usage(const char *name){ 312 unsigned int i; 313 printf( "usage:\n\t%s [options]\n", name ); 314 printf("valid options:\n"); 315 for( i=0; long_options[i].name != 0; i++) { 316 printf("--%-10s| -%c %-10s\t\t%s\n", long_options[i].name, long_options[i].val, option_arg_name[i], help_options[i] ); 317 } 318 } 319 320 int main(int argc, const char * argv[]){ 321 322 const char * log_file_path = NULL; 323 324 // set default device path 325 config.device_name = "/dev/tty.usbmodemEF437DF524C51"; 326 327 // parse command line parameters 328 while(true){ 329 int c = getopt_long( argc, (char* const *)argv, short_options, long_options, NULL ); 330 if (c < 0) { 331 break; 332 } 333 if (c == '?'){ 334 break; 335 } 336 switch (c) { 337 case 'u': 338 config.device_name = optarg; 339 break; 340 case 'l': 341 log_file_path = optarg; 342 break; 343 case 'r': 344 tlv_reset = true; 345 break; 346 case 'b': 347 sscanf_bd_addr(optarg, random_address); 348 break; 349 case 'h': 350 default: 351 usage(argv[0]); 352 return EXIT_FAILURE; 353 } 354 } 355 /// GET STARTED with BTstack /// 356 btstack_memory_init(); 357 btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 358 359 // log into file using HCI_DUMP_PACKETLOGGER format 360 if (log_file_path == NULL){ 361 log_file_path = "/tmp/hci_dump.pklg"; 362 } 363 hci_dump_posix_fs_open(log_file_path, HCI_DUMP_PACKETLOGGER); 364 const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); 365 hci_dump_init(hci_dump_impl); 366 printf("Packet Log: %s\n", log_file_path); 367 368 printf("H4 device: %s\n", config.device_name); 369 370 // init HCI 371 const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); 372 const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); 373 hci_init(transport, (void*) &config); 374 375 #ifdef HAVE_PORTAUDIO 376 btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance()); 377 btstack_audio_source_set_instance(btstack_audio_portaudio_source_get_instance()); 378 #endif 379 380 // set BD_ADDR for CSR without Flash/unique address 381 // bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; 382 // btstack_chipset_csr_set_bd_addr(own_address); 383 384 // inform about BTstack state 385 hci_event_callback_registration.callback = &packet_handler; 386 hci_add_event_handler(&hci_event_callback_registration); 387 388 // register callback for CTRL-c 389 btstack_signal_register_callback(SIGINT, &trigger_shutdown); 390 391 // setup app 392 btstack_main(argc, argv); 393 394 // go 395 btstack_run_loop_execute(); 396 397 return 0; 398 } 399