Iwpriv工作流程及常用命令使用
=>main
=>set_private
=>iw_get_priv_info获取wireless网卡所能处理的所有wlan_private_args类型.
=>wext_handle_ioctl
=>wireless_process_ioctl
if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
return ioctl_standard_call(dev, ifr, cmd,
&iw_handler_get_private);
static int ioctl_standard_call(struct net_device * dev,
struct ifreq * ifr,
unsigned int cmd,
iw_handler handler)
{
...
/* Call the handler */
ret = handler(dev, &info, &(iwr->u), extra);
if (user_length < iwr->u.data.length) {
kfree(extra);
return -E2BIG;
//通知iwpriv,本wifi网卡对应的private命令还没有完,还有,这样iwpriv将会继续
//maxpriv默认为16,即将以16个为一组,一组一组的从wifi网卡驱动读取该网卡所能支持的所有private_args参数
//newpriv = realloc(priv, maxpriv * sizeof(priv[0]));继续申请,继续拷贝,知道将wifi网卡自定义的wlan_private_args参数全部
//传出到iwpriv为止.
}
...
}
/* New driver API : try to find the handler */
handler = get_handler(dev, cmd);//获取
/* Standard and private are not the same */
if (cmd < SIOCIWFIRSTPRIV)
return ioctl_standard_call(dev, ifr, cmd, handler);
else
return ioctl_private_call(dev, ifr, cmd, handler);
}
/* Old driver API : call driver ioctl handler */
if (dev->do_ioctl)
//如果dev->wireless_handlers->standard和dev->wireless_handlers->private[index都不对该cmd作处理,那么由
//dev->do_ioctl = wlan_do_ioctl;我们驱动的最后处理函数wlan_do_ioctl处理.
return dev->do_ioctl(dev, ifr, cmd);
{
/* Don't "optimise" the following variable, it will crash */
unsigned int index; /* *MUST* be unsigned */
if (dev->wireless_handlers == NULL)
return NULL;
index = cmd - SIOCIWFIRST;
if (index < dev->wireless_handlers->num_standard)
return dev->wireless_handlers->standard[index];
index = cmd - SIOCIWFIRSTPRIV;//
return dev->wireless_handlers->private[index];//该private命令的handler.
/* Not found */
return NULL;
}
num_standard:sizeof(wlan_handler) / sizeof(iw_handler),
num_private:sizeof(wlan_private_handler) / sizeof(iw_handler),
num_private_args:sizeof(wlan_private_args) / sizeof(struct iw_priv_args),
standard:(iw_handler *) wlan_handler,
private:(iw_handler *) wlan_private_handler,
private_args:(struct iw_priv_args *) wlan_private_args,
#if WIRELESS_EXT > 20
get_wireless_stats:wlan_get_wireless_stats,
#endif
};
"extscan"/ "hostcmd"/ "arpfilter"/ "regrdwr"/ "sdcmd52rw"/
"sdcmd53rw"/ "setgetconf"/ "getcis"/ "scantype"/ "deauth"
"getNF"/ "getRSSI"/ "bgscan"/ "enable11d"/ "adhocgrate"
"sdioclock"/ "wmm"/ "uapsdnullgen"/ "setcoalescing"/ "adhocgprot"
"setpowercons"/ "wmm_qosinfo"/ "lolisteninter"/ "fwwakeupmethod"
"psnullinterval"/ "bcnmisto"/ "adhocawakepd"/ "moduletype"
"autodeepsleep"/ "enhanceps"/ "wakeupmt"/ "setrxant"/ "settxant"
"authalgs"/ "encryptionmode"/ "setregioncode"/ "setlisteninter"
"setmultipledtim"/ "setbcnavg"/ "setdataavg"/ "associate"/ "getregioncode"
"getlisteninter"/ "getmultipledtim"/ "gettxrate"/ "getbcnavg"
"getdataavg"/ "getrxant"/ "gettxant"/ "gettsf"/ "wpssession"
"deepsleep"/ "adhocstop"/ "radioon"/ "radiooff"/ "rmaeskey"
"crypto_test"/ "reasso-on"/ "reasso-off"/ "wlanidle-on"/ "wlanidle-off"
"sleepparams"/ "requesttpc"/ "powercap"/ "measreq"/ "bca-ts"
"scanmode"/ "getadhocstatus"/ "setgenie"/ "getgenie"/ "qstatus"
"ts_status"/ "setaeskey"/ "getaeskey"/ "version"/ "verext"/ "setwpaie"
"setband"/ "setadhocch"/ "chanswann"/ "getband"/ "getadhocch"
"getlog"/ "tpccfg"/ "scanprobes"/ "ledgpio"/ "sleeppd"/ "rateadapt"
"getSNR"/ "getrate"/ "getrxinfo"/ "atimwindow"/ "bcninterval"/ "sdiopullctrl"
"scantime"/ "sysclock"/ "txcontrol"/ "hscfg"/ "hssetpara"/ "inactoext"
"dbgscfg"/ "drvdbg"/ "drvdelaymax"/ "intfctrl"/ "setquietie"/ ""
"setuserscan"/ "getscantable"/ "setmrvltlv"/ "getassocrsp"/ "addts"
"delts"/ "qconfig"/ "qstats"/ "txpktstats"/ "getcfptable"/ "mefcfg"
"getmem"
1.应用层程序iwpriv
wireless tools网络配置应用程序iwpriv命令格式:
iwpriv ethX private-command [parameters]
int main(int argc, char *argv[])
{
...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
...
ioctl(sockfd, ioctl_val, &iwr);//将控制命令通过ioctl发送到无线网卡
...
}
====================
2.系统调用sys_ioctl
应用层通过ioctl(sockfd, ioctl_val, &iwr);触发sys_ioctl系统调用,实际流程:
sys_ioctl=>vfs_ioctl=>do_ioctl=最后调用
filp->f_op->unlocked_ioctl执行具体的ioctl操作,该操作就是sock_ioctl,至于为什么是sock_ioctl,后边作了进一步分析
sock_ioctl=>
{
...
#ifdef CONFIG_WIRELESS_EXT
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
err = dev_ioctl(net, cmd, argp);//
#endif
...
}
dev_ioctl=>wext_handle_ioctl
{
...
/* Take care of Wireless Extensions */
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
return wext_handle_ioctl(net, &ifr, cmd, arg);
...
}
wext_handle_ioctl=>wireless_process_ioctl=>
然后通过if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)函数,
从系统管理的net链表中,把ioctl指定的ethX对应的struct net_device摘出来,
最后调用ioctl_private_call(handler)或者调用dev->do_ioctl(dev, ifr, cmd)来处理该ioctl,
这两个函数分别指向wlan_handler_def和wlan_do_ioctl
====================
3.wifi网卡是怎么登记到kernel上的
wlan_probe()=>wlan_add_card()=>alloc_etherdev()=>
之后将操作方法添加到struct net_device *dev=alloc_etherdev()申请的dev上去,其中包括:
...
/* Setup the OS Interface to our functions */
dev->open = wlan_open;
dev->hard_start_xmit = wlan_hard_start_xmit;
dev->stop = wlan_close;
dev->do_ioctl = wlan_do_ioctl;
dev->set_mac_address = wlan_set_mac_address;
dev->get_stats = wlan_get_stats;
dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
dev->set_multicast_list = wlan_set_multicast_list;
...
4.socket系统调用如何关联上ioctl和ethX设备
接下来从net_families全局管理结构体中找到当前family对应的ops操作集,
net_proto_family *pf=net_families[family];
pf->create(net, sock, protocol);//核心调用,对于ipv4,就是inet_create
以ipv4为例
static struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
.owner = THIS_MODULE,
};
还记得上面应用层创建sokcet的函数吧,
sockfd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET虽然等于PF_INET,但是因为种种原因我们提倡使用PF_INET
可见family等于AF_INET,type等于SOCK_STREAM,协议protocol为0,也就是采用IP协议,
inet_create=>inetsw[sock->type]也就是inetsw[SOCK_STREAM],
从inetsw[sock->type]中找到已经登记的protocol网络协议处理函数,
inetsw[]是怎么填充的呢?inet_init()=>inet_register_protosw(inetsw_array)=>这样inetsw_array中的所有protocol处理模块都将登记到inetsw中了,
static struct inet_protosw inetsw_array[] =
{
{
.type = SOCK_STREAM,
.protocol = IPPROTO_TCP,
.prot = &tcp_prot,
.ops = &inet_stream_ops,
.capability = -1,
.no_check = 0,
.flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK,
},
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
.prot = &udp_prot,
.ops = &inet_dgram_ops,
.capability = -1,
.no_check = UDP_CSUM_DEFAULT,
.flags = INET_PROTOSW_PERMANENT,
},
.type = SOCK_RAW,
.protocol = IPPROTO_IP, /* wild card */
.prot = &raw_prot,
.ops = &inet_sockraw_ops,
.capability = CAP_NET_RAW,
.no_check = UDP_CSUM_DEFAULT,
.flags = INET_PROTOSW_REUSE,
}
};
至 于inet_init,则是以fs_initcall(inet_init)方式,以5号优先级被build in到了内核中,当kernel启动时会在start_kernel=>rest_init=>kernel_init=> do_basic_setup=>do_initcalls中依据优先级号优先于其他module驱动被调用.
这样sock->ops = answer->ops;对于ipv4也就等于inet_stream_ops,
接下来就是将ops填充到file操作指针中了,
sys_socket=>sock_map_fd=>sock_attach_fd=>
dentry->d_op = &sockfs_dentry_operations;
init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE, &socket_file_ops);
file->private_data = sock;
其中init_file=>file->f_op = fop;也就是file->f_op = socket_file_ops;
所以read(),wirte(),poll()和ioctl()应用程序调用的file->f_op就是socket_file_ops了,
比如:
read()对应sock_aio_read网络异步读
write()对应sock_aio_write网络异步写
ioctl()对应sock_ioctl
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, /* special open code to disallow open via /proc */
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
};
网卡控制因为涉及到的知识点比较多,上面只是从宏观上对数据流程做了一个简单的介绍,深入到其中的每个知识点,都会牵扯出一系列文章,读者需要自己去一个个的慢慢深入,希望本文能够对刚刚接触网络驱动的读者有所帮助和启发【gliethttp.Leith】
wlan_add_card=>
wlan_create_thread(wlan_service_main_thread, &priv->MainThread, "wlan_main_service");
=>wlan_service_main_thread=>wlan_exec_next_cmd=>
将调用wlan_enter_ps和wlan_exit_ps
在mmc_signal_sdio_irq=>将调用wake_up_process(host->sdio_irq_thread);来唤醒该irq处理线程,可能还有其他命令需要处理wlan_exec_next_cmd
这个pxamci_irq就是mmc的物理irq中断了,pxamci_irq=>mmc_signal_sdio_irq(host->mmc);
那么就会执行wlan_dnld_cmd_to_fw(wlan_private * priv, CmdCtrlNode * CmdNode)将CmdNode中的数据下发下去,
然后重新触发wlan_mod_timer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_5S);
也就是wlan_cmd_timeout_func命令超时处理函数,
在cmd已经有了恢复之后,在主线程中调用wlan_process_cmdresp,立即调用wlan_cancel_timer(&Adapter->MrvDrvCommandTimer);来删除定时器
====
/* Execute the next command */
if (!priv->wlan_dev.cmd_sent && !Adapter->CurCmd)
wlan_exec_next_cmd(priv);
====
wlan_hostcmd_ioctl=>
获取一个空闲的CmdNode节点wlan_get_cmd_node,当完成赋值之后,执行如下语句,将CmdNode节点添加到处理队列中:
wlan_insert_cmd_to_pending_q(Adapter, CmdNode, TRUE);
wake_up_interruptible(&priv->MainThread.waitQ);
另外在数组中
/*
* iwconfig settable callbacks
*/
static const iw_handler wlan_handler[]这个数组中全部是回调函数,
struct iw_handler_def wlan_handler_def = {
num_standard:sizeof(wlan_handler) / sizeof(iw_handler),
num_private:sizeof(wlan_private_handler) / sizeof(iw_handler),
num_private_args:sizeof(wlan_private_args) / sizeof(struct iw_priv_args),
standard:(iw_handler *) wlan_handler,
private:(iw_handler *) wlan_private_handler,
private_args:(struct iw_priv_args *) wlan_private_args,
#if WIRELESS_EXT > 20
get_wireless_stats:wlan_get_wireless_stats,
#endif
};
在wlan_add_card函数中
dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
{
/* Don't "optimise" the following variable, it will crash */
unsigned int index; /* *MUST* be unsigned */
if (dev->wireless_handlers == NULL)
return NULL;
index = cmd - SIOCIWFIRST;
if (index < dev->wireless_handlers->num_standard)
return dev->wireless_handlers->standard[index];
index = cmd - SIOCIWFIRSTPRIV;
if (index < dev->wireless_handlers->num_private)
return dev->wireless_handlers->private[index];
return NULL;
}
=>dev_ioctl
+++/* Take care of Wireless Extensions */
+++if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
+++return wext_handle_ioctl(net, &ifr, cmd, arg);
=>wext_handle_ioctl
=>wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd)
=>get_handler(dev, cmd);如果没有实现该cmd,那么将调用dev->do_ioctl来处理,
wmm_start_queue=>
wlan_tx_packet=>
wlan_tx_timeout=>
wlan_remove_card=>
wlan_hostcmd_ioctl=>
wlan_auto_deep_sleep=>
wlan_set_deep_sleep=>
wlan_prepare_cmd=>
wlan_cmd_timeout_func=>
将调用wake_up_interruptible(&priv->MainThread.waitQ);唤醒wlan_service_main_thread主处理线程.
dev->tx_timeout = wlan_tx_timeout;
wlan_initialize_timer(&Adapter->MrvDrvCommandTimer, wlan_cmd_timeout_func, priv);
{
...
case WLAN_WAKEUP_MT:
if (wrq->u.data.length > 0)
Adapter->IntCounter++;
wake_up_interruptible(&priv->MainThread.waitQ);
break;
...
}
wlan_insert_cmd_to_free_q=>wlan_clean_cmd_noder,从命令链表上删除已经处理完成的cmd_node,
wlan_clean_cmd_noder然后pTempNode->CmdWaitQWoken = TRUE;同时如果该cmd_node是一个被阻塞等待的,那么唤醒等待的程序.
wake_up_interruptible(&pTempNode->cmdwait_q);
set (8BE2) : set 1024 char & get 0
connStatus (0004) : set 1024 char & get 2047 char
driverVer (0005) : set 1024 char & get 2047 char
bainfo (0006) : set 1024 char & get 2047 char
descinfo (0007) : set 1024 char & get 2047 char
radio_off (000A) : set 1024 char & get 2047 char
radio_on (000B) : set 1024 char & get 2047 char
show (0015) : set 1024 char & get 2047 char
adhocEntry (0016) : set 1024 char & get 2047 char
bbp (8BE3) : set 2047 char & get 2047 char
mac (8BE5) : set 1024 char & get 1024 char
rf (8BF3) : set 2047 char & get 2047 char
e2p (8BE7) : set 1024 char & get 1024 char
stat (8BE9) : set 0 & get 2047 char
iwpriv ra0 set SSID=""
iwpriv ra0 set Channel=0
iwpriv ra0 set NetworkType=Infra
iwpriv ra0 set AuthMode=SHARED
iwpriv ra0 set EncrypType=WEP
iwpriv ra0 set DefaultKeyID=1
iwpriv ra0 set Key1="whatever"
iwpriv ra0 set SSID="some_ssed"
iwpriv ra0 set WPAPSK="wpa_key"
iwpriv ra0 show NetworkType
iwpriv ra0 show Key1
iwpriv ra0 show WPAPSK
ra0 show:
SSID
WirelessMode
TxBurst
TxPreamble
TxPower
Channel
BGProtection
RTSThreshold
FragThreshold
HtBw
HtMcs
HtGi
HtOpMode
HtExtcha
HtMpduDensity
HtBaWinSize
HtRdg
HtAmsdu
HtAutoBa
CountryRegion
CountryRegionABand
CountryCode
PktAggregate
WmmCapable
IEEE80211H
NetworkType
WPAPSK
AutoReconnect
AuthMode
EncrypType
DefaultKeyID
Key1
Key2
Key3
Key4
PMK
Iwpriv工作流程及常用命令使用的更多相关文章
- Iwpriv工作流程及常用命令使用之二
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- git详情、git工作流程、常用命令、忽略文件、分支操作、gitee远程仓库使用
今日内容概要 git详情 git工作流程 git常用命令 过滤文件 分支操作 git远程仓库使用 可参照:https://www.cnblogs.com/liuqingzheng/p/15328319 ...
- git flow 工作流程以及常用命令
一.分支介绍 master 也是产品分支,只有一个,一般情况下不会在这个分支上进行代码操作 develop 只有一个,新特性的开发是基于 develop 开发的,但是不能直接在 develop 上进行 ...
- Git 工作原理以及常用命令操作
GIT工作原理 要了解GIT工作原理,先了解GIT的这几块区域: 工作区域划分 工作区:指的是本地工作空间,如果刚拉取下来的代码,没有修改的内容,这块区域是空白的 (modified-已修改状态) 暂 ...
- git开发流程、常用命令及工具、TortoiseGit使用及常见问题
根据我最近使用git的一些经历,git是基于分支的版本控制工具,分支有远程分支和本地分支. 一.开发流程 - 从远程服务器的master,clone一份项目文件到本地,然后本地master的基础上br ...
- [工作需求]linux常用命令以及vim常用命令
一. Linux 常用命令 mkdir dirname新建文件夹 cd ~ 进入自己的家目录 cd dirname 进入名字为dirname的目录: l 显示当前文件夹下的文件 ...
- 工作中git常用命令
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 16.0px; font: 14.0px "PingFang SC" } ...
- 【mysql】工作中mysql常用命令及语句
1.查看mysql版本号 MySQL [release_test_oa]> select version(); +------------+ | version() | +----------- ...
- Git的使用流程及常用命令汇总
Git是一个很好用的版本控制系统,本文对于常用的一些命令进行了汇总. 创建一个存储仓库(repository) https://github.com/右上角点击"+"号,New r ...
随机推荐
- DOM对象和JQuery对象的区别
DOM对象和JQuery对象的区别 jQuery对象和DOM对象使用说明,需要的朋友可以参考下.1.jQuery对象和DOM对象第一次学习jQuery,经常分辨不清哪些是jQuery对象,哪些是 DO ...
- HDU4276 The Ghost Blows Light SPFA&&树dp
题目的介绍以及思路完全参考了下面的博客:http://blog.csdn.net/acm_cxlove/article/details/7964739 做这道题主要是为了加强自己对SPFA的代码的训练 ...
- POJ 1723
#include <iostream> #include <algorithm> #define MAXN 10005 using namespace std; struct ...
- POJ 2029 Get Many Persimmon Trees(DP||二维树状数组)
题目链接 题意 : 给你每个柿子树的位置,给你已知长宽的矩形,让这个矩形包含最多的柿子树.输出数目 思路 :数据不是很大,暴力一下就行,也可以用二维树状数组来做. #include <stdio ...
- JSP include标签和include指令
test1.jsp <% int a = 5; out.println(a); %> test2.jsp <jsp:include page="/test1.jsp&quo ...
- Android 用Activity的onTouchEvent来监听滑动手势
package com.example.activityOnTouchEvent; import android.app.Activity; import android.os.Bundle; imp ...
- *[hackerrank]Maximizing XOR
https://www.hackerrank.com/contests/w1/challenges/maximizing-xor/ 找了半天规律,答案竟然是暴力,伤感.我找到的方法是利用规律2^x X ...
- Linux开机启动流程
开机过程指的是从打开计算机电源直到LINUX显示用户登录画面的全过程: 1)加载BIOS 2)读取MBR 3)Boot Loader 4)加载内核 ...
- iOS开发--计时器-NSTimer与CADisplayLink
如果程序要让某个方法重复执行,可以借助定时器来完成.CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器,NSTimer的精确度低了点,比如NSTimer的触发时间 ...
- esriControlsMousePointer 控制鼠标指针
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerHourglass; 控制鼠标指针选项. 不变 值 描述 esriPo ...