您的位置:首页 > 其它

wpa_supplicant 驱动分析

2015-06-01 14:19 399 查看


1. 接口定义实现wpa_drivers

wpa_drivers的定义如下:

[cpp] view
plaincopy

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中定义:

[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中使用。

[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) {

/* default to first driver in the list */

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,

[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中实现,其代码如下:

[cpp] view
plaincopy

/**

* wpa_driver_wext_init - Initialize WE driver interface

* @ctx: context to be used when calling wpa_supplicant functions,

* e.g., wpa_supplicant_event()

* @ifname: interface name, e.g., wlan0

* Returns: Pointer to private data, %NULL on failure

*/

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));

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中被定义,如我的如下:

[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

/*

* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear

* in the operation structures but are done directly via the socketcall() multiplexor.

*/

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, /* special open code to disallow open via /proc */

.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中定义的>,并返回结果)

[cpp] view
plaincopy

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); //执行dev_ioctl

} else

#endif

...

}

return err;

}

[cpp] view
plaincopy

int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)

{

struct ifreq ifr;

int ret;

char *colon;

/*

* See which interface the caller is talking about.

*/

switch (cmd) {

/*

* Unknown or private ioctl.

*/

default:

/* Take care of Wireless Extensions */

if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)

return wext_handle_ioctl(net, &ifr, cmd, arg); // 执行wext_handle_ioctl

return -ENOTTY;

}

}

[cpp] view
plaincopy

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, // 执行wext_ioctl_dispatch

ioctl_standard_call,

ioctl_private_call);

if (ret >= 0 &&

IW_IS_GET(cmd) &&

copy_to_user(arg, ifr, sizeof(struct iwreq))) // 把执行结果copy到用户空间

return -EFAULT;

return ret;

}

[cpp] view
plaincopy

/* entry point from dev ioctl */

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); //执行wireless_process_ioctl

rtnl_unlock();

return ret;

}

[cpp] view
plaincopy

static iw_handler get_handler(struct net_device *dev, unsigned int cmd)

{

/* Don't "optimise" the following variable, it will crash */

unsigned int index; /* *MUST* be unsigned */

const struct iw_handler_def *handlers = NULL;

//printk("***IDONG_WIFI:%s,cmd=0x%x\n",__FUNCTION__,cmd);

#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;

/* Try as a standard command */

index = IW_IOCTL_IDX(cmd);

if (index < handlers->num_standard)

return handlers->standard[index];

#ifdef CONFIG_WEXT_PRIV

/* Try as a private command */

index = cmd - SIOCIWFIRSTPRIV;

if (index < handlers->num_private)

return handlers->private[index];

#endif

/* Not found */

return NULL;

}

[cpp] view
plaincopy

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;

/* Permissions are already checked in dev_ioctl() before calling us.

* The copy_to/from_user() of ifr is also dealt with in there */

/* Make sure the device exist */

if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)

return -ENODEV;

/* A bunch of special cases, then the generic case...

* Note that 'cmd' is already filtered in dev_ioctl() with

* (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */

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

/* Basic check */

if (!netif_device_present(dev))

return -ENODEV;

/* New driver API : try to find the handler */

handler = get_handler(dev, cmd);

if (handler) {

/* Standard and private are not the same */

if (cmd < SIOCIWFIRSTPRIV)

return standard(dev, iwr, cmd, info, handler); // 去执行对应的iw_handler

else if (private)

return private(dev, iwr, cmd, info, handler);

}

/* Old driver API : call driver ioctl handler */

if (dev->netdev_ops->ndo_do_ioctl)

return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);

return -EOPNOTSUPP;

}


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 = (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) {

/*

* Try to receive all events in one eloop call in order to

* limit race condition on cases where AssocInfo event, Assoc

* event, and EAPOL frames are received more or less at the

* same time. We want to process the event messages first

* before starting EAPOL processing.

*/

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函数详细代码如下:

[cpp] view
plaincopy

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) {

/* need to complete scan in cfg80211 */

local->scan_req = req;

aborted = true;

goto out_complete;

} else

goto out;

}

/*

* Avoid re-scheduling when the sdata is going away.

*/

if (!ieee80211_sdata_running(sdata)) {

aborted = true;

goto out_complete;

}

/*

* as long as no delay is required advance immediately

* without scheduling a new work

*/

do {

if (!ieee80211_sdata_running(sdata)) {

aborted = true;

goto out_complete;

}

switch (local->next_scan_state) {

case SCAN_DECISION:

/* if no more bands/channels left, complete scan */

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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: