WL127x WLAN API Information

From Texas Instruments Wiki
Jump to: navigation, search

Introduction

This page will provide a user with the technical information needed to develop applications around the WLAN driver and mac802.11 APIs.

mac802.11 Basics

mac802.11 Open Source Architecture


Nlcp layer.PNG

cfg80211

  • cfg80211 is the new Linux wireless configuration API which replaces the Wireless-Extensions (wext)
  • It has the proper interface to the nl80211 layer which is used to configure a cfg80211 device.
  • cfg80211 is implemented in kernel space, and nl80211 is implemented in user space.
  • cfg80211 is generic configuration layer that can be used for fullmac driver configuration or work with the mac80211 layer for softmac drivers.
  • TI solution uses cfg80211 to configure the mac80211 layer for softmac driver.



For more information on cfg80211 API see <cfg API>

nl80211

nl80211 is the new 802.11 netlink interface public header. Together with cfg80211 it is intended to replace Wireless-Extensions.
Current users of nl80211:

  • iw
  • crda
  • hostapd
  • wpa_supplicant (with -Dnl80211)


nl80211 provides series of API in User space to configure the WLAN driver.
the APIs are described in nl80211.h file located in linux/kernel/git/linville/wireless-2.6.git
Some APIs for example are:

API Description
NL80211_CMD_GET_SCAN get scan results
NL80211_CMD_TRIGGER_SCAN trigger a new scan with the given parameters
NL80211_CMD_CONNECT connection request and notification, this command requests to connect to a specified network but without separating auth and assoc steps. For this, you need to specify the SSID in a NL80211_ATTR_SSID attribute
NL80211_CMD_DISCONNECT drop a given connection; also used to notify userspace that a connection was dropped by the AP or due to other reasons, for this the NL80211_ATTR_DISCONNECTED_BY_AP and NL80211_ATTR_REASON_CODE attributes are used.
NL80211_CMD_AUTHENTICATE request authentication request and notification
NL80211_CMD_ASSOCIATE association request and notification
NL80211_CMD_JOIN_IBSS Join a new IBSS given at least an SSID and a FREQ attribute (for the initial frequency if no peer can be found) and optionally a MAC (as BSSID). Another optional parameter is the beacon interval given in the NL80211_ATTR_BEACON_INTERVAL attribute, which if not given defaults to 100 TU (102.4ms).



For more information on API refer to <nl80211 information>


wpa_supplicant

  • wpa_supplicant is a free software implementation of an IEEE 802.11i supplicant for Linux.
  • wpa_supplicant is a full-featured WPA2 supplicant, and also has support for WPA and older wireless LAN security protocols.
  • wpa_supplicant is a userspace application which acts like WPA supplicant and SME (to handle initiating MLME commands).


Supported features include:

  • WPA and full IEEE 802.11i/RSN/WPA2
  • WPA-PSK and WPA2-PSK (pre-shared key) ("WPA-Personal")
  • WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise")
  • key management for CCMP, TKIP, WEP (both 104/128 and 40/64 bit)
  • RSN: PMKSA caching, pre-authentication


User Interface:
Included with the supplicant are a graphical user interface and a command line interface utility (wpa_cli) for interacting with the running supplicant. From either of these interfaces it is possible to review a list of currently visible networks, select one of them, provide any additional security information needed to authenticate with the network (e.g. a passphrase or username and password) and add it to the preference list to enable automatic reconnection in the future.
The graphical user interface is built on top of the Qt library from Qt Software, which is used in the SDK as is.

