18bb555aaSBjoern Hartmann /*
274f83314SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH
38bb555aaSBjoern Hartmann *
48bb555aaSBjoern Hartmann * Redistribution and use in source and binary forms, with or without
58bb555aaSBjoern Hartmann * modification, are permitted provided that the following conditions
68bb555aaSBjoern Hartmann * are met:
78bb555aaSBjoern Hartmann *
88bb555aaSBjoern Hartmann * 1. Redistributions of source code must retain the above copyright
98bb555aaSBjoern Hartmann * notice, this list of conditions and the following disclaimer.
108bb555aaSBjoern Hartmann * 2. Redistributions in binary form must reproduce the above copyright
118bb555aaSBjoern Hartmann * notice, this list of conditions and the following disclaimer in the
128bb555aaSBjoern Hartmann * documentation and/or other materials provided with the distribution.
138bb555aaSBjoern Hartmann * 3. Neither the name of the copyright holders nor the names of
148bb555aaSBjoern Hartmann * contributors may be used to endorse or promote products derived
158bb555aaSBjoern Hartmann * from this software without specific prior written permission.
168bb555aaSBjoern Hartmann * 4. Any redistribution, use, or modification is done solely for
178bb555aaSBjoern Hartmann * personal benefit and not for any commercial purpose or for
188bb555aaSBjoern Hartmann * monetary gain.
198bb555aaSBjoern Hartmann *
208bb555aaSBjoern Hartmann * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
218bb555aaSBjoern Hartmann * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
228bb555aaSBjoern Hartmann * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
238bb555aaSBjoern Hartmann * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
248bb555aaSBjoern Hartmann * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
258bb555aaSBjoern Hartmann * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
268bb555aaSBjoern Hartmann * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
278bb555aaSBjoern Hartmann * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
288bb555aaSBjoern Hartmann * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
298bb555aaSBjoern Hartmann * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
308bb555aaSBjoern Hartmann * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318bb555aaSBjoern Hartmann * SUCH DAMAGE.
328bb555aaSBjoern Hartmann *
338bb555aaSBjoern Hartmann * Please inquire about commercial licensing options at
348bb555aaSBjoern Hartmann * [email protected]
358bb555aaSBjoern Hartmann *
368bb555aaSBjoern Hartmann */
378bb555aaSBjoern Hartmann
388bb555aaSBjoern Hartmann #define BTSTACK_FILE__ "btstack_chipset_realtek.c"
398bb555aaSBjoern Hartmann
408bb555aaSBjoern Hartmann /*
418bb555aaSBjoern Hartmann * btstack_chipset_realtek.c
428bb555aaSBjoern Hartmann *
438bb555aaSBjoern Hartmann * Adapter to use REALTEK-based chipsets with BTstack
448bb555aaSBjoern Hartmann */
458bb555aaSBjoern Hartmann
468bb555aaSBjoern Hartmann #include "btstack_chipset_realtek.h"
478bb555aaSBjoern Hartmann
488bb555aaSBjoern Hartmann #include <stddef.h> /* NULL */
498bb555aaSBjoern Hartmann #include <stdio.h>
508bb555aaSBjoern Hartmann #include <string.h> /* memcpy */
518bb555aaSBjoern Hartmann
528bb555aaSBjoern Hartmann #include "btstack_control.h"
538bb555aaSBjoern Hartmann #include "btstack_debug.h"
548bb555aaSBjoern Hartmann #include "btstack_event.h"
557977fdcaSMatthias Ringwald #include "btstack_linked_list.h"
568bb555aaSBjoern Hartmann #include "btstack_util.h"
578bb555aaSBjoern Hartmann #include "hci.h"
588bb555aaSBjoern Hartmann #include "hci_transport.h"
598bb555aaSBjoern Hartmann
6074f83314SMatthias Ringwald #ifdef _MSC_VER
6174f83314SMatthias Ringwald // ignore deprecated warning for fopen
6274f83314SMatthias Ringwald #pragma warning(disable : 4996)
6374f83314SMatthias Ringwald #endif
6474f83314SMatthias Ringwald
658bb555aaSBjoern Hartmann #define ROM_LMP_NONE 0x0000
668bb555aaSBjoern Hartmann #define ROM_LMP_8723a 0x1200
678bb555aaSBjoern Hartmann #define ROM_LMP_8723b 0x8723
687977fdcaSMatthias Ringwald #define ROM_LMP_8821a 0x8821
697977fdcaSMatthias Ringwald #define ROM_LMP_8761a 0x8761
707977fdcaSMatthias Ringwald #define ROM_LMP_8822b 0x8822
717977fdcaSMatthias Ringwald #define ROM_LMP_8852a 0x8852
727977fdcaSMatthias Ringwald #define ROM_LMP_8851b 0x8851
738bb555aaSBjoern Hartmann
747977fdcaSMatthias Ringwald #define HCI_OPCODE_HCI_RTK_DOWNLOAD_FW 0xFC20
757977fdcaSMatthias Ringwald #define HCI_OPCODE_HCI_RTK_READ_ROM_VERSION 0xFC6D
768bb555aaSBjoern Hartmann
777977fdcaSMatthias Ringwald #define READ_SEC_PROJ 4
787977fdcaSMatthias Ringwald
797977fdcaSMatthias Ringwald #define HCI_CMD_SET_OPCODE(buf, opcode) little_endian_store_16(buf, 0, opcode)
807977fdcaSMatthias Ringwald #define HCI_CMD_SET_LENGTH(buf, length) buf[2] = length
817977fdcaSMatthias Ringwald #define HCI_CMD_DOWNLOAD_SET_INDEX(buf, index) buf[3] = index
827977fdcaSMatthias Ringwald #define HCI_CMD_DOWNLOAD_COPY_FW_DATA(buf, firmware, ptr, len) memcpy(buf + 4, firmware + ptr, len)
837977fdcaSMatthias Ringwald
847977fdcaSMatthias Ringwald #define PATCH_SNIPPETS 0x01
857977fdcaSMatthias Ringwald #define PATCH_DUMMY_HEADER 0x02
867977fdcaSMatthias Ringwald #define PATCH_SECURITY_HEADER 0x03
877977fdcaSMatthias Ringwald #define PATCH_OTA_FLAG 0x04
887977fdcaSMatthias Ringwald #define SECTION_HEADER_SIZE 8
897977fdcaSMatthias Ringwald
907977fdcaSMatthias Ringwald /* software id */
917977fdcaSMatthias Ringwald #define RTLPREVIOUS 0x00
927977fdcaSMatthias Ringwald #define RTL8822BU 0x70
937977fdcaSMatthias Ringwald #define RTL8723DU 0x71
947977fdcaSMatthias Ringwald #define RTL8821CU 0x72
957977fdcaSMatthias Ringwald #define RTL8822CU 0x73
967977fdcaSMatthias Ringwald #define RTL8761BU 0x74
977977fdcaSMatthias Ringwald #define RTL8852AU 0x75
987977fdcaSMatthias Ringwald #define RTL8723FU 0x76
997977fdcaSMatthias Ringwald #define RTL8852BU 0x77
1007977fdcaSMatthias Ringwald #define RTL8852CU 0x78
1017977fdcaSMatthias Ringwald #define RTL8822EU 0x79
1027977fdcaSMatthias Ringwald #define RTL8851BU 0x7A
1037977fdcaSMatthias Ringwald
1041747cbabSMatthias Ringwald #pragma pack(push, 1)
1057977fdcaSMatthias Ringwald struct rtk_epatch_entry {
1067977fdcaSMatthias Ringwald uint16_t chipID;
1077977fdcaSMatthias Ringwald uint16_t patch_length;
1087977fdcaSMatthias Ringwald uint32_t start_offset;
1091747cbabSMatthias Ringwald };
1107977fdcaSMatthias Ringwald
1117977fdcaSMatthias Ringwald struct rtk_epatch {
1127977fdcaSMatthias Ringwald uint8_t signature[8];
1137977fdcaSMatthias Ringwald uint32_t fw_version;
1147977fdcaSMatthias Ringwald uint16_t number_of_total_patch;
1157977fdcaSMatthias Ringwald struct rtk_epatch_entry entry[0];
1161747cbabSMatthias Ringwald };
1177977fdcaSMatthias Ringwald
1187977fdcaSMatthias Ringwald struct rtk_extension_entry {
1197977fdcaSMatthias Ringwald uint8_t opcode;
1207977fdcaSMatthias Ringwald uint8_t length;
1217977fdcaSMatthias Ringwald uint8_t *data;
1221747cbabSMatthias Ringwald };
1237977fdcaSMatthias Ringwald
1247977fdcaSMatthias Ringwald struct rtb_section_hdr {
1257977fdcaSMatthias Ringwald uint32_t opcode;
1267977fdcaSMatthias Ringwald uint32_t section_len;
1277977fdcaSMatthias Ringwald uint32_t soffset;
1281747cbabSMatthias Ringwald };
1297977fdcaSMatthias Ringwald
1307977fdcaSMatthias Ringwald struct rtb_new_patch_hdr {
1317977fdcaSMatthias Ringwald uint8_t signature[8];
1327977fdcaSMatthias Ringwald uint8_t fw_version[8];
1337977fdcaSMatthias Ringwald uint32_t number_of_section;
1341747cbabSMatthias Ringwald };
1351747cbabSMatthias Ringwald #pragma pack(pop)
1361747cbabSMatthias Ringwald
1378bb555aaSBjoern Hartmann
1388bb555aaSBjoern Hartmann enum {
1397977fdcaSMatthias Ringwald // Pre-Init: runs before HCI Reset
1407977fdcaSMatthias Ringwald STATE_PHASE_1_READ_LMP_SUBVERSION,
1417977fdcaSMatthias Ringwald STATE_PHASE_1_W4_READ_LMP_SUBVERSION,
1427977fdcaSMatthias Ringwald STATE_PHASE_1_READ_HCI_REVISION,
1437977fdcaSMatthias Ringwald STATE_PHASE_1_W4_READ_HCI_REVISION,
1447977fdcaSMatthias Ringwald STATE_PHASE_1_DONE,
1457977fdcaSMatthias Ringwald // Custom Init: runs after HCI Reset
1467977fdcaSMatthias Ringwald STATE_PHASE_2_READ_ROM_VERSION,
1477977fdcaSMatthias Ringwald STATE_PHASE_2_READ_SEC_PROJ,
1487977fdcaSMatthias Ringwald STATE_PHASE_2_W4_SEC_PROJ,
1497977fdcaSMatthias Ringwald STATE_PHASE_2_LOAD_FIRMWARE,
1507977fdcaSMatthias Ringwald STATE_PHASE_2_RESET,
1517977fdcaSMatthias Ringwald STATE_PHASE_2_DONE,
1528bb555aaSBjoern Hartmann };
1538bb555aaSBjoern Hartmann enum { FW_DONE, FW_MORE_TO_DO };
1548bb555aaSBjoern Hartmann
1558bb555aaSBjoern Hartmann typedef struct {
1568bb555aaSBjoern Hartmann uint16_t prod_id;
1578bb555aaSBjoern Hartmann uint16_t lmp_sub;
1588bb555aaSBjoern Hartmann char * mp_patch_name;
1598bb555aaSBjoern Hartmann char * patch_name;
1608bb555aaSBjoern Hartmann char * config_name;
1618bb555aaSBjoern Hartmann
1628bb555aaSBjoern Hartmann uint8_t *fw_cache1;
1638bb555aaSBjoern Hartmann int fw_len1;
1647977fdcaSMatthias Ringwald uint8_t chip_type;
1658bb555aaSBjoern Hartmann } patch_info;
1668bb555aaSBjoern Hartmann
1677977fdcaSMatthias Ringwald static const patch_info fw_patch_table[] = {
1687977fdcaSMatthias Ringwald /* { pid, lmp_sub, mp_fw_name, fw_name, config_name, chip_type } */
1697977fdcaSMatthias Ringwald {0x1724, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* RTL8723A */
1707977fdcaSMatthias Ringwald {0x8723, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AE */
1717977fdcaSMatthias Ringwald {0xA723, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AE for LI */
1727977fdcaSMatthias Ringwald {0x0723, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AE */
1737977fdcaSMatthias Ringwald {0x3394, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AE for Azurewave */
1748bb555aaSBjoern Hartmann
1757977fdcaSMatthias Ringwald {0x0724, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AU */
1767977fdcaSMatthias Ringwald {0x8725, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AU */
1777977fdcaSMatthias Ringwald {0x872A, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AU */
1787977fdcaSMatthias Ringwald {0x872B, 0x1200, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0, RTLPREVIOUS}, /* 8723AU */
1798bb555aaSBjoern Hartmann
1807977fdcaSMatthias Ringwald {0xb720, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BU */
1817977fdcaSMatthias Ringwald {0xb72A, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BU */
1827977fdcaSMatthias Ringwald {0xb728, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for LC */
1837977fdcaSMatthias Ringwald {0xb723, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1847977fdcaSMatthias Ringwald {0xb72B, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1857977fdcaSMatthias Ringwald {0xb001, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for HP */
1867977fdcaSMatthias Ringwald {0xb002, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1877977fdcaSMatthias Ringwald {0xb003, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1887977fdcaSMatthias Ringwald {0xb004, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1897977fdcaSMatthias Ringwald {0xb005, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE */
1903366b4c1SMatthias Ringwald
1917977fdcaSMatthias Ringwald {0x3410, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Azurewave */
1927977fdcaSMatthias Ringwald {0x3416, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Azurewave */
1937977fdcaSMatthias Ringwald {0x3459, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Azurewave */
1947977fdcaSMatthias Ringwald {0xE085, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Foxconn */
1957977fdcaSMatthias Ringwald {0xE08B, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Foxconn */
1967977fdcaSMatthias Ringwald {0xE09E, 0x8723, "mp_rtl8723b_fw", "rtl8723b_fw", "rtl8723b_config", NULL, 0, RTLPREVIOUS}, /* RTL8723BE for Foxconn */
1978bb555aaSBjoern Hartmann
1987977fdcaSMatthias Ringwald {0xA761, 0x8761, "mp_rtl8761a_fw", "rtl8761au_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AU only */
1997977fdcaSMatthias Ringwald {0x818B, 0x8761, "mp_rtl8761a_fw", "rtl8761aw_fw", "rtl8761aw_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AW + 8192EU */
2007977fdcaSMatthias Ringwald {0x818C, 0x8761, "mp_rtl8761a_fw", "rtl8761aw_fw", "rtl8761aw_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AW + 8192EU */
2017977fdcaSMatthias Ringwald {0x8760, 0x8761, "mp_rtl8761a_fw", "rtl8761au8192ee_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AU + 8192EE */
2027977fdcaSMatthias Ringwald {0xB761, 0x8761, "mp_rtl8761a_fw", "rtl8761au_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AUV only */
2037977fdcaSMatthias Ringwald {0x8761, 0x8761, "mp_rtl8761a_fw", "rtl8761au8192ee_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AU + 8192EE for LI */
2047977fdcaSMatthias Ringwald {0x8A60, 0x8761, "mp_rtl8761a_fw", "rtl8761au8812ae_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AU + 8812AE */
2057977fdcaSMatthias Ringwald {0x3527, 0x8761, "mp_rtl8761a_fw", "rtl8761au8192ee_fw", "rtl8761a_config", NULL, 0, RTLPREVIOUS}, /* RTL8761AU + 8814AE */
2063366b4c1SMatthias Ringwald
2077977fdcaSMatthias Ringwald {0x8821, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2087977fdcaSMatthias Ringwald {0x0821, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2097977fdcaSMatthias Ringwald {0x0823, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AU */
2107977fdcaSMatthias Ringwald {0x3414, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2117977fdcaSMatthias Ringwald {0x3458, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2127977fdcaSMatthias Ringwald {0x3461, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2137977fdcaSMatthias Ringwald {0x3462, 0x8821, "mp_rtl8821a_fw", "rtl8821a_fw", "rtl8821a_config", NULL, 0, RTLPREVIOUS}, /* RTL8821AE */
2143366b4c1SMatthias Ringwald
2157977fdcaSMatthias Ringwald {0xb82c, 0x8822, "mp_rtl8822bu_fw", "rtl8822bu_fw", "rtl8822bu_config", NULL, 0, RTL8822BU}, /* RTL8822BU */
2163366b4c1SMatthias Ringwald
2177977fdcaSMatthias Ringwald {0xd720, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", NULL, 0, RTL8723DU}, /* RTL8723DU */
2187977fdcaSMatthias Ringwald {0xd723, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", NULL, 0, RTL8723DU}, /* RTL8723DU */
2197977fdcaSMatthias Ringwald {0xd739, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", NULL, 0, RTL8723DU}, /* RTL8723DU */
2207977fdcaSMatthias Ringwald {0xb009, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", NULL, 0, RTL8723DU}, /* RTL8723DU */
2217977fdcaSMatthias Ringwald {0x0231, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", NULL, 0, RTL8723DU}, /* RTL8723DU for LiteOn */
2228bb555aaSBjoern Hartmann
2237977fdcaSMatthias Ringwald {0xb820, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CU */
2247977fdcaSMatthias Ringwald {0xc820, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CU */
2257977fdcaSMatthias Ringwald {0xc821, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2267977fdcaSMatthias Ringwald {0xc823, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2277977fdcaSMatthias Ringwald {0xc824, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2287977fdcaSMatthias Ringwald {0xc825, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2297977fdcaSMatthias Ringwald {0xc827, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2307977fdcaSMatthias Ringwald {0xc025, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2317977fdcaSMatthias Ringwald {0xc024, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2327977fdcaSMatthias Ringwald {0xc030, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2337977fdcaSMatthias Ringwald {0xb00a, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2347977fdcaSMatthias Ringwald {0xb00e, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2357977fdcaSMatthias Ringwald {0xc032, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2367977fdcaSMatthias Ringwald {0x4000, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for LiteOn */
2377977fdcaSMatthias Ringwald {0x4001, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for LiteOn */
2387977fdcaSMatthias Ringwald {0x3529, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2397977fdcaSMatthias Ringwald {0x3530, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2407977fdcaSMatthias Ringwald {0x3532, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2417977fdcaSMatthias Ringwald {0x3533, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2427977fdcaSMatthias Ringwald {0x3538, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2437977fdcaSMatthias Ringwald {0x3539, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2447977fdcaSMatthias Ringwald {0x3558, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2457977fdcaSMatthias Ringwald {0x3559, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2467977fdcaSMatthias Ringwald {0x3581, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for Azurewave */
2477977fdcaSMatthias Ringwald {0x3540, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE */
2487977fdcaSMatthias Ringwald {0x3541, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for GSD */
2497977fdcaSMatthias Ringwald {0x3543, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CE for GSD */
2507977fdcaSMatthias Ringwald {0xc80c, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", NULL, 0, RTL8821CU}, /* RTL8821CUH */
2518bb555aaSBjoern Hartmann
2527977fdcaSMatthias Ringwald {0xc82c, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CU */
2537977fdcaSMatthias Ringwald {0xc82e, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CU */
2547977fdcaSMatthias Ringwald {0xc81d, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CU */
2557977fdcaSMatthias Ringwald {0xd820, 0x8822, "mp_rtl8821du_fw", "rtl8821du_fw", "rtl8821du_config", NULL, 0, RTL8822CU}, /* RTL8821DU */
2563366b4c1SMatthias Ringwald
2577977fdcaSMatthias Ringwald {0xc822, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2587977fdcaSMatthias Ringwald {0xc82b, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2597977fdcaSMatthias Ringwald {0xb00c, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2607977fdcaSMatthias Ringwald {0xb00d, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2617977fdcaSMatthias Ringwald {0xc123, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2627977fdcaSMatthias Ringwald {0xc126, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2637977fdcaSMatthias Ringwald {0xc127, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2647977fdcaSMatthias Ringwald {0xc128, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2657977fdcaSMatthias Ringwald {0xc129, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2667977fdcaSMatthias Ringwald {0xc131, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2677977fdcaSMatthias Ringwald {0xc136, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2687977fdcaSMatthias Ringwald {0x3549, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE for Azurewave */
2697977fdcaSMatthias Ringwald {0x3548, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE for Azurewave */
2707977fdcaSMatthias Ringwald {0xc125, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2717977fdcaSMatthias Ringwald {0x4005, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE for LiteOn */
2727977fdcaSMatthias Ringwald {0x3051, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE for LiteOn */
2737977fdcaSMatthias Ringwald {0x18ef, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2747977fdcaSMatthias Ringwald {0x161f, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2757977fdcaSMatthias Ringwald {0x3053, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2767977fdcaSMatthias Ringwald {0xc547, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2777977fdcaSMatthias Ringwald {0x3553, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2787977fdcaSMatthias Ringwald {0x3555, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE */
2797977fdcaSMatthias Ringwald {0xc82f, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE-VS */
2807977fdcaSMatthias Ringwald {0xc02f, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE-VS */
2817977fdcaSMatthias Ringwald {0xc03f, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", NULL, 0, RTL8822CU}, /* RTL8822CE-VS */
2823366b4c1SMatthias Ringwald
2837977fdcaSMatthias Ringwald {0x8771, 0x8761, "mp_rtl8761b_fw", "rtl8761bu_fw", "rtl8761bu_config", NULL, 0, RTL8761BU}, /* RTL8761BU only */
2847977fdcaSMatthias Ringwald {0xa725, 0x8761, "mp_rtl8761b_fw", "rtl8725au_fw", "rtl8725au_config", NULL, 0, RTL8761BU}, /* RTL8725AU */
2857977fdcaSMatthias Ringwald {0xa72A, 0x8761, "mp_rtl8761b_fw", "rtl8725au_fw", "rtl8725au_config", NULL, 0, RTL8761BU}, /* RTL8725AU BT only */
2868bb555aaSBjoern Hartmann
2877977fdcaSMatthias Ringwald {0x885a, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AU */
2887977fdcaSMatthias Ringwald {0x8852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2897977fdcaSMatthias Ringwald {0xa852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2907977fdcaSMatthias Ringwald {0x2852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2917977fdcaSMatthias Ringwald {0x385a, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2927977fdcaSMatthias Ringwald {0x3852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2937977fdcaSMatthias Ringwald {0x1852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2947977fdcaSMatthias Ringwald {0x4852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2957977fdcaSMatthias Ringwald {0x4006, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2967977fdcaSMatthias Ringwald {0x3561, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2977977fdcaSMatthias Ringwald {0x3562, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2987977fdcaSMatthias Ringwald {0x588a, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
2997977fdcaSMatthias Ringwald {0x589a, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3007977fdcaSMatthias Ringwald {0x590a, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3017977fdcaSMatthias Ringwald {0xc125, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3027977fdcaSMatthias Ringwald {0xe852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3037977fdcaSMatthias Ringwald {0xb852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3047977fdcaSMatthias Ringwald {0xc852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3057977fdcaSMatthias Ringwald {0xc549, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3067977fdcaSMatthias Ringwald {0xc127, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3077977fdcaSMatthias Ringwald {0x3565, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", NULL, 0, RTL8852AU}, /* RTL8852AE */
3088bb555aaSBjoern Hartmann
3097977fdcaSMatthias Ringwald {0xb733, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", NULL, 0, RTL8723FU}, /* RTL8723FU */
3107977fdcaSMatthias Ringwald {0xb73a, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", NULL, 0, RTL8723FU}, /* RTL8723FU */
3117977fdcaSMatthias Ringwald {0xf72b, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", NULL, 0, RTL8723FU}, /* RTL8723FU */
3123366b4c1SMatthias Ringwald
3137977fdcaSMatthias Ringwald {0x8851, 0x8852, "mp_rtl8851au_fw", "rtl8851au_fw", "rtl8851au_config", NULL, 0, RTL8852BU}, /* RTL8851AU */
3147977fdcaSMatthias Ringwald {0xa85b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BU */
3157977fdcaSMatthias Ringwald {0xb85b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3167977fdcaSMatthias Ringwald {0xb85c, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3177977fdcaSMatthias Ringwald {0x3571, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3187977fdcaSMatthias Ringwald {0x3570, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3197977fdcaSMatthias Ringwald {0x3572, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3207977fdcaSMatthias Ringwald {0x4b06, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3217977fdcaSMatthias Ringwald {0x885b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3227977fdcaSMatthias Ringwald {0x886b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3237977fdcaSMatthias Ringwald {0x887b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3247977fdcaSMatthias Ringwald {0xc559, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3257977fdcaSMatthias Ringwald {0xb052, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3267977fdcaSMatthias Ringwald {0xb152, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3277977fdcaSMatthias Ringwald {0xb252, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3287977fdcaSMatthias Ringwald {0x4853, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3297977fdcaSMatthias Ringwald {0x1670, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", NULL, 0, RTL8852BU}, /* RTL8852BE */
3303366b4c1SMatthias Ringwald
3317977fdcaSMatthias Ringwald {0xc85a, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CU */
3327977fdcaSMatthias Ringwald {0x0852, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3337977fdcaSMatthias Ringwald {0x5852, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3347977fdcaSMatthias Ringwald {0xc85c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3357977fdcaSMatthias Ringwald {0x885c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3367977fdcaSMatthias Ringwald {0x886c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3377977fdcaSMatthias Ringwald {0x887c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3387977fdcaSMatthias Ringwald {0x4007, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", NULL, 0, RTL8852CU}, /* RTL8852CE */
3393366b4c1SMatthias Ringwald
3407977fdcaSMatthias Ringwald {0xe822, 0x8822, "mp_rtl8822eu_fw", "rtl8822eu_fw", "rtl8822eu_config", NULL, 0, RTL8822EU}, /* RTL8822EU */
3417977fdcaSMatthias Ringwald {0xa82a, 0x8822, "mp_rtl8822eu_fw", "rtl8822eu_fw", "rtl8822eu_config", NULL, 0, RTL8822EU}, /* RTL8822EU */
3423366b4c1SMatthias Ringwald
3437977fdcaSMatthias Ringwald {0xb851, 0x8851, "mp_rtl8851bu_fw", "rtl8851bu_fw", "rtl8851bu_config", NULL, 0, RTL8851BU}, /* RTL8851BU */
3448bb555aaSBjoern Hartmann
3458bb555aaSBjoern Hartmann /* NOTE: must append patch entries above the null entry */
3467977fdcaSMatthias Ringwald {0, 0, NULL, NULL, NULL, NULL, 0, 0}
3477977fdcaSMatthias Ringwald };
3488bb555aaSBjoern Hartmann
3497977fdcaSMatthias Ringwald static uint16_t project_id[] = {
3508bb555aaSBjoern Hartmann ROM_LMP_8723a, ROM_LMP_8723b, ROM_LMP_8821a, ROM_LMP_8761a, ROM_LMP_NONE,
3518bb555aaSBjoern Hartmann ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8822b, ROM_LMP_8723b, /* RTL8723DU */
3528bb555aaSBjoern Hartmann ROM_LMP_8821a, /* RTL8821CU */
3538bb555aaSBjoern Hartmann ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8822b, /* RTL8822CU */
3548bb555aaSBjoern Hartmann ROM_LMP_8761a, /* index 14 for 8761BU */
3557977fdcaSMatthias Ringwald ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8852a, /* index 18 for 8852AU */
3567977fdcaSMatthias Ringwald ROM_LMP_8723b, /* index 19 for 8723FU */
3577977fdcaSMatthias Ringwald ROM_LMP_8852a, /* index 20 for 8852BU */
3587977fdcaSMatthias Ringwald ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8852a, /* index 25 for 8852CU */
3597977fdcaSMatthias Ringwald ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_NONE,
3607977fdcaSMatthias Ringwald ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8822b, /* index 33 for 8822EU */
3617977fdcaSMatthias Ringwald ROM_LMP_NONE, ROM_LMP_NONE, ROM_LMP_8851b, /* index 36 for 8851BU */
3628bb555aaSBjoern Hartmann };
3638bb555aaSBjoern Hartmann
3648bb555aaSBjoern Hartmann static btstack_packet_callback_registration_t hci_event_callback_registration;
3657977fdcaSMatthias Ringwald static uint8_t state;
3668bb555aaSBjoern Hartmann static uint8_t rom_version;
3678bb555aaSBjoern Hartmann static uint16_t lmp_subversion;
3688bb555aaSBjoern Hartmann static uint16_t product_id;
3697977fdcaSMatthias Ringwald static const patch_info * patch;
3707977fdcaSMatthias Ringwald static uint8_t g_key_id = 0;
3718bb555aaSBjoern Hartmann
3728bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
3738bb555aaSBjoern Hartmann static const char *firmware_folder_path = ".";
3748bb555aaSBjoern Hartmann static const char *firmware_file_path;
3758bb555aaSBjoern Hartmann static const char *config_folder_path = ".";
3768bb555aaSBjoern Hartmann static const char *config_file_path;
3778bb555aaSBjoern Hartmann static char firmware_file[1000];
3788bb555aaSBjoern Hartmann static char config_file[1000];
3798bb555aaSBjoern Hartmann #endif
3808bb555aaSBjoern Hartmann
3817977fdcaSMatthias Ringwald static const uint8_t FW_SIGNATURE[8] = {0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x63, 0x68};
3827977fdcaSMatthias Ringwald static const uint8_t FW_SIGNATURE_NEW[8] = {0x52, 0x54, 0x42, 0x54, 0x43, 0x6F, 0x72, 0x65};
3837977fdcaSMatthias Ringwald static const uint8_t EXTENSION_SIGNATURE[4] = {0x51, 0x04, 0xFD, 0x77};
3848bb555aaSBjoern Hartmann
hci_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)3858bb555aaSBjoern Hartmann static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
3868bb555aaSBjoern Hartmann UNUSED(channel);
3878bb555aaSBjoern Hartmann UNUSED(size);
3887977fdcaSMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) {
3898bb555aaSBjoern Hartmann return;
3908bb555aaSBjoern Hartmann }
3917977fdcaSMatthias Ringwald if (hci_event_packet_get_type(packet) != HCI_EVENT_COMMAND_COMPLETE) {
3927977fdcaSMatthias Ringwald return;
3937977fdcaSMatthias Ringwald }
3948bb555aaSBjoern Hartmann
3957977fdcaSMatthias Ringwald uint16_t opcode = hci_event_command_complete_get_command_opcode(packet);
3967977fdcaSMatthias Ringwald const uint8_t * return_para = hci_event_command_complete_get_return_parameters(packet);
3978bb555aaSBjoern Hartmann switch (opcode) {
3987977fdcaSMatthias Ringwald case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION:
3997977fdcaSMatthias Ringwald lmp_subversion = little_endian_read_16(packet, 12);
4007977fdcaSMatthias Ringwald break;
4017977fdcaSMatthias Ringwald case HCI_OPCODE_HCI_RTK_READ_ROM_VERSION:
4027977fdcaSMatthias Ringwald rom_version = return_para[1];
4038bb555aaSBjoern Hartmann log_info("Received ROM version 0x%02x", rom_version);
4047977fdcaSMatthias Ringwald printf("Realtek: Received ROM version 0x%02x\n", rom_version);
4057977fdcaSMatthias Ringwald if (patch->lmp_sub != lmp_subversion) {
4067977fdcaSMatthias Ringwald printf("Realtek: Firmware already exists\n");
4077977fdcaSMatthias Ringwald state = STATE_PHASE_2_DONE;
4087977fdcaSMatthias Ringwald }
4097977fdcaSMatthias Ringwald break;
4107977fdcaSMatthias Ringwald case HCI_OPCODE_HCI_RTK_READ_CARD_INFO:
4117977fdcaSMatthias Ringwald switch (state){
4127977fdcaSMatthias Ringwald case STATE_PHASE_1_W4_READ_LMP_SUBVERSION:
4137977fdcaSMatthias Ringwald log_info("Read Card: LMP Subversion");
4147977fdcaSMatthias Ringwald if (little_endian_read_16(hci_event_command_complete_get_return_parameters(packet), 1) == 0x8822){
4157977fdcaSMatthias Ringwald state = STATE_PHASE_1_READ_HCI_REVISION;
4167977fdcaSMatthias Ringwald } else {
4177977fdcaSMatthias Ringwald state = STATE_PHASE_1_DONE;
4187977fdcaSMatthias Ringwald }
4197977fdcaSMatthias Ringwald break;
4207977fdcaSMatthias Ringwald case STATE_PHASE_1_W4_READ_HCI_REVISION:
4217977fdcaSMatthias Ringwald log_info("Read Card: HCI Revision");
4227977fdcaSMatthias Ringwald if (little_endian_read_16(hci_event_command_complete_get_return_parameters(packet), 1) == 0x000e){
4237977fdcaSMatthias Ringwald state = STATE_PHASE_2_READ_ROM_VERSION;
4247977fdcaSMatthias Ringwald } else {
4257977fdcaSMatthias Ringwald state = STATE_PHASE_1_DONE;
4267977fdcaSMatthias Ringwald }
4277977fdcaSMatthias Ringwald break;
4287977fdcaSMatthias Ringwald case STATE_PHASE_2_W4_SEC_PROJ:
4297977fdcaSMatthias Ringwald g_key_id = return_para[1];
4307977fdcaSMatthias Ringwald printf("Realtek: Received key id 0x%02x\n", g_key_id);
4317977fdcaSMatthias Ringwald state = STATE_PHASE_2_LOAD_FIRMWARE;
4327977fdcaSMatthias Ringwald break;
4337977fdcaSMatthias Ringwald default:
4347977fdcaSMatthias Ringwald btstack_assert(false);
4357977fdcaSMatthias Ringwald break;
4367977fdcaSMatthias Ringwald }
4378bb555aaSBjoern Hartmann break;
4388bb555aaSBjoern Hartmann default:
4398bb555aaSBjoern Hartmann break;
4408bb555aaSBjoern Hartmann }
4418bb555aaSBjoern Hartmann }
4428bb555aaSBjoern Hartmann
chipset_init(const void * config)4438bb555aaSBjoern Hartmann static void chipset_init(const void *config) {
4448bb555aaSBjoern Hartmann UNUSED(config);
4457977fdcaSMatthias Ringwald
4467977fdcaSMatthias Ringwald // pre-set lmp subversion: HCI starts custom download only if HCI Version = 0x00e, and LMP Subversion = 0x8822
4477977fdcaSMatthias Ringwald lmp_subversion = 0x8822;
4487977fdcaSMatthias Ringwald
4498bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
4508bb555aaSBjoern Hartmann // determine file path
4518bb555aaSBjoern Hartmann if (firmware_file_path == NULL || config_file_path == NULL) {
4528bb555aaSBjoern Hartmann log_info("firmware or config file path is empty. Using product id 0x%04x!", product_id);
4538bb555aaSBjoern Hartmann patch = NULL;
45492728706SMatthias Ringwald for (uint16_t i = 0; i < sizeof(fw_patch_table) / sizeof(patch_info); i++) {
4558bb555aaSBjoern Hartmann if (fw_patch_table[i].prod_id == product_id) {
4568bb555aaSBjoern Hartmann patch = &fw_patch_table[i];
4578bb555aaSBjoern Hartmann break;
4588bb555aaSBjoern Hartmann }
4598bb555aaSBjoern Hartmann }
4608bb555aaSBjoern Hartmann if (patch == NULL) {
4618bb555aaSBjoern Hartmann log_info("Product id 0x%04x is unknown", product_id);
4627977fdcaSMatthias Ringwald state = STATE_PHASE_2_DONE;
4638bb555aaSBjoern Hartmann return;
4648bb555aaSBjoern Hartmann }
465c75b474dSMatthias Ringwald btstack_snprintf_assert_complete(firmware_file, sizeof(firmware_file), "%s/%s", firmware_folder_path, patch->patch_name);
466c75b474dSMatthias Ringwald btstack_snprintf_assert_complete(config_file, sizeof(config_file), "%s/%s", config_folder_path, patch->config_name);
4678bb555aaSBjoern Hartmann firmware_file_path = &firmware_file[0];
4688bb555aaSBjoern Hartmann config_file_path = &config_file[0];
4697977fdcaSMatthias Ringwald //lmp_subversion = patch->lmp_sub;
4708bb555aaSBjoern Hartmann }
4718bb555aaSBjoern Hartmann log_info("Using firmware '%s' and config '%s'", firmware_file_path, config_file_path);
4727977fdcaSMatthias Ringwald printf("Realtek: Using firmware '%s' and config '%s'\n", firmware_file_path, config_file_path);
4738bb555aaSBjoern Hartmann
4748bb555aaSBjoern Hartmann // activate hci callback
4758bb555aaSBjoern Hartmann hci_event_callback_registration.callback = &hci_packet_handler;
4768bb555aaSBjoern Hartmann hci_add_event_handler(&hci_event_callback_registration);
4777977fdcaSMatthias Ringwald state = STATE_PHASE_1_READ_LMP_SUBVERSION;
4788bb555aaSBjoern Hartmann #endif
4798bb555aaSBjoern Hartmann }
4808bb555aaSBjoern Hartmann
4818bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
4828bb555aaSBjoern Hartmann
4838bb555aaSBjoern Hartmann /**
4848bb555aaSBjoern Hartmann * @brief Opens the specified file and stores content to an allocated buffer
4858bb555aaSBjoern Hartmann *
4868bb555aaSBjoern Hartmann * @param file
4878bb555aaSBjoern Hartmann * @param buf
4888bb555aaSBjoern Hartmann * @param name
4898bb555aaSBjoern Hartmann * @return uint32_t Length of file
4908bb555aaSBjoern Hartmann */
read_file(FILE ** file,uint8_t ** buf,const char * name)4918bb555aaSBjoern Hartmann static uint32_t read_file(FILE **file, uint8_t **buf, const char *name) {
4928bb555aaSBjoern Hartmann uint32_t size;
4938bb555aaSBjoern Hartmann
4948bb555aaSBjoern Hartmann // open file
4958bb555aaSBjoern Hartmann *file = fopen(name, "rb");
4968bb555aaSBjoern Hartmann if (*file == NULL) {
4978bb555aaSBjoern Hartmann log_info("Failed to open file %s", name);
4988bb555aaSBjoern Hartmann return 0;
4998bb555aaSBjoern Hartmann }
5008bb555aaSBjoern Hartmann
5018bb555aaSBjoern Hartmann // determine length of file
5028bb555aaSBjoern Hartmann fseek(*file, 0, SEEK_END);
5038bb555aaSBjoern Hartmann size = ftell(*file);
5048bb555aaSBjoern Hartmann fseek(*file, 0, SEEK_SET);
5058bb555aaSBjoern Hartmann if (size <= 0) {
5068bb555aaSBjoern Hartmann return 0;
5078bb555aaSBjoern Hartmann }
5088bb555aaSBjoern Hartmann
5098bb555aaSBjoern Hartmann // allocate memory
5108bb555aaSBjoern Hartmann *buf = malloc(size);
5118bb555aaSBjoern Hartmann if (*buf == NULL) {
5128bb555aaSBjoern Hartmann fclose(*file);
5138bb555aaSBjoern Hartmann *file = NULL;
5148bb555aaSBjoern Hartmann log_info("Failed to allocate %u bytes for file %s", size, name);
5158bb555aaSBjoern Hartmann return 0;
5168bb555aaSBjoern Hartmann }
5178bb555aaSBjoern Hartmann
5188bb555aaSBjoern Hartmann // read file
51958080ea6SMatthias Ringwald size_t ret = fread(*buf, size, 1, *file);
5208bb555aaSBjoern Hartmann if (ret != 1) {
52109fffc16SMatthias Ringwald log_info("Failed to read %u bytes from file %s (ret = %d)", size, name, (int) ret);
5228bb555aaSBjoern Hartmann fclose(*file);
5238bb555aaSBjoern Hartmann free(*buf);
5248bb555aaSBjoern Hartmann *file = NULL;
5258bb555aaSBjoern Hartmann *buf = NULL;
5268bb555aaSBjoern Hartmann return 0;
5278bb555aaSBjoern Hartmann }
5288bb555aaSBjoern Hartmann
5298bb555aaSBjoern Hartmann log_info("Opened file %s and read %u bytes", name, size);
5308bb555aaSBjoern Hartmann return size;
5318bb555aaSBjoern Hartmann }
5328bb555aaSBjoern Hartmann
finalize_file_and_buffer(FILE ** file,uint8_t ** buffer)5338bb555aaSBjoern Hartmann static void finalize_file_and_buffer(FILE **file, uint8_t **buffer) {
5348bb555aaSBjoern Hartmann fclose(*file);
5358bb555aaSBjoern Hartmann free(*buffer);
5368bb555aaSBjoern Hartmann *buffer = NULL;
5378bb555aaSBjoern Hartmann *file = NULL;
5388bb555aaSBjoern Hartmann }
5398bb555aaSBjoern Hartmann
rtk_get_fw_project_id(uint8_t * p_buf)5407977fdcaSMatthias Ringwald static uint8_t rtk_get_fw_project_id(uint8_t * p_buf)
5417977fdcaSMatthias Ringwald {
5427977fdcaSMatthias Ringwald uint8_t opcode;
5437977fdcaSMatthias Ringwald uint8_t len;
5447977fdcaSMatthias Ringwald uint8_t data = 0;
5457977fdcaSMatthias Ringwald
5467977fdcaSMatthias Ringwald do {
5477977fdcaSMatthias Ringwald opcode = *p_buf;
5487977fdcaSMatthias Ringwald len = *(p_buf - 1);
5497977fdcaSMatthias Ringwald if (opcode == 0x00) {
5507977fdcaSMatthias Ringwald if (len == 1) {
5517977fdcaSMatthias Ringwald data = *(p_buf - 2);
5527977fdcaSMatthias Ringwald log_info
5537977fdcaSMatthias Ringwald ("rtk_get_fw_project_id: opcode %d, len %d, data %d",
5547977fdcaSMatthias Ringwald opcode, len, data);
5557977fdcaSMatthias Ringwald break;
5567977fdcaSMatthias Ringwald } else {
5577977fdcaSMatthias Ringwald log_error
5587977fdcaSMatthias Ringwald ("rtk_get_fw_project_id: invalid len %d",
5597977fdcaSMatthias Ringwald len);
5607977fdcaSMatthias Ringwald }
5617977fdcaSMatthias Ringwald }
5627977fdcaSMatthias Ringwald p_buf -= len + 2;
5637977fdcaSMatthias Ringwald } while (*p_buf != 0xFF);
5647977fdcaSMatthias Ringwald
5657977fdcaSMatthias Ringwald return data;
5667977fdcaSMatthias Ringwald }
5677977fdcaSMatthias Ringwald
5687977fdcaSMatthias Ringwald struct rtb_ota_flag {
5697977fdcaSMatthias Ringwald uint8_t eco;
5707977fdcaSMatthias Ringwald uint8_t enable;
5717977fdcaSMatthias Ringwald uint16_t reserve;
5727977fdcaSMatthias Ringwald };
5737977fdcaSMatthias Ringwald
5747977fdcaSMatthias Ringwald struct patch_node {
5757977fdcaSMatthias Ringwald btstack_linked_item_t item;
5767977fdcaSMatthias Ringwald uint8_t eco;
5777977fdcaSMatthias Ringwald uint8_t pri;
5787977fdcaSMatthias Ringwald uint8_t key_id;
5797977fdcaSMatthias Ringwald uint8_t reserve;
5807977fdcaSMatthias Ringwald uint32_t len;
5817977fdcaSMatthias Ringwald uint8_t *payload;
5827977fdcaSMatthias Ringwald };
5837977fdcaSMatthias Ringwald
5847977fdcaSMatthias Ringwald /* Add a node to alist that is in ascending order. */
insert_queue_sort(btstack_linked_list_t * list,struct patch_node * node)5857977fdcaSMatthias Ringwald static void insert_queue_sort(btstack_linked_list_t * list, struct patch_node *node)
5867977fdcaSMatthias Ringwald {
5877977fdcaSMatthias Ringwald btstack_assert(list != NULL);
5887977fdcaSMatthias Ringwald btstack_assert(node != NULL);
5897977fdcaSMatthias Ringwald
5907977fdcaSMatthias Ringwald struct patch_node *next;
5917977fdcaSMatthias Ringwald btstack_linked_item_t *it;
5927977fdcaSMatthias Ringwald
5937977fdcaSMatthias Ringwald for (it = (btstack_linked_item_t *) list; it->next ; it = it->next){
5947977fdcaSMatthias Ringwald next = (struct patch_node *) it->next;
5957977fdcaSMatthias Ringwald if(next->pri >= node->pri) {
5967977fdcaSMatthias Ringwald break;
5977977fdcaSMatthias Ringwald }
5987977fdcaSMatthias Ringwald }
5997977fdcaSMatthias Ringwald node->item.next = it->next;
6007977fdcaSMatthias Ringwald it->next = (btstack_linked_item_t *) node;
6017977fdcaSMatthias Ringwald }
6027977fdcaSMatthias Ringwald
insert_patch(btstack_linked_list_t * patch_list,uint8_t * section_pos,uint32_t opcode,uint32_t * patch_len,uint8_t * sec_flag)6037977fdcaSMatthias Ringwald static int insert_patch(btstack_linked_list_t * patch_list, uint8_t *section_pos,
6047977fdcaSMatthias Ringwald uint32_t opcode, uint32_t *patch_len, uint8_t *sec_flag)
6057977fdcaSMatthias Ringwald {
6067977fdcaSMatthias Ringwald struct patch_node *tmp;
6077977fdcaSMatthias Ringwald uint32_t i;
6087977fdcaSMatthias Ringwald uint32_t numbers;
6097977fdcaSMatthias Ringwald uint32_t section_len = 0;
6107977fdcaSMatthias Ringwald uint8_t eco = 0;
6117977fdcaSMatthias Ringwald uint8_t *pos = section_pos + 8;
6127977fdcaSMatthias Ringwald
6137977fdcaSMatthias Ringwald numbers = little_endian_read_16(pos, 0);
6147977fdcaSMatthias Ringwald log_info("number 0x%04x", numbers);
6157977fdcaSMatthias Ringwald
6167977fdcaSMatthias Ringwald pos += 4;
6177977fdcaSMatthias Ringwald for (i = 0; i < numbers; i++) {
6187977fdcaSMatthias Ringwald eco = (uint8_t)*(pos);
6197977fdcaSMatthias Ringwald log_info("eco 0x%02x, Eversion:%02x", eco, rom_version);
6207977fdcaSMatthias Ringwald if (eco == rom_version + 1) {
6217977fdcaSMatthias Ringwald //tmp = (struct patch_node*)kzalloc(sizeof(struct patch_node), GFP_KERNEL);
6227977fdcaSMatthias Ringwald tmp = (struct patch_node*)malloc(sizeof(struct patch_node));
6237977fdcaSMatthias Ringwald tmp->pri = (uint8_t)*(pos + 1);
6247977fdcaSMatthias Ringwald if(opcode == PATCH_SECURITY_HEADER)
6257977fdcaSMatthias Ringwald tmp->key_id = (uint8_t)*(pos + 1);
6267977fdcaSMatthias Ringwald
6277977fdcaSMatthias Ringwald section_len = little_endian_read_32(pos, 4);
6287977fdcaSMatthias Ringwald tmp->len = section_len;
6297977fdcaSMatthias Ringwald *patch_len += section_len;
6307977fdcaSMatthias Ringwald log_info("Pri:%d, Patch length 0x%04x", tmp->pri, tmp->len);
6317977fdcaSMatthias Ringwald tmp->payload = pos + 8;
6327977fdcaSMatthias Ringwald if(opcode != PATCH_SECURITY_HEADER) {
6337977fdcaSMatthias Ringwald insert_queue_sort(patch_list, tmp);
6347977fdcaSMatthias Ringwald } else {
6357977fdcaSMatthias Ringwald if((g_key_id == tmp->key_id) && (g_key_id > 0)) {
6367977fdcaSMatthias Ringwald insert_queue_sort(patch_list, tmp);
6377977fdcaSMatthias Ringwald *sec_flag = 1;
6387977fdcaSMatthias Ringwald } else {
6397977fdcaSMatthias Ringwald pos += (8 + section_len);
6407977fdcaSMatthias Ringwald free(tmp);
6417977fdcaSMatthias Ringwald continue;
6427977fdcaSMatthias Ringwald }
6437977fdcaSMatthias Ringwald }
6447977fdcaSMatthias Ringwald } else {
6457977fdcaSMatthias Ringwald section_len = little_endian_read_32(pos, 4);
6467977fdcaSMatthias Ringwald log_info("Patch length 0x%04x", section_len);
6477977fdcaSMatthias Ringwald }
6487977fdcaSMatthias Ringwald pos += (8 + section_len);
6497977fdcaSMatthias Ringwald }
6507977fdcaSMatthias Ringwald return 0;
6517977fdcaSMatthias Ringwald }
rtb_get_patch_header(uint32_t * len,btstack_linked_list_t * patch_list,uint8_t * epatch_buf,uint8_t key_id)6527977fdcaSMatthias Ringwald static uint8_t *rtb_get_patch_header(uint32_t *len,
6537977fdcaSMatthias Ringwald btstack_linked_list_t * patch_list, uint8_t * epatch_buf,
6547977fdcaSMatthias Ringwald uint8_t key_id)
6557977fdcaSMatthias Ringwald {
656*5449042eSMatthias Ringwald UNUSED(key_id);
6577977fdcaSMatthias Ringwald uint16_t i, j;
6587977fdcaSMatthias Ringwald struct rtb_new_patch_hdr *new_patch;
6597977fdcaSMatthias Ringwald uint8_t sec_flag = 0;
6607977fdcaSMatthias Ringwald uint32_t number_of_ota_flag;
6617977fdcaSMatthias Ringwald uint32_t patch_len = 0;
6627977fdcaSMatthias Ringwald uint8_t *section_pos;
6637977fdcaSMatthias Ringwald uint8_t *ota_flag_pos;
6647977fdcaSMatthias Ringwald uint32_t number_of_section;
6657977fdcaSMatthias Ringwald
6667977fdcaSMatthias Ringwald struct rtb_section_hdr section_hdr;
6677977fdcaSMatthias Ringwald struct rtb_ota_flag ota_flag;
6687977fdcaSMatthias Ringwald
6697977fdcaSMatthias Ringwald new_patch = (struct rtb_new_patch_hdr *)epatch_buf;
6707977fdcaSMatthias Ringwald number_of_section = new_patch->number_of_section;
6717977fdcaSMatthias Ringwald
6727977fdcaSMatthias Ringwald log_info("FW version 0x%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x",
6737977fdcaSMatthias Ringwald *(epatch_buf + 8), *(epatch_buf + 9), *(epatch_buf + 10),
6747977fdcaSMatthias Ringwald *(epatch_buf + 11),*(epatch_buf + 12), *(epatch_buf + 13),
6757977fdcaSMatthias Ringwald *(epatch_buf + 14), *(epatch_buf + 15));
6767977fdcaSMatthias Ringwald
6777977fdcaSMatthias Ringwald section_pos = epatch_buf + 20;
6787977fdcaSMatthias Ringwald
6797977fdcaSMatthias Ringwald for (i = 0; i < number_of_section; i++) {
6807977fdcaSMatthias Ringwald section_hdr.opcode = little_endian_read_32(section_pos, 0);
6817977fdcaSMatthias Ringwald section_hdr.section_len = little_endian_read_32(section_pos, 4);
6827977fdcaSMatthias Ringwald log_info("opcode 0x%04x", section_hdr.opcode);
6837977fdcaSMatthias Ringwald switch (section_hdr.opcode) {
6847977fdcaSMatthias Ringwald case PATCH_SNIPPETS:
6857977fdcaSMatthias Ringwald insert_patch(patch_list, section_pos, PATCH_SNIPPETS, &patch_len, NULL);
6867977fdcaSMatthias Ringwald printf("Realtek: patch len is %d\n",patch_len);
6877977fdcaSMatthias Ringwald break;
6887977fdcaSMatthias Ringwald case PATCH_SECURITY_HEADER:
6897977fdcaSMatthias Ringwald if(!g_key_id)
6907977fdcaSMatthias Ringwald break;
6917977fdcaSMatthias Ringwald
6927977fdcaSMatthias Ringwald sec_flag = 0;
6937977fdcaSMatthias Ringwald insert_patch(patch_list, section_pos, PATCH_SECURITY_HEADER, &patch_len, &sec_flag);
6947977fdcaSMatthias Ringwald if(sec_flag)
6957977fdcaSMatthias Ringwald break;
6967977fdcaSMatthias Ringwald
6977977fdcaSMatthias Ringwald for (i = 0; i < number_of_section; i++) {
6987977fdcaSMatthias Ringwald section_hdr.opcode = little_endian_read_32(section_pos, 0);
6997977fdcaSMatthias Ringwald section_hdr.section_len = little_endian_read_32(section_pos, 4);
7007977fdcaSMatthias Ringwald if(section_hdr.opcode == PATCH_DUMMY_HEADER) {
7017977fdcaSMatthias Ringwald insert_patch(patch_list, section_pos, PATCH_DUMMY_HEADER, &patch_len, NULL);
7027977fdcaSMatthias Ringwald }
7037977fdcaSMatthias Ringwald section_pos += (SECTION_HEADER_SIZE + section_hdr.section_len);
7047977fdcaSMatthias Ringwald }
7057977fdcaSMatthias Ringwald break;
7067977fdcaSMatthias Ringwald case PATCH_DUMMY_HEADER:
7077977fdcaSMatthias Ringwald if(g_key_id) {
7087977fdcaSMatthias Ringwald break;
7097977fdcaSMatthias Ringwald }
7107977fdcaSMatthias Ringwald insert_patch(patch_list, section_pos, PATCH_DUMMY_HEADER, &patch_len, NULL);
7117977fdcaSMatthias Ringwald break;
7127977fdcaSMatthias Ringwald case PATCH_OTA_FLAG:
7137977fdcaSMatthias Ringwald ota_flag_pos = section_pos + 4;
7147977fdcaSMatthias Ringwald number_of_ota_flag = little_endian_read_32(ota_flag_pos, 0);
7157977fdcaSMatthias Ringwald ota_flag.eco = (uint8_t)*(ota_flag_pos + 1);
7167977fdcaSMatthias Ringwald if (ota_flag.eco == rom_version + 1) {
7177977fdcaSMatthias Ringwald for (j = 0; j < number_of_ota_flag; j++) {
7187977fdcaSMatthias Ringwald if (ota_flag.eco == rom_version + 1) {
7197977fdcaSMatthias Ringwald ota_flag.enable = little_endian_read_32(ota_flag_pos, 4);
7207977fdcaSMatthias Ringwald }
7217977fdcaSMatthias Ringwald }
7227977fdcaSMatthias Ringwald }
7237977fdcaSMatthias Ringwald break;
7247977fdcaSMatthias Ringwald default:
7257977fdcaSMatthias Ringwald log_error("Unknown Opcode");
7267977fdcaSMatthias Ringwald break;
7277977fdcaSMatthias Ringwald }
7287977fdcaSMatthias Ringwald section_pos += (SECTION_HEADER_SIZE + section_hdr.section_len);
7297977fdcaSMatthias Ringwald }
7307977fdcaSMatthias Ringwald *len = patch_len;
7317977fdcaSMatthias Ringwald
7327977fdcaSMatthias Ringwald return NULL;
7337977fdcaSMatthias Ringwald }
7347977fdcaSMatthias Ringwald
get_max_patch_size(uint8_t chip_type)7357977fdcaSMatthias Ringwald static inline int get_max_patch_size(uint8_t chip_type)
7367977fdcaSMatthias Ringwald {
7377977fdcaSMatthias Ringwald int max_patch_size = 0;
7387977fdcaSMatthias Ringwald
7397977fdcaSMatthias Ringwald switch (chip_type) {
7407977fdcaSMatthias Ringwald case RTLPREVIOUS:
7417977fdcaSMatthias Ringwald max_patch_size = 24 * 1024;
7427977fdcaSMatthias Ringwald break;
7437977fdcaSMatthias Ringwald case RTL8822BU:
7447977fdcaSMatthias Ringwald max_patch_size = 25 * 1024;
7457977fdcaSMatthias Ringwald break;
7467977fdcaSMatthias Ringwald case RTL8723DU:
7477977fdcaSMatthias Ringwald case RTL8822CU:
7487977fdcaSMatthias Ringwald case RTL8761BU:
7497977fdcaSMatthias Ringwald case RTL8821CU:
7507977fdcaSMatthias Ringwald max_patch_size = 40 * 1024;
7517977fdcaSMatthias Ringwald break;
7527977fdcaSMatthias Ringwald case RTL8852AU:
7537977fdcaSMatthias Ringwald max_patch_size = 0x114D0 + 529; /* 69.2KB */
7547977fdcaSMatthias Ringwald break;
7557977fdcaSMatthias Ringwald case RTL8723FU:
7567977fdcaSMatthias Ringwald max_patch_size = 0xC4Cf + 529; /* 49.2KB */
7577977fdcaSMatthias Ringwald break;
7587977fdcaSMatthias Ringwald case RTL8852BU:
7597977fdcaSMatthias Ringwald case RTL8851BU:
7607977fdcaSMatthias Ringwald max_patch_size = 0x104D0 + 529; /* 65KB */
7617977fdcaSMatthias Ringwald break;
7627977fdcaSMatthias Ringwald case RTL8852CU:
7637977fdcaSMatthias Ringwald max_patch_size = 0x130D0 + 529; /* 76.2KB */
7647977fdcaSMatthias Ringwald break;
7657977fdcaSMatthias Ringwald case RTL8822EU:
7667977fdcaSMatthias Ringwald max_patch_size = 0x24620 + 529; /* 145KB */
7677977fdcaSMatthias Ringwald break;
7687977fdcaSMatthias Ringwald default:
7697977fdcaSMatthias Ringwald max_patch_size = 40 * 1024;
7707977fdcaSMatthias Ringwald break;
7717977fdcaSMatthias Ringwald }
7727977fdcaSMatthias Ringwald
7737977fdcaSMatthias Ringwald return max_patch_size;
7747977fdcaSMatthias Ringwald }
7757977fdcaSMatthias Ringwald
update_firmware(const char * firmware,const char * config,uint8_t * hci_cmd_buffer)7768bb555aaSBjoern Hartmann static uint8_t update_firmware(const char *firmware, const char *config, uint8_t *hci_cmd_buffer) {
7778bb555aaSBjoern Hartmann static uint8_t *patch_buf = NULL;
7788bb555aaSBjoern Hartmann static uint32_t fw_total_len;
7798bb555aaSBjoern Hartmann static uint32_t fw_ptr;
7808bb555aaSBjoern Hartmann static uint8_t index;
7818bb555aaSBjoern Hartmann
7828bb555aaSBjoern Hartmann // read firmware and config
7838bb555aaSBjoern Hartmann if (patch_buf == NULL) {
7848bb555aaSBjoern Hartmann uint16_t patch_length = 0;
785*5449042eSMatthias Ringwald uint32_t offset = 0;
7868bb555aaSBjoern Hartmann FILE * fw = NULL;
7878bb555aaSBjoern Hartmann uint32_t fw_size;
7888bb555aaSBjoern Hartmann uint8_t *fw_buf = NULL;
7898bb555aaSBjoern Hartmann
7908bb555aaSBjoern Hartmann FILE * conf = NULL;
7918bb555aaSBjoern Hartmann uint32_t conf_size;
7928bb555aaSBjoern Hartmann uint8_t *conf_buf = NULL;
7938bb555aaSBjoern Hartmann
7947977fdcaSMatthias Ringwald uint32_t fw_version;
7957977fdcaSMatthias Ringwald uint16_t fw_num_patches;
7967977fdcaSMatthias Ringwald
7977977fdcaSMatthias Ringwald struct patch_node *tmp;
798*5449042eSMatthias Ringwald unsigned max_patch_size = 0;
7997977fdcaSMatthias Ringwald
8008bb555aaSBjoern Hartmann if (firmware == NULL || config == NULL) {
8018bb555aaSBjoern Hartmann log_info("Please specify realtek firmware and config file paths");
8028bb555aaSBjoern Hartmann return FW_DONE;
8038bb555aaSBjoern Hartmann }
8047977fdcaSMatthias Ringwald // read config
8057977fdcaSMatthias Ringwald conf_size = read_file(&conf, &conf_buf, config);
8067977fdcaSMatthias Ringwald if (conf_size == 0) {
8077977fdcaSMatthias Ringwald log_info("Config size is 0, using efuse settings!");
8087977fdcaSMatthias Ringwald }
8098bb555aaSBjoern Hartmann // read firmware
8108bb555aaSBjoern Hartmann fw_size = read_file(&fw, &fw_buf, firmware);
8118bb555aaSBjoern Hartmann if (fw_size == 0) {
8128bb555aaSBjoern Hartmann log_info("Firmware size is 0. Quit!");
8137977fdcaSMatthias Ringwald if (conf_size != 0){
8147977fdcaSMatthias Ringwald finalize_file_and_buffer(&conf, &conf_buf);
8157977fdcaSMatthias Ringwald }
8168bb555aaSBjoern Hartmann return FW_DONE;
8178bb555aaSBjoern Hartmann }
8188bb555aaSBjoern Hartmann // check signature
8197977fdcaSMatthias Ringwald if (((memcmp(fw_buf, FW_SIGNATURE, 8) != 0) && (memcmp(fw_buf, FW_SIGNATURE_NEW, 8) != 0))
8207977fdcaSMatthias Ringwald || memcmp(fw_buf + fw_size - 4, EXTENSION_SIGNATURE, 4) != 0) {
8218bb555aaSBjoern Hartmann log_info("Wrong signature. Quit!");
8228bb555aaSBjoern Hartmann finalize_file_and_buffer(&fw, &fw_buf);
8238bb555aaSBjoern Hartmann finalize_file_and_buffer(&conf, &conf_buf);
8248bb555aaSBjoern Hartmann return FW_DONE;
8258bb555aaSBjoern Hartmann }
8268bb555aaSBjoern Hartmann // check project id
8277977fdcaSMatthias Ringwald if (lmp_subversion != project_id[rtk_get_fw_project_id(fw_buf + fw_size - 5)]) {
8288bb555aaSBjoern Hartmann log_info("Wrong project id. Quit!");
8298bb555aaSBjoern Hartmann finalize_file_and_buffer(&fw, &fw_buf);
8308bb555aaSBjoern Hartmann finalize_file_and_buffer(&conf, &conf_buf);
8318bb555aaSBjoern Hartmann return FW_DONE;
8328bb555aaSBjoern Hartmann }
8337977fdcaSMatthias Ringwald // init ordered list for new firmware signature
8347977fdcaSMatthias Ringwald btstack_linked_list_t patch_list = NULL;
8357977fdcaSMatthias Ringwald bool have_new_firmware_signature = memcmp(fw_buf, FW_SIGNATURE_NEW, 8) == 0;
8367977fdcaSMatthias Ringwald if (have_new_firmware_signature){
8377977fdcaSMatthias Ringwald printf("Realtek: Using new signature\n");
8387977fdcaSMatthias Ringwald uint8_t key_id = g_key_id;
839*5449042eSMatthias Ringwald if (key_id == 0) {
8407977fdcaSMatthias Ringwald log_info("Wrong key id. Quit!");
8417977fdcaSMatthias Ringwald finalize_file_and_buffer(&fw, &fw_buf);
8427977fdcaSMatthias Ringwald finalize_file_and_buffer(&conf, &conf_buf);
8437977fdcaSMatthias Ringwald return FW_DONE;
8447977fdcaSMatthias Ringwald }
8458bb555aaSBjoern Hartmann
8467977fdcaSMatthias Ringwald rtb_get_patch_header(&fw_total_len, &patch_list, fw_buf, key_id);
8477977fdcaSMatthias Ringwald if (fw_total_len == 0) {
8487977fdcaSMatthias Ringwald finalize_file_and_buffer(&fw, &fw_buf);
8497977fdcaSMatthias Ringwald finalize_file_and_buffer(&conf, &conf_buf);
8507977fdcaSMatthias Ringwald return FW_DONE;
8517977fdcaSMatthias Ringwald }
8527977fdcaSMatthias Ringwald fw_total_len += conf_size;
8537977fdcaSMatthias Ringwald } else {
8547977fdcaSMatthias Ringwald printf("Realtek: Using old signature\n");
8558bb555aaSBjoern Hartmann // read firmware version
8567977fdcaSMatthias Ringwald fw_version = little_endian_read_32(fw_buf, 8);
8578bb555aaSBjoern Hartmann log_info("Firmware version: 0x%x", fw_version);
8588bb555aaSBjoern Hartmann
8598bb555aaSBjoern Hartmann // read number of patches
8607977fdcaSMatthias Ringwald fw_num_patches = little_endian_read_16(fw_buf, 12);
8618bb555aaSBjoern Hartmann log_info("Number of patches: %d", fw_num_patches);
8628bb555aaSBjoern Hartmann
8638bb555aaSBjoern Hartmann // find correct entry
8648bb555aaSBjoern Hartmann for (uint16_t i = 0; i < fw_num_patches; i++) {
8658bb555aaSBjoern Hartmann if (little_endian_read_16(fw_buf, 14 + 2 * i) == rom_version + 1) {
8668bb555aaSBjoern Hartmann patch_length = little_endian_read_16(fw_buf, 14 + 2 * fw_num_patches + 2 * i);
8678bb555aaSBjoern Hartmann offset = little_endian_read_32(fw_buf, 14 + 4 * fw_num_patches + 4 * i);
8688bb555aaSBjoern Hartmann log_info("patch_length %u, offset %u", patch_length, offset);
8698bb555aaSBjoern Hartmann break;
8708bb555aaSBjoern Hartmann }
8718bb555aaSBjoern Hartmann }
8728bb555aaSBjoern Hartmann if (patch_length == 0) {
8738bb555aaSBjoern Hartmann log_debug("Failed to find valid patch");
8748bb555aaSBjoern Hartmann finalize_file_and_buffer(&fw, &fw_buf);
8758bb555aaSBjoern Hartmann finalize_file_and_buffer(&conf, &conf_buf);
8768bb555aaSBjoern Hartmann return FW_DONE;
8778bb555aaSBjoern Hartmann }
8788bb555aaSBjoern Hartmann fw_total_len = patch_length + conf_size;
8797977fdcaSMatthias Ringwald }
8807977fdcaSMatthias Ringwald
8817977fdcaSMatthias Ringwald max_patch_size = get_max_patch_size(patch->chip_type);
8827977fdcaSMatthias Ringwald printf("Realtek: FW/CONFIG total length is %d, max patch size id %d\n", fw_total_len, max_patch_size);
8837977fdcaSMatthias Ringwald if (fw_total_len > max_patch_size) {
8847977fdcaSMatthias Ringwald printf("FRealtek: W/CONFIG total length larger than allowed %d\n", max_patch_size);
8857977fdcaSMatthias Ringwald finalize_file_and_buffer(&fw, &fw_buf);
8867977fdcaSMatthias Ringwald finalize_file_and_buffer(&conf, &conf_buf);
8877977fdcaSMatthias Ringwald return FW_DONE;
8887977fdcaSMatthias Ringwald }
8897977fdcaSMatthias Ringwald // allocate patch buffer
8908bb555aaSBjoern Hartmann patch_buf = malloc(fw_total_len);
8918bb555aaSBjoern Hartmann if (patch_buf == NULL) {
8928bb555aaSBjoern Hartmann log_debug("Failed to allocate %u bytes for patch buffer", fw_total_len);
8938bb555aaSBjoern Hartmann finalize_file_and_buffer(&fw, &fw_buf);
8948bb555aaSBjoern Hartmann finalize_file_and_buffer(&conf, &conf_buf);
8958bb555aaSBjoern Hartmann return FW_DONE;
8968bb555aaSBjoern Hartmann }
8977977fdcaSMatthias Ringwald if (have_new_firmware_signature) {
8987977fdcaSMatthias Ringwald int tmp_len = 0;
8997977fdcaSMatthias Ringwald // append patches based on priority and free
9007977fdcaSMatthias Ringwald while (patch_list) {
9017977fdcaSMatthias Ringwald tmp = (struct patch_node *) patch_list;
9027977fdcaSMatthias Ringwald log_info("len = 0x%x", tmp->len);
9037977fdcaSMatthias Ringwald memcpy(patch_buf + tmp_len, tmp->payload, tmp->len);
9047977fdcaSMatthias Ringwald tmp_len += tmp->len;
9057977fdcaSMatthias Ringwald patch_list = patch_list->next;
9067977fdcaSMatthias Ringwald free(tmp);
9077977fdcaSMatthias Ringwald }
9087977fdcaSMatthias Ringwald if (conf_size) {
9097977fdcaSMatthias Ringwald memcpy(&patch_buf[fw_total_len - conf_size], conf_buf, conf_size);
9107977fdcaSMatthias Ringwald }
9117977fdcaSMatthias Ringwald } else {
9128bb555aaSBjoern Hartmann // copy patch
9138bb555aaSBjoern Hartmann memcpy(patch_buf, fw_buf + offset, patch_length);
9148bb555aaSBjoern Hartmann memcpy(patch_buf + patch_length - 4, &fw_version, 4);
9158bb555aaSBjoern Hartmann memcpy(patch_buf + patch_length, conf_buf, conf_size);
9167977fdcaSMatthias Ringwald }
9178bb555aaSBjoern Hartmann fw_ptr = 0;
9188bb555aaSBjoern Hartmann index = 0;
9198bb555aaSBjoern Hartmann
9208bb555aaSBjoern Hartmann // close files
9218bb555aaSBjoern Hartmann finalize_file_and_buffer(&fw, &fw_buf);
9228bb555aaSBjoern Hartmann finalize_file_and_buffer(&conf, &conf_buf);
9238bb555aaSBjoern Hartmann }
9248bb555aaSBjoern Hartmann
9258bb555aaSBjoern Hartmann uint8_t len;
9268bb555aaSBjoern Hartmann if (fw_total_len - fw_ptr > 252) {
9278bb555aaSBjoern Hartmann len = 252;
9288bb555aaSBjoern Hartmann } else {
9298bb555aaSBjoern Hartmann len = fw_total_len - fw_ptr;
9308bb555aaSBjoern Hartmann index |= 0x80; // end
9318bb555aaSBjoern Hartmann }
9328bb555aaSBjoern Hartmann
9338bb555aaSBjoern Hartmann if (len) {
9347977fdcaSMatthias Ringwald little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_HCI_RTK_DOWNLOAD_FW);
9357977fdcaSMatthias Ringwald HCI_CMD_SET_LENGTH(hci_cmd_buffer, len + 1);
9367977fdcaSMatthias Ringwald HCI_CMD_DOWNLOAD_SET_INDEX(hci_cmd_buffer, index);
9377977fdcaSMatthias Ringwald HCI_CMD_DOWNLOAD_COPY_FW_DATA(hci_cmd_buffer, patch_buf, fw_ptr, len);
9388bb555aaSBjoern Hartmann index++;
9397977fdcaSMatthias Ringwald if (index > 0x7f) {
9407977fdcaSMatthias Ringwald index = (index & 0x7f) +1;
9417977fdcaSMatthias Ringwald }
9428bb555aaSBjoern Hartmann fw_ptr += len;
9438bb555aaSBjoern Hartmann return FW_MORE_TO_DO;
9448bb555aaSBjoern Hartmann }
9458bb555aaSBjoern Hartmann
9468bb555aaSBjoern Hartmann // cleanup and return
9478bb555aaSBjoern Hartmann free(patch_buf);
9488bb555aaSBjoern Hartmann patch_buf = NULL;
9497977fdcaSMatthias Ringwald printf("Realtek: Init process finished\n");
9508bb555aaSBjoern Hartmann return FW_DONE;
9518bb555aaSBjoern Hartmann }
9528bb555aaSBjoern Hartmann
9538bb555aaSBjoern Hartmann #endif // HAVE_POSIX_FILE_IO
9548bb555aaSBjoern Hartmann
9557977fdcaSMatthias Ringwald static const uint8_t hci_realtek_read_sec_proj[] = {0x61, 0xfc, 0x05, 0x10, 0xA4, 0x0D, 0x00, 0xb0 };
9567977fdcaSMatthias Ringwald static const uint8_t hci_realtek_read_lmp_subversion[] = {0x61, 0xfc, 0x05, 0x10, 0x38, 0x04, 0x28, 0x80 };
9577977fdcaSMatthias Ringwald static const uint8_t hci_realtek_read_hci_revision[] = {0x61, 0xfc, 0x05, 0x10, 0x3A, 0x04, 0x28, 0x80 };
9587977fdcaSMatthias Ringwald
chipset_next_command(uint8_t * hci_cmd_buffer)9598bb555aaSBjoern Hartmann static btstack_chipset_result_t chipset_next_command(uint8_t *hci_cmd_buffer) {
9608bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
9618bb555aaSBjoern Hartmann uint8_t ret;
9628bb555aaSBjoern Hartmann while (true) {
9638bb555aaSBjoern Hartmann switch (state) {
9647977fdcaSMatthias Ringwald case STATE_PHASE_1_READ_LMP_SUBVERSION:
9657977fdcaSMatthias Ringwald memcpy(hci_cmd_buffer, hci_realtek_read_lmp_subversion, sizeof(hci_realtek_read_lmp_subversion));
9667977fdcaSMatthias Ringwald state = STATE_PHASE_1_W4_READ_LMP_SUBVERSION;
9678bb555aaSBjoern Hartmann break;
9687977fdcaSMatthias Ringwald case STATE_PHASE_1_READ_HCI_REVISION:
9697977fdcaSMatthias Ringwald memcpy(hci_cmd_buffer, hci_realtek_read_hci_revision, sizeof(hci_realtek_read_hci_revision));
9707977fdcaSMatthias Ringwald state = STATE_PHASE_1_W4_READ_HCI_REVISION;
9717977fdcaSMatthias Ringwald break;
9727977fdcaSMatthias Ringwald case STATE_PHASE_1_DONE:
9737977fdcaSMatthias Ringwald // custom pre-init done, continue with read ROM version in main custom init
9747977fdcaSMatthias Ringwald state = STATE_PHASE_2_READ_ROM_VERSION;
9757977fdcaSMatthias Ringwald return BTSTACK_CHIPSET_DONE;
9767977fdcaSMatthias Ringwald case STATE_PHASE_2_READ_ROM_VERSION:
9777977fdcaSMatthias Ringwald HCI_CMD_SET_OPCODE(hci_cmd_buffer, HCI_OPCODE_HCI_RTK_READ_ROM_VERSION);
9787977fdcaSMatthias Ringwald HCI_CMD_SET_LENGTH(hci_cmd_buffer, 0);
9797977fdcaSMatthias Ringwald state = STATE_PHASE_2_READ_SEC_PROJ;
9807977fdcaSMatthias Ringwald break;
9817977fdcaSMatthias Ringwald case STATE_PHASE_2_READ_SEC_PROJ:
9827977fdcaSMatthias Ringwald memcpy(hci_cmd_buffer, hci_realtek_read_sec_proj, sizeof(hci_realtek_read_sec_proj));
9837977fdcaSMatthias Ringwald state = STATE_PHASE_2_W4_SEC_PROJ;
9847977fdcaSMatthias Ringwald break;
9857977fdcaSMatthias Ringwald case STATE_PHASE_2_LOAD_FIRMWARE:
9868bb555aaSBjoern Hartmann if (lmp_subversion != ROM_LMP_8723a) {
9878bb555aaSBjoern Hartmann ret = update_firmware(firmware_file_path, config_file_path, hci_cmd_buffer);
9888bb555aaSBjoern Hartmann } else {
9898bb555aaSBjoern Hartmann log_info("Realtek firmware for old patch style not implemented");
9908bb555aaSBjoern Hartmann ret = FW_DONE;
9918bb555aaSBjoern Hartmann }
9928bb555aaSBjoern Hartmann if (ret != FW_DONE) {
9938bb555aaSBjoern Hartmann break;
9948bb555aaSBjoern Hartmann }
9957977fdcaSMatthias Ringwald // we are done
9967977fdcaSMatthias Ringwald state = STATE_PHASE_2_RESET;
9977977fdcaSMatthias Ringwald
9987977fdcaSMatthias Ringwald /* fall through */
9997977fdcaSMatthias Ringwald
10007977fdcaSMatthias Ringwald case STATE_PHASE_2_RESET:
10017977fdcaSMatthias Ringwald HCI_CMD_SET_OPCODE(hci_cmd_buffer, HCI_OPCODE_HCI_RESET);
10027977fdcaSMatthias Ringwald HCI_CMD_SET_LENGTH(hci_cmd_buffer, 0);
10037977fdcaSMatthias Ringwald state = STATE_PHASE_2_DONE;
10048bb555aaSBjoern Hartmann break;
10057977fdcaSMatthias Ringwald case STATE_PHASE_2_DONE:
10068bb555aaSBjoern Hartmann hci_remove_event_handler(&hci_event_callback_registration);
10078bb555aaSBjoern Hartmann return BTSTACK_CHIPSET_DONE;
10088bb555aaSBjoern Hartmann default:
10098bb555aaSBjoern Hartmann log_info("Invalid state %d", state);
10108bb555aaSBjoern Hartmann return BTSTACK_CHIPSET_DONE;
10118bb555aaSBjoern Hartmann }
10128bb555aaSBjoern Hartmann return BTSTACK_CHIPSET_VALID_COMMAND;
10138bb555aaSBjoern Hartmann }
10148bb555aaSBjoern Hartmann #else // HAVE_POSIX_FILE_IO
10158bb555aaSBjoern Hartmann log_info("Realtek without File IO is not implemented yet");
10168bb555aaSBjoern Hartmann return BTSTACK_CHIPSET_NO_INIT_SCRIPT;
10178bb555aaSBjoern Hartmann #endif // HAVE_POSIX_FILE_IO
10188bb555aaSBjoern Hartmann }
10198bb555aaSBjoern Hartmann
btstack_chipset_realtek_set_firmware_file_path(const char * path)10208bb555aaSBjoern Hartmann void btstack_chipset_realtek_set_firmware_file_path(const char *path) {
10218bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
10228bb555aaSBjoern Hartmann firmware_file_path = path;
10238bb555aaSBjoern Hartmann #endif
10248bb555aaSBjoern Hartmann }
10258bb555aaSBjoern Hartmann
btstack_chipset_realtek_set_firmware_folder_path(const char * path)10268bb555aaSBjoern Hartmann void btstack_chipset_realtek_set_firmware_folder_path(const char *path) {
10278bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
10288bb555aaSBjoern Hartmann firmware_folder_path = path;
10298bb555aaSBjoern Hartmann #endif
10308bb555aaSBjoern Hartmann }
10318bb555aaSBjoern Hartmann
btstack_chipset_realtek_set_config_file_path(const char * path)10328bb555aaSBjoern Hartmann void btstack_chipset_realtek_set_config_file_path(const char *path) {
10338bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
10348bb555aaSBjoern Hartmann config_file_path = path;
10358bb555aaSBjoern Hartmann #endif
10368bb555aaSBjoern Hartmann }
10378bb555aaSBjoern Hartmann
btstack_chipset_realtek_set_config_folder_path(const char * path)10388bb555aaSBjoern Hartmann void btstack_chipset_realtek_set_config_folder_path(const char *path) {
10398bb555aaSBjoern Hartmann #ifdef HAVE_POSIX_FILE_IO
10408bb555aaSBjoern Hartmann config_folder_path = path;
10418bb555aaSBjoern Hartmann #endif
10428bb555aaSBjoern Hartmann }
10438bb555aaSBjoern Hartmann
btstack_chipset_realtek_set_product_id(uint16_t id)10445a4c0fdaSMatthias Ringwald void btstack_chipset_realtek_set_product_id(uint16_t id) {
10455a4c0fdaSMatthias Ringwald product_id = id;
10465a4c0fdaSMatthias Ringwald }
10475a4c0fdaSMatthias Ringwald
btstack_chipset_realtek_get_num_usb_controllers(void)10485a4c0fdaSMatthias Ringwald uint16_t btstack_chipset_realtek_get_num_usb_controllers(void){
10495a4c0fdaSMatthias Ringwald return (sizeof(fw_patch_table) / sizeof(patch_info)) - 1; // sentinel
10505a4c0fdaSMatthias Ringwald }
10515a4c0fdaSMatthias Ringwald
btstack_chipset_realtek_get_vendor_product_id(uint16_t index,uint16_t * out_vendor_id,uint16_t * out_product_id)10525a4c0fdaSMatthias Ringwald void btstack_chipset_realtek_get_vendor_product_id(uint16_t index, uint16_t * out_vendor_id, uint16_t * out_product_id){
10535a4c0fdaSMatthias Ringwald btstack_assert(index < ((sizeof(fw_patch_table) / sizeof(patch_info)) - 1));
10545a4c0fdaSMatthias Ringwald *out_vendor_id = 0xbda;
10555a4c0fdaSMatthias Ringwald *out_product_id = fw_patch_table[index].prod_id;
10565a4c0fdaSMatthias Ringwald }
10578bb555aaSBjoern Hartmann
10588bb555aaSBjoern Hartmann static const btstack_chipset_t btstack_chipset_realtek = {
10598bb555aaSBjoern Hartmann "REALTEK", chipset_init, chipset_next_command,
10608bb555aaSBjoern Hartmann NULL, // chipset_set_baudrate_command,
10618bb555aaSBjoern Hartmann NULL, // chipset_set_bd_addr_command not supported or implemented
10628bb555aaSBjoern Hartmann };
10638bb555aaSBjoern Hartmann
btstack_chipset_realtek_instance(void)10648bb555aaSBjoern Hartmann const btstack_chipset_t *btstack_chipset_realtek_instance(void) { return &btstack_chipset_realtek; }
1065