mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-11-10 16:49:17 +00:00
Keep the product-specific syscfg writes and restore all patch uploads, including patch configuration. Derive the syscfg condition from the current product readback without retaining a loader flag. Update regression checks for full patch uploads on both products and syscfg write failures, and document the reported hardware results and remaining validation.
144 lines
6.0 KiB
Python
144 lines
6.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Exercise extracted loader paths with mocked USB requests, without hardware."""
|
|
from pathlib import Path
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def block(source, signature):
|
|
start = source.index(signature)
|
|
brace = source.index("{", start)
|
|
end, depth = brace + 1, 1
|
|
while depth:
|
|
depth += (source[end] == "{") - (source[end] == "}")
|
|
end += 1
|
|
return source[start:end]
|
|
|
|
|
|
loader = (ROOT / "drivers/aic8800/aic_load_fw/aic_compat_8800d80.c").read_text()
|
|
header = (ROOT / "drivers/aic8800/aic_load_fw/aic_compat_8800d80.h").read_text()
|
|
header = "\n".join(line for line in header.splitlines() if not line.startswith("#include"))
|
|
config = block(loader, "int system_config_8800d80(")
|
|
normal = block(loader, "if(testmode == FW_NORMAL_MODE)")
|
|
connect = (ROOT / "drivers/aic8800/aic8800_fdrv/rwnx_main.c").read_text()
|
|
guard = block(connect[connect.index("static int rwnx_cfg80211_connect("):],
|
|
"if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING")
|
|
prelude = r'''
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
typedef uint32_t u32;
|
|
typedef uint8_t u8;
|
|
#define printk(...) ((void)0)
|
|
#define AICWFDBG(...) ((void)0)
|
|
#define CHIP_REV_U01 1
|
|
#define CHIP_REV_U02 3
|
|
#define CHIP_REV_U03 7
|
|
#define FW_NORMAL_MODE 0
|
|
#define HOST_START_APP_AUTO 0
|
|
struct aic_usb_dev {
|
|
u32 id, cache;
|
|
int syscfg_writes, syscfg_masks, patches, fmacs, starts;
|
|
};
|
|
struct dbg_mem_read_cfm { u32 memdata; };
|
|
struct aicbt_patch_info_t { u32 addr_adid, addr_patch; };
|
|
static u8 chip_id, chip_mcu_id;
|
|
static int testmode = FW_NORMAL_MODE, fail_read, fail_write, fail_mask;
|
|
static u32 fail_write_addr;
|
|
static u32 syscfg_tbl_8800d80[0][2], syscfg_tbl_masked_8800d80[0][3];
|
|
static int rwnx_send_dbg_mem_read_req(struct aic_usb_dev *dev, u32 addr,
|
|
struct dbg_mem_read_cfm *cfm) {
|
|
if (fail_read) return -EIO;
|
|
cfm->memdata = addr == 0x40500000 ? dev->id : dev->cache; return 0;
|
|
}
|
|
static int rwnx_send_dbg_mem_write_req(struct aic_usb_dev *dev, u32 addr, u32 val) {
|
|
if (fail_write && (!fail_write_addr || addr == fail_write_addr)) return -EIO;
|
|
if (addr == 0x40100020) dev->cache = val;
|
|
if (addr == 0x40500010) { assert(val == 2); dev->syscfg_writes++; }
|
|
return 0;
|
|
}
|
|
static int rwnx_send_dbg_mem_mask_write_req(struct aic_usb_dev *dev, u32 addr, u32 mask, u32 val) {
|
|
assert(addr == 0x40506024 && mask == 0xff && val == 0xdf);
|
|
if (fail_mask) return -EIO;
|
|
dev->syscfg_masks++; return 0;
|
|
}
|
|
static int rwnx_plat_bin_fw_upload_android(struct aic_usb_dev *dev, u32 addr, const char *name) {
|
|
if (name[0] == 'f' && name[1] == 'm') {
|
|
assert(addr == 0x120000); dev->fmacs++;
|
|
} else { dev->patches++; }
|
|
return 0;
|
|
}
|
|
static int aicbt_ext_patch_data_load(struct aic_usb_dev *dev, struct aicbt_patch_info_t *info, const char *name) {
|
|
dev->patches++; return 0;
|
|
}
|
|
static int aicbt_patch_table_load(struct aic_usb_dev *dev, void *head) {
|
|
dev->patches++; return 0;
|
|
}
|
|
static int rwnx_send_dbg_start_app_req(struct aic_usb_dev *dev, u32 addr, int mode) {
|
|
assert(addr == 0x120000); dev->starts++; return 0;
|
|
}
|
|
'''
|
|
normal_wrapper = r'''
|
|
int aicwf_patch_config_8800d80(struct aic_usb_dev *dev) { dev->patches++; return 0; }
|
|
static int load_normal(struct aic_usb_dev *usb_dev) {
|
|
struct aicbt_patch_info_t patch_info = {0};
|
|
void *head = 0;
|
|
'''
|
|
busy_wrapper = r'''
|
|
return 0;
|
|
}
|
|
enum { RWNX_DRV_STATUS_DISCONNECTED, RWNX_DRV_STATUS_CONNECTING,
|
|
RWNX_DRV_STATUS_DISCONNECTING };
|
|
struct vif { int drv_conn_state; };
|
|
#define atomic_read(p) (*(p))
|
|
static void rwnx_set_conn_state(struct vif *vif, int *state, int val) { *state = val; }
|
|
static int busy(struct vif *rwnx_vif) {
|
|
'''
|
|
checks = r'''
|
|
return 0;
|
|
}
|
|
int main(void) {
|
|
struct aic_usb_dev m80 = {.id = 0x00078820}, d80 = {.id = 0x00078800};
|
|
/* Both products need the full patch layer; only 0x8820 gets extra syscfg. */
|
|
assert(system_config_8800d80(&m80) == 0);
|
|
assert(system_config_8800d80(&d80) == 0);
|
|
assert(load_normal(&m80) == 0 && m80.patches == 5 && m80.fmacs == 1 && m80.starts == 1);
|
|
assert(load_normal(&d80) == 0 && d80.patches == 5 && d80.fmacs == 1 && d80.starts == 1);
|
|
assert(m80.syscfg_writes == 1 && m80.syscfg_masks == 1 && (m80.cache & 1));
|
|
assert(d80.syscfg_writes == 0 && d80.syscfg_masks == 0 && (d80.cache & 1));
|
|
/* Re-read the product on reprobe in both directions. */
|
|
m80.id = 0x00078800; m80.patches = m80.fmacs = m80.starts = 0;
|
|
assert(system_config_8800d80(&m80) == 0);
|
|
assert(load_normal(&m80) == 0 && m80.patches == 5 && m80.fmacs == 1 && m80.starts == 1);
|
|
assert(m80.syscfg_writes == 1 && m80.syscfg_masks == 1);
|
|
d80.id = 0x00078820; d80.patches = d80.fmacs = d80.starts = 0;
|
|
assert(system_config_8800d80(&d80) == 0);
|
|
assert(load_normal(&d80) == 0 && d80.patches == 5 && d80.fmacs == 1 && d80.starts == 1);
|
|
assert(d80.syscfg_writes == 1 && d80.syscfg_masks == 1);
|
|
fail_read = 1; assert(system_config_8800d80(&d80) == -EIO);
|
|
fail_read = 0; fail_write = 1; assert(system_config_8800d80(&d80) == -EIO);
|
|
fail_write_addr = 0x40500010;
|
|
assert(system_config_8800d80(&d80) == -EIO);
|
|
fail_write = 0; fail_mask = 1;
|
|
assert(system_config_8800d80(&d80) == -EIO);
|
|
for (int state = RWNX_DRV_STATUS_CONNECTING; state <= RWNX_DRV_STATUS_DISCONNECTING; state++) {
|
|
struct vif vif = {.drv_conn_state = state};
|
|
assert(busy(&vif) == -EBUSY && vif.drv_conn_state == state);
|
|
}
|
|
return 0;
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory(prefix="aic-8820-test-") as temp:
|
|
c_file, binary = Path(temp) / "loader.c", Path(temp) / "loader"
|
|
c_file.write_text(prelude + header + config + normal_wrapper + normal +
|
|
busy_wrapper + guard + checks)
|
|
subprocess.run([os.environ.get("CC", "cc"), "-std=gnu11", "-o", str(binary),
|
|
str(c_file)], check=True)
|
|
subprocess.run([str(binary)], check=True)
|
|
print("PASS: full patch uploads for both products, per-probe syscfg, MCU1 cache fix, write errors, busy connect state")
|
|
|