xref: /btstack/chipset/em9301/btstack_chipset_em9301.c (revision c32dba203d4af5ccae95e4d7b5aa9cabd63fc4ec)
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