The following steps are used when associating with an AP using WPA:

  • Before wpa_supplicant can do its work, the network interface must be available. That means that the physical device must be present and enabled, and the driver for the device must have be loaded.
  • wpa_supplicant requests the kernel driver to scan neighboring BSSes
  • wpa_supplicant selects a BSS based on its configuration
  • wpa_supplicant requests the kernel driver to associate with the chosen BSS
  • If WPA-EAP: integrated IEEE 802.1X Supplicant or external Xsupplicant completes EAP authentication with the authentication server (proxied by the Authenticator in the AP)
  • If WPA-EAP: master key is received from the IEEE 802.1X Supplicant
  • If WPA-PSK: wpa_supplicant uses PSK as the master session key
  • wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake with the Authenticator (AP)
  • wpa_supplicant configures encryption keys for unicast and broadcast
  • normal data packets can be transmitted and received



How to run the WPA_Supplicant: In most common cases, wpa_supplicant is started with:

wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0

This makes the process fork into background and wait for the wlan0 interface if it is not available at startup time.
The easiest way to debug problems, and to get debug log for bug reports, is to start wpa_supplicant on foreground with debugging enabled:

wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d


OpenSSL

  • OpenSSL is an open source implementation of the SSL (Secure Sockets Layer )and TLS (Transport Layer Security) protocols.
  • The core library (written in the C programming language) implements the basic cryptographic functions and provides various utility functions.
  • Wrappers allowing the use of the OpenSSL library in a variety of computer languages are available.


HostAPD

  • hostapd is a user space daemon for access point and authentication servers.
  • It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators, RADIUS client, EAP server, and RADIUS authentication server.
  • hostapd uses a network interfaces on startup specified in the configuration file hostapd.conf. The interface is used to access the Host AP, which is a wireless interface running in Host AP mode.
  • Host AP mode can be enabled using ifconfig.


Supported WPA/IEEE 802.11i/EAP/IEEE 802.1X features

  • WPA-PSK ("WPA-Personal")
  • WPA with EAP (with integrated EAP server or an external RADIUS backend authentication server) ("WPA-Enterprise")
  • key management for CCMP, TKIP, WEP104, WEP40
  • WPA and full IEEE 802.11i/RSN/WPA2
  • RSN: PMKSA caching, pre-authentication
  • IEEE 802.11r
  • IEEE 802.11w
  • RADIUS accounting
  • RADIUS authentication server with EAP
  • Wi-Fi Protected Setup (WPS)


Supported EAP methods (integrated EAP server and RADIUS authentication server)

  • EAP-TLS
  • EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)
  • EAP-PEAP/TLS (both PEAPv0 and PEAPv1)
  • EAP-PEAP/GTC (both PEAPv0 and PEAPv1)
  • EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)
  • EAP-TTLS/EAP-MD5-Challenge
  • EAP-TTLS/EAP-GTC
  • EAP-TTLS/EAP-MSCHAPv2
  • EAP-TTLS/MSCHAPv2
  • EAP-TTLS/EAP-TLS
  • EAP-TTLS/MSCHAP
  • EAP-TTLS/PAP
  • EAP-TTLS/CHAP
  • EAP-SIM
  • EAP-AKA
  • EAP-AKA'
  • EAP-PAX
  • EAP-PSK
  • EAP-SAKE
  • EAP-FAST
  • EAP-IKEv2
  • EAP-GPSK




mac802.11

  • mac80211 is a framework which driver developers can use to write drivers for SoftMAC (where the MLME is expected to be managed in software) wireless devices
  • SoftMAC devices allow for a finer control of the hardware, allowing for 802.11 frame management to be done in software for them, for both parsing and generation of 802.11 wireless frames. Most 802.11 devices today tend to be of this type, FullMAC devices have become scarce.
  • mac80211 implements the cfg80211 callbacks for SoftMAC devices, mac80211 then depends on cfg80211 for both registration to the networking subsystem and for configuration. Configuration is handled by cfg80211 both through nl80211 and wireless extensions.
  • In mac80211 the MLME is done in the kernel for station mode (STA) and in userspace for AP mode (hostapd).

mac80211 supports the MAC layer as defined by IEEE 802.11abgn, IEEE 802.11d, QoS standards, also supports BSS and IBSS mode.

