分析wpa_supplicant起始函数main源码

wpa_supplicant的目录及文件

本篇blog的源码来源于安卓10,对应的wpa_supplicant版本为8。
先来看下wpa_supplicant代码的目录结构
源码目录:

xxx@ubuntu-07:~/workspace/rk3399-android-10/external/wpa_supplicant_8$ ls
Android.mk    CONTRIBUTIONS  hostapd  MODULE_LICENSE_BSD_LIKE  OWNERS  src    wpa_supplicant
CleanSpec.mk  COPYING        hs20     NOTICE                   README  tests

xxx@ubuntu-07:~/workspace/rk3399-android-10/external/wpa_supplicant_8$ cd src/

xxx@ubuntu-07:~/workspace/rk3399-android-10/external/wpa_supplicant_8/src$ ls
ap      crypto   eap_common  eapol_supp  eap_server  l2_packet  Makefile  pae     rsn_supp  utils
common  drivers  eapol_auth  eap_peer    fst         lib.rules  p2p       radius  tls       wps

关于上面每个文件夹大致的功能是什么网上有很多blog来讲述,讲的也非常清楚,可自行查看。

main

分析初始化之前,先看下安卓10跑起来后,在控制台输入logcat指令以后输出的系统debug信息。
logcat输出:

[17:16:13][   46.176721] init: starting service 'wpa_supplicant'...
。。。。。一些其他的init输出
[17:16:13]11-18 11:10:06.091 +0000  2017  2017 I wpa_supplicant: argc = 2

第一句话是系统内核输出的,并非wpa_supplicant;这句话意味着wpas服务被启动,即调用了wpas的开始函数。经对比上方的输出和下方的代码,即可知,wpa_supplicant服务一开始进入的函数就是它~/wpa_supplicant/main.c里的main函数,上面贴出的最后一句输出和对应main里的printf对应上了。

wpa_supplicant的main函数:~/rk3399-android-10/external/wpa_supplicant_8/wpa_supplicant/main.c

#define BROADCOM_MODULE_NAME "[broadcom]"
#define REALTEK_MODULE_NAME "[realtek]"
#define SSV_MODULE_NAME "[ssv]"
#define ESP_MODULE_NAME "[esp]"

int main(int argc, char *argv[])
{
        int ret = -1;
        char module_type[20]={0};//实际上没有使用到

        wpa_printf(MSG_INFO,"argc = %d\n",argc);
        //这就是log里输出的那句,说明这是整个wpas服务的起始函数
        //至于谁实际上调用了这个main函数并将argc和argv传进来,我暂时没找到,希望清楚这里的大佬指导一下
        if(argc == 2) {
                if (check_wifi_chip_type() == REALTEK_WIFI) {//别的文件里定义的函数和属性,见之后贴出的代码
                        wpa_printf(MSG_INFO,"Start rtl_wpa_supplicant\n");
                        ret = read_wpa_param_config(REALTEK_MODULE_NAME,argv[1]);//根据不同的芯片类型,读取wpa_config.txt中的不同属性
                        //REALTEK_MODULE_NAME为上方定义的全局变量
                } else if (check_wifi_chip_type() == BROADCOM_WIFI) {//以下同上
                        wpa_printf(MSG_INFO,"Start bcm_wpa_supplicant\n");
                        ret = read_wpa_param_config(BROADCOM_MODULE_NAME,argv[1]);
                } else if (check_wifi_chip_type() == RK912_WIFI ||
                                check_wifi_chip_type() == SSV_WIFI) {
                        wpa_printf(MSG_INFO,"Start ssv_wpa_supplicant\n");
                        ret = read_wpa_param_config(SSV_MODULE_NAME,argv[1]);
                } else if (check_wifi_chip_type() == ESP_WIFI) {
                        wpa_printf(MSG_INFO,"Start esp_wpa_supplicant\n");
                        ret = read_wpa_param_config(ESP_MODULE_NAME,argv[1]);
                } else {
                        wpa_printf(MSG_INFO,"Start wpa_supplicant\n");
                        ret = read_wpa_param_config(BROADCOM_MODULE_NAME,argv[1]);
                } 
        } else {//如果传进来的第一个参数并非2,则调用main_loop
                wpa_printf(MSG_INFO,"Start wpa_supplicant\n");
                ret = main_loop(argc, argv);
        }
        return ret;
}

