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 MATTHIAS 24 * RINGWALD 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 #endif 151 152 // CRC32 implementation using 4-bit lookup table created by pycrc v0.9.1, https://pycrc.org 153 // ./pycrc.py --model crc-32 --algorithm table-driven --table-idx-width=4 --generate c 154 static const uint32_t crc32_table[16] = { 155 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 156 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 157 }; 158 159 uint32_t btstack_crc32(const uint8_t *buf, uint16_t size){ 160 uint16_t pos; 161 uint32_t crc = 0xffffffff; 162 for (pos=0 ; pos<size ; pos++){ 163 int tbl_idx = crc ^ buf[pos]; 164 crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); 165 tbl_idx = crc ^ (buf[pos] >> 4); 166 crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); 167 } 168 return ~crc; 169 } 170 171 static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ 172 little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02)); 173 hci_cmd_buffer[2] = 0x06; 174 reverse_bd_addr(addr, &hci_cmd_buffer[3]); 175 } 176 177 static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){ 178 // lookup baudrates 179 int i; 180 int found = 0; 181 for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){ 182 if (baudrates[i] == baudrate){ 183 found = i; 184 break; 185 } 186 } 187 if (!found){ 188 log_error("Baudrate %u not found in table", baudrate); 189 return; 190 } 191 little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07)); 192 hci_cmd_buffer[2] = 0x01; 193 hci_cmd_buffer[3] = i; 194 } 195 196 #ifdef HAVE_EM9304_PATCH_CONTAINER 197 static void chipset_init(const void * config){ 198 UNUSED(config); 199 container_blob_offset = 0; 200 em_cpu_reset_sent = 0; 201 upload_state = UPLOAD_IDLE; 202 } 203 204 static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){ 205 log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size); 206 207 if (container_blob_offset >= container_blob_size) { 208 if (0 == em_cpu_reset_sent){ 209 // send EM CPU Reset 210 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET); 211 hci_cmd_buffer[2] = 0; 212 em_cpu_reset_sent = 1; 213 return BTSTACK_CHIPSET_VALID_COMMAND; 214 } else { 215 return BTSTACK_CHIPSET_DONE; 216 } 217 } 218 219 uint32_t tag; 220 uint16_t bytes_to_upload; 221 uint32_t crc; 222 uint32_t container_size; 223 224 switch (upload_state){ 225 case UPLOAD_IDLE: 226 // check for 'em93' tag 227 tag = little_endian_read_32(container_blob_data, container_blob_offset); 228 if (0x656d3933 != tag) { 229 log_error("Expected 0x656d3933 ('em934') but got %08x", (int) tag); 230 return BTSTACK_CHIPSET_DONE; 231 } 232 // fetch info for current container 233 container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4); 234 container_end = container_blob_offset + container_size; 235 // start uploading (<= 59 bytes) 236 patch_sequence_number = 1; 237 bytes_to_upload = btstack_min(59, container_end - container_blob_offset); 238 crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); 239 log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u", 240 (int) container_blob_data[container_blob_offset+9], 241 (int) container_blob_data[container_blob_offset+10], 242 (int) little_endian_read_16(container_blob_data, container_blob_offset+12), 243 (int) little_endian_read_16(container_blob_data, container_blob_offset+14), 244 (int) container_size); 245 // build command 246 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START); 247 hci_cmd_buffer[2] = 5 + bytes_to_upload; 248 hci_cmd_buffer[3] = 0; // upload to iRAM1 249 little_endian_store_32(hci_cmd_buffer, 4, crc); 250 memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload); 251 container_blob_offset += bytes_to_upload; 252 if (container_blob_offset < container_end){ 253 upload_state = UPLOAD_ACTIVE; 254 } 255 return BTSTACK_CHIPSET_VALID_COMMAND; 256 case UPLOAD_ACTIVE: 257 // Upload next segement 258 bytes_to_upload = btstack_min(58, container_end - container_blob_offset); 259 crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); 260 // build command 261 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE); 262 hci_cmd_buffer[2] = 6 + bytes_to_upload; 263 little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++); 264 little_endian_store_32(hci_cmd_buffer, 5, crc); 265 memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload); 266 container_blob_offset += bytes_to_upload; 267 if (container_blob_offset >= container_end){ 268 log_info("container done maybe another one"); 269 upload_state = UPLOAD_IDLE; 270 } 271 return BTSTACK_CHIPSET_VALID_COMMAND; 272 } 273 return BTSTACK_CHIPSET_DONE; 274 } 275 #endif 276 277 static const btstack_chipset_t btstack_chipset_em9301 = { 278 "EM9301", 279 #ifdef HAVE_EM9304_PATCH_CONTAINER 280 chipset_init, 281 chipset_next_command, 282 #else 283 NULL, 284 NULL, 285 #endif 286 chipset_set_baudrate_command, 287 chipset_set_bd_addr_command, 288 }; 289 290 // MARK: public API 291 const btstack_chipset_t * btstack_chipset_em9301_instance(void){ 292 return &btstack_chipset_em9301; 293 } 294