xref: /btstack/port/posix-h4/main.c (revision ff479fcfe6e87e91c43cb840a0a9b88d5183e418)
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(&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 }
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