1f5c04f62SMatthias Ringwald /* 2f5c04f62SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3f5c04f62SMatthias Ringwald * 4f5c04f62SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5f5c04f62SMatthias Ringwald * modification, are permitted provided that the following conditions 6f5c04f62SMatthias Ringwald * are met: 7f5c04f62SMatthias Ringwald * 8f5c04f62SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9f5c04f62SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10f5c04f62SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11f5c04f62SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12f5c04f62SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13f5c04f62SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14f5c04f62SMatthias Ringwald * contributors may be used to endorse or promote products derived 15f5c04f62SMatthias Ringwald * from this software without specific prior written permission. 16f5c04f62SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17f5c04f62SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18f5c04f62SMatthias Ringwald * monetary gain. 19f5c04f62SMatthias Ringwald * 20f5c04f62SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21f5c04f62SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22f5c04f62SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23f5c04f62SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24f5c04f62SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25f5c04f62SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26f5c04f62SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27f5c04f62SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28f5c04f62SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29f5c04f62SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30f5c04f62SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f5c04f62SMatthias Ringwald * SUCH DAMAGE. 32f5c04f62SMatthias Ringwald * 33f5c04f62SMatthias Ringwald * Please inquire about commercial licensing options at 34f5c04f62SMatthias Ringwald * [email protected] 35f5c04f62SMatthias Ringwald * 36f5c04f62SMatthias Ringwald */ 37f5c04f62SMatthias Ringwald 38f5c04f62SMatthias Ringwald #define __BTSTACK_FILE__ "main.c" 39f5c04f62SMatthias Ringwald 40f5c04f62SMatthias Ringwald // ***************************************************************************** 41f5c04f62SMatthias Ringwald // 42f5c04f62SMatthias Ringwald // minimal setup for HCI code 43f5c04f62SMatthias Ringwald // 44f5c04f62SMatthias Ringwald // ***************************************************************************** 45f5c04f62SMatthias Ringwald 46f5c04f62SMatthias Ringwald #include <stdint.h> 4788d4cc4fSMatthias Ringwald #include <inttypes.h> 48f5c04f62SMatthias Ringwald #include <stdio.h> 49f5c04f62SMatthias Ringwald #include <stdlib.h> 5088d4cc4fSMatthias Ringwald #include <unistd.h> 51f5c04f62SMatthias Ringwald #include <string.h> 52f5c04f62SMatthias Ringwald #include <signal.h> 5388d4cc4fSMatthias Ringwald #include <errno.h> 54f5c04f62SMatthias Ringwald 55f5c04f62SMatthias Ringwald #include "btstack_config.h" 56f5c04f62SMatthias Ringwald 57f5c04f62SMatthias Ringwald #include "btstack_debug.h" 58f5c04f62SMatthias Ringwald #include "btstack_event.h" 59f5c04f62SMatthias Ringwald #include "btstack_link_key_db_fs.h" 60f5c04f62SMatthias Ringwald #include "btstack_memory.h" 61f5c04f62SMatthias Ringwald #include "btstack_run_loop.h" 62f5c04f62SMatthias Ringwald #include "btstack_run_loop_posix.h" 63f5c04f62SMatthias Ringwald #include "bluetooth_company_id.h" 64f5c04f62SMatthias Ringwald #include "hci.h" 65f5c04f62SMatthias Ringwald #include "hci_dump.h" 66f5c04f62SMatthias Ringwald #include "btstack_stdin.h" 67f5c04f62SMatthias Ringwald 68f5c04f62SMatthias Ringwald #include "btstack_chipset_bcm.h" 69f5c04f62SMatthias Ringwald #include "btstack_chipset_bcm_download_firmware.h" 7011e995b1SMatthias Ringwald #include "btstack_control_raspi.h" 71f5c04f62SMatthias Ringwald 72f5c04f62SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 73f5c04f62SMatthias Ringwald 7488d4cc4fSMatthias Ringwald typedef enum { 7588d4cc4fSMatthias Ringwald UART_INVALID, 7688d4cc4fSMatthias Ringwald UART_SOFTWARE_NO_FLOW, 7788d4cc4fSMatthias Ringwald UART_HARDWARE_NO_FLOW, 7888d4cc4fSMatthias Ringwald UART_HARDWARE_FLOW 7988d4cc4fSMatthias Ringwald } uart_type_t; 80f5c04f62SMatthias Ringwald 81e0814c90SMatthias Ringwald // default config, updated depending on RasperryPi UART configuration 82f5c04f62SMatthias Ringwald static hci_transport_config_uart_t transport_config = { 83f5c04f62SMatthias Ringwald HCI_TRANSPORT_CONFIG_UART, 84f5c04f62SMatthias Ringwald 115200, 85e0814c90SMatthias Ringwald 0, // main baudrate 86f5c04f62SMatthias Ringwald 0, // flow control 87f5c04f62SMatthias Ringwald NULL, 88f5c04f62SMatthias Ringwald }; 89f5c04f62SMatthias Ringwald static btstack_uart_config_t uart_config; 90f5c04f62SMatthias Ringwald 91f5c04f62SMatthias Ringwald static int main_argc; 92f5c04f62SMatthias Ringwald static const char ** main_argv; 93f5c04f62SMatthias Ringwald 94f5c04f62SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 95f5c04f62SMatthias Ringwald 96f5c04f62SMatthias Ringwald static void sigint_handler(int param){ 97f5c04f62SMatthias Ringwald UNUSED(param); 98f5c04f62SMatthias Ringwald 99f5c04f62SMatthias Ringwald printf("CTRL-C - SIGINT received, shutting down..\n"); 100f5c04f62SMatthias Ringwald log_info("sigint_handler: shutting down"); 101f5c04f62SMatthias Ringwald 102f5c04f62SMatthias Ringwald // reset anyway 103f5c04f62SMatthias Ringwald btstack_stdin_reset(); 104f5c04f62SMatthias Ringwald 105f5c04f62SMatthias Ringwald // power down 106f5c04f62SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 107f5c04f62SMatthias Ringwald hci_close(); 108f5c04f62SMatthias Ringwald log_info("Good bye, see you.\n"); 109f5c04f62SMatthias Ringwald exit(0); 110f5c04f62SMatthias Ringwald } 111f5c04f62SMatthias Ringwald 112f5c04f62SMatthias Ringwald static int led_state = 0; 113f5c04f62SMatthias Ringwald void hal_led_toggle(void){ 114f5c04f62SMatthias Ringwald led_state = 1 - led_state; 115f5c04f62SMatthias Ringwald printf("LED State %u\n", led_state); 116f5c04f62SMatthias Ringwald } 117f5c04f62SMatthias Ringwald 118f5c04f62SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 119f5c04f62SMatthias Ringwald bd_addr_t addr; 120f5c04f62SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 121f5c04f62SMatthias Ringwald switch (hci_event_packet_get_type(packet)){ 122f5c04f62SMatthias Ringwald case BTSTACK_EVENT_STATE: 123f5c04f62SMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 124f5c04f62SMatthias Ringwald gap_local_bd_addr(addr); 125f5c04f62SMatthias Ringwald printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); 126f5c04f62SMatthias Ringwald break; 127f5c04f62SMatthias Ringwald default: 128f5c04f62SMatthias Ringwald break; 129f5c04f62SMatthias Ringwald } 130f5c04f62SMatthias Ringwald } 131f5c04f62SMatthias Ringwald 13288d4cc4fSMatthias Ringwald // see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart 133e0814c90SMatthias Ringwald static int raspi_get_bd_addr(bd_addr_t addr){ 13488d4cc4fSMatthias Ringwald 13588d4cc4fSMatthias Ringwald FILE *fd = fopen( "/proc/device-tree/serial-number", "r" ); 13688d4cc4fSMatthias Ringwald if( fd == NULL ){ 13788d4cc4fSMatthias Ringwald fprintf(stderr, "can't read serial number, %s\n", strerror( errno ) ); 13888d4cc4fSMatthias Ringwald return -1; 13988d4cc4fSMatthias Ringwald } 140*1b6b55dfSMatthias Ringwald fscanf( fd, "%*08x" "%*02x" "%02" SCNx8 "%02" SCNx8 "%02" SCNx8, &addr[3], &addr[4], &addr[5] ); 14188d4cc4fSMatthias Ringwald fclose( fd ); 14288d4cc4fSMatthias Ringwald 14388d4cc4fSMatthias Ringwald addr[0] = 0xb8; addr[1] = 0x27; addr[2] = 0xeb; 14488d4cc4fSMatthias Ringwald addr[3] ^= 0xaa; addr[4] ^= 0xaa; addr[5] ^= 0xaa; 14588d4cc4fSMatthias Ringwald 14688d4cc4fSMatthias Ringwald return 0; 14788d4cc4fSMatthias Ringwald } 14888d4cc4fSMatthias Ringwald 14988d4cc4fSMatthias Ringwald // see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart 15088d4cc4fSMatthias Ringwald // on UART_INVALID errno is set 15188d4cc4fSMatthias Ringwald static uart_type_t raspi_get_bluetooth_uart_type(void){ 15288d4cc4fSMatthias Ringwald 153e0814c90SMatthias Ringwald uint8_t deviceUart0[21] = { 0 }; 154e0814c90SMatthias Ringwald FILE *fd = fopen( "/proc/device-tree/aliases/uart0", "r" ); 155e0814c90SMatthias Ringwald if( fd == NULL ) return UART_INVALID; 15688d4cc4fSMatthias Ringwald fscanf( fd, "%20s", deviceUart0 ); 15788d4cc4fSMatthias Ringwald fclose( fd ); 15888d4cc4fSMatthias Ringwald 159e0814c90SMatthias Ringwald uint8_t deviceSerial1[21] = { 0 }; 16088d4cc4fSMatthias Ringwald fd = fopen( "/proc/device-tree/aliases/serial1", "r" ); 16188d4cc4fSMatthias Ringwald if( fd == NULL ) return UART_INVALID; 16288d4cc4fSMatthias Ringwald fscanf( fd, "%20s", deviceSerial1 ); 16388d4cc4fSMatthias Ringwald fclose( fd ); 16488d4cc4fSMatthias Ringwald 165e0814c90SMatthias Ringwald // test if uart0 is an alias for serial1 166e0814c90SMatthias Ringwald if( strncmp( (const char *) deviceUart0, (const char *) deviceSerial1, 21 ) == 0 ){ 16788d4cc4fSMatthias Ringwald // HW uart 16888d4cc4fSMatthias Ringwald size_t count = 0; 16988d4cc4fSMatthias Ringwald uint8_t buf[16]; 17088d4cc4fSMatthias Ringwald fd = fopen( "/proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm,pins", "r" ); 17188d4cc4fSMatthias Ringwald if( fd == NULL ) return UART_INVALID; 17288d4cc4fSMatthias Ringwald count = fread( buf, 1, 16, fd ); 17388d4cc4fSMatthias Ringwald fclose( fd ); 17488d4cc4fSMatthias Ringwald 175e0814c90SMatthias Ringwald // contains assigned pins 176e0814c90SMatthias Ringwald int pins = count / 4; 177e0814c90SMatthias Ringwald if( pins == 4 ){ 17888d4cc4fSMatthias Ringwald return UART_HARDWARE_FLOW; 179e0814c90SMatthias Ringwald } else { 18088d4cc4fSMatthias Ringwald return UART_HARDWARE_NO_FLOW; 18188d4cc4fSMatthias Ringwald } 182e0814c90SMatthias Ringwald } else { 18388d4cc4fSMatthias Ringwald return UART_SOFTWARE_NO_FLOW; 18488d4cc4fSMatthias Ringwald } 18588d4cc4fSMatthias Ringwald } 18688d4cc4fSMatthias Ringwald 187f5c04f62SMatthias Ringwald static void phase2(int status); 188f5c04f62SMatthias Ringwald int main(int argc, const char * argv[]){ 189f5c04f62SMatthias Ringwald 190f5c04f62SMatthias Ringwald /// GET STARTED with BTstack /// 191f5c04f62SMatthias Ringwald btstack_memory_init(); 192f5c04f62SMatthias Ringwald 193f5c04f62SMatthias Ringwald // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT 194f5c04f62SMatthias Ringwald const char * pklg_path = "/tmp/hci_dump.pklg"; 195f5c04f62SMatthias Ringwald hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER); 196f5c04f62SMatthias Ringwald printf("Packet Log: %s\n", pklg_path); 197f5c04f62SMatthias Ringwald 198f5c04f62SMatthias Ringwald // setup run loop 199f5c04f62SMatthias Ringwald btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 200f5c04f62SMatthias Ringwald 201f5c04f62SMatthias Ringwald // pick serial port and configure uart block driver 202f5c04f62SMatthias Ringwald transport_config.device_name = "/dev/serial1"; 203f5c04f62SMatthias Ringwald 20488d4cc4fSMatthias Ringwald // derive bd_addr from serial number 20588d4cc4fSMatthias Ringwald bd_addr_t addr = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; 20688d4cc4fSMatthias Ringwald raspi_get_bd_addr(addr); 207f5c04f62SMatthias Ringwald 20888d4cc4fSMatthias Ringwald // set UART config based on raspi Bluetooth UART type 20988d4cc4fSMatthias Ringwald switch (raspi_get_bluetooth_uart_type()){ 21088d4cc4fSMatthias Ringwald case UART_INVALID: 21188d4cc4fSMatthias Ringwald fprintf(stderr, "can't verify HW uart, %s\n", strerror( errno ) ); 21288d4cc4fSMatthias Ringwald return -1; 21388d4cc4fSMatthias Ringwald case UART_SOFTWARE_NO_FLOW: 21488d4cc4fSMatthias Ringwald printf("Software UART without flowcontrol\n"); 21588d4cc4fSMatthias Ringwald transport_config.baudrate_main = 460800; 21688d4cc4fSMatthias Ringwald transport_config.flowcontrol = 0; 21788d4cc4fSMatthias Ringwald break; 21888d4cc4fSMatthias Ringwald case UART_HARDWARE_NO_FLOW: 21988d4cc4fSMatthias Ringwald printf("Hardware UART without flowcontrol\n"); 22088d4cc4fSMatthias Ringwald transport_config.baudrate_main = 921600; 22188d4cc4fSMatthias Ringwald transport_config.flowcontrol = 0; 22288d4cc4fSMatthias Ringwald break; 22388d4cc4fSMatthias Ringwald case UART_HARDWARE_FLOW: 22488d4cc4fSMatthias Ringwald printf("Hardware UART with flowcontrol\n"); 22588d4cc4fSMatthias Ringwald transport_config.baudrate_main = 3000000; 22688d4cc4fSMatthias Ringwald transport_config.flowcontrol = 1; 22788d4cc4fSMatthias Ringwald break; 22888d4cc4fSMatthias Ringwald } 229f5c04f62SMatthias Ringwald 230f5c04f62SMatthias Ringwald // get BCM chipset driver 231f5c04f62SMatthias Ringwald const btstack_chipset_t * chipset = btstack_chipset_bcm_instance(); 232f5c04f62SMatthias Ringwald chipset->init(&transport_config); 233f5c04f62SMatthias Ringwald 234f5c04f62SMatthias Ringwald // set path to firmware files 235e0814c90SMatthias Ringwald btstack_chipset_bcm_set_hcd_folder_path("/lib/firmware"); 236f5c04f62SMatthias Ringwald 237f5c04f62SMatthias Ringwald // set chipset name 238f5c04f62SMatthias Ringwald btstack_chipset_bcm_set_device_name("BCM43430A1"); 239f5c04f62SMatthias Ringwald 240f5c04f62SMatthias Ringwald // setup UART driver 241f5c04f62SMatthias Ringwald const btstack_uart_block_t * uart_driver = btstack_uart_block_posix_instance(); 242f5c04f62SMatthias Ringwald 243f5c04f62SMatthias Ringwald // extract UART config from transport config 244f5c04f62SMatthias Ringwald uart_config.baudrate = transport_config.baudrate_init; 245f5c04f62SMatthias Ringwald uart_config.flowcontrol = transport_config.flowcontrol; 246f5c04f62SMatthias Ringwald uart_config.device_name = transport_config.device_name; 247f5c04f62SMatthias Ringwald uart_driver->init(&uart_config); 248f5c04f62SMatthias Ringwald 249f5c04f62SMatthias Ringwald // setup HCI (to be able to use bcm chipset driver) 250f5c04f62SMatthias Ringwald const hci_transport_t * transport = hci_transport_h5_instance(uart_driver); 251f5c04f62SMatthias Ringwald const btstack_link_key_db_t * link_key_db = btstack_link_key_db_fs_instance(); 252f5c04f62SMatthias Ringwald hci_init(transport, (void*) &transport_config); 25388d4cc4fSMatthias Ringwald hci_set_bd_addr( addr ); 254f5c04f62SMatthias Ringwald hci_set_chipset(btstack_chipset_bcm_instance()); 25511e995b1SMatthias Ringwald hci_set_link_key_db(link_key_db); 256f5c04f62SMatthias Ringwald 257f5c04f62SMatthias Ringwald // inform about BTstack state 258f5c04f62SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 259f5c04f62SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 260f5c04f62SMatthias Ringwald 261f5c04f62SMatthias Ringwald // handle CTRL-c 262f5c04f62SMatthias Ringwald signal(SIGINT, sigint_handler); 263f5c04f62SMatthias Ringwald 264f5c04f62SMatthias Ringwald main_argc = argc; 265f5c04f62SMatthias Ringwald main_argv = argv; 266f5c04f62SMatthias Ringwald 267f5c04f62SMatthias Ringwald // phase #1 download firmware 268f5c04f62SMatthias Ringwald printf("Phase 1: Download firmware\n"); 269f5c04f62SMatthias Ringwald 27011e995b1SMatthias Ringwald // power cycle Bluetooth controller 27111e995b1SMatthias Ringwald btstack_control_t *control = btstack_control_raspi_get_instance(); 27211e995b1SMatthias Ringwald control->init(NULL); 27311e995b1SMatthias Ringwald control->off(); 27411e995b1SMatthias Ringwald sleep( 1 ); 27511e995b1SMatthias Ringwald control->on(); 27688d4cc4fSMatthias Ringwald 277f5c04f62SMatthias Ringwald // phase #2 start main app 278f5c04f62SMatthias Ringwald btstack_chipset_bcm_download_firmware(uart_driver, transport_config.baudrate_main, &phase2); 279f5c04f62SMatthias Ringwald 280f5c04f62SMatthias Ringwald // go 281f5c04f62SMatthias Ringwald btstack_run_loop_execute(); 282f5c04f62SMatthias Ringwald return 0; 283f5c04f62SMatthias Ringwald } 284f5c04f62SMatthias Ringwald 285f5c04f62SMatthias Ringwald static void phase2(int status){ 286f5c04f62SMatthias Ringwald 287f5c04f62SMatthias Ringwald if (status){ 288f5c04f62SMatthias Ringwald printf("Download firmware failed\n"); 289f5c04f62SMatthias Ringwald return; 290f5c04f62SMatthias Ringwald } 291f5c04f62SMatthias Ringwald 292f5c04f62SMatthias Ringwald printf("Phase 2: Main app\n"); 293f5c04f62SMatthias Ringwald 294f5c04f62SMatthias Ringwald // setup app 295f5c04f62SMatthias Ringwald btstack_main(main_argc, main_argv); 296f5c04f62SMatthias Ringwald } 297f5c04f62SMatthias Ringwald 298