IW

  • IW is a new nl80211 based CLI configuration utility for wireless devices.
  • IW is used for the configuration of the wlan interface
  • IW sources can be downloaded from the following git: git://git.sipsolutions.net/iw.git
  • IW commands allows you to modify the station configuration on the fly, using IW commands. This option supports only non-secured networks and WEP secured networks, without involving the WPA supplicant. for more information (refer to: <IW commands description>)
  • IW home page (refe to <IW home page>)



CRDA

CRDA - Central Regulatory Domain Agent

  • CRDA acts as the udev helper for communication between the kernel and userspace for regulatory compliance.
  • It relies on nl80211 for communication.



Diagram of Components in the Regulatory Infrastructure and their Interaction

Crda.png

cfg80211 role in the Regulatory Domain function
cfg80211 has regulatory compliance built into it.
Upon the initialization of the wireless core cfg80211) a world regulatory domain (highly restrictive) will be set as the central regulatory domain. When the wl12xx device driver registers it sends to the cfg80211 its supported bands and channels, and the regulatory domain is updated accordingly (intersection of the two supported channels by the device and the supported channels in the current domain). After connection to an AP was established, if that AP transmits a country information element which indicate a different domain then the currently set, cfg80211 will send a uevent to the userspace to notify crda on the requested change in the regulatory domain.
cfg80211 contains a static version of the world regulatory domain, in case crda is not available. If crda or the userspace regulatory database are not available to the kernel, then the static hardcoded version of the world regulatory domain will remain the set regulatory for the entire session, even if outside APs or other user commands (like iw) will try to change the current domain.

Regulatory database
After getting a request for a regulatory domain definition from the kernel, the CRDA opens the regulatory database binary and searches for the relevant domain. The regulatory binary is signed with John Linville's RSA private key (the maintainer of the official regulatory database) and it is varified by the CRDA.

For Regulatory Domain information - use the following < Regulatory Domain >



mac802.11 APIs

APIs:

  1. nl80211
  2. network stack

Glossary (WLAN Basic Terms)

MLME
MLME Stands for "Media Access Control (MAC) Sublayer Management Entity". MLME is the management entity where the Physical layer (PHY) MAC state machines reside. Examples of states a MLME may assist in reaching:

  • Authenticate
  • Deauthenticate
  • Associate
  • Disassociate
  • Reassociate
  • Beacon
  • Probe


PHY
physical-layer controller

SSID
SSID stands for Service Set IDentifier. The SSID is a code attached to all packets on a wireless network to identify each packet as part of that network. The code consists of a string of 1-32 octets (usually represented as case sensitive alphanumeric characters).

mac802.11 Driver Architecture

The WL12xx has couple of interfaces:

  • Interface with the MAC80211 - This interface defines the interface with the 80211 API, such as suspend/resume/scan functionality.
  • Interface with the Firmware - The interface goes through the SDIO between the driver and the firmware. The firmware is responsible for operating the low level hardware of the physical Wl12xx chip.

In this section we will explain these interfaces and we will dive into some of the code of the WL12xx in order to explain how the interaction is done.

SDIO Driver Registration

The Interface of the WL1271/3 wireless chip to the Host (OMAP) is done through:

  1. SDIO BUS (4 bit data)
  2. WLAN enable GPIO - which controls enabling and disabling the WL12xx chip
  3. WLAN IRQ GPIO - which enables interrupts from the WL12xx chip (e.g. incoming packet)


If we build the compat-wireless 2.6, we can see the driver registration under: /drivers/net/wireless/wl12xx/sdio.c:

static int __init wl1271_init(void)
{
    return sdio_register_driver(&wl1271_sdio_driver);
}

It corresponds with the following command from Linux:

insmod wl12xx_sdio.ko

The function sdio_register_driver() is defined in Linux kernel under /drivers/mmc/core/sdio_bus.c The structure wl1271_sdio_driver is sdio_driver type and is defined as follows:

