1. 接口定义实现wpa_drivers
wpa_drivers的定义如下:
- struct wpa_driver_ops *wpa_drivers[] =
- {
- #ifdef CONFIG_DRIVER_WEXT
- &wpa_driver_wext_ops,
- #endif /* CONFIG_DRIVER_WEXT */
- #ifdef CONFIG_DRIVER_NL80211 // 现在流行的NL80211接口
- &wpa_driver_nl80211_ops,
- #endif /* CONFIG_DRIVER_NL80211 */
- #ifdef CONFIG_DRIVER_HOSTAP
- &wpa_driver_hostap_ops,
- #endif /* CONFIG_DRIVER_HOSTAP */
- #ifdef CONFIG_DRIVER_MADWIFI
- &wpa_driver_madwifi_ops,
- #endif /* CONFIG_DRIVER_MADWIFI */
- #ifdef CONFIG_DRIVER_BROADCOM
- &wpa_driver_broadcom_ops,
- #endif /* CONFIG_DRIVER_BROADCOM */
- #ifdef CONFIG_DRIVER_BSD
- &wpa_driver_bsd_ops,
- #endif /* CONFIG_DRIVER_BSD */
- #ifdef CONFIG_DRIVER_NDIS
- &wpa_driver_ndis_ops,
- #endif /* CONFIG_DRIVER_NDIS */
- #ifdef CONFIG_DRIVER_WIRED
- &wpa_driver_wired_ops,
- #endif /* CONFIG_DRIVER_WIRED */
- #ifdef CONFIG_DRIVER_TEST
- &wpa_driver_test_ops,
- #endif /* CONFIG_DRIVER_TEST */
- #ifdef CONFIG_DRIVER_RALINK
- &wpa_driver_ralink_ops,
- #endif /* CONFIG_DRIVER_RALINK */
- #ifdef CONFIG_DRIVER_OSX
- &wpa_driver_osx_ops,
- #endif /* CONFIG_DRIVER_OSX */
- #ifdef CONFIG_DRIVER_IPHONE
- &wpa_driver_iphone_ops,
- #endif /* CONFIG_DRIVER_IPHONE */
- #ifdef CONFIG_DRIVER_ROBOSWITCH
- &wpa_driver_roboswitch_ops,
- #endif /* CONFIG_DRIVER_ROBOSWITCH */
- #ifdef CONFIG_DRIVER_ATHEROS
- &wpa_driver_atheros_ops,
- #endif /* CONFIG_DRIVER_ATHEROS */
- #ifdef CONFIG_DRIVER_NONE
- &wpa_driver_none_ops,
- #endif /* CONFIG_DRIVER_NONE */
- NULL
- };
具体选择哪一个driver,由wpa_supplicant的命令参数决定,如我的如下:
在init.myboard.rc中定义:
- 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中使用。
- 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];
- 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
- 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,
- .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,
- #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
- 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,
- [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry,
- [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode,
- [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode,
- [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower,
- [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower,
- [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie,
- [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
- [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
- [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
- [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,
- [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv
- };
-
- 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中实现,其代码如下:
-
-
-
-
-
-
-
- void * wpa_driver_wext_init(void *ctx, const char *ifname)
- {
- 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);
- 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);
- if (drv->netlink == NULL) {
- os_free(cfg);
- goto err2;
- }
-
- rcfg = os_zalloc(sizeof(*rcfg));
- if (rcfg == NULL)
- goto err3;
- rcfg->ctx = drv;
- os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
- rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
- rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
- drv->rfkill = rfkill_init(rcfg);
- if (drv->rfkill == NULL) {
- wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
- os_free(rcfg);
- }
-
- drv->mlme_sock = -1;
- #ifdef ANDROID
- drv->errors = 0;
- drv->driver_is_started = TRUE;
- drv->skip_disconnect = 0;
- drv->bgscan_enabled = 0;
- #endif
-
- if (wpa_driver_wext_finish_drv_init(drv) < 0)
- goto err3;
-
- wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);
-
- return drv;
-
- err3:
- rfkill_deinit(drv->rfkill);
- netlink_deinit(drv->netlink);
- err2:
- close(drv->ioctl_sock);
- err1:
- os_free(drv);
- return NULL;
- }
其中参数ifname在/data/misc/wifi/wpa_supplicant.conf中被定义,如我的如下:
- 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文件操作如下:
-
-
-
-
-
- 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,
- #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<cfg80211_handlers中定义的>,并返回结果)
- static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
- {
- struct socket *sock;
- struct sock *sk;
- void __user *argp = (void __user *)arg;
- int pid, err;
- struct net *net;
-
- sock = file->private_data;
- sk = sock->sk;
- net = sock_net(sk);
- if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
- err = dev_ioctl(net, cmd, argp);
- } else
- #ifdef CONFIG_WEXT_CORE
- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- err = dev_ioctl(net, cmd, argp);
- } else
- #endif
- ...
- }
- return err;
- }
- int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
- {
- struct ifreq ifr;
- int ret;
- char *colon;
-
-
-
-
-
-
- switch (cmd) {
-
-
-
-
- default:
-
- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
- return wext_handle_ioctl(net, &ifr, cmd, arg);
- return -ENOTTY;
- }
- }
- int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
- void __user *arg)
- {
- struct iw_request_info info = { .cmd = cmd, .flags = 0 };
- int ret;
-
- ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
- ioctl_standard_call,
- ioctl_private_call);
- if (ret >= 0 &&
- IW_IS_GET(cmd) &&
- copy_to_user(arg, ifr, sizeof(struct iwreq)))
- return -EFAULT;
-
- return ret;
- }
-
- static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
- unsigned int cmd, struct iw_request_info *info,
- wext_ioctl_func standard,
- wext_ioctl_func private)
- {
- int ret = wext_permission_check(cmd);
-
- if (ret)
- return ret;
-
- dev_load(net, ifr->ifr_name);
- rtnl_lock();
- ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
-
- rtnl_unlock();
-
- return ret;
- }
- static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
- {
-
- unsigned int index;
- const struct iw_handler_def *handlers = NULL;
-
- #ifdef CONFIG_CFG80211_WEXT
- if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
- handlers = dev->ieee80211_ptr->wiphy->wext;
- #endif
- #ifdef CONFIG_WIRELESS_EXT
- if (dev->wireless_handlers)
- handlers = dev->wireless_handlers;
- #endif
-
- if (!handlers)
- return NULL;
-
-
- index = IW_IOCTL_IDX(cmd);
- if (index < handlers->num_standard)
- return handlers->standard[index];
-
- #ifdef CONFIG_WEXT_PRIV
-
- index = cmd - SIOCIWFIRSTPRIV;
- if (index < handlers->num_private)
- return handlers->private[index];
- #endif
-
-
- return NULL;
- }
- static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
- unsigned int cmd,
- struct iw_request_info *info,
- wext_ioctl_func standard,
- wext_ioctl_func private)
- {
- struct iwreq *iwr = (struct iwreq *) ifr;
- struct net_device *dev;
- iw_handler handler;
-
-
-
-
-
- if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
- return -ENODEV;
-
-
-
-
- if (cmd == SIOCGIWSTATS)
- return standard(dev, iwr, cmd, info,
- &iw_handler_get_iwstats);
-
- #ifdef CONFIG_WEXT_PRIV
- if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
- return standard(dev, iwr, cmd, info,
- iw_handler_get_private);
- #endif
-
-
- if (!netif_device_present(dev))
- return -ENODEV;
-
-
- handler = get_handler(dev, cmd);
- if (handler) {
-
- if (cmd < SIOCIWFIRSTPRIV)
- return standard(dev, iwr, cmd, info, handler);
- else if (private)
- return private(dev, iwr, cmd, info, handler);
- }
-
- if (dev->netdev_ops->ndo_do_ioctl)
- return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
- return -EOPNOTSUPP;
- }
2.3.2 用户态初始化netlink
- 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
- 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,
- (struct sockaddr *) &from, &fromlen);
- if (left < 0) {
- if (errno != EINTR && errno != EAGAIN)
- wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s",
- strerror(errno));
- return;
- }
-
- h = (struct nlmsghdr *) buf;
- while (NLMSG_OK(h, left)) {
- switch (h->nlmsg_type) {
- case RTM_NEWLINK:
- netlink_receive_link(netlink, netlink->cfg->newlink_cb,
- h);
- break;
- case RTM_DELLINK:
- netlink_receive_link(netlink, netlink->cfg->dellink_cb,
- h);
- break;
- }
-
- h = NLMSG_NEXT(h, left);
- }
-
- if (left > 0) {
- wpa_printf(MSG_DEBUG, "netlink: %d extra bytes in the end of "
- "netlink message", left);
- }
-
- if (--max_events > 0) {
-
-
-
-
-
-
-
- goto try_again;
- }
- }
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
• ieee80211_scan_work函数详细代码如下:
- void ieee80211_scan_work(struct work_struct *work)
- {
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, scan_work.work);
- struct ieee80211_sub_if_data *sdata;
- unsigned long next_delay = 0;
- bool aborted, hw_scan;
-
- mutex_lock(&local->mtx);
-
- sdata = local->scan_sdata;
-
- if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
- aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
- goto out_complete;
- }
-
- if (!sdata || !local->scan_req)
- goto out;
-
- if (local->scan_req && !local->scanning) {
- struct cfg80211_scan_request *req = local->scan_req;
- int rc;
-
- local->scan_req = NULL;
- local->scan_sdata = NULL;
-
- rc = __ieee80211_start_scan(sdata, req);
- if (rc) {
-
- local->scan_req = req;
- aborted = true;
- goto out_complete;
- } else
- goto out;
- }
-
-
-
-
- if (!ieee80211_sdata_running(sdata)) {
- aborted = true;
- goto out_complete;
- }
-
-
-
-
-
- do {
- if (!ieee80211_sdata_running(sdata)) {
- aborted = true;
- goto out_complete;
- }
-
- switch (local->next_scan_state) {
- case SCAN_DECISION:
-
- if (local->scan_channel_idx >= local->scan_req->n_channels) {
- aborted = false;
- goto out_complete;
- }
- ieee80211_scan_state_decision(local, &next_delay);
- break;
- case SCAN_SET_CHANNEL:
- ieee80211_scan_state_set_channel(local, &next_delay);
- break;
- case SCAN_SEND_PROBE:
- ieee80211_scan_state_send_probe(local, &next_delay);
- break;
- case SCAN_LEAVE_OPER_CHANNEL:
- ieee80211_scan_state_leave_oper_channel(local, &next_delay);
- break;
- case SCAN_ENTER_OPER_CHANNEL:
- ieee80211_scan_state_enter_oper_channel(local, &next_delay);
- break;
- }
- } while (next_delay == 0);
-
- ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
- goto out;
-
- out_complete:
- hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
- __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
- out:
- mutex_unlock(&local->mtx);
- }