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
btstack_crc32(const uint8_t * buf,uint16_t size)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
chipset_set_bd_addr_command(bd_addr_t addr,uint8_t * hci_cmd_buffer)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
chipset_set_baudrate_command(uint32_t baudrate,uint8_t * hci_cmd_buffer)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
chipset_init(const void * config)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
chipset_next_command(uint8_t * hci_cmd_buffer)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
btstack_chipset_em9301_instance(void)295 const btstack_chipset_t * btstack_chipset_em9301_instance(void){
296 return &btstack_chipset_em9301;
297 }
298