feat: 添加蓝牙支持及固件更新

This commit is contained in:
Shen Mintao
2026-02-27 18:19:39 +08:00
parent 96e1d9cd3d
commit 8b90bd8f45
56 changed files with 363 additions and 12 deletions
+26
View File
@@ -1,3 +1,4 @@
# AIC8800 USB Mass Storage mode switch rules
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5723", SYMLINK+="tendaudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5724", SYMLINK+="ugreenax900", RUN+="/usr/bin/eject /dev/%k"
@@ -6,3 +7,28 @@ KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5726", SYMLINK+="ten
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5727", SYMLINK+="tendaudiskv4", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="572a", SYMLINK+="tendaudiskv5", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="572c", SYMLINK+="cudydiskv2", RUN+="/usr/bin/eject /dev/%k"
# AIC8800D80 "Pandora" clone adapter - automatic mode switch & driver binding
# Triggers usb_modeswitch when the device is plugged in as 1111:1111
# --- Mode Switch ---
ACTION=="add", ATTRS{idVendor}=="1111", ATTRS{idProduct}=="1111", RUN+="/usr/sbin/usb_modeswitch -c /etc/usb_modeswitch.d/1111:1111"
# --- WiFi Driver Binding ---
# After mode switch, the device re-enumerates as a69c:8d81 (Radxa fw) or a69c:8d83 (Brostrend fw).
# If aic8800_fdrv doesn't auto-bind to the WiFi interface, add the VID:PID dynamically:
ACTION=="add", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'echo a69c 8d81 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
ACTION=="add", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d83", RUN+="/bin/sh -c 'echo a69c 8d83 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
ACTION=="add", ATTRS{idVendor}=="368b", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'echo 368b 8d81 > /sys/bus/usb/drivers/aic8800_fdrv/new_id 2>/dev/null || true'"
# --- Bluetooth Driver Binding ---
# PID 8d81 (Radxa fw with BT enabled) exposes BT interfaces.
# If aic_btusb doesn't auto-bind, add the VID:PID dynamically.
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d81", ATTR{bInterfaceClass}=="e0", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProtocol}=="01", RUN+="/bin/sh -c 'echo a69c 8d81 > /sys/bus/usb/drivers/aic_btusb/new_id 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d83", ATTR{bInterfaceClass}=="e0", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProtocol}=="01", RUN+="/bin/sh -c 'echo a69c 8d83 > /sys/bus/usb/drivers/aic_btusb/new_id 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="368b", ATTRS{idProduct}=="8d81", ATTR{bInterfaceClass}=="e0", ATTR{bInterfaceSubClass}=="01", ATTR{bInterfaceProtocol}=="01", RUN+="/bin/sh -c 'echo 368b 8d81 > /sys/bus/usb/drivers/aic_btusb/new_id 2>/dev/null || true'"
# Unblock rfkill for Bluetooth
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="8d83", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="368b", ATTRS{idProduct}=="8d81", RUN+="/bin/sh -c 'rfkill unblock bluetooth 2>/dev/null || true'"
@@ -386,7 +386,6 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
int i = 0;
#if 0
if (chip_id == CHIP_REV_U01) {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80);
} else {
@@ -414,11 +413,10 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
}
printk("addr_adid 0x%x, addr_patch 0x%x\n", patch_info.addr_adid, patch_info.addr_patch);
#endif
if(testmode == FW_NORMAL_MODE){
if (chip_id != CHIP_REV_U01){
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
@@ -433,7 +431,6 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
#endif
if (IS_CHIP_ID_H()){
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_H_U02))
@@ -456,7 +453,6 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
return -1;
}
}else {
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80)) {
return -1;
}
@@ -472,7 +468,6 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
return -1;
}
#endif
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80, FW_BASE_NAME_8800D80)) {
return -1;
}
@@ -482,7 +477,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
}
}else if(testmode == FW_TEST_MODE){
if (chip_id != CHIP_REV_U01){
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
@@ -508,7 +503,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
return -1;
}
}
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80_U02, FW_RF_BASE_NAME_8800D80_U02)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
+5
View File
@@ -1366,6 +1366,10 @@ static int aicloadfw_chipmatch(struct aic_usb_dev *usb_dev, u16 vid, u16 pid){
}else if(pid == USB_DEVICE_ID_AIC_8800D89X2 && vid == USB_VENDOR_ID_AIC_V2){
usb_dev->chipid = PRODUCT_ID_AIC8800D89X2;
AICWFDBG(LOGINFO, "%s USE AIC8800D89X2\r\n", __func__);
return 0;
}else if(pid == USB_DEVICE_ID_AIC_8800D81 && vid == USB_VENDOR_ID_AIC_V2){
usb_dev->chipid = PRODUCT_ID_AIC8800D81;
AICWFDBG(LOGINFO, "%s USE AIC8800D81 (368b:8d81)\r\n", __func__);
return 0;
}else{
return -1;
@@ -1846,6 +1850,7 @@ static struct usb_device_id aicwf_usb_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D80X2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D81X2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D89X2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D81)}, /* 368b:8d81 */
{}
};
+30
View File
@@ -0,0 +1,30 @@
# AIC USERCONFIG 2021/0911/2127
# txpwr_idx
enable=1
dsss=9
ofdmlowrate_2g4=10
ofdm64qam_2g4=10
ofdm256qam_2g4=9
ofdm1024qam_2g4=8
ofdmlowrate_5g=10
ofdm64qam_5g=9
ofdm256qam_5g=9
ofdm1024qam_5g=8
# txpwr_ofst
ofst_enable=0
ofst_chan_1_4=0
ofst_chan_5_9=0
ofst_chan_10_13=0
ofst_chan_36_64=0
ofst_chan_100_120=0
ofst_chan_122_140=0
ofst_chan_142_165=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
# END
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,118 @@
# AIC POWERLIMIT 2024/1108/1900
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## END
# Table 2:
## 2.4G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
## END
# Table 4:
## 5G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
## END
# Table 5:
## 5G, 80M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH42 15 16 16 16 15
# 5G Band 2
CH58 15 16 16 16 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
# 5G Band 4
CH155 16 16 11 NA 11
## END
@@ -0,0 +1,121 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=18
lvl_11b_11ag_2m_2g4=18
lvl_11b_11ag_5m5_2g4=18
lvl_11b_11ag_11m_2g4=18
lvl_11b_11ag_6m_2g4=18
lvl_11b_11ag_9m_2g4=18
lvl_11b_11ag_12m_2g4=18
lvl_11b_11ag_18m_2g4=18
lvl_11b_11ag_24m_2g4=16
lvl_11b_11ag_36m_2g4=16
lvl_11b_11ag_48m_2g4=15
lvl_11b_11ag_54m_2g4=15
lvl_11n_11ac_mcs0_2g4=18
lvl_11n_11ac_mcs1_2g4=18
lvl_11n_11ac_mcs2_2g4=18
lvl_11n_11ac_mcs3_2g4=18
lvl_11n_11ac_mcs4_2g4=16
lvl_11n_11ac_mcs5_2g4=16
lvl_11n_11ac_mcs6_2g4=15
lvl_11n_11ac_mcs7_2g4=15
lvl_11n_11ac_mcs8_2g4=14
lvl_11n_11ac_mcs9_2g4=14
lvl_11ax_mcs0_2g4=18
lvl_11ax_mcs1_2g4=18
lvl_11ax_mcs2_2g4=18
lvl_11ax_mcs3_2g4=18
lvl_11ax_mcs4_2g4=16
lvl_11ax_mcs5_2g4=16
lvl_11ax_mcs6_2g4=15
lvl_11ax_mcs7_2g4=15
lvl_11ax_mcs8_2g4=14
lvl_11ax_mcs9_2g4=14
lvl_11ax_mcs10_2g4=13
lvl_11ax_mcs11_2g4=13
lvl_11a_6m_5g=18
lvl_11a_9m_5g=18
lvl_11a_12m_5g=18
lvl_11a_18m_5g=18
lvl_11a_24m_5g=16
lvl_11a_36m_5g=16
lvl_11a_48m_5g=15
lvl_11a_54m_5g=15
lvl_11n_11ac_mcs0_5g=18
lvl_11n_11ac_mcs1_5g=18
lvl_11n_11ac_mcs2_5g=18
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=16
lvl_11n_11ac_mcs5_5g=16
lvl_11n_11ac_mcs6_5g=15
lvl_11n_11ac_mcs7_5g=15
lvl_11n_11ac_mcs8_5g=14
lvl_11n_11ac_mcs9_5g=14
lvl_11ax_mcs0_5g=18
lvl_11ax_mcs1_5g=18
lvl_11ax_mcs2_5g=18
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=16
lvl_11ax_mcs5_5g=16
lvl_11ax_mcs6_5g=14
lvl_11ax_mcs7_5g=14
lvl_11ax_mcs8_5g=13
lvl_11ax_mcs9_5g=13
lvl_11ax_mcs10_5g=12
lvl_11ax_mcs11_5g=12
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_ant0_11b_chan_1_4=0
ofst_2g4_ant0_11b_chan_5_9=0
ofst_2g4_ant0_11b_chan_10_13=0
ofst_2g4_ant0_ofdm_highrate_chan_1_4=0
ofst_2g4_ant0_ofdm_highrate_chan_5_9=0
ofst_2g4_ant0_ofdm_highrate_chan_10_13=0
ofst_2g4_ant1_11b_chan_1_4=0
ofst_2g4_ant1_11b_chan_5_9=0
ofst_2g4_ant1_11b_chan_10_13=0
ofst_2g4_ant1_ofdm_highrate_chan_1_4=0
ofst_2g4_ant1_ofdm_highrate_chan_5_9=0
ofst_2g4_ant1_ofdm_highrate_chan_10_13=0
ofst_5g_ant0_ofdm_highrate_chan_42=0
ofst_5g_ant0_ofdm_highrate_chan_58=0
ofst_5g_ant0_ofdm_highrate_chan_106=0
ofst_5g_ant0_ofdm_highrate_chan_122=0
ofst_5g_ant0_ofdm_highrate_chan_138=0
ofst_5g_ant0_ofdm_highrate_chan_155=0
ofst_5g_ant1_ofdm_highrate_chan_42=0
ofst_5g_ant1_ofdm_highrate_chan_58=0
ofst_5g_ant1_ofdm_highrate_chan_106=0
ofst_5g_ant1_ofdm_highrate_chan_122=0
ofst_5g_ant1_ofdm_highrate_chan_138=0
ofst_5g_ant1_ofdm_highrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25
View File
@@ -278,6 +278,31 @@ install_firmware() {
print_warning "Udev rules file not found: $rules_source"
fi
# Install modprobe configuration for Bluetooth
local modprobe_source="${SCRIPT_DIR}/modprobe/aic8800-bt.conf"
local modprobe_dest="/etc/modprobe.d/aic8800-bt.conf"
if [ -f "$modprobe_source" ]; then
print_info "Installing modprobe configuration to $modprobe_dest..."
cp "$modprobe_source" "$modprobe_dest" >> "$LOG_FILE" 2>&1
print_success "Modprobe configuration installed successfully."
else
print_warning "Modprobe configuration file not found: $modprobe_source"
fi
# Install usb_modeswitch configuration
local modeswitch_source="${SCRIPT_DIR}/usb_modeswitch/1111_1111"
local modeswitch_dest="/etc/usb_modeswitch.d/1111:1111"
if [ -f "$modeswitch_source" ]; then
print_info "Installing usb_modeswitch configuration to $modeswitch_dest..."
mkdir -p /etc/usb_modeswitch.d >> "$LOG_FILE" 2>&1 || true
cp "$modeswitch_source" "$modeswitch_dest" >> "$LOG_FILE" 2>&1
print_success "USB modeswitch configuration installed successfully."
else
print_warning "USB modeswitch configuration file not found: $modeswitch_source"
fi
print_success "Firmware installed successfully."
}
+15
View File
@@ -0,0 +1,15 @@
# AIC8800D80 Bluetooth - prevent generic btusb from claiming the device
#
# The kernel's built-in btusb driver matches any USB device with Bluetooth
# interface class (0xe0/0x01/0x01), but it doesn't know how to initialize
# the AIC8800 BT controller, resulting in HCI_Reset timeout errors.
#
# The AIC-specific aic_btusb module must handle these devices instead.
# Ensure aic_btusb loads before btusb can claim AIC devices
softdep btusb pre: aic_btusb
# Auto-load aic_btusb when the AIC8800 device is present
alias usb:v0A69Cp8D83d*dc*dsc*dp*icE0isc01ip01in* aic_btusb
alias usb:v0A69Cp8D81d*dc*dsc*dp*icE0isc01ip01in* aic_btusb
alias usb:v368Bp8D81d*dc*dsc*dp*icE0isc01ip01in* aic_btusb
+16
View File
@@ -0,0 +1,16 @@
# AIC8800D80 "Pandora" clone adapter (VID:PID 1111:1111)
# Sends vendor-specific SCSI CDB to trigger mode switch from
# USB Mass Storage to WiFi+BT mode.
#
# The 16-byte CDB is: FD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F2
# Wrapped in a standard 31-byte SCSI CBW (Command Block Wrapper).
#
# Install as: /etc/usb_modeswitch.d/1111:1111
# (The filename must contain a colon on Linux; this file is named
# 1111_1111 in the repo because Windows/git can't handle colons.)
DefaultVendor=0x1111
DefaultProduct=0x1111
TargetVendor=0xa69c
TargetProduct=0x8d80
MessageContent="55534243123456780000000000001000fd000000000000000000000000000000f200000000000000000000000000000000"