您的位置:首页 > 移动开发 > Android开发

[RK3288][Android6.0] WiFi之Framework的socket(客户端)

2017-06-29 10:18 686 查看
Platform: Rockchip

OS: Android 6.0

Kernel: 3.10.92

连接:

WPAS运行起来之后(见wpa_supplicant启动),Framework就可以通过Socket连接上去了。

hardware/libhardware_legacy/wifi/wifi.c

/* Establishes the control and monitor socket connections on the interface */
int wifi_connect_to_supplicant()
{
static char path[PATH_MAX];
//IFACE_DIR为"/data/system/wpa_supplicant",不存在。
if (access(IFACE_DIR, F_OK) == 0) {
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
} else {
snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
}
return wifi_connect_on_socket_path(path);
}


//primary_iface在wifi_start_supplicant()中初始化

property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);


wifi.interface的值:

root@rk3288:/ # getprop wifi.interface

wlan0


因此,path就是@android:wpa_wlan0,和init.rc中描述的-g参数后面的一样了。

再来看wifi_connect_on_socket_path()

int wifi_connect_on_socket_path(const char *path)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
//发送命令给WPAS的控制对象
//内部会调用socket_local_client_connect()去connect
ctrl_conn = wpa_ctrl_open(path);
if (ctrl_conn == NULL) {
ALOGE("Unable to open connection to supplicant on \"%s\": %s",
path, strerror(errno));
return -1;
}
//接收WPAS事件的监控对象
monitor_conn = wpa_ctrl_open(path);
if (monitor_conn == NULL) {
wpa_ctrl_close(ctrl_conn);
ctrl_conn = NULL;
return -1;
}
//监控对象需要attach
if (wpa_ctrl_attach(monitor_conn) != 0) {
wpa_ctrl_close(monitor_conn);
wpa_ctrl_close(ctrl_conn);
ctrl_conn = monitor_conn = NULL;
return -1;
}

if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
wpa_ctrl_close(monitor_conn);
wpa_ctrl_close(ctrl_conn);
ctrl_conn = monitor_conn = NULL;
return -1;
}

return 0;
}


为什么直接打开一个socket用来发送和接收呢?

因为客户端接受WPAS事件需要通过wpa_ctrl_request()里带参数回调的方式(这个函数是用来发送命令给WPAS,回调只是为了需要返回发送命令要求的返回内容)来处理,这样就要先发送一个request,然后才能等待接收回复。

系统提供了另外一个API即wpa_ctrl_attach()来打开事件监听功能,然后再通过wpa_ctrl_recv()接受来自WPAS的事件就可以了,这样就可以达到只要接收不用发送命令给WPAS的目的了。

因此,客户端创建了两个控制对象分别处理发送命令和接收事件。

实现:

在wifi_send_command()和wifi_wait_for_event()可以看到就是通过wpa_ctrl_request()和wpa_ctrl_recv()来实现发送命令和接收事件的。

wifi_send_command():

int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
{
......
ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
......
}


wifi_wait_for_event():

int wifi_wait_for_event(char *buf, size_t buflen)
{
return wifi_wait_on_socket(buf, buflen);
}
int wifi_wait_on_socket(char *buf, size_t buflen)
{
......
result = wifi_ctrl_recv(buf, &nread);
......
}
int wifi_ctrl_recv(char *reply, size_t *reply_len)
{
......
return wpa_ctrl_recv(monitor_conn, reply, reply_len);
......
}


参考:

深入理解Android Wi-Fi、NFC和GPS卷 p148
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: