我是靠谱客的博主 魁梧热狗,最近开发中收集的这篇文章主要介绍wpa_supplicant的控制接口简单说明,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

1 说明

2 参考

2.1 函数基本说明

2.2 逻辑说明

3 应用程序的处理

3.1 事件通知消息说明

3.2 代码示例


1 说明

本文旨在用wpa_supplicant提供的API控制wifi模块以STA工作模式连接热点。wpa_supplicant程序一般运行在后台(./wpa_supplicant -B -cwpa_0_8.conf -iwlan0),用户通过它提供的接口让它做各种连接操作。

2 参考

http://w1.fi/wpa_supplicant/devel/wpa__ctrl_8h.html#a4e48c0a662d9150ea603e75365748b0b

wpa_supplicant-devel.pdf

https://www.kancloud.cn/alex_wsc/android-wifi-nfc-gps/414067

2.1 函数基本说明

struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);

打开wpa_supplicant的一个控制接口,参数ctrl_path一般为/var/run/wpa_supplicant/wlan0,wlan0为对应的网络节点。成功时返回控制结构体指针,后续的一系列函数都以该指针为参数。失败时返回NULL。

int wpa_ctrl_attach(struct wpa_ctrl *ctrl);

注册一个事件通知监视器。成功时返回。失败时返回-1。超时则返回-2。该函数成功之后,可以通过wpa_ctrl_pending和wpa_ctrl_recv处理事件通知。

int wpa_ctrl_pending(struct wpa_ctrl *ctrl);

检查是否有待处理的事件通知,如果有返回1,没有返回0,出错返回-1。

int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);

接收一条待处理的事件通知,将内容保存在reply指向的空间,内容的长度保存在reply_len指向的空间。

int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,

     char *reply, size_t *reply_len,

     void (*msg_cb)(char *msg, size_t len));

发送一条命令给wpa_supplicant。cmd和cmd_len描述该条命令。reply和reply_len用于保存本次命令的响应。msg_cb一般为NULL即可。成功时返回0,出错(发送或接收失败)返回-1,超时则返回-2。

int wpa_ctrl_detach(struct wpa_ctrl *ctrl);

注销事件通知监视器。成功时返回0,出错返回-1,超时则返回-2。

void wpa_ctrl_close(struct wpa_ctrl *ctrl);

关闭控制接口。

2.2 逻辑说明

wpa_supplicant处理命令的结果分成两种:状态信息和事件通知。状态信息可以理解成命令的响应很快,可以立即拿到结果,比如"PING"、"LIST_NETWORKS"、"STATUS"、"ADD_NETWORK"、

"SET_NETWORK"、"ENABLE_NETWORK"、"SAVE_CONFIG"等,成功时能立即返回并将结果保存在相应的函数参数中。事件通知可以理解成异步事件,比如发送了"ENABLE_NETWORK",该命令能成功且立即返回,但连接热点的过程比较复杂且耗时较长,连接是否成功则通过事件通知告诉用户。

3 应用程序的处理

找出跟wpa_cli相关的文件,将这些文件做成库文件

通过查看编译过程信息,结合makefile,找到了wpa_cli相关的源文件,将这些源文件编译成库文件。在makefile中的wpa_cli: $(OBJS_c)下面添加一行

AR -crv wpa_cli.a $(OBJS_c),AR的值由开发环境决定,如arm-himix100-linux-ar,即可得到想要的库文件。

应用程序使用上述生成的wpa_cli.a和wpa_supplicant包中的wpa_ctrl.h即可控制各种连接操作。

3.1 事件通知消息说明

热点连接成功或者失败的响应消息依赖于驱动程序的实现,比如用户给出错误的SSID或密码不能连接时的打印:

WPA: 4-Way Handshake failed - pre-shared key may be incorrect

CTRL-EVENT-DISCONNECTED bssid=ec:41:18:45:06:5a reason=0

连接成功时的打印:

