根据模块根据调用check_wifi_chip_type_string函数获取的type来决定WiFi/BT模块的模组厂。其中常见WiFi/BT模组的接口有USB、SDIO以及PCIE。对应的路径如下:
- USB:/sys/bus/usb/devices;
- SDIO:/sys/bus/sdio/devices;
- PCIE:/sys/bus/pci/devices
static const char USB_DIR[] = "/sys/bus/usb/devices";
static const char SDIO_DIR[]= "/sys/bus/sdio/devices";
static const char PCIE_DIR[]= "/sys/bus/pci/devices";
static const char PREFIX_SDIO[] = "SDIO_ID=";
static const char PREFIX_PCIE[] = "PCI_ID=";
static const char PREFIX_USB[] = "PRODUCT=";
int check_wifi_chip_type_string(char *type)
{
if (identify_sucess == -1) {
//调用get_wifi_device_id函数获取对应的模组ID,对应的路径:
// USB接口:/sys/bus/pci/devices;
// SDIO接口:/sys/bus/sdio/devices;
// PCIE接口:/sys/bus/pci/devices
if (get_wifi_device_id(SDIO_DIR, PREFIX_SDIO) == 0)
ALOGD("%s:%d SDIO WIFI identify sucess",__FUNCTION__,__LINE__);
else if (get_wifi_device_id(USB_DIR, PREFIX_USB) == 0)
ALOGD("%s:%d USB WIFI identify sucess",__FUNCTION__,__LINE__);
else if (get_wifi_device_id(PCIE_DIR, PREFIX_PCIE) == 0)
PLOG(DEBUG) << "PCIE WIFI identify sucess";
ALOGD("%s:%d PCIE WIFI identify sucess",__FUNCTION__,__LINE__);
else {
ALOGD("%s:%d maybe there is no usb wifi or sdio or pcie wifi,set default wifi module Brocom APXXX",__FUNCTION__,__LINE__);
//如果上面三种获取不到,则使用默认APXXX
strcpy(recoginze_wifi_chip, "APXXX");
identify_sucess = 1 ;
}
}
strcpy(type, recoginze_wifi_chip);
ALOGE("%s:%d check_wifi_chip_type_string : %s",__FUNCTION__,__LINE__,type);
return 0;
}
具体是通过get_wifi_device_id函数来获取,接口如下:
typedef struct _wifi_devices
{
char wifi_name[64];
char wifi_vid_pid[64];
} wifi_device;
// wifi devices 对应 wifi name和 vid/pid
static wifi_device supported_wifi_devices[] = {
{"RTL8188EU", "0bda:8179"},
{"RTL8188EU", "0bda:0179"},
{"RTL8723BU", "0bda:b720"},
{"RTL8723BS", "024c:b723"},
{"RTL8822BS", "024c:b822"},
{"RTL8723CS", "024c:b703"},
{"RTL8723DS", "024c:d723"},
{"RTL8188FU", "0bda:f179"},
{"RTL8822BU", "0bda:b82c"},
{"RTL8189ES", "024c:8179"},
{"RTL8189FS", "024c:f179"},
{"RTL8192DU", "0bda:8194"},
{"RTL8812AU", "0bda:8812"},
{"RTL8821CS", "024c:c821"},
{"RTL8822CU", "0bda:c82c"},
{"RTL8822CS", "024c:c822"},
{"SSV6051", "3030:3030"},
{"ESP8089", "6666:1111"},
{"AP6354", "02d0:4354"},
{"AP6330", "02d0:4330"},
{"AP6356S", "02d0:4356"},
{"AP6335", "02d0:4335"},
{"AP6255", "02d0:a9bf"},
{"RTL8822BE", "10ec:b822"},
{"MVL88W8977", "02df:9145"},
{"SPRDWL", "0000:0000"},
};
int get_wifi_device_id(const char *bus_dir, const char *prefix)
{
int idnum;
int i = 0;
int ret = invalid_wifi_device_id;
DIR *dir;
struct dirent *next;
FILE *fp = NULL;
//获取支持的模组数组列表数
idnum = sizeof(supported_wifi_devices) / sizeof(supported_wifi_devices[0]);
// 根据模组接口类型打开对应的路径
dir = opendir(bus_dir);
if (!dir) {
ALOGE("%s:%d open dir failed: %s",__FUNCTION__,__LINE__,strerror(errno));
return invalid_wifi_device_id;
}
while ((next = readdir(dir)) != NULL) {
char line[256];
char uevent_file[256] = {0};
//将格式化的路径写入到uevent_file,最终路径是:
// USB接口:/sys/bus/pci/devices/*/uevent;
// SDIO接口:/sys/bus/sdio/devices/*/uevent;
// PCIE接口:/sys/bus/pci/devices/*/uevent;
sprintf(uevent_file, "%s/%s/uevent", bus_dir, next->d_name);
ALOGD("%s:%d uevent path: %s",__FUNCTION__,__LINE__,uevent_file);
//读取uevent数据
fp = fopen(uevent_file, "r");
if (NULL == fp) {
continue;
}
while (fgets(line, sizeof(line), fp)) {
char *pos = NULL;
int product_vid = 0;
int product_did = 0;
int producd_bcddev = 0;
char temp[10] = {0};
//找到prefix在line中第一次出现位置
pos = strstr(line, prefix);
ALOGD("%s:%d line: %s , prefix: %s .",__FUNCTION__,__LINE__,line, prefix);
if (pos != NULL) {
//根据路径来获取对应vid和pid
if (strncmp(bus_dir, USB_DIR, sizeof(USB_DIR)) == 0)
//从指定字符串读取特定格式的数据
sscanf(pos + 8, "%x/%x/%x", &product_vid, &product_did, &producd_bcddev);
else if (strncmp(bus_dir, SDIO_DIR, sizeof(SDIO_DIR)) == 0)
sscanf(pos + 8, "%x:%x", &product_vid, &product_did);
else if (strncmp(bus_dir, PCIE_DIR, sizeof(PCIE_DIR)) == 0)
sscanf(pos + 7, "%x:%x", &product_vid, &product_did);
else
return invalid_wifi_device_id;
//将vid和pid格式化输出到temp中
sprintf(temp, "%04x:%04x", product_vid, product_did);
ALOGD("%s:%d pid:vid : %04x:%04x ",__FUNCTION__,__LINE__,product_vid, product_did);
for (i = 0; i < idnum; i++) {
//读到的pid和支持pid比较确认对应的模组名称
if (0 == strncmp(temp, supported_wifi_devices[i].wifi_vid_pid, 9)) {
ALOGE("%s:%d found device pid:vid : %04x:%04x ",__FUNCTION__,__LINE__,product_vid, product_did);
strcpy(recoginze_wifi_chip, supported_wifi_devices[i].wifi_name);
identify_sucess = 1 ;
ret = 0;
fclose(fp);
goto ready;
}
}
}
}
fclose(fp);
}
ret = invalid_wifi_device_id;
ready:
closedir(dir);
//PLOG(DEBUG) << "wifi detectd return ret:" << ret;
ALOGD("%s:%d wifi detectd return ret: %d",__FUNCTION__,__LINE__,ret);
return ret;
}
至此,可以看出获取wifi模组的过程(以PCIE为例):读取/sys/bus/pci/devices/*/uevent中以“PCI_ID=”开头的数据。然后截取其中的pid,然后所支持的列表的对比,来获取对应的WiFi/BT/模组名称。如果不在列表则为APXXX代替:
//设备上是对应的接口如下
ribeye:/ # cat sys/bus/pci/devices/0002\:21\:00.0/uevent
DRIVER=pcieh
PCI_CLASS=28000
PCI_ID=14E4:4475
PCI_SUBSYS_ID=14E4:4375
PCI_SLOT_NAME=0002:21:00.0
MODALIAS=pci:v000014E4d00004475sv000014E4sd00004375bc02sc80i00
//kernel-5.10/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmdevs.h
#define BCM4375_CHIP_ID 0x4375 /* 4375 chipcommon chipid */
#define BCM4375_D11AX_ID 0x4475 /* 4375 802.11ax dualband device */
设备日志分析:从日志看,我们设备没有配置对应的芯片所以这里check_wifi_chip_type_string为APXXX
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:205 uevent path: /sys/bus/pci/devices/./uevent
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:205 uevent path: /sys/bus/pci/devices/../uevent
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:205 uevent path: /sys/bus/pci/devices/0002:21:00.0/uevent
......
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: DRIVER=pcieh
03-14 10:59:23.488 1724 1724 D wpa_supplicant: , prefix: PCI_ID= .
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: PCI_CLASS=28000
03-14 10:59:23.488 1724 1724 D wpa_supplicant: , prefix: PCI_ID= .
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: PCI_ID=14E4:4475
03-14 10:59:23.488 1724 1724 D wpa_supplicant: , prefix: PCI_ID= .
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:232 pid:vid : 14e4:4475
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: PCI_SUBSYS_ID=14E4:4375
03-14 10:59:23.488 1724 1724 D wpa_supplicant: , prefix: PCI_ID= .
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: PCI_SLOT_NAME=0002:21:00.0
03-14 10:59:23.488 1724 1724 D wpa_supplicant: , prefix: PCI_ID= .
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:219 line: MODALIAS=pci:v000014E4d00004475sv000014E4sd00004375bc02sc80i00
......
03-14 10:59:23.488 1724 1724 D wpa_supplicant: get_wifi_device_id:253 wifi detectd return ret: -1
03-14 10:59:23.488 1724 1724 D wpa_supplicant: check_wifi_chip_type_string:270 maybe there is no usb wifi or sdio or pcie wifi,set default wifi module Brocom APXXX
03-14 10:59:23.488 1724 1724 I wpa_supplicant: check_wifi_chip_type_string:278 check_wifi_chip_type_string : APXXX
因此,需要在supported_wifi_devices列表中增加我们对应的芯片和vid与pid,其中VID(Vendor ID)表示芯片厂商,DID(Device ID)表示具体的模组型号,对应如下,14e4表示博通芯片,4475表示博通下BCM4375一款芯片。这里遗留一个问题PCIE设备的Vid和Did是如何获取的?
{"AP6275HH3", "14e4:4475"},
添加后对应的设备日志如下:
03-15 02:27:20.984 478 478 D android.hardware.wifi@1.0-service: get_wifi_device_id:229 pid:vid : 14e4:4475
03-15 02:27:20.985 478 478 I android.hardware.wifi@1.0-service: get_wifi_device_id:232 found device pid:vid : 14e4:4475
03-15 02:27:20.985 478 478 D android.hardware.wifi@1.0-service: get_wifi_device_id:248 wifi detectd return ret: 0
03-15 02:27:20.985 478 478 D android.hardware.wifi@1.0-service: check_wifi_chip_type_string:259 PCIE WIFI identify sucess
03-15 02:27:20.985 478 478 I android.hardware.wifi@1.0-service: check_wifi_chip_type_string:268 check_wifi_chip_type_string : AP6275HH3
03-15 02:27:36.957 478 478 E android.hardware.wifi@1.0-service: falied to find wifi driver for type=: Success
03-15 02:27:36.957 478 478 E android.hardware.wifi@1.0-service: Failed to load WiFi driver
03-15 02:27:36.957 478 478 E android.hardware.wifi@1.0-service: Failed to initialize firmware mode controller
03-15 02:27:36.957 478 478 E android.hardware.wifi@1.0-service: Wifi HAL start failed
03-15 02:27:36.957 815 1250 E HalDevMgr: Cannot start IWifi: 9 ()
03-15 02:27:36.957 815 1250 E WifiVendorHal: Failed to start vendor HAL
03-15 02:27:36.957 815 1250 E WifiNative: Failed to start vendor HAL
03-15 02:27:36.957 815 1250 E WifiNative: Failed to start Hal
发现WiFi无法启动,对比正常日志应该是我们修改上面配置后,获取不到对应的module path,driver name,hal 那么等导致的问题。具体代码如下:
typedef struct _wifi_file_name
{
char wifi_name[64];
char wifi_driver_name[64];
char wifi_module_path[128];
char wifi_module_arg[128];
char wifi_hal_name[64];
}wifi_file_name;
const wifi_file_name module_list[] =
{
{"RTL8723BU", RTL8723BU_DRIVER_MODULE_NAME, RTL8723BU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8188EU", RTL8188EU_DRIVER_MODULE_NAME, RTL8188EU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8192DU", RTL8192DU_DRIVER_MODULE_NAME, RTL8192DU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8822BU", RTL8822BU_DRIVER_MODULE_NAME, RTL8822BU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8822BS", RTL8822BS_DRIVER_MODULE_NAME, RTL8822BS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8188FU", RTL8188FU_DRIVER_MODULE_NAME, RTL8188FU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8189ES", RTL8189ES_DRIVER_MODULE_NAME, RTL8189ES_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8723BS", RTL8723BS_DRIVER_MODULE_NAME, RTL8723BS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8723CS", RTL8723CS_DRIVER_MODULE_NAME, RTL8723CS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8723DS", RTL8723DS_DRIVER_MODULE_NAME, RTL8723DS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8812AU", RTL8812AU_DRIVER_MODULE_NAME, RTL8812AU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8189FS", RTL8189FS_DRIVER_MODULE_NAME, RTL8189FS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8822BE", RTL8822BE_DRIVER_MODULE_NAME, RTL8822BE_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8821CS", RTL8821CS_DRIVER_MODULE_NAME, RTL8821CS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8822CU", RTL8822CU_DRIVER_MODULE_NAME, RTL8822CU_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"RTL8822CS", RTL8822CS_DRIVER_MODULE_NAME, RTL8822CS_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, REALTEK_WIFI_HAL},
{"SSV6051", SSV6051_DRIVER_MODULE_NAME, SSV6051_DRIVER_MODULE_PATH, SSV6051_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"ESP8089", ESP8089_DRIVER_MODULE_NAME, ESP8089_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"AP6335", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"AP6330", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"AP6354", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"AP6356S", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"AP6255", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"APXXX", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"MVL88W8977", MVL_DRIVER_MODULE_NAME, MVL_DRIVER_MODULE_PATH, MVL88W8977_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"RK912", RK912_DRIVER_MODULE_NAME, RK912_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
{"SPRDWL", SPRDWL_DRIVER_MODULE_NAME, SPRDWL_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, SPRD_WIFI_HAL},
{"BES2600", BES2600_DRIVER_MODULE_NAME, BES2600_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BES_WIFI_HAL},
};
const char *get_wifi_driver_name(void)
{
if (wifi_type[0] == 0) {
check_wifi_chip_type_string(wifi_type);
}
//对应module list对应wifi_type是否一致
for (int i = 0; i< (int)(sizeof(module_list) / sizeof(module_list[0])); i++) {
if (strncmp(wifi_type, module_list[i].wifi_name, strlen(wifi_type)) == 0) {
ALOGI("%s:%d matched wifi_driver_name: %s",__FUNCTION__,__LINE__,module_list[i].wifi_driver_name);
return module_list[i].wifi_driver_name;
}
}
return NULL;
}
const char *get_wifi_module_path(void)
{
if (wifi_type[0] == 0) {
check_wifi_chip_type_string(wifi_type);
}
for (int i = 0; i< (int)(sizeof(module_list) / sizeof(module_list[0])); i++) {
if (strncmp(wifi_type, module_list[i].wifi_name, strlen(wifi_type)) == 0) {
ALOGI("%s:%d matched wifi_module_path: %s",__FUNCTION__,__LINE__,module_list[i].wifi_module_path);
return module_list[i].wifi_module_path;
}
}
return NULL;
}
const char *get_wifi_module_arg(void)
{
if (wifi_type[0] == 0) {
check_wifi_chip_type_string(wifi_type);
}
for (int i = 0; i< (int)(sizeof(module_list) / sizeof(module_list[0])); i++) {
if (strncmp(wifi_type, module_list[i].wifi_name, strlen(wifi_type)) == 0) {
ALOGI("%s:%d matched wifi_module_arg: %s",__FUNCTION__,__LINE__,module_list[i].wifi_module_arg);
return module_list[i].wifi_module_arg;
}
}
return NULL;
}
const char *get_wifi_hal_name(void)
{
if (wifi_type[0] == 0) {
check_wifi_chip_type_string(wifi_type);
}
for (int i = 0; i< (int)(sizeof(module_list) / sizeof(module_list[0])); i++) {
if (strncmp(wifi_type, module_list[i].wifi_name, strlen(wifi_type)) == 0) {
ALOGI("%s:%d matched wifi_hal_name: %s ",__FUNCTION__,__LINE__,module_list[i].wifi_hal_name);
return module_list[i].wifi_hal_name;
}
}
return NULL;
}
从代码可以看出,以上接口首先会通过check_wifi_chip_type_string获取到wifi type的名称是module_list中,如果不在在获取为NULL,WiFi将无法加载。我们在没有添加我们对应的vid之前,使用的是默认的名称如下,可以找到对应的MODULE NAME/MODULE_PATH和WIFI HAL。
{"APXXX", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
因此,我们只需要将module_list中也添加我们的module name就可以识别到:
{"AP6275HH3", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKOWN_DRIVER_MODULE_ARG, BROADCOM_WIFI_HAL},
添加后对应日志如下:
03-15 06:35:19.596 483 483 I android.hardware.wifi@1.0-service: get_wifi_module_path:295 matched wifi_module_path: /vendor/lib/modules/bcmdhd.ko
03-15 06:35:19.596 483 483 I android.hardware.wifi@1.0-service: get_wifi_module_arg:309 matched wifi_module_arg:
03-15 06:35:19.597 483 483 I android.hardware.wifi@1.0-service: get_wifi_hal_name:323 matched wifi_hal_name: libwifi-hal-bcm.so
03-15 06:35:19.597 483 483 D RKWifiHAL: libwifi hal name: libwifi-hal-bcm.so
03-15 06:35:19.612 483 483 I android.hardware.wifi@1.0-service: check_wifi_chip_type_string:269 check_wifi_chip_type_string : AP6275HH3
03-15 06:35:21.255 464 479 D android.hardware.bluetooth@1.0-service: get_wifi_device_id:230 pid:vid : 14e4:4475
03-15 06:35:21.255 464 479 I android.hardware.bluetooth@1.0-service: get_wifi_device_id:233 found device pid:vid : 14e4:4475
03-15 06:35:21.255 464 479 D android.hardware.bluetooth@1.0-service: get_wifi_device_id:249 wifi detectd return ret: 0
03-15 06:35:21.255 464 479 D android.hardware.bluetooth@1.0-service: check_wifi_chip_type_string:260 PCIE WIFI identify sucess
03-15 06:35:21.255 464 479 I android.hardware.bluetooth@1.0-service: check_wifi_chip_type_string:269 check_wifi_chip_type_string : AP6275HH3
03-15 06:35:21.255 464 479 D android.hardware.bluetooth@1.0-impl: Open: libbt-vendor.so