Analysis on the wifi driver of atheros
Ar6003 driver document summary <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + IDxpbWcgc3JjPQ = "http://www.2cto.com/uploadfile/Collfiles/20140831/2014083109355817.png" alt = "\">
1. wmi: wireless module interface // wireless module structure
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: production data and consumption data
Wireless module interface (WMI): communication protocol between host and target
Host/target communications (HTC): send and receive data
Hardware interface (ICF): Call the Hardware interface to send and receive data (sdio interface is used here)
Bootloader message interface (BMI): communication protocol when the wifi Chip starts. You can download the binfile to the wifi chip.
Ar6000 wifi driver analysis (AP Mode Analysis)
Main process of Code Execution
// Mount the sdio driver to the kernel and register the network device
Module_init (_ ar6000_init_module );
À _ ar6000_init_module
À status = ar6000_init_module ();
À status = HIFInit (& osdrvCallbacks );
À status = sdio_register_driver (& ar6k_driver); register the sdio Driver (the kernel sdio protocol stack called directly here)
À. probe = hifDeviceInserted, // execute the driver's probe function
À ret = hifEnableFunc (device, func );
À kthread_create (async_task, // A sdio asynchronous data sending process is enabled in the kernel
À taskFunc = startup_task; // start a kernel process and execute the startup_task process.
À if (osdrvCallbacks. deviceInsertedHandler (osdrvCallbacks. context, device ))! = A_ OK) // call the function pointer ar6000_android_avail_ev for wifi device installation. This function is registered in android_module_init.
À ar6000 _ android_avail_ev
À ret = ar6000_avail_ev_p (context, hif_handle );
À ar6000 _ avail_ev // This function pointer assignment is very tortuous. First, it is assigned to osdrvCallbacks in the ar6000_init_module (void) function. deviceInsertedHandler = ar6000_avail_ev; then, in android_module_init (& osdrvCallbacks); ar6000_avail_ev_p = osdrvCallbacks-> deviceinsertetedhandler;
À BMIInit (); // start the wifi Module
À ar-> arHtcTarget = HTCCreate (ar-> arHifDevice, & htcInfo); // create htc and disable interruption
À status = (ar6000_init (dev) = 0 )? A_ OK: A_ERROR; // initialize a network device
À (BMIDone (ar-> arHifDevice )! = A_ OK) // The bmi starts successfully.
À status = HTCStart (ar-> arHtcTarget); // start htc and enable interruption
À status = DevUnmaskInterrupts (& target-> Device); // enable interrupt and register the interrupt handler
À HIFUnMaskInterrupt (pDev-> HIFDevice); // registers the interrupt handler.
À ret = sdio_claim_irq (device-> func, hifIRQHandler); // register the interrupt handler. After the interrupt, The hifIRQHandler handler is called.
À if (register_netdev (dev) // register a network device with the kernel. The Initialization is complete.
// Code process after interruption
À hifIRQHandler (struct sdio_func * func) // interrupt processing function (guid. c)
À status = device-> htcCallbacks. dsrHandler (device-> htcCallbacks. context); // function pointer of the device processing function
À A _ STATUS DevDsrHandler (void * context); this function is filled in the HTCCreate function after htc is created: HTCCreate-> DevSetup à htcCallbacks. dsrHandler = DevDsrHandler; (ar6k_events.c)
À status = ProcessPendingIRQs (pDev, & done, & asyncProc); // The function for processing pending events, which will be processed cyclically here (ar6k_events.c)
À status = pDev-> MessagePendingCallback (); this function pointer is also the target-> Device. MessagePendingCallback = HTCRecvMessagePendingHandler filled in HTCCreate; (htc_recv.c)
À HTCRecvMessagePendingHandler ();
À DO_RCV_COMPLETION (pEndpoint, & container );
À DoRecvCompletion ();
À pEndpoint-> EpCallBacks. epRecv (pEndpoint-> EpCallBacks. pContext, pPacket); // This function pointer is the connect. epCallbacks. epRecv = ar6000_rx; ar6000_rx is a very important function.
À ar6000_rx (void * Context, HTC_PACKET * pPacket)
// Data sending Process
À 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, // passed to the sido Bus
À AddToAsyncList (device, busrequest); // Add the data packet to be sent to the asynchronous sending queue
À up (& device-> sem_async); // gets the semaphore and sends data using the kernel process.
À static int async_task (void * param) // send data
À _ HIFReadWrite (); // send data
À sdio_writesb (); sdio_memcpy_toio (); sdio_readsb (); sdio_memcpy_fromio ();
À down_interruptible (& busrequest-> sem_req )! = 0 // release the semaphore
// Interrupt sending or receiving process
À HTCRecvMessagePendingHandler
À status = HTCIssueRecv (target, pPacket); // receives data packets asynchronously.
À status = HIFReadWrite (pDev-> HIFDevice, // The command is sent to the sdio bus.
À is the same as the sending Process
// Sta connection process
À ar6000_rx (); when the connection command is received, ar-> arControlEp = ept = 1
À wmi_control_rx (arPriv-> arWmi, skb); // resolution command
À case (WMI_CONNECT_EVENTID): // connection command
À 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); // send event wext-core.c to the network layer
À skb _ queue_tail (& dev_net (dev)-> wext_nlevents, skb); // wext-core.c
-------------------------------- Processed by the network layer --------------------------------------------------------------------
À 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); // This is the function registered with the registered network device. ndo_do_ioctl = ar6000_ioctl,
--------------------------- The function of the driver layer called at the network layer ----------------------------------------
À 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 );
// Data transmission process
À ar6000_rx (); when the connection data is received, ept = 2
À ar6000_deliver_frames_to_nw_stack (void *) arPriv-> arNetDev, (void *) skb );
À A_NETIF_RX_NI (skb );
À netif _ rx_ni (skb) // transmits data to the ip layer
Hostapd: Set the 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); //. commit = ar6000_commit assigned in driver_ar6000.c
À ar6000 _ commit (void * priv) // driver_ar6000.c
-------------------- Enter the driver layer through ioctl at the application layer ---------------------------------------------------------------
À if (ioctl (drv-> ioctl_sock, SIOCSIWCOMMIT, & iwr) <0) {// (iw_handler) ar6000_ioctl_siwcommit assigned in wireless_ext.c,
À 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_pai_send (wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG); // wmi. c