zoukankan      html  css  js  c++  java
  • atheros wifi 动因分析

    Ar6003 驱动文档摘要

     

    1、  wmi : wireless module interface //无线模块结构

    2、  bmi : bootloader message interface

    3、  htc : host target communications

    4、  wps:wifi protected setup

    5、  CS:connection services module

    6、  STA:station

    7、  AP:access point

     

     

    Wireless application : 生产数据和消费数据

    Wireless module interface (WMI):host target 之间的通信协议

    Host/target communications (HTC): 发送和接收数据

    Hardware interface (HIF) :调用硬件接口发送和接收数据(这里用的是sdio 接口)

    Bootloader message interface (BMI):wifi芯片启动时通信协议。能够下载bin文件到wifi芯片中。

     

     

    Ar6000 wifi 驱动分析(AP 模式分析)

     

    代码运行的主要流程

    //挂载sdio 驱动到内核和注冊网络设备

    module_init(__ar6000_init_module);

    à__ar6000_init_module

    àstatus = ar6000_init_module();

    àstatus = HIFInit(&osdrvCallbacks);

    à status = sdio_register_driver(&ar6k_driver);注冊sdio 驱动(这里直接调用的内核sdio协议栈)

    à.probe = hifDeviceInserted, //运行驱动的probe 函数

    àret = hifEnableFunc(device, func);

    à kthread_create(async_task, //内核开了一个sdio 异步发送数据的进程

    à taskFunc = startup_task; //开一个内核进程,运行startup_task 进程

    àif ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK)//调用安装wifi 设备的函数指针ar6000_android_avail_ev。这个函数是在android_module_init中注冊的。

    àar6000_android_avail_ev

    àret = ar6000_avail_ev_p(context, hif_handle)

    àar6000_avail_ev//这个函数指针赋值赋的非常曲折首先在ar6000_init_module(void)函数中赋给了osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev;然后在android_module_init(&osdrvCallbacks);ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler;赋给了ar6000_avail_ev_p;

    à BMIInit();//開始启动wifi模块

    àar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo);//创建htc ,关闭中断

    à status = (ar6000_init(dev)==0) ?

    A_OK : A_ERROR; // 初始化网络设备

    à (BMIDone(ar->arHifDevice) != A_OK))//bmi 启动完毕

    à  status = HTCStart(ar->arHtcTarget);//启动htc ,开启中断

    àstatus = DevUnmaskInterrupts(&target->Device);//开启中断, 注冊中断处理函数

    àHIFUnMaskInterrupt(pDev->HIFDevice);//注冊中断处理函数

    àret = sdio_claim_irq(device->func, hifIRQHandler);//注冊中断处理函数,中断后就会调用hifIRQHandler 这个处理函数

    à if (register_netdev(dev)) //向内核注冊网络设备。到此初始化完毕。

     

    //产生中断后的代码流程

    àhifIRQHandler(struct sdio_func *func) //中断处理函数 (hif.c)

    àstatus = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); //设备处理函数的函数指针

    àA_STATUS  DevDsrHandler(void *context);这函数是在创建htc HTCCreate 函数中填充的:HTCCreate—>DevSetupàhtcCallbacks.dsrHandler = DevDsrHandler;(ar6k_events.c)

    àstatus = ProcessPendingIRQs(pDev, &done, &asyncProc);//处理未决事件的函数,在这里会循环处理(ar6k_events.c)

    àstatus = pDev->MessagePendingCallback();这个函数指针也是在HTCCreate 中填充的target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;(htc_recv.c)

    àHTCRecvMessagePendingHandler();

    à DO_RCV_COMPLETION(pEndpoint,&container);

    à DoRecvCompletion();

    à pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);//这个函数指针是在ar6000_init 中填充的connect.EpCallbacks.EpRecv = ar6000_rx; ar6000_rx 是一个很重要的函数。

    à ar6000_rx(void *Context, HTC_PACKET *pPacket)

     

    //数据发送流程

    à ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)

    à HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);

    à return HTCSendPktsMultiple(HTCHandle, &queue);

    à HTCTrySend(target, pEndpoint, pPktQueue);

    à HTCIssueSend(target, pPacket);

    à status = DevSendPacket(&target->Device,

    à status = HIFReadWrite(pDev->HIFDevice, //传给了sido 总线

    à AddToAsyncList(device, busrequest);//把要发送的数据包增加异步发送队列

    à up(&device->sem_async); //获取信号量,用内核进程进行数据发送

    à static int async_task(void *param) //发送数据

    à __HIFReadWrite();//发送数据

    à sdio_writesb();sdio_memcpy_toio();sdio_readsb();sdio_memcpy_fromio();

    à down_interruptible(&busrequest->sem_req) != 0 //释放信号量

     

     

    //中断发送或,接收流程

    àHTCRecvMessagePendingHandler

    à status = HTCIssueRecv(target, pPacket);//异步接收数据包

    à status = HIFReadWrite(pDev->HIFDevice, //命令传给sdio 总线

    à与发送流程同样

    //sta 连接流程

    à ar6000_rx ();收到连接的命令,此时的ar->arControlEp=ept=1

    à wmi_control_rx(arPriv->arWmi, skb)//解析命令

    à case (WMI_CONNECT_EVENTID): //连接命令

    à status = wmi_connect_event_rx(wmip, datap, len);

    à A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev);

    à ar6000_connect_event((devt), (pEvt));

    à wireless_send_event(arPriv->arNetDev, IWEVREGISTERED, &wrqu, NULL); //向网络层发送事件 wext-core.c

    àskb_queue_tail(&dev_net(dev)->wext_nlevents, skb); //wext-core.c

    ----------------------------------经过网络层的处理--------------------------------------------------------------------

    àsock_ioctl(struct file *file, unsigned cmd, unsigned long arg)//  net/socket.c

    àerr = dev_ioctl(net, cmd, argp); // net/core/dev.c

    àreturn wext_handle_ioctl(net, &ifr, cmd, arg); // net/wireless/wext-core.c

    àret = wext_ioctl_dispatch(net, ifr, cmd, &info,

                                           ioctl_standard_call,

                                           ioctl_private_call); // net/wireless/wext-core.c

    àret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); //net/wireless/wext-core.c

    à return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);//这个是在注冊网络设备注冊的函数.ndo_do_ioctl           = ar6000_ioctl,

    ---------------------------网络层调用驱动层的函数----------------------------------------

    à int ar6000_ioctl();  // ioctl.c

    à case IEEE80211_IOCTL_SETKEY:  //ioctl.c

    à ar6000_ioctl_setkey(arPriv, &keydata); //ioctl.c

    à status = ar6000_sendkey(arPriv, ik, keyUsage); //ioctl.c

    à status = wmi_addKey_cmd()

    à status = wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag);

     

     

     

    //传输数据流程

    à ar6000_rx ();收到连接的数据,此时ept=2

    à ar6000_deliver_frames_to_nw_stack((void *) arPriv->arNetDev, (void *)skb);

    à A_NETIF_RX_NI(skb);

    ànetif_rx_ni(skb) //将数据传给ip

     

     

    Hostapd 设置ssid

    àint main(int argc, char *argv[]);  //main.c

    àinterfaces.iface[i] = hostapd_interface_init(&interfaces, //main.c

    àhostapd_setup_interface(iface)) {  //main.c

    àret = setup_interface(iface); //hostapd.c

    àreturn hostapd_setup_interface_complete(iface, 0); //hostapd.c

    àif (hostapd_driver_commit(hapd) < 0) { // ap_drv_ops.c

    àreturn hapd->driver->commit(hapd->drv_priv);//driver_ar6000.c 中赋值的.commit             = ar6000_commit

    àar6000_commit(void *priv)//driver_ar6000.c

    ----------------------从应用层通过ioctl 进入驱动层---------------------------------------------------------------

    àif (ioctl(drv->ioctl_sock, SIOCSIWCOMMIT, &iwr) < 0) { //wireless_ext.c 中赋值的(iw_handler) ar6000_ioctl_siwcommit,

    àar6000_ioctl_siwcommit(struct net_device *dev, // wireless_ext.c

    àar6000_ap_mode_profile_commit(arPriv); //ar6000_dr.c

    àwmi_ap_profile_commit(arPriv->arWmi, &p); //wmi.c

    àstatus = wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG); //wmi.c

     

    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    关于@Mapper和@Repository的一点小理解
    记一下数据库的多表查询
    移动端时间控件 HTML5+ 的 pickDate 和 MUI 的 dtpicker 的使用与对比
    即时搜索:对于ios自带输入法输入中文时多次触发input事件的处理
    thead固定,tbody高度超出时滚动的实现方法
    数字位数不够,进行前补零的JS最简实现方案
    hbuilder ios 打包失败,无法导入p12证书的解决方案
    通过jQuery获取容器尺寸的方法height()、innerHeight()、outerHeight()的区别总结
    通过js添加的DOM节点的click事件绑定不上的解决方案以及IOS下click事件委派失效的解决方案
    vue.js项目构建——构建方式:vue-cli脚手架
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4854135.html
Copyright © 2011-2022 走看看