static struct sdio_driver wl1271_sdio_driver = {
    .name     = "wl1271_sdio",
    .id_table = wl1271_devices,
    .probe    = wl1271_probe,
    .remove   = __devexit_p(wl1271_remove),
    .drv = {
        .pm = &wl1271_sdio_pm_ops,
    },
};

We fill in the necessary fields which are:

  • .name - The driver name
  • .id_table - List of device ID's
  • .probe - The probe function which is invoked by SDIO when SD Card / WLAN chip presents
  • .remove - Function invoked when SD card / WLAN chip is removed
  • .drv - Device driver structure. We fill here only the suspend/resume functionality (wl1271_sdio_pm_ops)


When the wl1271_probe() function is called, it calls the following functions:

  1. wl1271_alloc_hw()
  2. wl1271_init_ieee80211()
  3. wl1271_register_hw()

We will elaborate on each of these functions one at a time.

MAC82011 Interface

wl1271_alloc_hw() Function

This function is implemented under compat-wireless-2.6/drivers/net/wireless/wl12xx/main.c
Inside main.c there is a structure which is a callback for the necessary mac80211 calls. It looks as follows:

static const struct ieee80211_ops wl1271_ops = {
    .start = wl1271_op_start,
    .stop = wl1271_op_stop,
    .add_interface = wl1271_op_add_interface,
    .remove_interface = wl1271_op_remove_interface,
    .suspend = wl1271_op_suspend,
    .resume = wl1271_op_resume,
    .config = wl1271_op_config,
    .prepare_multicast = wl1271_op_prepare_multicast,
    .configure_filter = wl1271_op_configure_filter,
    .tx = wl1271_op_tx,
    .set_key = wl1271_op_set_key,
    .hw_scan = wl1271_op_hw_scan,
    .cancel_hw_scan = wl1271_op_cancel_hw_scan,
    .sched_scan_start = wl1271_op_sched_scan_start,
    .sched_scan_stop = wl1271_op_sched_scan_stop,
    .bss_info_changed = wl1271_op_bss_info_changed,
    .set_frag_threshold = wl1271_op_set_frag_threshold,
    .set_rts_threshold = wl1271_op_set_rts_threshold,
    .conf_tx = wl1271_op_conf_tx,
    .get_tsf = wl1271_op_get_tsf,
    .get_survey = wl1271_op_get_survey,
    .sta_add = wl1271_op_sta_add,
    .sta_remove = wl1271_op_sta_remove,
    .ampdu_action = wl1271_op_ampdu_action,
    .tx_frames_pending = wl1271_tx_frames_pending,
    CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};

The structure ieee80211_ops is defined under compat-wireless-2.6/include/net/mac80211.h. Link to the file can be found <mac80211.h file>
Main fields are as follows:

