Android8.1 hal loading wifi ko module process

If Android finds that the wifi does not start normally, follow the following two aspects:

1. Is the wifi ko file compiled normally? If not, it means there is a problem with the compilation. The address of the ko file is vendor/lib/module/devices/wifi.

2. If the ko file is compiled, but it still prompts Wifi HAL start failed, first use insmod to manually load the ko file and check whether the wifi can start normally. If it can, it means that the ko file has not been loaded successfully. Find the reason as follows:

When Android starts, it will load the wifi module. At this time, this part of the code is in frameworks\opt\net\wifi\libwifi_hal\. The main function of this part of the code is to obtain the wifi under the system by reading uevnt. The VIP and pid of the module are used to find out which wifi module it is from the code list, and then the driver code of the wifi module is obtained from the list, and then insmod xxxx.ko is called to load the wifi module.
 

frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
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"},
	{"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"},
};


frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp

//wifi模块的驱动ko,文件的路径地址"/vendor/lib/modules/"
#define WIFI_MODULE_PATH		"/vendor/lib/modules/"
wifi_ko_file_name module_list[] =
{
	{"RTL8723BU", RTL8723BU_DRIVER_MODULE_NAME, RTL8723BU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8188EU", RTL8188EU_DRIVER_MODULE_NAME, RTL8188EU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8192DU", RTL8192DU_DRIVER_MODULE_NAME, RTL8192DU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8822BU", RTL8822BU_DRIVER_MODULE_NAME, RTL8822BU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8822BS", RTL8822BS_DRIVER_MODULE_NAME, RTL8822BS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8188FU", RTL8188FU_DRIVER_MODULE_NAME, RTL8188FU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8189ES", RTL8189ES_DRIVER_MODULE_NAME, RTL8189ES_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8723BS", RTL8723BS_DRIVER_MODULE_NAME, RTL8723BS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8723CS", RTL8723CS_DRIVER_MODULE_NAME, RTL8723CS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8723DS", RTL8723DS_DRIVER_MODULE_NAME, RTL8723DS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8812AU", RTL8812AU_DRIVER_MODULE_NAME, RTL8812AU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8189FS", RTL8189FS_DRIVER_MODULE_NAME, RTL8189FS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"RTL8822BE", RTL8822BE_DRIVER_MODULE_NAME, RTL8822BE_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"SSV6051",     SSV6051_DRIVER_MODULE_NAME,   SSV6051_DRIVER_MODULE_PATH, SSV6051_DRIVER_MODULE_ARG},
	{"ESP8089",     ESP8089_DRIVER_MODULE_NAME,   ESP8089_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"AP6335",          BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"AP6330",          BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"AP6354",          BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"AP6356S",         BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"AP6255",          BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"APXXX",           BCM_DRIVER_MODULE_NAME,       BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"MVL88W8977",      MVL_DRIVER_MODULE_NAME,       MVL_DRIVER_MODULE_PATH, MVL88W8977_DRIVER_MODULE_ARG},
        {"RK912",         RK912_DRIVER_MODULE_NAME,     RK912_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
	{"UNKNOW",       DRIVER_MODULE_NAME_UNKNOW,    DRIVER_MODULE_PATH_UNKNOW, UNKKOWN_DRIVER_MODULE_ARG}

};
hardware\interfaces\wifi\1.2\default\service.cpp
//加载 WifiModeController然后会调用到WifiModeController::WifiModeController()
android::sp<android::hardware::wifi::V1_2::IWifi> service =
        new android::hardware::wifi::V1_2::implementation::Wifi(
            std::make_shared<WifiLegacyHal>(),
            std::make_shared<WifiModeController>(), 
            std::make_shared<WifiFeatureFlags>());


hardware\interfaces\wifi\1.2\default\wifi_mode_controller.cpp
WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
    bool WifiModeController::initialize() {
    if (!driver_tool_->LoadDriver()) {       //调用到下面的 LoadDriver
        LOG(ERROR) << "Failed to load WiFi driver";
        return false;
    }
    return true;
}


加载wifi驱动代码调用路径
frameworks\opt\net\wifi\libwifi_hal\driver_tool.cpp
    bool DriverTool::LoadDriver()
           return ::wifi_load_driver()
                    wifi_load_driver()  //frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp
                   check_wifi_chip_type_string  //frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp
                   if (!strcmp(wifi_type , module_list[i].wifi_name)) {
						wifi_ko_path = module_list[i].wifi_module_path;   //从module_list中获取到wifi驱动,xxxx.ko的路径,在这里是"/vendor/lib/modules/xxxx.ko"   
						wifi_ko_arg = module_list[i].wifi_module_arg;
                   }
				   save_wifi_chip_type(wifi_type);     //保存我们加载wifi的一些信息,这些信息用来给wpa_supplicant加载对于的wifi启动参数。
                   insmod(wifi_ko_path, wifi_ko_arg); //加载ko模块,和我们手动命令insmod xxxx.ko效果一样的

                 

//此功能为了从supported_wifi_devices这个列表里面获取当前SDIO上面挂载的是那个模块
int check_wifi_chip_type_string(char *type)
{
	if (identify_sucess == -1) {
		if (get_wifi_device_id(SDIO_DIR, PREFIX_SDIO) == 0)
			PLOG(DEBUG) << "SDIO WIFI identify sucess";
		else if (get_wifi_device_id(USB_DIR, PREFIX_USB) == 0)
			PLOG(DEBUG) << "USB WIFI identify sucess";
		else if (get_wifi_device_id(PCIE_DIR, PREFIX_PCIE) == 0)
			PLOG(DEBUG) << "PCIE WIFI identify sucess";
		else {
			PLOG(DEBUG) << "maybe there is no usb wifi or sdio or pcie wifi,set default wifi module Brocom APXXX";
			strcpy(recoginze_wifi_chip, "APXXX");
			identify_sucess = 1 ;
		}
	}

	strcpy(type, recoginze_wifi_chip);    //复制supported_wifi_devices里面的wifi_name的值
	PLOG(ERROR) << "check_wifi_chip_type_string : " << type;
	return 0;
} 
                        

The wifi startup driver loads fw process.
Nowadays, the wifi module loads a fw firmware when it starts. What is this firmware used for? It may be used by the manufacturer to make differential configurations, or to load radio frequency parameters for use. You can understand it as loading a bin file into the wifi module. It needs to be loaded every time the wif module is powered on. The loading operation When loading the wifi driver, the bin files loaded by different manufacturers are different. Below we can see the following print through the log printed when the system is started. The following example is the printing of Broadcom's wifi module, Realtek is different.
 

Broadcom wifi loading process

               Final fw_path=/vendor/etc/firmware/fw_bcm43438a1.bin
[   64.276445] Final nv_path=/vendor/etc/firmware/nvram_ap6212a.txt
[   64.276669] Final clm_path=/vendor/etc/firmware/clm.blob
[   64.276896] Final conf_path=/vendor/etc/firmware/config.txt
[   64.279224] dhd_os_open_image: /vendor/etc/firmware/fw_bcm43438a1.bin (414665 bytes) open success
[   64.365150] dhd_os_open_image: /vendor/etc/firmware/nvram_ap6212a.txt (1003 bytes) open success
[   64.365249] NVRAM version: AP6212A_NVRAM_V1.0.1_20160606

grep "Final fw_path=" -nr
通过查找Final fw_path=查找出在那里打印出的log,从而找到。
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c:8341:        printf("Final fw_path=%s\n", bus->fw_path);
所以可以知道在驱动里面会加载fw固件,但是这个固件的地址是在那里传进来的需要进一步追踪bus->fw_path这个值。

After tracing, I found that on the rockchip platform, the firmware path is hard-coded in the kernel. The code defines a function int rkwifi_set_firmware(char *fw, char *nvram in kernel\drivers\net\wireless\rockchip_wlan\rkwifi\rk_wifi_config.c ), this function is called in Broadcom's wifi driver to obtain the burning address of the wifi firmware. It is called in bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) in kernel\drivers\net\wireless\rockchip_wlan\rkwifi\bcmdhd\dhd_linux.c .

For Broadcom's wifi and Bluetooth two and one chips, it is generally necessary to load three firmwares corresponding to wifi and Bluetooth:
for the wifi part there are fw_bcm43438a1.bin and nvram_ap6212a.txt and
for the bluetooth part there is
bcm43438a1.hcd

For Realtek's wifi, the wifi part does not need to load firmware, but Bluetooth needs to load firmware. The address of the firmware is defined in kernel\drivers\bluetooth\rtk_btusb.c

static patch_info fw_patch_table[] = {
/* { vid, pid, lmp_sub_default, lmp_sub, everion, mp_fw_name, fw_name, config_name, fw_cache, fw_len, mac_offset } */
{ 0x0BDA, 0x1724, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723A */
{ 0x0BDA, 0x8723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
{ 0x0BDA, 0xA723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for LI */
{ 0x0BDA, 0x0723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
{ 0x13D3, 0x3394, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for Azurewave*/

When Bluetooth loads the driver, the kernel layer will call request_firmware(&cfg, config_name, &udev->dev); to download the firmware.
For how to use request_firmware, please refer to: https://blog.csdn.net/magod/article/details/6049558.
When the kernel calls the request_firmware function, a node will be generated in the directory /sys/class/firmware at the application layer. This node is divided into three attributes:
 

loading
这个属性应当被加载固件的用户空间进程设置为 1. 当加载进程完成, 它应当设为 0. 写一个值 -1 到 loading 会中止固件加载进程.

data
data 是一个二进制的接收固件数据自身的属性. 在设置 loading 后, 用户空间进程应当写固件到这个属性.

device
这个属性是一个符号连接到 /sys/devices 下面的被关联入口项.

It can be speculated from this that when Bluetooth firmware needs to be downloaded, the application layer will definitely write the firmware data to the data attribute.

The android hal loading wpa_supplicant process
has been explained in our previous "android hal loading wifi ko module process". After the system starts, it will obtain the wifi chip vid pid, load the corresponding wifi ko driver, and then save the wifi chip while loading the ko driver. Some information, for example, if the wifi module we load is from Broadcom, we will save the name of Broadcom wifi. If the module we load is from Realtek, we will save the name of Realtek wifi. After the system starts, the system will read the init.connectivity.rc script. This script will start the wpa_supplicant service. This application service will reside in the background. When starting wpa_supplicant, you need to specify the parameters of the wifi module. The parameters are saved in "/ vendor/etc/wifi/wpa_config.txt", the source code directory is placed in /device/rockchip/common/wpa_config.txt.

Where does librkwifi-ctrl.so come from?
In \frameworks\opt\net\wifi\libwifi_hal\Android.bp

cc_library_shared {               //编译成可执行文件,cc_library_shared编译成动态库
    name: "librkwifi-ctrl",     //生成librkwifi-ctrl.so库
    vendor: true,                 //编译出来放在/vendor目录下(默认是放在/system目录下)
    cflags: wifi_hal_cflags,
    local_include_dirs: ["include"],       //用户值定的头文件查找路径
    shared_libs: ["libbase"],              //编译依赖的动态库   
    header_libs: ["libcutils_headers"],
    srcs: ["rk_wifi_ctrl.cpp"],               //源文件,格式["a.cpp", "b.cpp"]
}

Guess you like

Origin blog.csdn.net/u010823818/article/details/132846446