1. 接口定义实现wpa_drivers
wpa_drivers的定义如下:
[cpp] view plaincopy
struct wpa_driver_ops *wpa_drivers[] =
{
#ifdef CONFIG_DRIVER_WEXT
&wpa_driver_wext_ops, // 我的系统使用的这个老的接口
#endif
#ifdef CONFIG_DRIVER_NL80211 // 现在流行的NL80211接口
&wpa_driver_nl80211_ops,
#endif
#ifdef CONFIG_DRIVER_HOSTAP
&wpa_driver_hostap_ops,
#endif
#ifdef CONFIG_DRIVER_MADWIFI
&wpa_driver_madwifi_ops,
#endif
#ifdef CONFIG_DRIVER_BROADCOM
&wpa_driver_broadcom_ops,
#endif
#ifdef CONFIG_DRIVER_BSD
&wpa_driver_bsd_ops,
#endif
#ifdef CONFIG_DRIVER_NDIS
&wpa_driver_ndis_ops,
#endif
#ifdef CONFIG_DRIVER_WIRED
&wpa_driver_wired_ops,
#endif
#ifdef CONFIG_DRIVER_TEST
&wpa_driver_test_ops,
#endif
#ifdef CONFIG_DRIVER_RALINK
&wpa_driver_ralink_ops,
#endif
#ifdef CONFIG_DRIVER_OSX
&wpa_driver_osx_ops,
#endif
#ifdef CONFIG_DRIVER_IPHONE
&wpa_driver_iphone_ops,
#endif
#ifdef CONFIG_DRIVER_ROBOSWITCH
&wpa_driver_roboswitch_ops,
#endif
#ifdef CONFIG_DRIVER_ATHEROS
&wpa_driver_atheros_ops,
#endif
#ifdef CONFIG_DRIVER_NONE
&wpa_driver_none_ops,
#endif
NULL
};
具体选择哪一个driver,由wpa_supplicant的命令参数决定,如我的如下:
在init.myboard.rc中定义:
[cpp] view plaincopy
service wpa_supplicant /system/bin/wpa_supplicant \
-Dwext -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf
#-Dnl80211 -iwlan0 -puse_p2p_group_interface=1 -e/data/misc/wifi/entropy.bin
# we will start as root and wpa_supplicant will switch to user wifi
# after setting up the capabilities required for WEXT
# user wifi
# group wifi inet keystore
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
由上可见,我的选择是wext, 即选择了:wpa_driver_wext_ops。具体选择在以下函数中实现,并最后保存在wpa_supplicant->driver中,以供在wpa_drv_scan中使用。
首先需要讲解一下,在android4.0之后,wifi的工作方式基本都采用的是比较标准的nl80211方式,以前的wext方式现在使用的已经很少了,关于nl80211和wext的区别,小弟由于接触的少,所以简单的说两句(有错误的请各位大大指正啊,万谢!)
wext:supplicant通过wext直接给wifi driver下命令,即不通过kernel,所以一般以wext工作的driver是不需要load cfg80211.ko的,这个cfg80211.ko就是kernel里面的wireless部分,主要对接supplicant和driver的。
nl80211:supplicant的命令以nl80211的方式下给kernel,经过kernel再发送给driver,这样子做的好处是 supplicant和driver之间的通讯方式更加标准话,是以后的主流方式,我后面讲的driver都是以这种方式工作的。
[cpp] view plaincopy
static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
const char *name)
{
int i;
size_t len;
const char *pos, *driver = name;
if (wpa_s == NULL)
return -1;
wpa_msg(wpa_s,MSG_ERROR,"***MY_WIFI:%s,name=%s\n",__FUNCTION__,name);
if (wpa_drivers[0] == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
"wpa_supplicant");
return -1;
}
if (name == NULL) {
wpa_s->driver = wpa_drivers[0];
wpa_s->global_drv_priv = wpa_s->global->drv_priv[0];
return 0;
}
do {
pos = os_strchr(driver, ',');
if (pos)
len = pos - driver;
else
len = os_strlen(driver);
for (i = 0; wpa_drivers[i]; i++) {
if (os_strlen(wpa_drivers[i]->name) == len &&
os_strncmp(driver, wpa_drivers[i]->name, len) ==
0) {
wpa_s->driver = wpa_drivers[i]; // 根据name进行匹配,并最后保存到wpa_supplicant->dirver中
wpa_s->global_drv_priv =
wpa_s->global->drv_priv[i];
return 0;
}
}
driver = pos + 1;
} while (pos);
wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
return -1;
}
2. 接口操作函数实现
2.1 用户态实现
用户态实现的操作函数如下:
实现代码见:/external/wpa_supplicant_8/wpa_supplicant/src/drivers/driver_wext.c
[cpp] view plaincopy
const struct wpa_driver_ops wpa_driver_wext_ops = {
.name = "wext",
.desc = "Linux wireless extensions (generic)",
.get_bssid = wpa_driver_wext_get_bssid,
.get_ssid = wpa_driver_wext_get_ssid,
#ifdef WAPI
.set_wapi = wpa_driver_wext_set_wapi,
#endif
.set_key = wpa_driver_wext_set_key,
.set_countermeasures = wpa_driver_wext_set_countermeasures,
.scan2 = wpa_driver_wext_scan,
.get_scan_results2 = wpa_driver_wext_get_scan_results,
.deauthenticate = wpa_driver_wext_deauthenticate,
.disassociate = wpa_driver_wext_disassociate,
.associate = wpa_driver_wext_associate,
.init = wpa_driver_wext_init, // 初始ioctl socket, netlink socket
.deinit = wpa_driver_wext_deinit,
.add_pmkid = wpa_driver_wext_add_pmkid,
.remove_pmkid = wpa_driver_wext_remove_pmkid,
.flush_pmkid = wpa_driver_wext_flush_pmkid,
.get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate,
.get_radio_name = wext_get_radio_name,
#ifdef ANDROID
.signal_poll = wpa_driver_signal_poll,
.driver_cmd = wpa_driver_wext_driver_cmd, // 对应驱动中的 cfg80211_wext_setpriv
#endif
};
.driver_cmd处理以DRIVER开始的命令,如:
DRIVER MACADDR
DRIVER BTCOEXSCAN-STOP
DRIVER RXFILTER-ADD 3
DRIVER RXFILTER-START
DRIVER RXFILTER-STOP
DRIVER RXFILTER-REMOVE 2
DRIVER RXFILTER-START
DRIVER SETBAND 0
DRIVER SCAN-ACTIVE
DRIVER SCAN-PASSIVE
执行流程如下所示:
wpa_supplicant_ctrl_iface_process-> (根据命令字符串调用对应的函数)
wpa_supplicant_driver_cmd->
wpa_drv_driver_cmd->
wpa_s->driver->driver_cmd->
wpa_driver_wext_driver_cmd-> (User)
...
cfg80211_wext_setpriv(Kernel)
2.2 Kernel态实现
Kernel态实现的操作函数如下:
实现代码见:net/wireless/wext_compat.c
[cpp] view plaincopy
static const iw_handler cfg80211_handlers[] = {
[IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
[IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
[IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,
[IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,
[IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,
[IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange,
[IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap,
[IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap,
[IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,
[IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,
[IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,
[IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid,
[IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid,
[IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,
[IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,
[IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts,
[IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts,
[IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,
[IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,
[IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower,
[IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower,
[IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry,
..........................
const struct iw_handler_def cfg80211_wext_handler = {
.num_standard = ARRAY_SIZE(cfg80211_handlers),
.standard = cfg80211_handlers,
.get_wireless_stats = cfg80211_wireless_stats,
};
2.3 用户态与Kernel态的交互
用户态向Kernel态发送请求时,通过ioctl来实现。
Kernel态向用户态发送事件通知,通过netlink来实现。
其交互的初始化在wpa_driver_wext_init中实现,其代码如下:
[cpp] view plaincopy
void * wpa_driver_wext_init(void *ctx, const char *ifname) // 我的ifname为wlan0
{
struct wpa_driver_wext_data *drv;
struct netlink_config *cfg;
struct rfkill_config *rcfg;
char path[128];
struct stat buf;
wpa_printf(MSG_ERROR,"***MY_WIFI:%s,ifname=%s\n",__FUNCTION__,ifname);
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
drv->ctx = ctx;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
if (stat(path, &buf) == 0) {
wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
drv->cfg80211 = 1;
wext_get_phy_name(drv);
}
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); // 此drv->ioctl_sock用作为ioctl命令的fd
if (drv->ioctl_sock < 0) {
perror("socket(PF_INET,SOCK_DGRAM)");
goto err1;
}
cfg = os_zalloc(sizeof(*cfg));
if (cfg == NULL)
goto err1;
cfg->ctx = drv;
cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
drv->netlink = netlink_init(cfg); // 初始化netlink,并注册事件接收函数
if (drv->netlink == NULL) {
os_free(cfg);
goto err2;
}
rcfg = os_zalloc(sizeof(*rcfg));
其中参数ifname在/data/misc/wifi/wpa_supplicant.conf中被定义,如我的如下:
[cpp] view plaincopy
update_config=1
ctrl_interface=wlan0
eapol_version=1
ap_scan=1
fast_reauth=1
2.3.1 ioctl实现方案
在用户态可简单执行一个ioctl(fd,cmd,...)命令即可。
在Kernel态则是通过唯一的cmd (SIOCIWFIRST--SIOCIWLAST) 来进行区分,从而执行cfg80211_handlers中对应的函数。
socket文件操作如下:
[cpp] view plaincopy
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
.aio_write = sock_aio_write,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl, // 这个就是被执行的ioctl
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap,
.open = sock_no_open,
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};
从sock_ioctl到iw_handler的执行注程如下所示:
sock_ioctl->
dev_ioctl->
wext_handle_ioctl-> (把执行结果从kernel态copy到用户态)
wext_ioctl_dispatch->
wireless_process_ioctl->
1) get_handler
2) ioctl_standard_call (执行cmd指定的iw_handler,并返回结果)
2.3.2 用户态初始化netlink
[cpp] view plaincopy
struct netlink_data * netlink_init(struct netlink_config *cfg)
{
struct netlink_data *netlink;
struct sockaddr_nl local;
netlink = os_zalloc(sizeof(*netlink));
if (netlink == NULL)
return NULL;
netlink->cfg = cfg;
netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (netlink->sock < 0) {
wpa_printf(MSG_ERROR, "netlink: Failed to open netlink "
"socket: %s", strerror(errno));
netlink_deinit(netlink);
return NULL;
}
os_memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_groups = RTMGRP_LINK;
if (bind(netlink->sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
wpa_printf(MSG_ERROR, "netlink: Failed to bind netlink "
"socket: %s", strerror(errno));
netlink_deinit(netlink);
return NULL;
}
eloop_register_read_sock(netlink->sock, netlink_receive, netlink,
NULL);
return netlink;
}
2.3.3 用户态netlink事件接收函数netlink_receive
[cpp] view plaincopy
static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
struct netlink_data *netlink = eloop_ctx;
char buf[8192];
int left;
struct sockaddr_nl from;
socklen_t fromlen;
struct nlmsghdr *h;
int max_events = 10;
try_again:
fromlen = sizeof(from);
left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, //从netlink读取事件
(struct sockaddr *) &from, &fromlen);
if (left < 0) {
if (errno != EINTR && errno != EAGAIN)
wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s",
strerror(errno));
return;
}
h =
}
3. SCAN流程
wpa_supplicant_ctrl_iface_process-> ( buf 内容为SCAN )
wpa_supplicant_req_scan->wpa_supplicant_scan->wpa_supplicant_trigger_scan->wpa_drv_scan->wpa_s->driver->scan2->wpa_driver_wext_scan-> (Request the driver to initiate scan)wpa_driver_wext_combo_scan->ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)-> (User)...cfg80211_wext_setpriv (cmd=CSCAN S)->cfg80211_wext_siwscan->rdev->ops->scan (cfg80211_ops mac80211_config_ops->scan)->ieee80211_scan-> ieee80211_request_scan->__ieee80211_start_scan->ieee80211_start_sw_scan-><1> drv_sw_scan_start->local->ops->sw_scan_start(ieee80211_ops ath9k_htc_ops->sw_scan_start)->ath9k_htc_sw_scan_start-> <2> ieee80211_hw_config-> (set power level at maximum rate for scanning)drv_config->local->ops->config( ieee80211_ops ath9k_htc_ops->config)-> ath9k_htc_config->ath9k_htc_setpower(priv,ATH9K_PM_AWAKE) <3> ieee80211_queue_delayed_work(&local->scan_work)->(注:INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work)) ieee80211_scan_work-> (根据local当前状态进行下一步工作,直到工作完成)__ieee80211_scan_completed-> (所有扫描的工作完成之后,调用此函数)drv_sw_scan_complete->local->ops->sw_scan_complete( ieee80211_ops ath9k_htc_ops->sw_scan_complete)ath9k_htc_sw_scan_complete
来源:oschina
链接:https://my.oschina.net/u/994235/blog/323261