/**
 * struct ieee80211_ops - callbacks from mac80211 to the driver
 *
 * This structure contains various callbacks that the driver may
 * handle or, in some cases, must handle, for example to configure
 * the hardware to a new channel or to transmit a frame.
 *
 * @tx: Handler that 802.11 module calls for each transmitted frame.
 *	skb contains the buffer starting from the IEEE 802.11 header.
 *	The low-level driver should send the frame out based on
 *	configuration in the TX control data. This handler should,
 *	preferably, never fail and stop queues appropriately, more
 *	importantly, however, it must never fail for A-MPDU-queues.
 *	This function should return NETDEV_TX_OK except in very
 *	limited cases.
 *	Must be implemented and atomic.
 *
 * @start: Called before the first netdevice attached to the hardware
 *	is enabled. This should turn on the hardware and must turn on
 *	frame reception (for possibly enabled monitor interfaces.)
 *	Returns negative error codes, these may be seen in userspace,
 *	or zero.
 *	When the device is started it should not have a MAC address
 *	to avoid acknowledging frames before a non-monitor device
 *	is added.
 *	Must be implemented and can sleep.
 *
 * @stop: Called after last netdevice attached to the hardware
 *	is disabled. This should turn off the hardware (at least
 *	it must turn off frame reception.)
 *	May be called right after add_interface if that rejects
 *	an interface. If you added any work onto the mac80211 workqueue
 *	you should ensure to cancel it on this callback.
 *	Must be implemented and can sleep.
 *
 * @suspend: Suspend the device; mac80211 itself will quiesce before and
 *	stop transmitting and doing any other configuration, and then
 *	ask the device to suspend. This is only invoked when WoWLAN is
 *	configured, otherwise the device is deconfigured completely and
 *	reconfigured at resume time.
 *
 * @resume: If WoWLAN was configured, this indicates that mac80211 is
 *	now resuming its operation, after this the device must be fully
 *	functional again. If this returns an error, the only way out is
 *	to also unregister the device. If it returns 1, then mac80211
 *	will also go through the regular complete restart on resume.
 *
 * @add_interface: Called when a netdevice attached to the hardware is
 *	enabled. Because it is not called for monitor mode devices, @start
 *	and @stop must be implemented.
 *	The driver should perform any initialization it needs before
 *	the device can be enabled. The initial configuration for the
 *	interface is given in the conf parameter.
 *	The callback may refuse to add an interface by returning a
 *	negative error code (which will be seen in userspace.)
 *	Must be implemented and can sleep.
 *
 * @remove_interface: Notifies a driver that an interface is going down.
 *	The @stop callback is called after this if it is the last interface
 *	and no monitor interfaces are present.
 *	When all interfaces are removed, the MAC address in the hardware
 *	must be cleared so the device no longer acknowledges packets,
 *	the mac_addr member of the conf structure is, however, set to the
 *	MAC address of the device going away.
 *	Hence, this callback must be implemented. It can sleep.
 *
 * @config: Handler for configuration requests. IEEE 802.11 code calls this
 *	function to change hardware configuration, e.g., channel.
 *	This function should never fail but returns a negative error code
 *	if it does. The callback can sleep.
 *
 * @prepare_multicast: Prepare for multicast filter configuration.
 *	This callback is optional, and its return value is passed
 *	to configure_filter(). This callback must be atomic.
 *
 * @configure_filter: Configure the device's RX filter.
 *	See the section "Frame filtering" for more information.
 *	This callback must be implemented and can sleep.
 *
 * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
 * 	must be set or cleared for a given STA. Must be atomic.
 *
 * @set_key: See the section "Hardware crypto acceleration"
 *	This callback is only called between add_interface and
 *	remove_interface calls, i.e. while the given virtual interface
 *	is enabled.
 *	Returns a negative error code if the key can't be added.
 *	The callback can sleep.
 *
 * @update_tkip_key: See the section "Hardware crypto acceleration"
 * 	This callback will be called in the context of Rx. Called for drivers
 * 	which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
 *	The callback must be atomic.
 *
 * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
 *	The driver should ask the hardware to cancel the scan (if possible),
 *	but the scan will be completed only after the driver will call
 *	ieee80211_scan_completed().
 *	This callback is needed for wowlan, to prevent enqueueing a new
 *	scan_work after the low-level driver was already suspended.
 *	The callback can sleep.
 *
 * @sched_scan_start: Ask the hardware to start scanning repeatedly at
 *	specific intervals.  The driver must call the
 *	ieee80211_sched_scan_results() function whenever it finds results.
 *	This process will continue until sched_scan_stop is called.
 *
 * @sched_scan_stop: Tell the hardware to stop an ongoing scheduled scan.
 *
 * @sw_scan_start: Notifier function that is called just before a software scan
 *	is started. Can be NULL, if the driver doesn't need this notification.
 *	The callback can sleep.
 *
 * @sw_scan_complete: Notifier function that is called just after a
 *	software scan finished. Can be NULL, if the driver doesn't need
 *	this notification.
 *	The callback can sleep.
 *
 * @get_stats: Return low-level statistics.
 * 	Returns zero if statistics are available.
 *	The callback can sleep.
 *
 * @get_tkip_seq: If your device implements TKIP encryption in hardware this
 *	callback should be provided to read the TKIP transmit IVs (both IV32
 *	and IV16) for the given key from hardware.
 *	The callback must be atomic.
 *
 * @set_frag_threshold: Configuration of fragmentation threshold. Assign this
 *	if the device does fragmentation by itself; if this callback is
 *	implemented then the stack will not do fragmentation.
 *	The callback can sleep.
 *
 * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
 *	The callback can sleep.
 *
 * @sta_add: Notifies low level driver about addition of an associated station,
 *	AP, IBSS/WDS/mesh peer etc. This callback can sleep.
 *
 * @sta_remove: Notifies low level driver about removal of an associated
 *	station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
 *
 * @sta_notify: Notifies low level driver about power state transition of an
 *	associated station, AP,  IBSS/WDS/mesh peer etc. For a VIF operating
 *	in AP mode, this callback will not be called when the flag
 *	%IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
 *
 * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
 *	bursting) for a hardware TX queue.
 *	Returns a negative error code on failure.
 *	The callback can sleep.
 *
 * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
 *	This is needed only for IBSS mode and the result of this function is
 *	used to determine whether to reply to Probe Requests.
 *	Returns non-zero if this device sent the last beacon.
 *	The callback can sleep.
 *
 * @get_survey: Return per-channel survey information
 *
 * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
 *	need to set wiphy->rfkill_poll to %true before registration,
 *	and need to call wiphy_rfkill_set_hw_state() in the callback.
 *	The callback can sleep.
 *
 * @set_coverage_class: Set slot time for given coverage class as specified
 *	in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout
 *	accordingly. This callback is not required and may sleep.
 *
 * @testmode_cmd: Implement a cfg80211 test mode command.
 *	The callback can sleep.
 *
 * @flush: Flush all pending frames from the hardware queue, making sure
 *	that the hardware queues are empty. If the parameter @drop is set
 *	to %true, pending frames may be dropped. The callback can sleep.
 *
 * @channel_switch: Drivers that need (or want) to offload the channel
 *	switch operation for CSAs received from the AP may implement this
 *	callback. They must then call ieee80211_chswitch_done() to indicate
 *	completion of the channel switch.
 *
 * @napi_poll: Poll Rx queue for incoming data frames.
 *
 * @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
 *	Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
 *	reject TX/RX mask combinations they cannot support by returning -EINVAL
 *	(also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
 *
 * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
 *
 * @tx_frames_pending: Check if there is any pending frame in the hardware
 *	queues before entering power save.
 *
 * @set_bitrate_mask: Set a mask of rates to be used for rate control selection
 *	when transmitting a frame. Currently only legacy rates are handled.
 *	The callback can sleep.
 */


