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 ...
随机推荐
- Unity3D 游戏开发构架篇 ——角色类的设计与持久化
在游戏开发中,游戏角色占了很大的篇幅,可以说游戏中所有的内容都是由主角所带动.这里就介绍一下角色类的设计和持久化. 一.角色类应用场景和设计思想 游戏中的角色类型不一而足,有不同的技能,有不同的属性等 ...
- mac上eclipse上配置hadoop
在mac上安装了eclipse之后,配置hadoop其实跟在linux上配置差不多,只是mac上得eclipse和界面和linux上得有点不同. 一:安装eclipse eclipse得安装比较简单, ...
- Javascript通过className选择元素
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- PHP-Phalcon框架中的数据库操作
> 本文描述了PHP-Phalcon框架中数据库操作方法,主要讨论Phalcon框架的Model组件中的操作方法.更详细的Model介绍请参考:官方文档 1. 连接数据库 在Phalcon框架中 ...
- 欧拉工程第63题:Powerful digit counts
题目链接 The 5-digit number, 16807=75, is also a fifth power. Similarly, the 9-digit number, 134217728=8 ...
- TCL语言笔记:TCL中的String命令
一.介绍 字符串是 Tcl 中的基本数据类型,所以有大量的字符串操作命令.一个比较重要的问题就是模式匹配,通过模式匹配将字符串与指定的模式(格式)相匹配来进行字符串的比较.搜索等操作. 二.strin ...
- HTML5 编辑 API 之 Range 对象(二)
1.Range.cloneContents()The Range.cloneContents() returns a DocumentFragment copying the objects of t ...
- [翻译] - <Entity Framework> - 直接执行数据库命令
原文:[翻译] - <Entity Framework> - 直接执行数据库命令 纯属学习上的记录, 非专业翻译, 如有错误欢迎指正! 原文地址: http://msdn.microsof ...
- NET Remoting 示例
.NET Remoting是.NET平台上允许存在于不同应用程序域中的对象相互知晓对方并进行通讯的基础设施.调用对象被称为客户端,而被调用对象则被称为服务器或者服务器对象.简而言之,它就是.NET平台 ...
- PHP文件下载原理
1.php下载原理图 2.文件下载源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?php $ ...