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__ "btstack_chipset_em9301.c" 39 40 /* 41 * btstack_chipset_em9301.c 42 * 43 * Adapter to use em9301-based chipsets with BTstack 44 * 45 * Allows to set public BD ADDR 46 */ 47 48 #include "btstack_config.h" 49 #include "btstack_chipset_em9301.h" 50 #include "btstack_debug.h" 51 52 #include <stddef.h> /* NULL */ 53 #include <string.h> /* memcpy */ 54 #include "hci.h" 55 56 // should go to some common place 57 #define OPCODE(ogf, ocf) (ocf | ogf << 10) 58 59 #define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27) 60 #define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28) 61 #define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29) 62 #define HCI_OPCODE_EM_CPU_RESET (0xFC32) 63 64 /** 65 * @param bd_addr 66 */ 67 const hci_cmd_t hci_vendor_em_set_public_address = { 68 0xFC02, "B" 69 }; 70 71 /** 72 * @param baud_rate_index 73 */ 74 const hci_cmd_t hci_vendor_em_set_uart_baudrate = { 75 0xFC07, "1" 76 }; 77 78 /** 79 * @param transmitter_test_mode 80 * @param channel_number 81 * @param packet_length 82 * @param packet_payload_type 83 */ 84 const hci_cmd_t hci_vendor_em_transmitter_test = { 85 0xFC11, "1111" 86 }; 87 88 /** 89 */ 90 const hci_cmd_t hci_vendor_em_transmitter_test_end = { 91 0xFC12, "" 92 }; 93 94 /** 95 * @param patch_index 96 */ 97 const hci_cmd_t hci_vendor_em_patch_query = { 98 0xFC34, "2" 99 }; 100 101 /** 102 * Change the state of the selected memory. 103 * @param memory_attribute 104 */ 105 const hci_cmd_t hci_vendor_em_set_memory_mode = { 106 0xFC2B, "1" 107 }; 108 109 /** 110 * @param sleep_option_settings 111 */ 112 const hci_cmd_t hci_vendor_em_set_sleep_options = { 113 0xFC2D, "1" 114 }; 115 116 // baudrate to index for hci_vendor_em_set_uart_baudrate 117 static const uint32_t baudrates[] = { 118 0, 119 0, 120 0, 121 9600, 122 14400, 123 19200, 124 28800, 125 38400, 126 57600, 127 76800, 128 115200, 129 230400, 130 460800, 131 921600, 132 1843200, 133 }; 134 135 #ifdef HAVE_EM9304_PATCH_CONTAINER 136 137 extern const uint8_t container_blob_data[]; 138 extern const uint32_t container_blob_size; 139 140 static uint32_t container_blob_offset = 0; 141 static uint32_t container_end; // current container 142 static uint16_t patch_sequence_number; 143 static int em_cpu_reset_sent; 144 145 static enum { 146 UPLOAD_IDLE, 147 UPLOAD_ACTIVE, 148 } upload_state; 149 150 151 // CRC32 implementation using 4-bit lookup table created by pycrc v0.9.1, https://pycrc.org 152 // ./pycrc.py --model crc-32 --algorithm table-driven --table-idx-width=4 --generate c 153 static const uint32_t crc32_table[16] = { 154 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 155 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 156 }; 157 158 static uint32_t btstack_crc32(const uint8_t *buf, uint16_t size){ 159 uint16_t pos; 160 uint32_t crc = 0xffffffff; 161 for (pos=0 ; pos<size ; pos++){ 162 int tbl_idx = crc ^ buf[pos]; 163 crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); 164 tbl_idx = crc ^ (buf[pos] >> 4); 165 crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); 166 } 167 return ~crc; 168 } 169 170 #endif 171 172 static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ 173 little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02)); 174 hci_cmd_buffer[2] = 0x06; 175 reverse_bd_addr(addr, &hci_cmd_buffer[3]); 176 } 177 178 static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){ 179 // lookup baudrates 180 unsigned i; 181 int found = 0; 182 for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){ 183 if (baudrates[i] == baudrate){ 184 found = i; 185 break; 186 } 187 } 188 if (!found){ 189 log_error("Baudrate %u not found in table", baudrate); 190 return; 191 } 192 little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07)); 193 hci_cmd_buffer[2] = 0x01; 194 hci_cmd_buffer[3] = i; 195 } 196 197 #ifdef HAVE_EM9304_PATCH_CONTAINER 198 static void chipset_init(const void * config){ 199 UNUSED(config); 200 container_blob_offset = 0; 201 em_cpu_reset_sent = 0; 202 upload_state = UPLOAD_IDLE; 203 } 204 205 static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){ 206 log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size); 207 208 if (container_blob_offset >= container_blob_size) { 209 if (0 == em_cpu_reset_sent){ 210 // send EM CPU Reset 211 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET); 212 hci_cmd_buffer[2] = 0; 213 em_cpu_reset_sent = 1; 214 return BTSTACK_CHIPSET_VALID_COMMAND; 215 } else { 216 return BTSTACK_CHIPSET_DONE; 217 } 218 } 219 220 uint32_t tag; 221 uint16_t bytes_to_upload; 222 uint32_t crc; 223 uint32_t container_size; 224 225 switch (upload_state){ 226 case UPLOAD_IDLE: 227 // check for 'em93' tag 228 tag = little_endian_read_32(container_blob_data, container_blob_offset); 229 if (0x656d3933 != tag) { 230 log_error("Expected 0x656d3933 ('em934') but got %08x", (int) tag); 231 return BTSTACK_CHIPSET_DONE; 232 } 233 // fetch info for current container 234 container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4); 235 container_end = container_blob_offset + container_size; 236 // start uploading (<= 59 bytes) 237 patch_sequence_number = 1; 238 bytes_to_upload = btstack_min(59, container_end - container_blob_offset); 239 crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); 240 log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u", 241 (int) container_blob_data[container_blob_offset+9], 242 (int) container_blob_data[container_blob_offset+10], 243 (int) little_endian_read_16(container_blob_data, container_blob_offset+12), 244 (int) little_endian_read_16(container_blob_data, container_blob_offset+14), 245 (int) container_size); 246 // build command 247 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START); 248 hci_cmd_buffer[2] = 5 + bytes_to_upload; 249 hci_cmd_buffer[3] = 0; // upload to iRAM1 250 little_endian_store_32(hci_cmd_buffer, 4, crc); 251 memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload); 252 container_blob_offset += bytes_to_upload; 253 if (container_blob_offset < container_end){ 254 upload_state = UPLOAD_ACTIVE; 255 } 256 return BTSTACK_CHIPSET_VALID_COMMAND; 257 case UPLOAD_ACTIVE: 258 // Upload next segement 259 bytes_to_upload = btstack_min(58, container_end - container_blob_offset); 260 crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); 261 // build command 262 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE); 263 hci_cmd_buffer[2] = 6 + bytes_to_upload; 264 little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++); 265 little_endian_store_32(hci_cmd_buffer, 5, crc); 266 memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload); 267 container_blob_offset += bytes_to_upload; 268 if (container_blob_offset >= container_end){ 269 log_info("container done maybe another one"); 270 upload_state = UPLOAD_IDLE; 271 } 272 return BTSTACK_CHIPSET_VALID_COMMAND; 273 default: 274 btstack_assert(false); 275 break; 276 } 277 return BTSTACK_CHIPSET_DONE; 278 } 279 #endif 280 281 static const btstack_chipset_t btstack_chipset_em9301 = { 282 "EM9301", 283 #ifdef HAVE_EM9304_PATCH_CONTAINER 284 chipset_init, 285 chipset_next_command, 286 #else 287 NULL, 288 NULL, 289 #endif 290 chipset_set_baudrate_command, 291 chipset_set_bd_addr_command, 292 }; 293 294 // MARK: public API 295 const btstack_chipset_t * btstack_chipset_em9301_instance(void){ 296 return &btstack_chipset_em9301; 297 } 298