Another structure which handles all SDIO functionality is defined as:

static struct wl1271_if_operations sdio_ops = {
    .read           = wl1271_sdio_raw_read,
    .write          = wl1271_sdio_raw_write,
    .power          = wl1271_sdio_set_power,
    .dev            = wl1271_sdio_wl_to_dev,
    .enable_irq     = wl1271_sdio_enable_interrupts,
    .disable_irq    = wl1271_sdio_disable_interrupts,
    .set_block_size = wl1271_sdio_set_block_size,
};

The wl1271_alloc_hw() allocates memory region for those structures and initializes some of the structure fields.
This is defined under sdio.c as follows:

hw = wl1271_alloc_hw();
...
wl = hw->priv;
...
wl->if_ops = &sdio_ops;


wl1271_init_ieee80211() Function

The wl1271_init_ieee80211() function simply takes the wl structure (of type struct wl1271), described in the above section, and initializes it (max rates/cipher suites/...).

wl1271_register_hw() Function

This function registers the hardware as follows: it calls ieee80211_register_hw() and passes the wl structure. This ieee80211_register_hw() function, which is implemented under compat-wireless-2.6/net/mac80211/main.c, performs the registration and also adds the interface of WLAN using ieee80211_if_add() function as follows:

int ieee80211_register_hw(struct ieee80211_hw *hw)
{
    ....
    result = ieee80211_if_add(local, "wlan%d", NULL, NL80211_IFTYPE_STATION, NULL);
    ....
}

