xref: /btstack/port/posix-h4/main.c (revision ceed67ffe68ea5103bbc5647a2e000ed0e08b747)
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     .type = HCI_TRANSPORT_CONFIG_UART,
103     .baudrate_init = 115200,
104     .baudrate_main = 0,
105     .flowcontrol = 1,
106 };
107 
108 static btstack_packet_callback_registration_t hci_event_callback_registration;
109 
110 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
111     UNUSED(channel);
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(&params[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     int oldopterr = opterr;
333     opterr = 0;
334     // parse command line parameters
335     while(true){
336         int c = getopt_long( argc, (char* const *)argv, short_options, long_options, NULL );
337         if (c < 0) {
338             break;
339         }
340         if (c == '?'){
341             continue;
342         }
343         switch (c) {
344             case 'u':
345                 config.device_name = optarg;
346                 break;
347             case 'l':
348                 log_file_path = optarg;
349                 break;
350             case 'r':
351                 tlv_reset = true;
352                 break;
353             case 'b':
354                 sscanf_bd_addr(optarg, random_address);
355                 break;
356             case 'h':
357             default:
358                 usage(argv[0]);
359                 break;
360         }
361     }
362     // reset getopt parsing, so it works as intended from btstack_main
363     optind = 1;
364     opterr = oldopterr;
365 
366     /// GET STARTED with BTstack ///
367 	btstack_memory_init();
368     btstack_run_loop_init(btstack_run_loop_posix_get_instance());
369 
370     // log into file using HCI_DUMP_PACKETLOGGER format
371     if (log_file_path == NULL){
372         log_file_path = "/tmp/hci_dump.pklg";
373     }
374     hci_dump_posix_fs_open(log_file_path, HCI_DUMP_PACKETLOGGER);
375     const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance();
376     hci_dump_init(hci_dump_impl);
377     printf("Packet Log: %s\n", log_file_path);
378 
379     printf("H4 device: %s\n", config.device_name);
380 
381     // init HCI
382     const btstack_uart_t * uart_driver = btstack_uart_posix_instance();
383 	const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver);
384 	hci_init(transport, (void*) &config);
385 
386 #ifdef HAVE_PORTAUDIO
387     btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance());
388     btstack_audio_source_set_instance(btstack_audio_portaudio_source_get_instance());
389 #endif
390 
391     // set BD_ADDR for CSR without Flash/unique address
392     // bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
393     // btstack_chipset_csr_set_bd_addr(own_address);
394 
395     // inform about BTstack state
396     hci_event_callback_registration.callback = &packet_handler;
397     hci_add_event_handler(&hci_event_callback_registration);
398 
399     // register callback for CTRL-c
400     btstack_signal_register_callback(SIGINT, &trigger_shutdown);
401 
402     // setup app
403     btstack_main(argc, argv);
404 
405     // go
406     btstack_run_loop_execute();
407 
408     btstack_stdin_reset();
409     return 0;
410 }
411