199e8f095SMatthias Ringwald /* 299e8f095SMatthias Ringwald * Copyright (C) 2017 BlueKitchen GmbH 399e8f095SMatthias Ringwald * 499e8f095SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 599e8f095SMatthias Ringwald * modification, are permitted provided that the following conditions 699e8f095SMatthias Ringwald * are met: 799e8f095SMatthias Ringwald * 899e8f095SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 999e8f095SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1099e8f095SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1199e8f095SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1299e8f095SMatthias Ringwald * documentation and/or other materials provided with the distribution. 1399e8f095SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1499e8f095SMatthias Ringwald * contributors may be used to endorse or promote products derived 1599e8f095SMatthias Ringwald * from this software without specific prior written permission. 1699e8f095SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1799e8f095SMatthias Ringwald * personal benefit and not for any commercial purpose or for 1899e8f095SMatthias Ringwald * monetary gain. 1999e8f095SMatthias Ringwald * 2099e8f095SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2199e8f095SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2299e8f095SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2599e8f095SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2699e8f095SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2799e8f095SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2899e8f095SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2999e8f095SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3099e8f095SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3199e8f095SMatthias Ringwald * SUCH DAMAGE. 3299e8f095SMatthias Ringwald * 3399e8f095SMatthias Ringwald * Please inquire about commercial licensing options at 3499e8f095SMatthias Ringwald * [email protected] 3599e8f095SMatthias Ringwald * 3699e8f095SMatthias Ringwald */ 3799e8f095SMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_chipset_bcm_download_firmware.c" 3999e8f095SMatthias Ringwald 4099e8f095SMatthias Ringwald // download firmware implementation 4199e8f095SMatthias Ringwald // requires hci_dump 4299e8f095SMatthias Ringwald // supports higher baudrate for patch upload 4399e8f095SMatthias Ringwald 4499e8f095SMatthias Ringwald #include <string.h> 45*0df9df8cSMatthias Ringwald #include <printf.h> 46*0df9df8cSMatthias Ringwald #include <unistd.h> 4799e8f095SMatthias Ringwald 4899e8f095SMatthias Ringwald #include "hci_dump.h" 4999e8f095SMatthias Ringwald #include "btstack_chipset_bcm.h" 5099e8f095SMatthias Ringwald #include "btstack_chipset_bcm_download_firmware.h" 5199e8f095SMatthias Ringwald #include "bluetooth.h" 5299e8f095SMatthias Ringwald #include "btstack_debug.h" 5399e8f095SMatthias Ringwald #include "btstack_chipset.h" 5499e8f095SMatthias Ringwald 5599e8f095SMatthias Ringwald static void bcm_send_hci_baudrate(void); 5699e8f095SMatthias Ringwald static void bcm_send_next_init_script_command(void); 5799e8f095SMatthias Ringwald static void bcm_set_local_baudrate(void); 5899e8f095SMatthias Ringwald static void bcm_w4_command_complete(void); 5999e8f095SMatthias Ringwald 6099e8f095SMatthias Ringwald static const btstack_uart_block_t * uart_driver; 6199e8f095SMatthias Ringwald static const btstack_chipset_t * chipset; 6299e8f095SMatthias Ringwald 6399e8f095SMatthias Ringwald static uint8_t response_buffer[260]; 6499e8f095SMatthias Ringwald static uint8_t command_buffer[260]; 6599e8f095SMatthias Ringwald 6699e8f095SMatthias Ringwald static const int hci_command_complete_len = 7; 6799e8f095SMatthias Ringwald static const uint8_t hci_reset_cmd[] = { 0x03, 0x0c, 0x00 }; 6899e8f095SMatthias Ringwald // static const uint8_t hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,0x00, 0x00, 0x00, 0x00 }; 6999e8f095SMatthias Ringwald static void (*download_complete)(int result); 7099e8f095SMatthias Ringwald static int baudrate; 7199e8f095SMatthias Ringwald 7299e8f095SMatthias Ringwald static void bcm_send_prepared_command(void){ 7399e8f095SMatthias Ringwald uart_driver->receive_block(&response_buffer[0], hci_command_complete_len); 7499e8f095SMatthias Ringwald int size = 1 + 3 + command_buffer[3]; 7599e8f095SMatthias Ringwald command_buffer[0] = 1; 7699e8f095SMatthias Ringwald hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, &command_buffer[1], size-1); 7799e8f095SMatthias Ringwald uart_driver->send_block(command_buffer, size); 7899e8f095SMatthias Ringwald } 7999e8f095SMatthias Ringwald 8099e8f095SMatthias Ringwald static void bcm_send_hci_reset(void){ 8199e8f095SMatthias Ringwald log_info("bcm: send HCI Reset"); 82*0df9df8cSMatthias Ringwald bool send_baudrate = (baudrate != 0) && (baudrate != 115200); 83*0df9df8cSMatthias Ringwald uart_driver->set_block_received(send_baudrate ? &bcm_send_hci_baudrate : &bcm_w4_command_complete); 8499e8f095SMatthias Ringwald uart_driver->receive_block(&response_buffer[0], hci_command_complete_len); 8599e8f095SMatthias Ringwald memcpy(&command_buffer[1], hci_reset_cmd, sizeof(hci_reset_cmd)); 8699e8f095SMatthias Ringwald bcm_send_prepared_command(); 8799e8f095SMatthias Ringwald } 8899e8f095SMatthias Ringwald 8999e8f095SMatthias Ringwald static void bcm_send_hci_baudrate(void){ 9099e8f095SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 0, &response_buffer[1], hci_command_complete_len-1); 9199e8f095SMatthias Ringwald chipset->set_baudrate_command(baudrate, &command_buffer[1]); 9299e8f095SMatthias Ringwald uart_driver->set_block_received(&bcm_set_local_baudrate); 9399e8f095SMatthias Ringwald uart_driver->receive_block(&response_buffer[0], hci_command_complete_len); 94*0df9df8cSMatthias Ringwald log_info("bcm: send baud rate command - %u", baudrate); 9599e8f095SMatthias Ringwald bcm_send_prepared_command(); 9699e8f095SMatthias Ringwald } 9799e8f095SMatthias Ringwald 9899e8f095SMatthias Ringwald static void bcm_set_local_baudrate(void){ 9999e8f095SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 0, &response_buffer[1], hci_command_complete_len-1); 10099e8f095SMatthias Ringwald uart_driver->set_baudrate(baudrate); 10199e8f095SMatthias Ringwald uart_driver->set_block_received(&bcm_w4_command_complete); 10299e8f095SMatthias Ringwald bcm_send_next_init_script_command(); 10399e8f095SMatthias Ringwald } 10499e8f095SMatthias Ringwald 10599e8f095SMatthias Ringwald static void bcm_w4_command_complete(void){ 10699e8f095SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 0, &response_buffer[1], hci_command_complete_len-1); 10799e8f095SMatthias Ringwald bcm_send_next_init_script_command(); 10899e8f095SMatthias Ringwald } 10999e8f095SMatthias Ringwald 11099e8f095SMatthias Ringwald static void bcm_send_next_init_script_command(void){ 11199e8f095SMatthias Ringwald int res = chipset->next_command(&command_buffer[1]); 11299e8f095SMatthias Ringwald switch (res){ 11399e8f095SMatthias Ringwald case BTSTACK_CHIPSET_VALID_COMMAND: 11499e8f095SMatthias Ringwald bcm_send_prepared_command(); 11599e8f095SMatthias Ringwald break; 11699e8f095SMatthias Ringwald case BTSTACK_CHIPSET_DONE: 11799e8f095SMatthias Ringwald log_info("bcm: init script done"); 118646a1850SMatthias Ringwald // disable init script for main startup 119646a1850SMatthias Ringwald btstack_chipset_bcm_enable_init_script(0); 120*0df9df8cSMatthias Ringwald // reset baudrate to default 12199e8f095SMatthias Ringwald uart_driver->set_baudrate(115200); 122646a1850SMatthias Ringwald // notify main 12399e8f095SMatthias Ringwald download_complete(0); 12499e8f095SMatthias Ringwald break; 12599e8f095SMatthias Ringwald default: 12699e8f095SMatthias Ringwald break; 12799e8f095SMatthias Ringwald } 12899e8f095SMatthias Ringwald } 12999e8f095SMatthias Ringwald 13099e8f095SMatthias Ringwald /** 13199e8f095SMatthias Ringwald * @brief Download firmware via uart_driver 13299e8f095SMatthias Ringwald * @param uart_driver -- already initialized 13399e8f095SMatthias Ringwald * @param done callback. 0 = Success 13499e8f095SMatthias Ringwald */ 13599e8f095SMatthias Ringwald 13678a48aa8SMatthias Ringwald void btstack_chipset_bcm_download_firmware_with_uart(const btstack_uart_t * the_uart_driver, int baudrate_upload, void (*done)(int result)){ 13799e8f095SMatthias Ringwald // 13899e8f095SMatthias Ringwald uart_driver = the_uart_driver; 13999e8f095SMatthias Ringwald chipset = btstack_chipset_bcm_instance(); 14099e8f095SMatthias Ringwald baudrate = baudrate_upload; 14199e8f095SMatthias Ringwald download_complete = done; 1428ac52328SMatthias Ringwald btstack_chipset_bcm_enable_init_script(1); 14399e8f095SMatthias Ringwald 14499e8f095SMatthias Ringwald int res = uart_driver->open(); 14599e8f095SMatthias Ringwald if (res) { 14699e8f095SMatthias Ringwald log_error("uart_block init failed %u", res); 14799e8f095SMatthias Ringwald download_complete(res); 14899e8f095SMatthias Ringwald return; 14999e8f095SMatthias Ringwald } 15099e8f095SMatthias Ringwald 151*0df9df8cSMatthias Ringwald // Reset with CTS asserted (low) 152*0df9df8cSMatthias Ringwald printf("Please reset Bluetooth Controller, e.g. via RESET button. Firmware download starts in:\n"); 153*0df9df8cSMatthias Ringwald uint8_t i; 154*0df9df8cSMatthias Ringwald for (i = 3; i > 0; i--){ 155*0df9df8cSMatthias Ringwald printf("%u\n", i); 156*0df9df8cSMatthias Ringwald sleep(1); 157*0df9df8cSMatthias Ringwald } 158*0df9df8cSMatthias Ringwald printf("Firmware download started\n"); 159*0df9df8cSMatthias Ringwald 16099e8f095SMatthias Ringwald bcm_send_hci_reset(); 16199e8f095SMatthias Ringwald } 162*0df9df8cSMatthias Ringwald 16378a48aa8SMatthias Ringwald void btstack_chipset_bcm_download_firmware(const btstack_uart_block_t * the_uart_driver, int baudrate_upload, void (*done)(int result)) { 16478a48aa8SMatthias Ringwald btstack_chipset_bcm_download_firmware_with_uart((const btstack_uart_t *) the_uart_driver, baudrate_upload, done); 16578a48aa8SMatthias Ringwald } 166