xref: /btstack/chipset/intel/btstack_chipset_intel_firmware.c (revision 8174b66a45d11902a458d5cf6417c05e03e29e00)
1*8174b66aSMatthias Ringwald #define __BTSTACK_FILE__ "btstack_chipset_intel_firmware.c"
2*8174b66aSMatthias Ringwald 
3*8174b66aSMatthias Ringwald #include <fcntl.h>
4*8174b66aSMatthias Ringwald #include <unistd.h>
5*8174b66aSMatthias Ringwald #include <stdio.h>
6*8174b66aSMatthias Ringwald 
7*8174b66aSMatthias Ringwald #include "btstack_chipset_intel_firmware.h"
8*8174b66aSMatthias Ringwald #include "hci_cmd.h"
9*8174b66aSMatthias Ringwald #include "bluetooth.h"
10*8174b66aSMatthias Ringwald #include "hci_dump.h"
11*8174b66aSMatthias Ringwald #include "btstack_event.h"
12*8174b66aSMatthias Ringwald #include "btstack_debug.h"
13*8174b66aSMatthias Ringwald #include "btstack_util.h"
14*8174b66aSMatthias Ringwald #include "btstack_run_loop.h"
15*8174b66aSMatthias Ringwald 
16*8174b66aSMatthias Ringwald // Vendor specific structs
17*8174b66aSMatthias Ringwald 
18*8174b66aSMatthias Ringwald typedef struct {
19*8174b66aSMatthias Ringwald     uint8_t status;
20*8174b66aSMatthias Ringwald     uint8_t hw_platform;
21*8174b66aSMatthias Ringwald     uint8_t hw_variant;
22*8174b66aSMatthias Ringwald     uint8_t hw_revision;
23*8174b66aSMatthias Ringwald     uint8_t fw_variant;
24*8174b66aSMatthias Ringwald     uint8_t fw_revision;
25*8174b66aSMatthias Ringwald     uint8_t fw_build_num;
26*8174b66aSMatthias Ringwald     uint8_t fw_build_ww;
27*8174b66aSMatthias Ringwald     uint8_t fw_build_yy;
28*8174b66aSMatthias Ringwald     uint8_t fw_patch_num;
29*8174b66aSMatthias Ringwald } intel_version_t;
30*8174b66aSMatthias Ringwald 
31*8174b66aSMatthias Ringwald typedef struct {
32*8174b66aSMatthias Ringwald     uint8_t     status;
33*8174b66aSMatthias Ringwald     uint8_t     otp_format;
34*8174b66aSMatthias Ringwald     uint8_t     otp_content;
35*8174b66aSMatthias Ringwald     uint8_t     otp_patch;
36*8174b66aSMatthias Ringwald     uint16_t    dev_revid;
37*8174b66aSMatthias Ringwald     uint8_t     secure_boot;
38*8174b66aSMatthias Ringwald     uint8_t     key_from_hdr;
39*8174b66aSMatthias Ringwald     uint8_t     key_type;
40*8174b66aSMatthias Ringwald     uint8_t     otp_lock;
41*8174b66aSMatthias Ringwald     uint8_t     api_lock;
42*8174b66aSMatthias Ringwald     uint8_t     debug_lock;
43*8174b66aSMatthias Ringwald     bd_addr_t   otp_bdaddr;
44*8174b66aSMatthias Ringwald     uint8_t     min_fw_build_nn;
45*8174b66aSMatthias Ringwald     uint8_t     min_fw_build_cw;
46*8174b66aSMatthias Ringwald     uint8_t     min_fw_build_yy;
47*8174b66aSMatthias Ringwald     uint8_t     limited_cce;
48*8174b66aSMatthias Ringwald     uint8_t     unlocked_state;
49*8174b66aSMatthias Ringwald } intel_boot_params_t;
50*8174b66aSMatthias Ringwald 
51*8174b66aSMatthias Ringwald // Vendor sepcific commands
52*8174b66aSMatthias Ringwald 
53*8174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_version = {
54*8174b66aSMatthias Ringwald     0xfc05, ""
55*8174b66aSMatthias Ringwald };
56*8174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_secure_boot_params = {
57*8174b66aSMatthias Ringwald     0xfc0d, ""
58*8174b66aSMatthias Ringwald };
59*8174b66aSMatthias Ringwald 
60*8174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_reset_param = {
61*8174b66aSMatthias Ringwald     0xfc01, "11111111"
62*8174b66aSMatthias Ringwald };
63*8174b66aSMatthias Ringwald 
64*8174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_set_event_mask = {
65*8174b66aSMatthias Ringwald     0xfc52, "11111111"
66*8174b66aSMatthias Ringwald };
67*8174b66aSMatthias Ringwald 
68*8174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_fc9f = {
69*8174b66aSMatthias Ringwald     0xfc9f, "1"
70*8174b66aSMatthias Ringwald };
71*8174b66aSMatthias Ringwald 
72*8174b66aSMatthias Ringwald // state
73*8174b66aSMatthias Ringwald 
74*8174b66aSMatthias Ringwald const hci_transport_t * transport;
75*8174b66aSMatthias Ringwald 
76*8174b66aSMatthias Ringwald static int state = 0;
77*8174b66aSMatthias Ringwald 
78*8174b66aSMatthias Ringwald static uint8_t hci_outgoing[300];
79*8174b66aSMatthias Ringwald static uint8_t fw_buffer[300];
80*8174b66aSMatthias Ringwald 
81*8174b66aSMatthias Ringwald static uint8_t  hw_variant;
82*8174b66aSMatthias Ringwald static uint16_t dev_revid;
83*8174b66aSMatthias Ringwald 
84*8174b66aSMatthias Ringwald static FILE *   fw_file;
85*8174b66aSMatthias Ringwald static uint32_t fw_offset;
86*8174b66aSMatthias Ringwald 
87*8174b66aSMatthias Ringwald static void (*done)(int result);
88*8174b66aSMatthias Ringwald 
89*8174b66aSMatthias Ringwald // functions
90*8174b66aSMatthias Ringwald 
91*8174b66aSMatthias Ringwald static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){
92*8174b66aSMatthias Ringwald     hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size);
93*8174b66aSMatthias Ringwald     return transport->send_packet(packet_type, (uint8_t *) packet, size);
94*8174b66aSMatthias Ringwald }
95*8174b66aSMatthias Ringwald 
96*8174b66aSMatthias Ringwald static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
97*8174b66aSMatthias Ringwald     uint8_t * packet = hci_outgoing;
98*8174b66aSMatthias Ringwald     uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
99*8174b66aSMatthias Ringwald     return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
100*8174b66aSMatthias Ringwald }
101*8174b66aSMatthias Ringwald 
102*8174b66aSMatthias Ringwald static int transport_send_cmd(const hci_cmd_t *cmd, ...){
103*8174b66aSMatthias Ringwald     va_list argptr;
104*8174b66aSMatthias Ringwald     va_start(argptr, cmd);
105*8174b66aSMatthias Ringwald     int res = transport_send_cmd_va_arg(cmd, argptr);
106*8174b66aSMatthias Ringwald     va_end(argptr);
107*8174b66aSMatthias Ringwald     return res;
108*8174b66aSMatthias Ringwald }
109*8174b66aSMatthias Ringwald 
110*8174b66aSMatthias Ringwald static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint16_t len){
111*8174b66aSMatthias Ringwald     little_endian_store_16(hci_outgoing, 0, 0xfc09);
112*8174b66aSMatthias Ringwald     hci_outgoing[2] = 1 + len;
113*8174b66aSMatthias Ringwald     hci_outgoing[3] = fragment_type;
114*8174b66aSMatthias Ringwald     memcpy(&hci_outgoing[4], data, len);
115*8174b66aSMatthias Ringwald     uint16_t size = 3 +  1 + len;
116*8174b66aSMatthias Ringwald     return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size);
117*8174b66aSMatthias Ringwald }
118*8174b66aSMatthias Ringwald 
119*8174b66aSMatthias Ringwald static int transport_send_intel_ddc(const uint8_t * data, uint16_t len){
120*8174b66aSMatthias Ringwald     little_endian_store_16(hci_outgoing, 0, 0xfc8b);
121*8174b66aSMatthias Ringwald     hci_outgoing[2] = len;
122*8174b66aSMatthias Ringwald     memcpy(&hci_outgoing[3], data, len);
123*8174b66aSMatthias Ringwald     uint16_t size = 3 +  len;
124*8174b66aSMatthias Ringwald     return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size);
125*8174b66aSMatthias Ringwald }
126*8174b66aSMatthias Ringwald 
127*8174b66aSMatthias Ringwald static void state_machine(uint8_t * packet);
128*8174b66aSMatthias Ringwald 
129*8174b66aSMatthias Ringwald // read data from fw file and send it via intel_secure + update state
130*8174b66aSMatthias Ringwald static int intel_send_fragment(uint8_t fragment_type, uint16_t len){
131*8174b66aSMatthias Ringwald     int res = fread(fw_buffer, 1, len, fw_file);
132*8174b66aSMatthias Ringwald     log_info("offset %6u, read %3u -> res %d", fw_offset, len, res);
133*8174b66aSMatthias Ringwald     fw_offset += res;
134*8174b66aSMatthias Ringwald     state++;
135*8174b66aSMatthias Ringwald     return transport_send_intel_secure(fragment_type, fw_buffer, len);
136*8174b66aSMatthias Ringwald }
137*8174b66aSMatthias Ringwald 
138*8174b66aSMatthias Ringwald // read data from  ddc file and send iva intel ddc command
139*8174b66aSMatthias Ringwald // @returns -1 on eof
140*8174b66aSMatthias Ringwald static int intel_send_ddc(void){
141*8174b66aSMatthias Ringwald     int res;
142*8174b66aSMatthias Ringwald     // read len
143*8174b66aSMatthias Ringwald     res = fread(fw_buffer, 1, 1, fw_file);
144*8174b66aSMatthias Ringwald     log_info("offset %6u, read 1 -> res %d", fw_offset, res);
145*8174b66aSMatthias Ringwald     if (res == 0) return -1;
146*8174b66aSMatthias Ringwald     uint8_t len = fw_buffer[0];
147*8174b66aSMatthias Ringwald     fw_offset += 1;
148*8174b66aSMatthias Ringwald     res = fread(&fw_buffer[1], 1, len, fw_file);
149*8174b66aSMatthias Ringwald     log_info("offset %6u, read %u -> res %d", fw_offset, 1, res);
150*8174b66aSMatthias Ringwald     return transport_send_intel_ddc(fw_buffer, 1 + len);
151*8174b66aSMatthias Ringwald }
152*8174b66aSMatthias Ringwald 
153*8174b66aSMatthias Ringwald static void dump_intel_version(intel_version_t     * version){
154*8174b66aSMatthias Ringwald     log_info("status       0x%02x", version->status);
155*8174b66aSMatthias Ringwald     log_info("hw_platform  0x%02x", version->hw_platform);
156*8174b66aSMatthias Ringwald     log_info("hw_variant   0x%02x", version->hw_variant);
157*8174b66aSMatthias Ringwald     log_info("hw_revision  0x%02x", version->hw_revision);
158*8174b66aSMatthias Ringwald     log_info("fw_variant   0x%02x", version->fw_variant);
159*8174b66aSMatthias Ringwald     log_info("fw_revision  0x%02x", version->fw_revision);
160*8174b66aSMatthias Ringwald     log_info("fw_build_num 0x%02x", version->fw_build_num);
161*8174b66aSMatthias Ringwald     log_info("fw_build_ww  0x%02x", version->fw_build_ww);
162*8174b66aSMatthias Ringwald     log_info("fw_build_yy  0x%02x", version->fw_build_yy);
163*8174b66aSMatthias Ringwald     log_info("fw_patch_num 0x%02x", version->fw_patch_num);
164*8174b66aSMatthias Ringwald }
165*8174b66aSMatthias Ringwald 
166*8174b66aSMatthias Ringwald static void dump_intel_boot_params(intel_boot_params_t * boot_params){
167*8174b66aSMatthias Ringwald     bd_addr_t addr;
168*8174b66aSMatthias Ringwald     reverse_bd_addr(boot_params->otp_bdaddr, addr);
169*8174b66aSMatthias Ringwald     log_info("Device revision: %u", dev_revid);
170*8174b66aSMatthias Ringwald     log_info("Secure Boot:  %s", boot_params->secure_boot ? "enabled" : "disabled");
171*8174b66aSMatthias Ringwald     log_info("OTP lock:     %s", boot_params->otp_lock    ? "enabled" : "disabled");
172*8174b66aSMatthias Ringwald     log_info("API lock:     %s", boot_params->api_lock    ? "enabled" : "disabled");
173*8174b66aSMatthias Ringwald     log_info("Debug lock:   %s", boot_params->debug_lock  ? "enabled" : "disabled");
174*8174b66aSMatthias Ringwald     log_info("Minimum firmware build %u week %u %u", boot_params->min_fw_build_nn, boot_params->min_fw_build_cw, 2000 + boot_params->min_fw_build_yy);
175*8174b66aSMatthias Ringwald     log_info("OTC BD_ADDR:  %s", bd_addr_to_str(addr));
176*8174b66aSMatthias Ringwald }
177*8174b66aSMatthias Ringwald 
178*8174b66aSMatthias Ringwald static int vendor_firmware_complete_received;
179*8174b66aSMatthias Ringwald static int waiting_for_command_complete;
180*8174b66aSMatthias Ringwald 
181*8174b66aSMatthias Ringwald static void state_machine(uint8_t * packet){
182*8174b66aSMatthias Ringwald     intel_version_t     * version;
183*8174b66aSMatthias Ringwald     intel_boot_params_t * boot_params;
184*8174b66aSMatthias Ringwald     char fw_name[30];
185*8174b66aSMatthias Ringwald     int res;
186*8174b66aSMatthias Ringwald     uint16_t buffer_offset;
187*8174b66aSMatthias Ringwald     bd_addr_t addr;
188*8174b66aSMatthias Ringwald 
189*8174b66aSMatthias Ringwald     if (packet){
190*8174b66aSMatthias Ringwald         // firmware upload complete event?
191*8174b66aSMatthias Ringwald         if (packet[0] == 0xff && packet[2] == 0x06) {
192*8174b66aSMatthias Ringwald             vendor_firmware_complete_received = 1;
193*8174b66aSMatthias Ringwald         }
194*8174b66aSMatthias Ringwald 
195*8174b66aSMatthias Ringwald         // command complete
196*8174b66aSMatthias Ringwald         if (packet[0] == 0x0e){
197*8174b66aSMatthias Ringwald             waiting_for_command_complete = 0;
198*8174b66aSMatthias Ringwald         }
199*8174b66aSMatthias Ringwald     }
200*8174b66aSMatthias Ringwald 
201*8174b66aSMatthias Ringwald     switch (state){
202*8174b66aSMatthias Ringwald         case 0:
203*8174b66aSMatthias Ringwald             state++;
204*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_reset);
205*8174b66aSMatthias Ringwald             break;
206*8174b66aSMatthias Ringwald         case 1:
207*8174b66aSMatthias Ringwald             // Read Intel Version
208*8174b66aSMatthias Ringwald             state++;
209*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_read_version);
210*8174b66aSMatthias Ringwald             break;
211*8174b66aSMatthias Ringwald         case 2:
212*8174b66aSMatthias Ringwald             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
213*8174b66aSMatthias Ringwald             dump_intel_version(version);
214*8174b66aSMatthias Ringwald 
215*8174b66aSMatthias Ringwald             hw_variant = version->hw_variant;
216*8174b66aSMatthias Ringwald 
217*8174b66aSMatthias Ringwald             // fw_variant = 0x06 bootloader mode / 0x23 operational mode
218*8174b66aSMatthias Ringwald             if (version->fw_variant == 0x23) {
219*8174b66aSMatthias Ringwald                 (*done)(0);
220*8174b66aSMatthias Ringwald                 break;
221*8174b66aSMatthias Ringwald             }
222*8174b66aSMatthias Ringwald 
223*8174b66aSMatthias Ringwald             if (version->fw_variant != 0x06){
224*8174b66aSMatthias Ringwald                 log_error("unknown fw_variant 0x%02x", version->fw_variant);
225*8174b66aSMatthias Ringwald                 break;
226*8174b66aSMatthias Ringwald             }
227*8174b66aSMatthias Ringwald 
228*8174b66aSMatthias Ringwald             // Read Intel Secure Boot Params
229*8174b66aSMatthias Ringwald             state++;
230*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_read_secure_boot_params);
231*8174b66aSMatthias Ringwald             break;
232*8174b66aSMatthias Ringwald         case 3:
233*8174b66aSMatthias Ringwald             boot_params = (intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet);
234*8174b66aSMatthias Ringwald             dump_intel_boot_params(boot_params);
235*8174b66aSMatthias Ringwald 
236*8174b66aSMatthias Ringwald             reverse_bd_addr(boot_params->otp_bdaddr, addr);
237*8174b66aSMatthias Ringwald             dev_revid = little_endian_read_16((uint8_t*)&boot_params->dev_revid, 0);
238*8174b66aSMatthias Ringwald 
239*8174b66aSMatthias Ringwald             // assert commmand complete is required
240*8174b66aSMatthias Ringwald             if (boot_params->limited_cce != 0) break;
241*8174b66aSMatthias Ringwald 
242*8174b66aSMatthias Ringwald             // firmware file
243*8174b66aSMatthias Ringwald             snprintf(fw_name, sizeof(fw_name), "ibt-%u-%u.sfi", hw_variant, dev_revid);
244*8174b66aSMatthias Ringwald             log_info("Open firmware %s", fw_name);
245*8174b66aSMatthias Ringwald             printf("Firwmare %s\n", fw_name);
246*8174b66aSMatthias Ringwald 
247*8174b66aSMatthias Ringwald             // open firmware file
248*8174b66aSMatthias Ringwald             fw_offset = 0;
249*8174b66aSMatthias Ringwald             fw_file = fopen(fw_name, "rb");
250*8174b66aSMatthias Ringwald             if (!fw_file){
251*8174b66aSMatthias Ringwald                 log_error("can't open file %s", fw_name);
252*8174b66aSMatthias Ringwald                 (*done)(1);
253*8174b66aSMatthias Ringwald                 return;
254*8174b66aSMatthias Ringwald             }
255*8174b66aSMatthias Ringwald 
256*8174b66aSMatthias Ringwald             vendor_firmware_complete_received = 0;
257*8174b66aSMatthias Ringwald 
258*8174b66aSMatthias Ringwald             // send CCS segment - offset 0
259*8174b66aSMatthias Ringwald             intel_send_fragment(0x00, 128);
260*8174b66aSMatthias Ringwald             break;
261*8174b66aSMatthias Ringwald         case 4:
262*8174b66aSMatthias Ringwald             // send public key / part 1 - offset 128
263*8174b66aSMatthias Ringwald             intel_send_fragment(0x03, 128);
264*8174b66aSMatthias Ringwald             break;
265*8174b66aSMatthias Ringwald         case 5:
266*8174b66aSMatthias Ringwald             // send public key / part 2 - offset 384
267*8174b66aSMatthias Ringwald             intel_send_fragment(0x03, 128);
268*8174b66aSMatthias Ringwald             break;
269*8174b66aSMatthias Ringwald         case 6:
270*8174b66aSMatthias Ringwald             // skip 4 bytes
271*8174b66aSMatthias Ringwald             res = fread(fw_buffer, 1, 4, fw_file);
272*8174b66aSMatthias Ringwald             log_info("read res %d", res);
273*8174b66aSMatthias Ringwald             fw_offset += res;
274*8174b66aSMatthias Ringwald 
275*8174b66aSMatthias Ringwald             // send signature / part 1 - offset 388
276*8174b66aSMatthias Ringwald             intel_send_fragment(0x02, 128);
277*8174b66aSMatthias Ringwald             break;
278*8174b66aSMatthias Ringwald         case 7:
279*8174b66aSMatthias Ringwald             // send signature / part 2 - offset 516
280*8174b66aSMatthias Ringwald             intel_send_fragment(0x02, 128);
281*8174b66aSMatthias Ringwald             break;
282*8174b66aSMatthias Ringwald         case 8:
283*8174b66aSMatthias Ringwald             // send firmware chunks - offset 644
284*8174b66aSMatthias Ringwald             // chunk len must be 4 byte aligned
285*8174b66aSMatthias Ringwald             // multiple commands can be combined
286*8174b66aSMatthias Ringwald             buffer_offset = 0;
287*8174b66aSMatthias Ringwald             do {
288*8174b66aSMatthias Ringwald                 res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file);
289*8174b66aSMatthias Ringwald                 log_info("fw_offset %6u, buffer_offset %u, read %3u -> res %d", fw_offset, buffer_offset, 3, res);
290*8174b66aSMatthias Ringwald                 fw_offset += res;
291*8174b66aSMatthias Ringwald                 if (res == 0 ){
292*8174b66aSMatthias Ringwald                     // EOF
293*8174b66aSMatthias Ringwald                     log_info("End of file");
294*8174b66aSMatthias Ringwald                     fclose(fw_file);
295*8174b66aSMatthias Ringwald                     fw_file = NULL;
296*8174b66aSMatthias Ringwald                     state++;
297*8174b66aSMatthias Ringwald                     break;
298*8174b66aSMatthias Ringwald                 }
299*8174b66aSMatthias Ringwald                 int param_len = fw_buffer[buffer_offset + 2];
300*8174b66aSMatthias Ringwald                 buffer_offset += 3;
301*8174b66aSMatthias Ringwald                 if (param_len){
302*8174b66aSMatthias Ringwald                     res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file);
303*8174b66aSMatthias Ringwald                     fw_offset     += res;
304*8174b66aSMatthias Ringwald                     buffer_offset += res;
305*8174b66aSMatthias Ringwald                 }
306*8174b66aSMatthias Ringwald             } while ((buffer_offset & 3) != 0);
307*8174b66aSMatthias Ringwald 
308*8174b66aSMatthias Ringwald             if (buffer_offset == 0) break;
309*8174b66aSMatthias Ringwald 
310*8174b66aSMatthias Ringwald             waiting_for_command_complete = 1;
311*8174b66aSMatthias Ringwald             transport_send_intel_secure(0x01, fw_buffer, buffer_offset);
312*8174b66aSMatthias Ringwald             break;
313*8174b66aSMatthias Ringwald 
314*8174b66aSMatthias Ringwald         case 9:
315*8174b66aSMatthias Ringwald             // expect Vendor Specific Event 0x06
316*8174b66aSMatthias Ringwald             if (!vendor_firmware_complete_received) break;
317*8174b66aSMatthias Ringwald 
318*8174b66aSMatthias Ringwald             printf("Firmware upload complete\n");
319*8174b66aSMatthias Ringwald             log_info("Vendor Event 0x06 - firmware complete");
320*8174b66aSMatthias Ringwald 
321*8174b66aSMatthias Ringwald             // Reset Params - constants from Windows Intel driver
322*8174b66aSMatthias Ringwald             state++;
323*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00);
324*8174b66aSMatthias Ringwald             break;
325*8174b66aSMatthias Ringwald 
326*8174b66aSMatthias Ringwald         case 10:
327*8174b66aSMatthias Ringwald             // expect Vendor Specific Event 0x02
328*8174b66aSMatthias Ringwald             if (packet[0] != 0xff) break;
329*8174b66aSMatthias Ringwald             if (packet[2] != 0x02) break;
330*8174b66aSMatthias Ringwald 
331*8174b66aSMatthias Ringwald             printf("Firmware operational\n");
332*8174b66aSMatthias Ringwald             log_info("Vendor Event 0x02 - firmware operational");
333*8174b66aSMatthias Ringwald 
334*8174b66aSMatthias Ringwald             // Read Intel Version
335*8174b66aSMatthias Ringwald             state++;
336*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_read_version);
337*8174b66aSMatthias Ringwald             break;
338*8174b66aSMatthias Ringwald 
339*8174b66aSMatthias Ringwald         case 11:
340*8174b66aSMatthias Ringwald             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
341*8174b66aSMatthias Ringwald             dump_intel_version(version);
342*8174b66aSMatthias Ringwald 
343*8174b66aSMatthias Ringwald             // ddc config
344*8174b66aSMatthias Ringwald             snprintf(fw_name, sizeof(fw_name), "ibt-%u-%u.ddc", hw_variant, dev_revid);
345*8174b66aSMatthias Ringwald             log_info("Open DDC %s", fw_name);
346*8174b66aSMatthias Ringwald 
347*8174b66aSMatthias Ringwald             // open ddc file
348*8174b66aSMatthias Ringwald             fw_offset = 0;
349*8174b66aSMatthias Ringwald             fw_file = fopen(fw_name, "rb");
350*8174b66aSMatthias Ringwald             if (!fw_file){
351*8174b66aSMatthias Ringwald                 log_error("can't open file %s", fw_name);
352*8174b66aSMatthias Ringwald 
353*8174b66aSMatthias Ringwald                 (*done)(1);
354*8174b66aSMatthias Ringwald                 return;
355*8174b66aSMatthias Ringwald             }
356*8174b66aSMatthias Ringwald 
357*8174b66aSMatthias Ringwald             // load ddc
358*8174b66aSMatthias Ringwald             state++;
359*8174b66aSMatthias Ringwald 
360*8174b66aSMatthias Ringwald             /* fall through */
361*8174b66aSMatthias Ringwald 
362*8174b66aSMatthias Ringwald         case 12:
363*8174b66aSMatthias Ringwald             res = intel_send_ddc();
364*8174b66aSMatthias Ringwald             if (res == 0) break;
365*8174b66aSMatthias Ringwald 
366*8174b66aSMatthias Ringwald             // DDC download complete
367*8174b66aSMatthias Ringwald             state++;
368*8174b66aSMatthias Ringwald             log_info("Load DDC Complete");
369*8174b66aSMatthias Ringwald 
370*8174b66aSMatthias Ringwald 
371*8174b66aSMatthias Ringwald             // Set Intel event mask 0xfc52
372*8174b66aSMatthias Ringwald             state++;
373*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
374*8174b66aSMatthias Ringwald             break;
375*8174b66aSMatthias Ringwald 
376*8174b66aSMatthias Ringwald         case 13:
377*8174b66aSMatthias Ringwald             // 9F FC 01 00
378*8174b66aSMatthias Ringwald             state++;
379*8174b66aSMatthias Ringwald             transport_send_cmd(&hci_intel_fc9f, 0x00);
380*8174b66aSMatthias Ringwald             break;
381*8174b66aSMatthias Ringwald 
382*8174b66aSMatthias Ringwald         case 14:
383*8174b66aSMatthias Ringwald             (*done)(0);
384*8174b66aSMatthias Ringwald             break;
385*8174b66aSMatthias Ringwald 
386*8174b66aSMatthias Ringwald         default:
387*8174b66aSMatthias Ringwald             break;
388*8174b66aSMatthias Ringwald     }
389*8174b66aSMatthias Ringwald }
390*8174b66aSMatthias Ringwald 
391*8174b66aSMatthias Ringwald static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
392*8174b66aSMatthias Ringwald     UNUSED(packet_type);
393*8174b66aSMatthias Ringwald     // we also get events with packet_type ACL from the controller
394*8174b66aSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
395*8174b66aSMatthias Ringwald     switch (hci_event_packet_get_type(packet)){
396*8174b66aSMatthias Ringwald         case HCI_EVENT_COMMAND_COMPLETE:
397*8174b66aSMatthias Ringwald         case HCI_EVENT_VENDOR_SPECIFIC:
398*8174b66aSMatthias Ringwald             state_machine(packet);
399*8174b66aSMatthias Ringwald             break;
400*8174b66aSMatthias Ringwald         default:
401*8174b66aSMatthias Ringwald             break;
402*8174b66aSMatthias Ringwald     }
403*8174b66aSMatthias Ringwald }
404*8174b66aSMatthias Ringwald 
405*8174b66aSMatthias Ringwald void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){
406*8174b66aSMatthias Ringwald 
407*8174b66aSMatthias Ringwald     done = callback;
408*8174b66aSMatthias Ringwald 
409*8174b66aSMatthias Ringwald 	transport = hci_transport;;
410*8174b66aSMatthias Ringwald     // transport->init(NULL);
411*8174b66aSMatthias Ringwald     transport->register_packet_handler(&transport_packet_handler);
412*8174b66aSMatthias Ringwald     transport->open();
413*8174b66aSMatthias Ringwald 
414*8174b66aSMatthias Ringwald     // get started
415*8174b66aSMatthias Ringwald     state = 0;
416*8174b66aSMatthias Ringwald     state_machine(NULL);
417*8174b66aSMatthias Ringwald }
418