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