1 /* 2 * Copyright (C) 2017 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__ "btstack_chipset_da145xx.c" 39 40 /* 41 * Adapter to use da1458x-based chipsets with BTstack 42 * 43 */ 44 45 #include "btstack_config.h" 46 #include "btstack_chipset_da145xx.h" 47 #include "btstack_debug.h" 48 49 50 #include <stddef.h> /* NULL */ 51 #include <string.h> /* memcpy */ 52 #include "hci.h" 53 54 // Firmware download protocol contstants 55 #define SOH 0x01 56 #define STX 0x02 57 #define ACK 0x06 58 #define NACK 0x15 59 #define CRC_INIT 0x00 60 61 // prototypes 62 static void da145xx_w4_stx(void); 63 static void da145xx_w4_command_sent(void); 64 static void da145xx_w4_fw_sent(void); 65 static void da145xx_w4_ack(void); 66 static void da145xx_w4_crc(void); 67 static void da145xx_w4_final_ack_sent(void); 68 69 // globals 70 static void (*download_complete)(int result); 71 static const btstack_uart_block_t * the_uart_driver; 72 73 static int download_count; 74 static uint8_t response_buffer[1]; 75 static uint8_t command_buffer[3]; 76 static const uint8_t * chipset_fw_data; 77 static uint16_t chipset_fw_size; 78 79 static void da145xx_start(void){ 80 // start to read 81 the_uart_driver->set_block_received(&da145xx_w4_stx); 82 the_uart_driver->receive_block(&response_buffer[0], 1); 83 log_info("da145xx_start: wait for 0x%02x", STX); 84 } 85 86 static void da145xx_w4_stx(void){ 87 log_debug("da145xx_w4_stx: read %x", response_buffer[0]); 88 switch (response_buffer[0]){ 89 case STX: 90 log_info("da145xx_w4_stx: send download command"); 91 // setup download config message 92 command_buffer[0] = SOH; 93 little_endian_store_16(command_buffer, 1, chipset_fw_size); 94 the_uart_driver->set_block_sent(da145xx_w4_command_sent); 95 the_uart_driver->send_block(command_buffer, 3); 96 break; 97 default: 98 // read again 99 the_uart_driver->receive_block(&response_buffer[0], 1); 100 break; 101 } 102 } 103 104 static void da145xx_w4_command_sent(void){ 105 log_info("da145xx_w4_command_sent: wait for ACK 0x%02x", ACK); 106 // write complete 107 the_uart_driver->set_block_received(&da145xx_w4_ack); 108 the_uart_driver->receive_block(&response_buffer[0], 1); 109 } 110 111 static void da145xx_w4_ack(void){ 112 log_info("da145xx_w4_ack: read %x", response_buffer[0]); 113 switch (response_buffer[0]){ 114 case ACK: 115 // calc crc 116 // send file 117 log_info("da145xx_w4_ack: ACK received, send firmware"); 118 the_uart_driver->set_block_sent(da145xx_w4_fw_sent); 119 the_uart_driver->send_block(chipset_fw_data, chipset_fw_size); 120 break; 121 case NACK: 122 // denied 123 the_uart_driver->close(); 124 download_complete(1); 125 break; 126 default: 127 download_count++; 128 if (download_count < 10){ 129 // something else went wrong try again 130 da145xx_start(); 131 } else { 132 // give up 133 the_uart_driver->close(); 134 download_complete(1); 135 } 136 break; 137 } 138 } 139 140 static void da145xx_w4_fw_sent(void){ 141 // write complete 142 log_info("da145xx_w4_fw_sent: wait for crc"); 143 the_uart_driver->set_block_received(&da145xx_w4_crc); 144 the_uart_driver->receive_block(&response_buffer[0], 1); 145 } 146 147 static void da145xx_w4_crc(void){ 148 log_info("da145xx_w4_crc: read %x\n", response_buffer[0]); 149 150 // calculate crc 151 int i; 152 uint8_t fcrc = CRC_INIT; 153 for (i = 0; i < chipset_fw_size; i++){ 154 fcrc ^= chipset_fw_data[i]; 155 } 156 157 // check crc 158 if (fcrc != response_buffer[0]){ 159 log_error("da145xx_w4_crc: got 0x%02x expected 0x%02x", response_buffer[0], fcrc); 160 download_complete(1); 161 return; 162 } 163 164 // everything's fine, send final ack 165 command_buffer[0] = ACK; 166 the_uart_driver->set_block_sent(&da145xx_w4_final_ack_sent); 167 the_uart_driver->send_block(command_buffer, 1); 168 } 169 170 static void da145xx_w4_final_ack_sent(void){ 171 download_complete(0); 172 } 173 174 void btstack_chipset_da145xx_download_firmware_with_uart(const btstack_uart_t * uart_driver, const uint8_t * fw_data, uint16_t fw_size, void (*done)(int result)){ 175 176 the_uart_driver = uart_driver; 177 download_complete = done; 178 chipset_fw_data = fw_data; 179 chipset_fw_size = fw_size; 180 181 int res = the_uart_driver->open(); 182 183 if (res) { 184 log_error("uart_block init failed %u", res); 185 download_complete(res); 186 } 187 188 download_count = 0; 189 da145xx_start(); 190 } 191 192 void btstack_chipset_da145xx_download_firmware(const btstack_uart_block_t * uart_driver, const uint8_t * fw, uint16_t fw_size, void (*done)(int result)){ 193 btstack_chipset_da145xx_download_firmware_with_uart(uart_driver, fw, fw_size, done); 194 } 195 196 // not used currently 197 198 static const btstack_chipset_t btstack_chipset_da145xx = { 199 "DA145xx", 200 NULL, // chipset_init not used 201 NULL, // chipset_next_command not used 202 NULL, // chipset_set_baudrate_command not needed as we're connected via SPI 203 NULL, // chipset_set_bd_addr not provided 204 }; 205 206 // MARK: public API 207 const btstack_chipset_t * btstack_chipset_da145xx_instance(void){ 208 return &btstack_chipset_da145xx; 209 } 210 211