CTRL-EVENT-CONNECTED

发送命令太频繁会导致消息紊乱,可能导致wpa_0_8.conf内容不完整,

所以建议不要自动发送命令,等待用户通过GUI调用API发送命令或者需要某个功能时才发送命令。 

3.2 代码示例

通过函数user_wifiConnectAP_func连接指定的wifi热点(pu8EncryptType可以为NULL),通过线程user_wifiHdlEvent_thread不断地监听事件通知。

int user_wifiConnectAP_func(char *pu8SSID, char *pu8Secret, char *pu8EncryptType)
{
    char au8ReplyBuf[2048] = {""};
    size_t reply_len;
	int ret;
	int i;
	int s32NetId = -1;
	char au8Path[128] = {""};
	
	/* wpa_ctrl_open */
    sprintf(au8Path, "/var/run/wpa_supplicant/wlan0");
	g_pstWpaCtrl = wpa_ctrl_open(au8Path);
	if(g_pstWpaCtrl == NULL)
	{
		printf("x1b[31m""%s %d, wpa_ctrl_open failed:%s!n""x1b[0m", __FILE__, __LINE__, strerror(errno));
		return -1;
	}

    /* wpa_ctrl_request ADD_NETWORK */
	memset(au8ReplyBuf, '', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, "ADD_NETWORK", strlen("ADD_NETWORK"), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '';
    }

    s32NetId = atoi(au8ReplyBuf);

	/* wpa_ctrl_request SET_NETWORK */
	char au8SsidBuf[128] = {""};
	snprintf(au8SsidBuf, sizeof(au8SsidBuf)-1, "SET_NETWORK %d ssid "%s"", s32NetId, pu8SSID);
	memset(au8ReplyBuf, '', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8SsidBuf, strlen(au8SsidBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '';
		printf("x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%sn""x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

    /* wpa_ctrl_request SET_NETWORK */
	char au8PskBuf[128] = {""};
	snprintf(au8PskBuf, sizeof(au8PskBuf)-1, "SET_NETWORK %d psk "%s"", s32NetId, pu8Secret);
	memset(au8ReplyBuf, '', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8PskBuf, strlen(au8PskBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '';
		printf("x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%sn""x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

    /* wpa_ctrl_request ENABLE_NETWORK */
	char au8EnableBuf[64] = {""};
	snprintf(au8EnableBuf, sizeof(au8EnableBuf)-1, "ENABLE_NETWORK %d", s32NetId);
	memset(au8ReplyBuf, '', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8EnableBuf, strlen(au8EnableBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '';
		printf("x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%sn""x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

	return ret;
}

void *user_wifiHdlEvent_thread(void *arg)
{
    char au8ReplyBuf[2048] = {""};
    size_t reply_len;
    int ret;
    char au8Cmdline[64] = {""};

	while(1)
	{
        if(wpa_ctrl_pending(g_pstWpaCtrl) > 0)
        {
            char buf[2048];
            size_t len = sizeof(buf) - 1;
            if(wpa_ctrl_recv(g_pstWpaCtrl, buf, &len) == 0)
            {
                buf[len] = '';
                if(strstr(buf, "CTRL-EVENT-CONNECTED") != NULL)
    			{
    			    sprintf(au8Cmdline, "udhcpc -i wlan0 -t 5 -T 2 -A 5 -q");
                    system(au8Cmdline);
                    /* wpa_ctrl_request SAVE_CONFIG */
                    wpa_ctrl_request(g_pstWpaCtrl, "SAVE_CONFIG", strlen("SAVE_CONFIG"), au8ReplyBuf, &reply_len, user_msgCb_func);
    			}
			}
		}
	}
        else
        {
            usleep(100000);
        }
	
	pthread_exit(NULL);
}

最后

以上就是魁梧热狗为你收集整理的wpa_supplicant的控制接口简单说明的全部内容,希望文章能够帮你解决wpa_supplicant的控制接口简单说明所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部