The printf style function (wlan%d) replaces the %d with the first available number. Normally the interface name would be wlan0.

WL12xx Interrupts

So far, we saw that the WL12xx drivers has access function to the SDIO driver in order to configure the WL12xx chip. On the other side, the WL12xx chip sends an interrupt when it needs to notify the WL12xx driver about incoming packets. This is done by the same wl1271_probe() function as follows:

...
ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, irqflags, DRIVER_NAME, wl);
...

The function request_threaded_irq() allocates an interrupt line where:

  • wl->irq is the interrupt line to allocate
  • wl1271_hardirq is the function to be called when IRQ occurs
  • wl1271_irq is the function called from IRQ handler thread
  • DRIVER_NAME is the ASCII name for the claiming device. DRIVER_NAME is defined as "wl1271".
  • wl is a cookie passed back to the handler function

Please refer to <this link> for further information.
If we look at the function wl1271_irq(), which is implemented under compat-wireless-2.6/drivers/net/wireless/wl12xx/main.c, it calls wl1271_rx():

...
if (likely(intr & WL1271_ACX_INTR_DATA)) {
    wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
    wl1271_rx(wl, wl->fw_status);
...

The wl1271_rx() function is responsible for handling the incoming packets.

WL12xx Chip Event Handling

As we saw in the WL12xx Interrupts section, the sdio.c file registers the function wl1271_irq() which handles the interrupts.
This function, in addition of handling incoming packets (RX), it handles events coming from the WL12xx chip, such as association/de-association/beacon loss/etc.
The handling is done via function called wl1271_event_handle() invoked by wl1271_irq().
The function wl1271_event_handle() located under drivers/net/wireless/wl12xx/event.c, calls wl1271_event_process() to process the incoming events.
Let's take an example from there were we have a beacon loss and the connection is lost:

(From drivers/net/wireless/wl12xx/event.c)
...
	if (wl->vif && beacon_loss)
		ieee80211_connection_loss(wl->vif);
...

The function ieee80211_connection_loss(), located under net/mac80211/mlme.c, schedules delayed work to be invoked when the interrupt is finished.
This delayed work is done via ieee80211_beacon_connection_loss_work() function. This function in turn will call __ieee80211_connection_loss() which calls ieee80211_send_deauth_disassoc() function.
When looking at ieee80211_send_deauth_disassoc() function we can see it calls cfg80211_send_disassoc() with argument mgmt of type struct ieee80211_mgmt *
This structure is important since it has a union which includes all the events that can be passed to the user space. The structure is located under include/linux/ieee80211.h file, and looks as follows:

struct ieee80211_mgmt {
	__le16 frame_control;
	__le16 duration;
	u8 da[6];
	u8 sa[6];
	u8 bssid[6];
	__le16 seq_ctrl;
	union {
		struct {
			__le16 auth_alg;
			__le16 auth_transaction;
			__le16 status_code;
			/* possibly followed by Challenge text */
			u8 variable[0];
		} __attribute__ ((packed)) auth;
		struct {
			__le16 reason_code;
		} __attribute__ ((packed)) deauth;
		struct {
			__le16 capab_info;
			__le16 listen_interval;
			/* followed by SSID and Supported rates */
			u8 variable[0];
		} __attribute__ ((packed)) assoc_req;
		struct {
			__le16 capab_info;
			__le16 status_code;
			__le16 aid;
			/* followed by Supported rates */
			u8 variable[0];
		} __attribute__ ((packed)) assoc_resp, reassoc_resp;
		struct {
			__le16 capab_info;
			__le16 listen_interval;
			u8 current_ap[6];
			/* followed by SSID and Supported rates */
			u8 variable[0];
		} __attribute__ ((packed)) reassoc_req;
		struct {
			__le16 reason_code;
		} __attribute__ ((packed)) disassoc;
		struct {
			__le64 timestamp;
			__le16 beacon_int;
			__le16 capab_info;
			/* followed by some of SSID, Supported rates,
			 * FH Params, DS Params, CF Params, IBSS Params, TIM */
			u8 variable[0];
		} __attribute__ ((packed)) beacon;
		struct {
			/* only variable items: SSID, Supported rates */
			u8 variable[0];
		} __attribute__ ((packed)) probe_req;
		struct {
			__le64 timestamp;
			__le16 beacon_int;
			__le16 capab_info;
			/* followed by some of SSID, Supported rates,
			 * FH Params, DS Params, CF Params, IBSS Params */
			u8 variable[0];
		} __attribute__ ((packed)) probe_resp;
		struct {
			u8 category;
			union {
				struct {
					u8 action_code;
					u8 dialog_token;
					u8 status_code;
					u8 variable[0];
				} __attribute__ ((packed)) wme_action;
				struct{
					u8 action_code;
					u8 element_id;
					u8 length;
					struct ieee80211_channel_sw_ie sw_elem;
				} __attribute__((packed)) chan_switch;
				struct{
					u8 action_code;
					u8 dialog_token;
					u8 element_id;
					u8 length;
					struct ieee80211_msrment_ie msr_elem;
				} __attribute__((packed)) measurement;
				struct{
					u8 action_code;
					u8 dialog_token;
					__le16 capab;
					__le16 timeout;
					__le16 start_seq_num;
				} __attribute__((packed)) addba_req;
				struct{
					u8 action_code;
					u8 dialog_token;
					__le16 status;
					__le16 capab;
					__le16 timeout;
				} __attribute__((packed)) addba_resp;
				struct{
					u8 action_code;
					__le16 params;
					__le16 reason_code;
				} __attribute__((packed)) delba;
				struct{
					u8 action_code;
					/* capab_info for open and confirm,
					 * reason for close
					 */
					__le16 aux;
					/* Followed in plink_confirm by status
					 * code, AID and supported rates,
					 * and directly by supported rates in
					 * plink_open and plink_close
					 */
					u8 variable[0];
				} __attribute__((packed)) plink_action;
				struct{
					u8 action_code;
					u8 variable[0];
				} __attribute__((packed)) mesh_action;
				struct {
					u8 action;
					u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
				} __attribute__ ((packed)) sa_query;
				struct {
					u8 action;
					u8 smps_control;
				} __attribute__ ((packed)) ht_smps;
				struct {
					u8 action;
					u8 oui[3];
					u8 variable[0];
				} __attribute__ ((packed)) public;

			} u;
		} __attribute__ ((packed)) action;
	} u;
} __attribute__ ((packed));

Kernel Space - User Space Interaction

The following table shows the commands invoked in user space, with their corresponding functions in kernel space.

Command in User Space Function being invoked in Kernel Space
insmod wl12xx_sdio.ko wl1271_init
rmmod wl12xx_sdio wl1271_exit
iw wlan0 scan wl1271_op_sched_scan_start
echo mem > /sys/power/state (suspend) wl1271_op_suspend
When suspend finishes wl1271_op_resume
Tx operation (e.g ping) wl1271_op_tx


Other Concepts Explained

Compat

  • For information on how drivers are kept compatible using Compat generation, please refer to: <Compat wireless

WLAN

  • Rates - use Sniffer log to verify WLAN rates (refer to: < WLAN rates >)
  • Channels - use Sniffer log to verify WLAN rates (refer to: < WLAN channels >)
  • Beacon (refer to: <Beacon>)
  • Address Resolution Protocol - ARP (refer to: <ARP>)
  • Power Save:
  • Scan - use Sniffer log to verify WLAN scan results (refer to: < Scan >)
  • QoS