1e501bae0SMatthias Ringwald /* 2e501bae0SMatthias Ringwald * Copyright (C) 2018 BlueKitchen GmbH 3e501bae0SMatthias Ringwald * 4e501bae0SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5e501bae0SMatthias Ringwald * modification, are permitted provided that the following conditions 6e501bae0SMatthias Ringwald * are met: 7e501bae0SMatthias Ringwald * 8e501bae0SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9e501bae0SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10e501bae0SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11e501bae0SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12e501bae0SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13e501bae0SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14e501bae0SMatthias Ringwald * contributors may be used to endorse or promote products derived 15e501bae0SMatthias Ringwald * from this software without specific prior written permission. 16e501bae0SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17e501bae0SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18e501bae0SMatthias Ringwald * monetary gain. 19e501bae0SMatthias Ringwald * 20e501bae0SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21e501bae0SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22e501bae0SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25e501bae0SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26e501bae0SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27e501bae0SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28e501bae0SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29e501bae0SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30e501bae0SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31e501bae0SMatthias Ringwald * SUCH DAMAGE. 32e501bae0SMatthias Ringwald * 33e501bae0SMatthias Ringwald * Please inquire about commercial licensing options at 34e501bae0SMatthias Ringwald * [email protected] 35e501bae0SMatthias Ringwald * 36e501bae0SMatthias Ringwald */ 37e501bae0SMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_chipset_intel_firmware.c" 398174b66aSMatthias Ringwald 408174b66aSMatthias Ringwald #include <fcntl.h> 418174b66aSMatthias Ringwald #include <stdio.h> 425965dbb8SMatthias Ringwald #include <inttypes.h> 438174b66aSMatthias Ringwald 448174b66aSMatthias Ringwald #include "btstack_chipset_intel_firmware.h" 457a4d61a3SMatthias Ringwald 468174b66aSMatthias Ringwald #include "bluetooth.h" 478174b66aSMatthias Ringwald #include "btstack_debug.h" 487a4d61a3SMatthias Ringwald #include "btstack_event.h" 498174b66aSMatthias Ringwald #include "btstack_run_loop.h" 507a4d61a3SMatthias Ringwald #include "btstack_util.h" 517a4d61a3SMatthias Ringwald #include "hci.h" 527a4d61a3SMatthias Ringwald #include "hci_cmd.h" 537a4d61a3SMatthias Ringwald #include "hci_dump.h" 547a4d61a3SMatthias Ringwald 55ce9d10fbSMatthias Ringwald #ifdef _MSC_VER 56ce9d10fbSMatthias Ringwald // ignore deprecated warning for fopen 57ce9d10fbSMatthias Ringwald #pragma warning(disable : 4996) 58ce9d10fbSMatthias Ringwald #endif 59ce9d10fbSMatthias Ringwald 607a4d61a3SMatthias Ringwald // assert outgoing and incoming hci packet buffers can hold max hci command resp. event packet 617a4d61a3SMatthias Ringwald #if HCI_OUTGOING_PACKET_BUFFER_SIZE < (HCI_CMD_HEADER_SIZE + 255) 627a4d61a3SMatthias Ringwald #error "HCI_OUTGOING_PACKET_BUFFER_SIZE to small. Outgoing HCI packet buffer to small for largest HCI Command packet. Please set HCI_ACL_PAYLOAD_SIZE to 258 or higher." 637a4d61a3SMatthias Ringwald #endif 647a4d61a3SMatthias Ringwald #if HCI_INCOMING_PACKET_BUFFER_SIZE < (HCI_EVENT_HEADER_SIZE_HEADER_SIZE + 255) 657a4d61a3SMatthias Ringwald #error "HCI_INCOMING_PACKET_BUFFER_SIZE to small. Incoming HCI packet buffer to small for largest HCI Event packet. Please set HCI_ACL_PAYLOAD_SIZE to 257 or higher." 667a4d61a3SMatthias Ringwald #endif 678174b66aSMatthias Ringwald 688174b66aSMatthias Ringwald // Vendor specific structs 698174b66aSMatthias Ringwald 708174b66aSMatthias Ringwald typedef struct { 718174b66aSMatthias Ringwald uint8_t status; 728174b66aSMatthias Ringwald uint8_t hw_platform; 738174b66aSMatthias Ringwald uint8_t hw_variant; 748174b66aSMatthias Ringwald uint8_t hw_revision; 758174b66aSMatthias Ringwald uint8_t fw_variant; 768174b66aSMatthias Ringwald uint8_t fw_revision; 778174b66aSMatthias Ringwald uint8_t fw_build_num; 788174b66aSMatthias Ringwald uint8_t fw_build_ww; 798174b66aSMatthias Ringwald uint8_t fw_build_yy; 808174b66aSMatthias Ringwald uint8_t fw_patch_num; 818174b66aSMatthias Ringwald } intel_version_t; 828174b66aSMatthias Ringwald 838174b66aSMatthias Ringwald typedef struct { 848174b66aSMatthias Ringwald uint8_t status; 858174b66aSMatthias Ringwald uint8_t otp_format; 868174b66aSMatthias Ringwald uint8_t otp_content; 878174b66aSMatthias Ringwald uint8_t otp_patch; 888174b66aSMatthias Ringwald uint16_t dev_revid; 898174b66aSMatthias Ringwald uint8_t secure_boot; 908174b66aSMatthias Ringwald uint8_t key_from_hdr; 918174b66aSMatthias Ringwald uint8_t key_type; 928174b66aSMatthias Ringwald uint8_t otp_lock; 938174b66aSMatthias Ringwald uint8_t api_lock; 948174b66aSMatthias Ringwald uint8_t debug_lock; 958174b66aSMatthias Ringwald bd_addr_t otp_bdaddr; 968174b66aSMatthias Ringwald uint8_t min_fw_build_nn; 978174b66aSMatthias Ringwald uint8_t min_fw_build_cw; 988174b66aSMatthias Ringwald uint8_t min_fw_build_yy; 998174b66aSMatthias Ringwald uint8_t limited_cce; 1008174b66aSMatthias Ringwald uint8_t unlocked_state; 1018174b66aSMatthias Ringwald } intel_boot_params_t; 1028174b66aSMatthias Ringwald 103f4b0d900SMatthias Ringwald typedef enum { 104f4b0d900SMatthias Ringwald INTEL_CONTROLLER_LEGACY, 105f4b0d900SMatthias Ringwald INTEL_CONTROLLER_TLV, 106f4b0d900SMatthias Ringwald } intel_controller_mode_t; 107f4b0d900SMatthias Ringwald 108bca4e2d9SMatthias Ringwald typedef enum { 109bca4e2d9SMatthias Ringwald STATE_INITIAL = 0, 110bca4e2d9SMatthias Ringwald STATE_HANDLE_HCI_RESET = 1, 111bca4e2d9SMatthias Ringwald STATE_HANDLE_READ_VERSION_1 = 2, 112bca4e2d9SMatthias Ringwald STATE_HANDLE_READ_SECURE_BOOT_PARAMS = 3, 113bca4e2d9SMatthias Ringwald STATE_SEND_PUBLIC_KEY_1 = 4, 114bca4e2d9SMatthias Ringwald STATE_SEND_PUBLIC_KEY_2 = 5, 115bca4e2d9SMatthias Ringwald STATE_SEND_SIGNATURE_PART_1 = 6, 116bca4e2d9SMatthias Ringwald STATE_SEND_SIGNATURE_PART_2 = 7, 117bca4e2d9SMatthias Ringwald STATE_SEND_FIRMWARE_CHUNK = 8, 118bca4e2d9SMatthias Ringwald STATE_HANDLE_FIRMWARE_CHUNKS_SENT = 9, 119bca4e2d9SMatthias Ringwald STATE_HANDLE_VENDOR_SPECIFIC_EVENT_02 = 10, 120bca4e2d9SMatthias Ringwald STATE_HANDLE_READ_VERSION_2 = 11, 121bca4e2d9SMatthias Ringwald STATE_SEND_DDC = 12, 122bca4e2d9SMatthias Ringwald STATE_DONE = 15 123bca4e2d9SMatthias Ringwald } state_t; 124bca4e2d9SMatthias Ringwald 125f4b0d900SMatthias Ringwald // Vendor specific commands 1268174b66aSMatthias Ringwald 1278174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_version = { 128db2cdd6dSMatthias Ringwald 0xfc05, "1" 1298174b66aSMatthias Ringwald }; 1308174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_read_secure_boot_params = { 1318174b66aSMatthias Ringwald 0xfc0d, "" 1328174b66aSMatthias Ringwald }; 1338174b66aSMatthias Ringwald 1348174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_reset_param = { 1358174b66aSMatthias Ringwald 0xfc01, "11111111" 1368174b66aSMatthias Ringwald }; 1378174b66aSMatthias Ringwald 1388174b66aSMatthias Ringwald static const hci_cmd_t hci_intel_set_event_mask = { 1398174b66aSMatthias Ringwald 0xfc52, "11111111" 1408174b66aSMatthias Ringwald }; 1418174b66aSMatthias Ringwald 1428174b66aSMatthias Ringwald // state 1438174b66aSMatthias Ringwald 144bca4e2d9SMatthias Ringwald const char * firmware_folder_path = "."; 145bca4e2d9SMatthias Ringwald 146bca4e2d9SMatthias Ringwald static intel_version_t intel_version; 147bca4e2d9SMatthias Ringwald static intel_boot_params_t intel_boot_params; 14829c6772bSMatthias Ringwald 149f4b0d900SMatthias Ringwald static intel_controller_mode_t controller_mode; 150f4b0d900SMatthias Ringwald 1518174b66aSMatthias Ringwald const hci_transport_t * transport; 1528174b66aSMatthias Ringwald 1535c04b733SMatthias Ringwald static state_t state; 1548174b66aSMatthias Ringwald 155bca4e2d9SMatthias Ringwald static int vendor_firmware_complete_received; 156bca4e2d9SMatthias Ringwald static int waiting_for_command_complete; 157bca4e2d9SMatthias Ringwald 1588174b66aSMatthias Ringwald static uint8_t hci_outgoing[300]; 1598174b66aSMatthias Ringwald static uint8_t fw_buffer[300]; 1608174b66aSMatthias Ringwald 1618174b66aSMatthias Ringwald static uint8_t hw_variant; 1628174b66aSMatthias Ringwald static uint16_t dev_revid; 1638174b66aSMatthias Ringwald 1648174b66aSMatthias Ringwald static FILE * fw_file; 165ce9d10fbSMatthias Ringwald static size_t fw_offset; 1668174b66aSMatthias Ringwald 1678174b66aSMatthias Ringwald static void (*done)(int result); 1688174b66aSMatthias Ringwald 1698174b66aSMatthias Ringwald // functions 1708174b66aSMatthias Ringwald 171*e9d8f008SMatthias Ringwald static int intel_get_firmware_name(intel_version_t *version, intel_boot_params_t *params, const char *folder_path, 172*e9d8f008SMatthias Ringwald const char *suffix, char *firmware_path, size_t firmware_path_len) { 173*e9d8f008SMatthias Ringwald switch (version->hw_variant) 174*e9d8f008SMatthias Ringwald { 175*e9d8f008SMatthias Ringwald case 0x0b: /* SfP */ 176*e9d8f008SMatthias Ringwald case 0x0c: /* WsP */ 177*e9d8f008SMatthias Ringwald snprintf(firmware_path, firmware_path_len, "%s/ibt-%u-%u.%s", 178*e9d8f008SMatthias Ringwald folder_path, 179*e9d8f008SMatthias Ringwald version->hw_variant, 180*e9d8f008SMatthias Ringwald little_endian_read_16((const uint8_t *)¶ms->dev_revid, 0), 181*e9d8f008SMatthias Ringwald suffix); 182*e9d8f008SMatthias Ringwald break; 183*e9d8f008SMatthias Ringwald case 0x11: /* JfP */ 184*e9d8f008SMatthias Ringwald case 0x12: /* ThP */ 185*e9d8f008SMatthias Ringwald case 0x13: /* HrP */ 186*e9d8f008SMatthias Ringwald case 0x14: /* CcP */ 187*e9d8f008SMatthias Ringwald snprintf(firmware_path, firmware_path_len, "%s/ibt-%u-%u-%u.%s", 188*e9d8f008SMatthias Ringwald folder_path, 189*e9d8f008SMatthias Ringwald version->hw_variant, 190*e9d8f008SMatthias Ringwald version->hw_revision, 191*e9d8f008SMatthias Ringwald version->fw_revision, 192*e9d8f008SMatthias Ringwald suffix); 193*e9d8f008SMatthias Ringwald break; 194*e9d8f008SMatthias Ringwald default: 195*e9d8f008SMatthias Ringwald printf("Unsupported Intel hardware variant (%u)\n", version->hw_variant); 196*e9d8f008SMatthias Ringwald break; 197*e9d8f008SMatthias Ringwald } 198*e9d8f008SMatthias Ringwald 199*e9d8f008SMatthias Ringwald return 0; 200*e9d8f008SMatthias Ringwald } 201*e9d8f008SMatthias Ringwald 2028174b66aSMatthias Ringwald static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){ 2038174b66aSMatthias Ringwald hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size); 2048174b66aSMatthias Ringwald return transport->send_packet(packet_type, (uint8_t *) packet, size); 2058174b66aSMatthias Ringwald } 2068174b66aSMatthias Ringwald 2078174b66aSMatthias Ringwald static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){ 2088174b66aSMatthias Ringwald uint8_t * packet = hci_outgoing; 2098174b66aSMatthias Ringwald uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr); 2108174b66aSMatthias Ringwald return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size); 2118174b66aSMatthias Ringwald } 2128174b66aSMatthias Ringwald 2138174b66aSMatthias Ringwald static int transport_send_cmd(const hci_cmd_t *cmd, ...){ 2148174b66aSMatthias Ringwald va_list argptr; 2158174b66aSMatthias Ringwald va_start(argptr, cmd); 2168174b66aSMatthias Ringwald int res = transport_send_cmd_va_arg(cmd, argptr); 2178174b66aSMatthias Ringwald va_end(argptr); 2188174b66aSMatthias Ringwald return res; 2198174b66aSMatthias Ringwald } 2208174b66aSMatthias Ringwald 221ce9d10fbSMatthias Ringwald static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint8_t len){ 2228174b66aSMatthias Ringwald little_endian_store_16(hci_outgoing, 0, 0xfc09); 2238174b66aSMatthias Ringwald hci_outgoing[2] = 1 + len; 2248174b66aSMatthias Ringwald hci_outgoing[3] = fragment_type; 2258174b66aSMatthias Ringwald memcpy(&hci_outgoing[4], data, len); 2268174b66aSMatthias Ringwald uint16_t size = 3 + 1 + len; 2278174b66aSMatthias Ringwald return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size); 2288174b66aSMatthias Ringwald } 2298174b66aSMatthias Ringwald 230ce9d10fbSMatthias Ringwald static int transport_send_intel_ddc(const uint8_t * data, uint8_t len){ 2318174b66aSMatthias Ringwald little_endian_store_16(hci_outgoing, 0, 0xfc8b); 2328174b66aSMatthias Ringwald hci_outgoing[2] = len; 2338174b66aSMatthias Ringwald memcpy(&hci_outgoing[3], data, len); 2348174b66aSMatthias Ringwald uint16_t size = 3 + len; 2358174b66aSMatthias Ringwald return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size); 2368174b66aSMatthias Ringwald } 2378174b66aSMatthias Ringwald 2385b4c35aeSMatthias Ringwald static void state_machine(uint8_t *packet, uint16_t size); 2398174b66aSMatthias Ringwald 2408174b66aSMatthias Ringwald // read data from fw file and send it via intel_secure + update state 241ce9d10fbSMatthias Ringwald static int intel_send_fragment(uint8_t fragment_type, uint8_t len){ 242ce9d10fbSMatthias Ringwald size_t res = fread(fw_buffer, 1, len, fw_file); 2435965dbb8SMatthias Ringwald log_info("offset %6" PRId32 ", read %3u -> res %" PRId32 "", (int32_t)fw_offset, len, (int32_t)res); 2448174b66aSMatthias Ringwald fw_offset += res; 2458174b66aSMatthias Ringwald return transport_send_intel_secure(fragment_type, fw_buffer, len); 2468174b66aSMatthias Ringwald } 2478174b66aSMatthias Ringwald 2488174b66aSMatthias Ringwald // read data from ddc file and send iva intel ddc command 2498174b66aSMatthias Ringwald // @returns -1 on eof 2508174b66aSMatthias Ringwald static int intel_send_ddc(void){ 251ce9d10fbSMatthias Ringwald size_t res; 2528174b66aSMatthias Ringwald // read len 2538174b66aSMatthias Ringwald res = fread(fw_buffer, 1, 1, fw_file); 2545965dbb8SMatthias Ringwald log_info("offset %6" PRId32 ", read 1 -> res %" PRId32 "", (int32_t)fw_offset, (int32_t)res); 2558174b66aSMatthias Ringwald if (res == 0) return -1; 2568174b66aSMatthias Ringwald uint8_t len = fw_buffer[0]; 2578174b66aSMatthias Ringwald fw_offset += 1; 2588174b66aSMatthias Ringwald res = fread(&fw_buffer[1], 1, len, fw_file); 2595965dbb8SMatthias Ringwald log_info("offset %6" PRId32 ", read %u -> res %" PRId32 "", (int32_t)fw_offset, 1, (int32_t)res); 2608174b66aSMatthias Ringwald return transport_send_intel_ddc(fw_buffer, 1 + len); 2618174b66aSMatthias Ringwald } 2628174b66aSMatthias Ringwald 2638174b66aSMatthias Ringwald static void dump_intel_version(intel_version_t * version){ 2648174b66aSMatthias Ringwald log_info("status 0x%02x", version->status); 2658174b66aSMatthias Ringwald log_info("hw_platform 0x%02x", version->hw_platform); 2668174b66aSMatthias Ringwald log_info("hw_variant 0x%02x", version->hw_variant); 2678174b66aSMatthias Ringwald log_info("hw_revision 0x%02x", version->hw_revision); 2688174b66aSMatthias Ringwald log_info("fw_variant 0x%02x", version->fw_variant); 2698174b66aSMatthias Ringwald log_info("fw_revision 0x%02x", version->fw_revision); 2708174b66aSMatthias Ringwald log_info("fw_build_num 0x%02x", version->fw_build_num); 2718174b66aSMatthias Ringwald log_info("fw_build_ww 0x%02x", version->fw_build_ww); 2728174b66aSMatthias Ringwald log_info("fw_build_yy 0x%02x", version->fw_build_yy); 2738174b66aSMatthias Ringwald log_info("fw_patch_num 0x%02x", version->fw_patch_num); 2748174b66aSMatthias Ringwald } 2758174b66aSMatthias Ringwald 2768174b66aSMatthias Ringwald static void dump_intel_boot_params(intel_boot_params_t * boot_params){ 2778174b66aSMatthias Ringwald bd_addr_t addr; 2788174b66aSMatthias Ringwald reverse_bd_addr(boot_params->otp_bdaddr, addr); 2798174b66aSMatthias Ringwald log_info("Device revision: %u", dev_revid); 2808174b66aSMatthias Ringwald log_info("Secure Boot: %s", boot_params->secure_boot ? "enabled" : "disabled"); 2818174b66aSMatthias Ringwald log_info("OTP lock: %s", boot_params->otp_lock ? "enabled" : "disabled"); 2828174b66aSMatthias Ringwald log_info("API lock: %s", boot_params->api_lock ? "enabled" : "disabled"); 2838174b66aSMatthias Ringwald log_info("Debug lock: %s", boot_params->debug_lock ? "enabled" : "disabled"); 2848174b66aSMatthias 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); 2858174b66aSMatthias Ringwald log_info("OTC BD_ADDR: %s", bd_addr_to_str(addr)); 2868174b66aSMatthias Ringwald } 2878174b66aSMatthias Ringwald 2885b4c35aeSMatthias Ringwald static void state_machine(uint8_t *packet, uint16_t size) { 289ce9d10fbSMatthias Ringwald size_t res; 290ce9d10fbSMatthias Ringwald size_t buffer_offset; 2918174b66aSMatthias Ringwald bd_addr_t addr; 29229c6772bSMatthias Ringwald char fw_path[300]; 2938174b66aSMatthias Ringwald 2948174b66aSMatthias Ringwald if (packet){ 2958174b66aSMatthias Ringwald // firmware upload complete event? 2968174b66aSMatthias Ringwald if (packet[0] == 0xff && packet[2] == 0x06) { 2978174b66aSMatthias Ringwald vendor_firmware_complete_received = 1; 2988174b66aSMatthias Ringwald } 2998174b66aSMatthias Ringwald 3008174b66aSMatthias Ringwald // command complete 3018174b66aSMatthias Ringwald if (packet[0] == 0x0e){ 3028174b66aSMatthias Ringwald waiting_for_command_complete = 0; 3038174b66aSMatthias Ringwald } 3048174b66aSMatthias Ringwald } 3058174b66aSMatthias Ringwald 3068174b66aSMatthias Ringwald switch (state){ 3075c04b733SMatthias Ringwald case STATE_INITIAL: 308f4b0d900SMatthias Ringwald controller_mode = INTEL_CONTROLLER_LEGACY; 3095c04b733SMatthias Ringwald state = STATE_HANDLE_HCI_RESET; 3108174b66aSMatthias Ringwald transport_send_cmd(&hci_reset); 3118174b66aSMatthias Ringwald break; 3125c04b733SMatthias Ringwald case STATE_HANDLE_HCI_RESET: 31388362d5eSMatthias Ringwald // check if HCI Reset was supported 31488362d5eSMatthias Ringwald if (packet[0] == 0x0e && packet[1] == 0x04 && packet[3] == 0x03 && packet[4] == 0x0c && packet[5] == 0x00){ 31588362d5eSMatthias Ringwald log_info("HCI Reset was successful, no need for firmware upload / or not an Intel chipset"); 31688362d5eSMatthias Ringwald (*done)(0); 31788362d5eSMatthias Ringwald break; 31888362d5eSMatthias Ringwald } 31988362d5eSMatthias Ringwald 3208174b66aSMatthias Ringwald // Read Intel Version 3215c04b733SMatthias Ringwald state = STATE_HANDLE_READ_VERSION_1; 322db2cdd6dSMatthias Ringwald transport_send_cmd(&hci_intel_read_version, 0xff); 3238174b66aSMatthias Ringwald break; 3245c04b733SMatthias Ringwald case STATE_HANDLE_READ_VERSION_1: 3255c04b733SMatthias Ringwald // detect legacy vs. new TLV mode based on Read Version response 326f4b0d900SMatthias Ringwald if ((size == sizeof(intel_version_t)) || (packet[1] != 0x037)){ 327f4b0d900SMatthias Ringwald controller_mode = INTEL_CONTROLLER_TLV; 328f4b0d900SMatthias Ringwald printf("\nERROR: Intel Controller uses new TLV mode. TLV mode is not supported yet\n"); 329f4b0d900SMatthias Ringwald printf("Details: https://github.com/torvalds/linux/blob/master/drivers/bluetooth/btintel.c\n\n"); 330f4b0d900SMatthias Ringwald log_error("TLV mode not supported"); 331f4b0d900SMatthias Ringwald (*done)(1); 332f4b0d900SMatthias Ringwald break; 333f4b0d900SMatthias Ringwald } 334f4b0d900SMatthias Ringwald 335f4b0d900SMatthias Ringwald // legacy mode 336bca4e2d9SMatthias Ringwald intel_version = *(intel_version_t*) hci_event_command_complete_get_return_parameters(packet); 337bca4e2d9SMatthias Ringwald dump_intel_version(&intel_version); 3388174b66aSMatthias Ringwald 339bca4e2d9SMatthias Ringwald hw_variant = intel_version.hw_variant; 3408174b66aSMatthias Ringwald 3418174b66aSMatthias Ringwald // fw_variant = 0x06 bootloader mode / 0x23 operational mode 342bca4e2d9SMatthias Ringwald if (intel_version.fw_variant == 0x23) { 3438174b66aSMatthias Ringwald (*done)(0); 3448174b66aSMatthias Ringwald break; 3458174b66aSMatthias Ringwald } 3468174b66aSMatthias Ringwald 347bca4e2d9SMatthias Ringwald if (intel_version.fw_variant != 0x06){ 348bca4e2d9SMatthias Ringwald log_error("unknown fw_variant 0x%02x", intel_version.fw_variant); 3498174b66aSMatthias Ringwald break; 3508174b66aSMatthias Ringwald } 3518174b66aSMatthias Ringwald 3528174b66aSMatthias Ringwald // Read Intel Secure Boot Params 3535c04b733SMatthias Ringwald state = STATE_HANDLE_READ_SECURE_BOOT_PARAMS; 3548174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_read_secure_boot_params); 3558174b66aSMatthias Ringwald break; 3565c04b733SMatthias Ringwald case STATE_HANDLE_READ_SECURE_BOOT_PARAMS: 357bca4e2d9SMatthias Ringwald intel_boot_params = *(intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet); 358bca4e2d9SMatthias Ringwald dump_intel_boot_params(&intel_boot_params); 3598174b66aSMatthias Ringwald 360bca4e2d9SMatthias Ringwald reverse_bd_addr(intel_boot_params.otp_bdaddr, addr); 361bca4e2d9SMatthias Ringwald dev_revid = little_endian_read_16((uint8_t*)&intel_boot_params.dev_revid, 0); 3628174b66aSMatthias Ringwald 3635c04b733SMatthias Ringwald // assert command complete is required 364bca4e2d9SMatthias Ringwald if (intel_boot_params.limited_cce != 0) break; 3658174b66aSMatthias Ringwald 3668174b66aSMatthias Ringwald // firmware file 367*e9d8f008SMatthias Ringwald intel_get_firmware_name(&intel_version, &intel_boot_params, firmware_folder_path, 368*e9d8f008SMatthias Ringwald "sfi", fw_path, sizeof(fw_path)); 36929c6772bSMatthias Ringwald log_info("Open firmware %s", fw_path); 3705c04b733SMatthias Ringwald printf("Firmware %s\n", fw_path); 3718174b66aSMatthias Ringwald 3728174b66aSMatthias Ringwald // open firmware file 3738174b66aSMatthias Ringwald fw_offset = 0; 37429c6772bSMatthias Ringwald fw_file = fopen(fw_path, "rb"); 3758174b66aSMatthias Ringwald if (!fw_file){ 37629c6772bSMatthias Ringwald log_error("can't open file %s", fw_path); 3778174b66aSMatthias Ringwald (*done)(1); 3788174b66aSMatthias Ringwald return; 3798174b66aSMatthias Ringwald } 3808174b66aSMatthias Ringwald 3818174b66aSMatthias Ringwald vendor_firmware_complete_received = 0; 3828174b66aSMatthias Ringwald 3838174b66aSMatthias Ringwald // send CCS segment - offset 0 3845c04b733SMatthias Ringwald state = STATE_SEND_PUBLIC_KEY_1; 3858174b66aSMatthias Ringwald intel_send_fragment(0x00, 128); 3868174b66aSMatthias Ringwald break; 3875c04b733SMatthias Ringwald case STATE_SEND_PUBLIC_KEY_1: 3888174b66aSMatthias Ringwald // send public key / part 1 - offset 128 3895c04b733SMatthias Ringwald state = STATE_SEND_PUBLIC_KEY_2; 3908174b66aSMatthias Ringwald intel_send_fragment(0x03, 128); 3918174b66aSMatthias Ringwald break; 3925c04b733SMatthias Ringwald case STATE_SEND_PUBLIC_KEY_2: 3938174b66aSMatthias Ringwald // send public key / part 2 - offset 384 3945c04b733SMatthias Ringwald state = STATE_SEND_SIGNATURE_PART_1; 3958174b66aSMatthias Ringwald intel_send_fragment(0x03, 128); 3968174b66aSMatthias Ringwald break; 3975c04b733SMatthias Ringwald case STATE_SEND_SIGNATURE_PART_1: 3988174b66aSMatthias Ringwald // skip 4 bytes 3998174b66aSMatthias Ringwald res = fread(fw_buffer, 1, 4, fw_file); 4005965dbb8SMatthias Ringwald log_info("read res %d", (int)res); 4018174b66aSMatthias Ringwald fw_offset += res; 4028174b66aSMatthias Ringwald 4038174b66aSMatthias Ringwald // send signature / part 1 - offset 388 4045c04b733SMatthias Ringwald state = STATE_SEND_SIGNATURE_PART_2; 4058174b66aSMatthias Ringwald intel_send_fragment(0x02, 128); 4068174b66aSMatthias Ringwald break; 4075c04b733SMatthias Ringwald case STATE_SEND_SIGNATURE_PART_2: 4088174b66aSMatthias Ringwald // send signature / part 2 - offset 516 4095c04b733SMatthias Ringwald state = STATE_SEND_FIRMWARE_CHUNK; 4108174b66aSMatthias Ringwald intel_send_fragment(0x02, 128); 4118174b66aSMatthias Ringwald break; 4125c04b733SMatthias Ringwald case STATE_SEND_FIRMWARE_CHUNK: 4138174b66aSMatthias Ringwald // send firmware chunks - offset 644 4148174b66aSMatthias Ringwald // chunk len must be 4 byte aligned 4158174b66aSMatthias Ringwald // multiple commands can be combined 4168174b66aSMatthias Ringwald buffer_offset = 0; 4178174b66aSMatthias Ringwald do { 4188174b66aSMatthias Ringwald res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file); 4195965dbb8SMatthias Ringwald log_info("fw_offset %6" PRId32 ", buffer_offset %" PRId32 ", read %3u -> res %" PRId32 "", (int32_t)fw_offset, (int32_t)buffer_offset, 3, (int32_t)res); 4208174b66aSMatthias Ringwald fw_offset += res; 4218174b66aSMatthias Ringwald if (res == 0 ){ 4228174b66aSMatthias Ringwald // EOF 4238174b66aSMatthias Ringwald log_info("End of file"); 4248174b66aSMatthias Ringwald fclose(fw_file); 4258174b66aSMatthias Ringwald fw_file = NULL; 4265c04b733SMatthias Ringwald state = STATE_HANDLE_FIRMWARE_CHUNKS_SENT; 4278174b66aSMatthias Ringwald break; 4288174b66aSMatthias Ringwald } 4298174b66aSMatthias Ringwald int param_len = fw_buffer[buffer_offset + 2]; 4308174b66aSMatthias Ringwald buffer_offset += 3; 4318174b66aSMatthias Ringwald if (param_len){ 4328174b66aSMatthias Ringwald res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file); 4338174b66aSMatthias Ringwald fw_offset += res; 4348174b66aSMatthias Ringwald buffer_offset += res; 4358174b66aSMatthias Ringwald } 4368174b66aSMatthias Ringwald } while ((buffer_offset & 3) != 0); 4378174b66aSMatthias Ringwald 4388174b66aSMatthias Ringwald if (buffer_offset == 0) break; 4398174b66aSMatthias Ringwald 4408174b66aSMatthias Ringwald waiting_for_command_complete = 1; 441ce9d10fbSMatthias Ringwald transport_send_intel_secure(0x01, fw_buffer, (uint8_t) buffer_offset); 4428174b66aSMatthias Ringwald break; 4438174b66aSMatthias Ringwald 4445c04b733SMatthias Ringwald case STATE_HANDLE_FIRMWARE_CHUNKS_SENT: 4458174b66aSMatthias Ringwald // expect Vendor Specific Event 0x06 4468174b66aSMatthias Ringwald if (!vendor_firmware_complete_received) break; 4478174b66aSMatthias Ringwald 4488174b66aSMatthias Ringwald printf("Firmware upload complete\n"); 4498174b66aSMatthias Ringwald log_info("Vendor Event 0x06 - firmware complete"); 4508174b66aSMatthias Ringwald 4518174b66aSMatthias Ringwald // Reset Params - constants from Windows Intel driver 4525c04b733SMatthias Ringwald state = STATE_HANDLE_VENDOR_SPECIFIC_EVENT_02; 4538174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00); 4548174b66aSMatthias Ringwald break; 4558174b66aSMatthias Ringwald 4565c04b733SMatthias Ringwald case STATE_HANDLE_VENDOR_SPECIFIC_EVENT_02: 4578174b66aSMatthias Ringwald // expect Vendor Specific Event 0x02 4588174b66aSMatthias Ringwald if (packet[0] != 0xff) break; 4598174b66aSMatthias Ringwald if (packet[2] != 0x02) break; 4608174b66aSMatthias Ringwald 4618174b66aSMatthias Ringwald printf("Firmware operational\n"); 4628174b66aSMatthias Ringwald log_info("Vendor Event 0x02 - firmware operational"); 4638174b66aSMatthias Ringwald 4648174b66aSMatthias Ringwald // Read Intel Version 4655c04b733SMatthias Ringwald state = STATE_HANDLE_READ_VERSION_2; 4668174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_read_version); 4678174b66aSMatthias Ringwald break; 4688174b66aSMatthias Ringwald 4695c04b733SMatthias Ringwald case STATE_HANDLE_READ_VERSION_2: 470bca4e2d9SMatthias Ringwald intel_version = *(intel_version_t*) hci_event_command_complete_get_return_parameters(packet); 471bca4e2d9SMatthias Ringwald dump_intel_version(&intel_version); 4728174b66aSMatthias Ringwald 4738174b66aSMatthias Ringwald // ddc config 474*e9d8f008SMatthias Ringwald intel_get_firmware_name(&intel_version, &intel_boot_params, firmware_folder_path, 475*e9d8f008SMatthias Ringwald "ddc", fw_path, sizeof(fw_path)); 47629c6772bSMatthias Ringwald log_info("Open DDC %s", fw_path); 4778174b66aSMatthias Ringwald 4788174b66aSMatthias Ringwald // open ddc file 4798174b66aSMatthias Ringwald fw_offset = 0; 48029c6772bSMatthias Ringwald fw_file = fopen(fw_path, "rb"); 4818174b66aSMatthias Ringwald if (!fw_file){ 48229c6772bSMatthias Ringwald log_error("can't open file %s", fw_path); 4838174b66aSMatthias Ringwald 4848174b66aSMatthias Ringwald (*done)(1); 4858174b66aSMatthias Ringwald return; 4868174b66aSMatthias Ringwald } 4878174b66aSMatthias Ringwald 4888174b66aSMatthias Ringwald // load ddc 4895c04b733SMatthias Ringwald state = STATE_SEND_DDC; 4908174b66aSMatthias Ringwald 4918174b66aSMatthias Ringwald /* fall through */ 4928174b66aSMatthias Ringwald 4935c04b733SMatthias Ringwald case STATE_SEND_DDC: 4948174b66aSMatthias Ringwald res = intel_send_ddc(); 4958174b66aSMatthias Ringwald if (res == 0) break; 4968174b66aSMatthias Ringwald 4978174b66aSMatthias Ringwald // DDC download complete 4988174b66aSMatthias Ringwald log_info("Load DDC Complete"); 4998174b66aSMatthias Ringwald 5005c04b733SMatthias Ringwald // TODO: check if we need to wait for HCI Command Complete, resp. add another state here 5018174b66aSMatthias Ringwald 5028174b66aSMatthias Ringwald // Set Intel event mask 0xfc52 5035c04b733SMatthias Ringwald state = STATE_DONE; 5048174b66aSMatthias Ringwald transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 5058174b66aSMatthias Ringwald break; 5068174b66aSMatthias Ringwald 5075c04b733SMatthias Ringwald case STATE_DONE: 5088174b66aSMatthias Ringwald (*done)(0); 5098174b66aSMatthias Ringwald break; 5108174b66aSMatthias Ringwald 5118174b66aSMatthias Ringwald default: 5128174b66aSMatthias Ringwald break; 5138174b66aSMatthias Ringwald } 5148174b66aSMatthias Ringwald } 5158174b66aSMatthias Ringwald 5168174b66aSMatthias Ringwald static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){ 5178174b66aSMatthias Ringwald UNUSED(packet_type); 5188174b66aSMatthias Ringwald // we also get events with packet_type ACL from the controller 5198174b66aSMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size); 5208174b66aSMatthias Ringwald switch (hci_event_packet_get_type(packet)){ 5218174b66aSMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 5228174b66aSMatthias Ringwald case HCI_EVENT_VENDOR_SPECIFIC: 5235b4c35aeSMatthias Ringwald state_machine(packet, size); 5248174b66aSMatthias Ringwald break; 5258174b66aSMatthias Ringwald default: 5268174b66aSMatthias Ringwald break; 5278174b66aSMatthias Ringwald } 5288174b66aSMatthias Ringwald } 5298174b66aSMatthias Ringwald 53029c6772bSMatthias Ringwald void btstack_chipset_intel_set_firmware_path(const char * path){ 531bca4e2d9SMatthias Ringwald firmware_folder_path = path; 53229c6772bSMatthias Ringwald } 53329c6772bSMatthias Ringwald 5348174b66aSMatthias Ringwald void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){ 5358174b66aSMatthias Ringwald 5368174b66aSMatthias Ringwald done = callback; 5378174b66aSMatthias Ringwald 5388174b66aSMatthias Ringwald transport = hci_transport;; 5398174b66aSMatthias Ringwald transport->register_packet_handler(&transport_packet_handler); 5408174b66aSMatthias Ringwald transport->open(); 5418174b66aSMatthias Ringwald 5428174b66aSMatthias Ringwald // get started 5435c04b733SMatthias Ringwald state = STATE_INITIAL; 5445b4c35aeSMatthias Ringwald state_machine(NULL, 0); 5458174b66aSMatthias Ringwald } 546