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