18174b66aSMatthias Ringwald #define __BTSTACK_FILE__ "btstack_chipset_intel_firmware.c" 28174b66aSMatthias Ringwald 38174b66aSMatthias Ringwald #include <fcntl.h> 48174b66aSMatthias Ringwald #include <unistd.h> 58174b66aSMatthias Ringwald #include <stdio.h> 68174b66aSMatthias Ringwald 78174b66aSMatthias Ringwald #include "btstack_chipset_intel_firmware.h" 88174b66aSMatthias Ringwald #include "hci_cmd.h" 98174b66aSMatthias Ringwald #include "bluetooth.h" 108174b66aSMatthias Ringwald #include "hci_dump.h" 118174b66aSMatthias Ringwald #include "btstack_event.h" 128174b66aSMatthias Ringwald #include "btstack_debug.h" 138174b66aSMatthias Ringwald #include "btstack_util.h" 148174b66aSMatthias Ringwald #include "btstack_run_loop.h" 158174b66aSMatthias Ringwald 168174b66aSMatthias Ringwald // Vendor specific structs 178174b66aSMatthias Ringwald 188174b66aSMatthias Ringwald typedef struct { 198174b66aSMatthias Ringwald uint8_t status; 208174b66aSMatthias Ringwald uint8_t hw_platform; 218174b66aSMatthias Ringwald uint8_t hw_variant; 228174b66aSMatthias Ringwald uint8_t hw_revision; 238174b66aSMatthias Ringwald uint8_t fw_variant; 248174b66aSMatthias Ringwald uint8_t fw_revision; 258174b66aSMatthias Ringwald uint8_t fw_build_num; 268174b66aSMatthias Ringwald uint8_t fw_build_ww; 278174b66aSMatthias Ringwald uint8_t fw_build_yy; 288174b66aSMatthias Ringwald uint8_t fw_patch_num; 298174b66aSMatthias Ringwald } intel_version_t; 308174b66aSMatthias Ringwald 318174b66aSMatthias Ringwald typedef struct { 328174b66aSMatthias Ringwald uint8_t status; 338174b66aSMatthias Ringwald uint8_t otp_format; 348174b66aSMatthias Ringwald uint8_t otp_content; 358174b66aSMatthias Ringwald uint8_t otp_patch; 368174b66aSMatthias Ringwald uint16_t dev_revid; 378174b66aSMatthias Ringwald uint8_t secure_boot; 388174b66aSMatthias Ringwald uint8_t key_from_hdr; 398174b66aSMatthias Ringwald uint8_t key_type; 408174b66aSMatthias Ringwald uint8_t otp_lock; 418174b66aSMatthias Ringwald uint8_t api_lock; 428174b66aSMatthias Ringwald uint8_t debug_lock; 438174b66aSMatthias Ringwald bd_addr_t otp_bdaddr; 448174b66aSMatthias Ringwald uint8_t min_fw_build_nn; 458174b66aSMatthias Ringwald uint8_t min_fw_build_cw; 468174b66aSMatthias Ringwald uint8_t min_fw_build_yy; 478174b66aSMatthias Ringwald uint8_t limited_cce; 488174b66aSMatthias Ringwald uint8_t unlocked_state; 498174b66aSMatthias Ringwald } intel_boot_params_t; 508174b66aSMatthias Ringwald 518174b66aSMatthias Ringwald // Vendor sepcific commands 528174b66aSMatthias Ringwald 538174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_version = { 548174b66aSMatthias Ringwald 0xfc05, "" 558174b66aSMatthias Ringwald }; 568174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_secure_boot_params = { 578174b66aSMatthias Ringwald 0xfc0d, "" 588174b66aSMatthias Ringwald }; 598174b66aSMatthias Ringwald 608174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_reset_param = { 618174b66aSMatthias Ringwald 0xfc01, "11111111" 628174b66aSMatthias Ringwald }; 638174b66aSMatthias Ringwald 648174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_set_event_mask = { 658174b66aSMatthias Ringwald 0xfc52, "11111111" 668174b66aSMatthias Ringwald }; 678174b66aSMatthias Ringwald 688174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_fc9f = { 698174b66aSMatthias Ringwald 0xfc9f, "1" 708174b66aSMatthias Ringwald }; 718174b66aSMatthias Ringwald 728174b66aSMatthias Ringwald // state 738174b66aSMatthias Ringwald 74*29c6772bSMatthias Ringwald const char * firmware_path = "."; 75*29c6772bSMatthias Ringwald 768174b66aSMatthias Ringwald const hci_transport_t * transport; 778174b66aSMatthias Ringwald 788174b66aSMatthias Ringwald static int state = 0; 798174b66aSMatthias Ringwald 808174b66aSMatthias Ringwald static uint8_t hci_outgoing[300]; 818174b66aSMatthias Ringwald static uint8_t fw_buffer[300]; 828174b66aSMatthias Ringwald 838174b66aSMatthias Ringwald static uint8_t hw_variant; 848174b66aSMatthias Ringwald static uint16_t dev_revid; 858174b66aSMatthias Ringwald 868174b66aSMatthias Ringwald static FILE * fw_file; 878174b66aSMatthias Ringwald static uint32_t fw_offset; 888174b66aSMatthias Ringwald 898174b66aSMatthias Ringwald static void (*done)(int result); 908174b66aSMatthias Ringwald 918174b66aSMatthias Ringwald // functions 928174b66aSMatthias Ringwald 938174b66aSMatthias Ringwald static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){ 948174b66aSMatthias Ringwald hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size); 958174b66aSMatthias Ringwald return transport->send_packet(packet_type, (uint8_t *) packet, size); 968174b66aSMatthias Ringwald } 978174b66aSMatthias Ringwald 988174b66aSMatthias Ringwald static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){ 998174b66aSMatthias Ringwald uint8_t * packet = hci_outgoing; 1008174b66aSMatthias Ringwald uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr); 1018174b66aSMatthias Ringwald return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size); 1028174b66aSMatthias Ringwald } 1038174b66aSMatthias Ringwald 1048174b66aSMatthias Ringwald static int transport_send_cmd(const hci_cmd_t *cmd, ...){ 1058174b66aSMatthias Ringwald va_list argptr; 1068174b66aSMatthias Ringwald va_start(argptr, cmd); 1078174b66aSMatthias Ringwald int res = transport_send_cmd_va_arg(cmd, argptr); 1088174b66aSMatthias Ringwald va_end(argptr); 1098174b66aSMatthias Ringwald return res; 1108174b66aSMatthias Ringwald } 1118174b66aSMatthias Ringwald 1128174b66aSMatthias Ringwald static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint16_t len){ 1138174b66aSMatthias Ringwald little_endian_store_16(hci_outgoing, 0, 0xfc09); 1148174b66aSMatthias Ringwald hci_outgoing[2] = 1 + len; 1158174b66aSMatthias Ringwald hci_outgoing[3] = fragment_type; 1168174b66aSMatthias Ringwald memcpy(&hci_outgoing[4], data, len); 1178174b66aSMatthias Ringwald uint16_t size = 3 + 1 + len; 1188174b66aSMatthias Ringwald return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size); 1198174b66aSMatthias Ringwald } 1208174b66aSMatthias Ringwald 1218174b66aSMatthias Ringwald static int transport_send_intel_ddc(const uint8_t * data, uint16_t len){ 1228174b66aSMatthias Ringwald little_endian_store_16(hci_outgoing, 0, 0xfc8b); 1238174b66aSMatthias Ringwald hci_outgoing[2] = len; 1248174b66aSMatthias Ringwald memcpy(&hci_outgoing[3], data, len); 1258174b66aSMatthias Ringwald uint16_t size = 3 + len; 1268174b66aSMatthias Ringwald return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size); 1278174b66aSMatthias Ringwald } 1288174b66aSMatthias Ringwald 1298174b66aSMatthias Ringwald static void state_machine(uint8_t * packet); 1308174b66aSMatthias Ringwald 1318174b66aSMatthias Ringwald // read data from fw file and send it via intel_secure + update state 1328174b66aSMatthias Ringwald static int intel_send_fragment(uint8_t fragment_type, uint16_t len){ 1338174b66aSMatthias Ringwald int res = fread(fw_buffer, 1, len, fw_file); 1348174b66aSMatthias Ringwald log_info("offset %6u, read %3u -> res %d", fw_offset, len, res); 1358174b66aSMatthias Ringwald fw_offset += res; 1368174b66aSMatthias Ringwald state++; 1378174b66aSMatthias Ringwald return transport_send_intel_secure(fragment_type, fw_buffer, len); 1388174b66aSMatthias Ringwald } 1398174b66aSMatthias Ringwald 1408174b66aSMatthias Ringwald // read data from ddc file and send iva intel ddc command 1418174b66aSMatthias Ringwald // @returns -1 on eof 1428174b66aSMatthias Ringwald static int intel_send_ddc(void){ 1438174b66aSMatthias Ringwald int res; 1448174b66aSMatthias Ringwald // read len 1458174b66aSMatthias Ringwald res = fread(fw_buffer, 1, 1, fw_file); 1468174b66aSMatthias Ringwald log_info("offset %6u, read 1 -> res %d", fw_offset, res); 1478174b66aSMatthias Ringwald if (res == 0) return -1; 1488174b66aSMatthias Ringwald uint8_t len = fw_buffer[0]; 1498174b66aSMatthias Ringwald fw_offset += 1; 1508174b66aSMatthias Ringwald res = fread(&fw_buffer[1], 1, len, fw_file); 1518174b66aSMatthias Ringwald log_info("offset %6u, read %u -> res %d", fw_offset, 1, res); 1528174b66aSMatthias Ringwald return transport_send_intel_ddc(fw_buffer, 1 + len); 1538174b66aSMatthias Ringwald } 1548174b66aSMatthias Ringwald 1558174b66aSMatthias Ringwald static void dump_intel_version(intel_version_t * version){ 1568174b66aSMatthias Ringwald log_info("status 0x%02x", version->status); 1578174b66aSMatthias Ringwald log_info("hw_platform 0x%02x", version->hw_platform); 1588174b66aSMatthias Ringwald log_info("hw_variant 0x%02x", version->hw_variant); 1598174b66aSMatthias Ringwald log_info("hw_revision 0x%02x", version->hw_revision); 1608174b66aSMatthias Ringwald log_info("fw_variant 0x%02x", version->fw_variant); 1618174b66aSMatthias Ringwald log_info("fw_revision 0x%02x", version->fw_revision); 1628174b66aSMatthias Ringwald log_info("fw_build_num 0x%02x", version->fw_build_num); 1638174b66aSMatthias Ringwald log_info("fw_build_ww 0x%02x", version->fw_build_ww); 1648174b66aSMatthias Ringwald log_info("fw_build_yy 0x%02x", version->fw_build_yy); 1658174b66aSMatthias Ringwald log_info("fw_patch_num 0x%02x", version->fw_patch_num); 1668174b66aSMatthias Ringwald } 1678174b66aSMatthias Ringwald 1688174b66aSMatthias Ringwald static void dump_intel_boot_params(intel_boot_params_t * boot_params){ 1698174b66aSMatthias Ringwald bd_addr_t addr; 1708174b66aSMatthias Ringwald reverse_bd_addr(boot_params->otp_bdaddr, addr); 1718174b66aSMatthias Ringwald log_info("Device revision: %u", dev_revid); 1728174b66aSMatthias Ringwald log_info("Secure Boot: %s", boot_params->secure_boot ? "enabled" : "disabled"); 1738174b66aSMatthias Ringwald log_info("OTP lock: %s", boot_params->otp_lock ? "enabled" : "disabled"); 1748174b66aSMatthias Ringwald log_info("API lock: %s", boot_params->api_lock ? "enabled" : "disabled"); 1758174b66aSMatthias Ringwald log_info("Debug lock: %s", boot_params->debug_lock ? "enabled" : "disabled"); 1768174b66aSMatthias 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); 1778174b66aSMatthias Ringwald log_info("OTC BD_ADDR: %s", bd_addr_to_str(addr)); 1788174b66aSMatthias Ringwald } 1798174b66aSMatthias Ringwald 1808174b66aSMatthias Ringwald static int vendor_firmware_complete_received; 1818174b66aSMatthias Ringwald static int waiting_for_command_complete; 1828174b66aSMatthias Ringwald 1838174b66aSMatthias Ringwald static void state_machine(uint8_t * packet){ 1848174b66aSMatthias Ringwald intel_version_t * version; 1858174b66aSMatthias Ringwald intel_boot_params_t * boot_params; 1868174b66aSMatthias Ringwald int res; 1878174b66aSMatthias Ringwald uint16_t buffer_offset; 1888174b66aSMatthias Ringwald bd_addr_t addr; 189*29c6772bSMatthias Ringwald char fw_path[300]; 1908174b66aSMatthias Ringwald 1918174b66aSMatthias Ringwald if (packet){ 1928174b66aSMatthias Ringwald // firmware upload complete event? 1938174b66aSMatthias Ringwald if (packet[0] == 0xff && packet[2] == 0x06) { 1948174b66aSMatthias Ringwald vendor_firmware_complete_received = 1; 1958174b66aSMatthias Ringwald } 1968174b66aSMatthias Ringwald 1978174b66aSMatthias Ringwald // command complete 1988174b66aSMatthias Ringwald if (packet[0] == 0x0e){ 1998174b66aSMatthias Ringwald waiting_for_command_complete = 0; 2008174b66aSMatthias Ringwald } 2018174b66aSMatthias Ringwald } 2028174b66aSMatthias Ringwald 2038174b66aSMatthias Ringwald switch (state){ 2048174b66aSMatthias Ringwald case 0: 2058174b66aSMatthias Ringwald state++; 2068174b66aSMatthias Ringwald transport_send_cmd(&hci_reset); 2078174b66aSMatthias Ringwald break; 2088174b66aSMatthias Ringwald case 1: 2098174b66aSMatthias Ringwald // Read Intel Version 2108174b66aSMatthias Ringwald state++; 2118174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_read_version); 2128174b66aSMatthias Ringwald break; 2138174b66aSMatthias Ringwald case 2: 2148174b66aSMatthias Ringwald version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet); 2158174b66aSMatthias Ringwald dump_intel_version(version); 2168174b66aSMatthias Ringwald 2178174b66aSMatthias Ringwald hw_variant = version->hw_variant; 2188174b66aSMatthias Ringwald 2198174b66aSMatthias Ringwald // fw_variant = 0x06 bootloader mode / 0x23 operational mode 2208174b66aSMatthias Ringwald if (version->fw_variant == 0x23) { 2218174b66aSMatthias Ringwald (*done)(0); 2228174b66aSMatthias Ringwald break; 2238174b66aSMatthias Ringwald } 2248174b66aSMatthias Ringwald 2258174b66aSMatthias Ringwald if (version->fw_variant != 0x06){ 2268174b66aSMatthias Ringwald log_error("unknown fw_variant 0x%02x", version->fw_variant); 2278174b66aSMatthias Ringwald break; 2288174b66aSMatthias Ringwald } 2298174b66aSMatthias Ringwald 2308174b66aSMatthias Ringwald // Read Intel Secure Boot Params 2318174b66aSMatthias Ringwald state++; 2328174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_read_secure_boot_params); 2338174b66aSMatthias Ringwald break; 2348174b66aSMatthias Ringwald case 3: 2358174b66aSMatthias Ringwald boot_params = (intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet); 2368174b66aSMatthias Ringwald dump_intel_boot_params(boot_params); 2378174b66aSMatthias Ringwald 2388174b66aSMatthias Ringwald reverse_bd_addr(boot_params->otp_bdaddr, addr); 2398174b66aSMatthias Ringwald dev_revid = little_endian_read_16((uint8_t*)&boot_params->dev_revid, 0); 2408174b66aSMatthias Ringwald 2418174b66aSMatthias Ringwald // assert commmand complete is required 2428174b66aSMatthias Ringwald if (boot_params->limited_cce != 0) break; 2438174b66aSMatthias Ringwald 2448174b66aSMatthias Ringwald // firmware file 245*29c6772bSMatthias Ringwald snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.sfi", firmware_path, hw_variant, dev_revid); 246*29c6772bSMatthias Ringwald log_info("Open firmware %s", fw_path); 247*29c6772bSMatthias Ringwald printf("Firwmare %s\n", fw_path); 2488174b66aSMatthias Ringwald 2498174b66aSMatthias Ringwald // open firmware file 2508174b66aSMatthias Ringwald fw_offset = 0; 251*29c6772bSMatthias Ringwald fw_file = fopen(fw_path, "rb"); 2528174b66aSMatthias Ringwald if (!fw_file){ 253*29c6772bSMatthias Ringwald log_error("can't open file %s", fw_path); 2548174b66aSMatthias Ringwald (*done)(1); 2558174b66aSMatthias Ringwald return; 2568174b66aSMatthias Ringwald } 2578174b66aSMatthias Ringwald 2588174b66aSMatthias Ringwald vendor_firmware_complete_received = 0; 2598174b66aSMatthias Ringwald 2608174b66aSMatthias Ringwald // send CCS segment - offset 0 2618174b66aSMatthias Ringwald intel_send_fragment(0x00, 128); 2628174b66aSMatthias Ringwald break; 2638174b66aSMatthias Ringwald case 4: 2648174b66aSMatthias Ringwald // send public key / part 1 - offset 128 2658174b66aSMatthias Ringwald intel_send_fragment(0x03, 128); 2668174b66aSMatthias Ringwald break; 2678174b66aSMatthias Ringwald case 5: 2688174b66aSMatthias Ringwald // send public key / part 2 - offset 384 2698174b66aSMatthias Ringwald intel_send_fragment(0x03, 128); 2708174b66aSMatthias Ringwald break; 2718174b66aSMatthias Ringwald case 6: 2728174b66aSMatthias Ringwald // skip 4 bytes 2738174b66aSMatthias Ringwald res = fread(fw_buffer, 1, 4, fw_file); 2748174b66aSMatthias Ringwald log_info("read res %d", res); 2758174b66aSMatthias Ringwald fw_offset += res; 2768174b66aSMatthias Ringwald 2778174b66aSMatthias Ringwald // send signature / part 1 - offset 388 2788174b66aSMatthias Ringwald intel_send_fragment(0x02, 128); 2798174b66aSMatthias Ringwald break; 2808174b66aSMatthias Ringwald case 7: 2818174b66aSMatthias Ringwald // send signature / part 2 - offset 516 2828174b66aSMatthias Ringwald intel_send_fragment(0x02, 128); 2838174b66aSMatthias Ringwald break; 2848174b66aSMatthias Ringwald case 8: 2858174b66aSMatthias Ringwald // send firmware chunks - offset 644 2868174b66aSMatthias Ringwald // chunk len must be 4 byte aligned 2878174b66aSMatthias Ringwald // multiple commands can be combined 2888174b66aSMatthias Ringwald buffer_offset = 0; 2898174b66aSMatthias Ringwald do { 2908174b66aSMatthias Ringwald res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file); 2918174b66aSMatthias Ringwald log_info("fw_offset %6u, buffer_offset %u, read %3u -> res %d", fw_offset, buffer_offset, 3, res); 2928174b66aSMatthias Ringwald fw_offset += res; 2938174b66aSMatthias Ringwald if (res == 0 ){ 2948174b66aSMatthias Ringwald // EOF 2958174b66aSMatthias Ringwald log_info("End of file"); 2968174b66aSMatthias Ringwald fclose(fw_file); 2978174b66aSMatthias Ringwald fw_file = NULL; 2988174b66aSMatthias Ringwald state++; 2998174b66aSMatthias Ringwald break; 3008174b66aSMatthias Ringwald } 3018174b66aSMatthias Ringwald int param_len = fw_buffer[buffer_offset + 2]; 3028174b66aSMatthias Ringwald buffer_offset += 3; 3038174b66aSMatthias Ringwald if (param_len){ 3048174b66aSMatthias Ringwald res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file); 3058174b66aSMatthias Ringwald fw_offset += res; 3068174b66aSMatthias Ringwald buffer_offset += res; 3078174b66aSMatthias Ringwald } 3088174b66aSMatthias Ringwald } while ((buffer_offset & 3) != 0); 3098174b66aSMatthias Ringwald 3108174b66aSMatthias Ringwald if (buffer_offset == 0) break; 3118174b66aSMatthias Ringwald 3128174b66aSMatthias Ringwald waiting_for_command_complete = 1; 3138174b66aSMatthias Ringwald transport_send_intel_secure(0x01, fw_buffer, buffer_offset); 3148174b66aSMatthias Ringwald break; 3158174b66aSMatthias Ringwald 3168174b66aSMatthias Ringwald case 9: 3178174b66aSMatthias Ringwald // expect Vendor Specific Event 0x06 3188174b66aSMatthias Ringwald if (!vendor_firmware_complete_received) break; 3198174b66aSMatthias Ringwald 3208174b66aSMatthias Ringwald printf("Firmware upload complete\n"); 3218174b66aSMatthias Ringwald log_info("Vendor Event 0x06 - firmware complete"); 3228174b66aSMatthias Ringwald 3238174b66aSMatthias Ringwald // Reset Params - constants from Windows Intel driver 3248174b66aSMatthias Ringwald state++; 3258174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00); 3268174b66aSMatthias Ringwald break; 3278174b66aSMatthias Ringwald 3288174b66aSMatthias Ringwald case 10: 3298174b66aSMatthias Ringwald // expect Vendor Specific Event 0x02 3308174b66aSMatthias Ringwald if (packet[0] != 0xff) break; 3318174b66aSMatthias Ringwald if (packet[2] != 0x02) break; 3328174b66aSMatthias Ringwald 3338174b66aSMatthias Ringwald printf("Firmware operational\n"); 3348174b66aSMatthias Ringwald log_info("Vendor Event 0x02 - firmware operational"); 3358174b66aSMatthias Ringwald 3368174b66aSMatthias Ringwald // Read Intel Version 3378174b66aSMatthias Ringwald state++; 3388174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_read_version); 3398174b66aSMatthias Ringwald break; 3408174b66aSMatthias Ringwald 3418174b66aSMatthias Ringwald case 11: 3428174b66aSMatthias Ringwald version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet); 3438174b66aSMatthias Ringwald dump_intel_version(version); 3448174b66aSMatthias Ringwald 3458174b66aSMatthias Ringwald // ddc config 346*29c6772bSMatthias Ringwald snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.ddc", firmware_path, hw_variant, dev_revid); 347*29c6772bSMatthias Ringwald log_info("Open DDC %s", fw_path); 3488174b66aSMatthias Ringwald 3498174b66aSMatthias Ringwald // open ddc file 3508174b66aSMatthias Ringwald fw_offset = 0; 351*29c6772bSMatthias Ringwald fw_file = fopen(fw_path, "rb"); 3528174b66aSMatthias Ringwald if (!fw_file){ 353*29c6772bSMatthias Ringwald log_error("can't open file %s", fw_path); 3548174b66aSMatthias Ringwald 3558174b66aSMatthias Ringwald (*done)(1); 3568174b66aSMatthias Ringwald return; 3578174b66aSMatthias Ringwald } 3588174b66aSMatthias Ringwald 3598174b66aSMatthias Ringwald // load ddc 3608174b66aSMatthias Ringwald state++; 3618174b66aSMatthias Ringwald 3628174b66aSMatthias Ringwald /* fall through */ 3638174b66aSMatthias Ringwald 3648174b66aSMatthias Ringwald case 12: 3658174b66aSMatthias Ringwald res = intel_send_ddc(); 3668174b66aSMatthias Ringwald if (res == 0) break; 3678174b66aSMatthias Ringwald 3688174b66aSMatthias Ringwald // DDC download complete 3698174b66aSMatthias Ringwald state++; 3708174b66aSMatthias Ringwald log_info("Load DDC Complete"); 3718174b66aSMatthias Ringwald 3728174b66aSMatthias Ringwald 3738174b66aSMatthias Ringwald // Set Intel event mask 0xfc52 3748174b66aSMatthias Ringwald state++; 3758174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 3768174b66aSMatthias Ringwald break; 3778174b66aSMatthias Ringwald 3788174b66aSMatthias Ringwald case 13: 3798174b66aSMatthias Ringwald // 9F FC 01 00 3808174b66aSMatthias Ringwald state++; 3818174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_fc9f, 0x00); 3828174b66aSMatthias Ringwald break; 3838174b66aSMatthias Ringwald 3848174b66aSMatthias Ringwald case 14: 3858174b66aSMatthias Ringwald (*done)(0); 3868174b66aSMatthias Ringwald break; 3878174b66aSMatthias Ringwald 3888174b66aSMatthias Ringwald default: 3898174b66aSMatthias Ringwald break; 3908174b66aSMatthias Ringwald } 3918174b66aSMatthias Ringwald } 3928174b66aSMatthias Ringwald 3938174b66aSMatthias Ringwald static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){ 3948174b66aSMatthias Ringwald UNUSED(packet_type); 3958174b66aSMatthias Ringwald // we also get events with packet_type ACL from the controller 3968174b66aSMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size); 3978174b66aSMatthias Ringwald switch (hci_event_packet_get_type(packet)){ 3988174b66aSMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 3998174b66aSMatthias Ringwald case HCI_EVENT_VENDOR_SPECIFIC: 4008174b66aSMatthias Ringwald state_machine(packet); 4018174b66aSMatthias Ringwald break; 4028174b66aSMatthias Ringwald default: 4038174b66aSMatthias Ringwald break; 4048174b66aSMatthias Ringwald } 4058174b66aSMatthias Ringwald } 4068174b66aSMatthias Ringwald 407*29c6772bSMatthias Ringwald void btstack_chipset_intel_set_firmware_path(const char * path){ 408*29c6772bSMatthias Ringwald firmware_path = path; 409*29c6772bSMatthias Ringwald } 410*29c6772bSMatthias Ringwald 4118174b66aSMatthias Ringwald void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){ 4128174b66aSMatthias Ringwald 4138174b66aSMatthias Ringwald done = callback; 4148174b66aSMatthias Ringwald 4158174b66aSMatthias Ringwald transport = hci_transport;; 4168174b66aSMatthias Ringwald // transport->init(NULL); 4178174b66aSMatthias Ringwald transport->register_packet_handler(&transport_packet_handler); 4188174b66aSMatthias Ringwald transport->open(); 4198174b66aSMatthias Ringwald 4208174b66aSMatthias Ringwald // get started 4218174b66aSMatthias Ringwald state = 0; 4228174b66aSMatthias Ringwald state_machine(NULL); 4238174b66aSMatthias Ringwald } 424