int main_loop(int argc, char *argv[])//不是本文重点,可忽略不看,只需知道是argv里各类参数的解析即可
{
        int c, i;
        struct wpa_interface *ifaces, *iface;
        int iface_count, exitcode = -1;
        struct wpa_params params;
        struct wpa_global *global;

        if (os_program_init())
                return -1;

        os_memset(&params, 0, sizeof(params));
        params.wpa_debug_level = MSG_DEBUG;

        iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
        if (ifaces == NULL)
                return -1;
        iface_count = 1;

        wpa_supplicant_fd_workaround(1);

        for (;;) {
                c = getopt(argc, argv,
                           "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
                if (c < 0)
                        break;
                switch (c) {//其实这部分,就相当于是解析wpa_config.txt里的参数的步骤
                case 'b':
                        iface->bridge_ifname = optarg;
                        break;
                case 'B':
                        params.daemonize++;
                        break;
               。。。。。。
               default:
                        usage();
                        exitcode = 0;
                        goto out;
                }
        }
        exitcode = 0;
        global = wpa_supplicant_init(&params);//调用初始化wpa_supplicant的函数
        if (global == NULL) {
                wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
                exitcode = -1;
                goto out;
        } else {
                wpa_printf(MSG_INFO, "Successfully initialized "
                           "wpa_supplicant");
        }
        if (fst_global_init()) {
                wpa_printf(MSG_ERROR, "Failed to initialize FST");
                exitcode = -1;
                goto out;
        }
       
        #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
        if (!fst_global_add_ctrl(fst_ctrl_cli))
                wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif
        for (i = 0; exitcode == 0 && i < iface_count; i++) {
                struct wpa_supplicant *wpa_s;

                if ((ifaces[i].confname == NULL &&
                     ifaces[i].ctrl_interface == NULL) ||
                    ifaces[i].ifname == NULL) {
                        if (iface_count == 1 && (params.ctrl_interface ||
#ifdef CONFIG_MATCH_IFACE
                                                 params.match_iface_count ||
#endif /* CONFIG_MATCH_IFACE */
                                                 params.dbus_ctrl_interface))
                                break;
                        usage();
                        exitcode = -1;
                        break;
                }
                wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
                if (wpa_s == NULL) {
                        exitcode = -1;
                        break;
                }
        }
        #ifdef CONFIG_MATCH_IFACE
        if (exitcode == 0)
                exitcode = wpa_supplicant_init_match(global);
#endif /* CONFIG_MATCH_IFACE */
        if (exitcode == 0)
                exitcode = wpa_supplicant_run(global);
        wpa_supplicant_deinit(global);
        fst_global_deinit();
out:
        wpa_supplicant_fd_workaround(0);
        os_free(ifaces);
#ifdef CONFIG_MATCH_IFACE
        os_free(params.match_ifaces);
#endif /* CONFIG_MATCH_IFACE */
        os_free(params.pid_file);
        os_program_deinit();
        return exitcode;
}

check_wifi_chip_type_string

文件位置:src/common/wpa_common.c

static char wifi_type[64] = {0};
extern int check_wifi_chip_type_string(char *type);
int check_wifi_chip_type()
{
        int type;
        if (wifi_type[0] == 0) {//若未赋值,则调用check_wifi_chip_type_string
        //函数定义位置在~/android10/frameworks/opt/net/wifi/libwifi_hal/rk_wifi_ctrl.cpp中
                check_wifi_chip_type_string(wifi_type);
                //调用完上面的函数,会将wifi_type赋值成当前能检测到的wifi chip的类型名称
                wpa_printf(MSG_INFO,"Current wifi chip is %s\n",wifi_type);
        }
        if (0 == strncmp(wifi_type, "RTL", 3)) {
                type = REALTEK_WIFI;
        } else if (0 == strncmp(wifi_type, "SSV", 3)) {
                type = SSV_WIFI;
        } else if (0 == strncmp(wifi_type, "ESP", 3)) {
                type = ESP_WIFI;
        } else if (0 == strncmp(wifi_type, "RK912", 5)) {
                type = RK912_WIFI;
        } else {
                type = BROADCOM_WIFI;
        }
                return type;
}

这个函数调用完毕,会返回当前所使用wifi_chip的类型名称,以便在main中匹配到不同的if分支。
上述代码涉及到的一些定义见下:
定义所在文件位置:src/common/defs.h

/**
  * enum wifi type
  */
enum wifi_tpye {
        REALTEK_WIFI = 1,
        BROADCOM_WIFI,
        SSV_WIFI,
        ESP_WIFI,
        RK912_WIFI,
};

read_wpa_param_config

文件位置:~/rk3399-android-10/external/wpa_supplicant_8/wpa_supplicant/main.c

int read_wpa_param_config(char *module_name, char *file_path) {
        char *wpa_param[50] = {0};
        char wpa_param_buf[50][50];
        int wpa_param_len = 0;
        char buf[256] = {0};
        FILE *fp = NULL;
        char *pos;
        int ret = -1;
        int found = 0;
        int i;
        fp = fopen(file_path, "r");//打开文件,~/rk3399-android-10/device/rockchip/common/wpa_config.txt
        wpa_printf(MSG_INFO,"module_name = %s\n",module_name);
        if (fp == NULL) {
                wpa_printf(MSG_ERROR,"%s not found\n",file_path);
                return -1;
        }
        while(fgets(buf, sizeof(buf) -1, fp)) {//读取文件内容,截取字符串
                pos = buf;
                while (*pos != '\0') {
                        if (*pos == '\n' || *pos == ' ') {
                                *pos = '\0';
                                break;
                        }
                        pos++;
                }
                if(found == 0) {//需要找到文件中,与当前所求模块对应的一系列参数
                        if(strstr(buf,module_name)) {
                                found = 1;
                                wpa_printf(MSG_INFO,"found %s\n",module_name);
                        }
                        continue;
                }
                if(buf[0] == '\n' || buf[0] == '\0'|| buf[0] == '#' || buf[0] == ' ' || buf[0] == '[') {
                        wpa_printf(MSG_INFO,"wpa_param_len = %d\n",wpa_param_len);
                        break;
                }
                strcpy(wpa_param_buf[wpa_param_len],buf);
                wpa_param_len++;//截取这些params字符串存储到wpa_param_buf中
        }
        fclose(fp);
        for(i = 0; i < wpa_param_len; i++) {
                wpa_param[i] = wpa_param_buf[i];//按行将每一行参数存到wpa_param中对应的行里
                wpa_printf(MSG_INFO,"wpa_param_len = %d | wpa_param[%d] = %s\n",wpa_param_len,i,wpa_param[i]);
        }
        if(wpa_param_len > 0)
                ret = main_loop(wpa_param_len,wpa_param);//跳转到main_loop中解析具体的每项参数,并且据此初始化一些接口
        else
                wpa_printf(MSG_ERROR,"%s not found\n",module_name);
        return ret;
}

wpa_config.txt

文件位置:~/rk3399-android-10/device/rockchip/common/wpa_config.txt
里面的内容大致如下:

[broadcom]
/vendor/bin/hw/wpa_supplicant
-O/data/vendor/wifi/wpa/sockets
-puse_p2p_group_interface=1
-g@android:wpa_wlan0

[realtek]
/vendor/bin/hw/wpa_supplicant
-O/data/vendor/wifi/wpa/sockets
-g@android:wpa_wlan0

......
//还有很多其他厂商的wpas配置信息

如果需要移植wifi驱动,则需要配置好与wpa_supplicant交互的各类属性接口。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值