The Wireless Local Area Network (WLAN) driver module is developed based on OpenHarmony Hardware Driver Foundation (HDF). It supports modular assembly and building, automatic adaptation to device differences, and cross-OS porting.
A wireless LAN (WLAN) allows users to easily connect to a wireless network to transmit and share data and move around within the area and remain connected to the network. The WLAN driver developed based on the Hardware Driver Foundation (HDF) shields hardware component differences and provides stable basic capability interfaces for upper-layer WLAN services, including starting a scan, associating with or disassociating from a hotspot, obtaining or setting MAC addresses, and obtaining link information.
### Working Principles
### Basic Concepts
You can modify your driver code based on the unified APIs provided by the WLAN module. The WLAN module provides:
Before development, you need to understand the following basic concepts related to WLAN:
- APIs for the underlying layer to implement capabilities, such as opening or closing a WLAN hotspot, scanning hotspots, and connecting to or disconnecting from a hotspot.
- APIs for the Hardware Device Interface (HDI) layer to implement capabilities, such as setting or obtaining the device Media Access Control (MAC) address and setting the transmit power.
- AP
The following figure shows the WLAN architecture. The WLAN driver module implements startup loading, parses configuration files, and provides bus abstraction APIs. The WLAN chip driver module provides the MAC Sublayer Management Entity (MLME).
A wireless access point (AP) is a central node of a network that provides the wireless access service. Once connecting to the wireless network, the device can access data.
A station (STA) is a basic component of a WLAN. Each terminal connected to a WLAN, such as a notebook and a personal digital assistant (PDA), is an STA.
The following figure shows the WLAN driver architecture.
- SSID
**Figure 2** WLAN driver architecture
A service set identifier (SSID) identifies a wireless network. Each WLAN has its SSID.
The WLAN driver consists of the following modules:
A basic service set identifier (BSSID) is a 48-bit MAC address that uniquely identifies a basic service set on a WLAN.
1. WLAN Message: provides an independent interface for each service or a composite service interface for multiple dependent services. It can run in the user mode, kernel mode, and MCU to implement complete decoupling between components.
A terminal device scans the wireless network to obtain visible wireless network information, including the hotspot SSID, operating frequency band, and signal strength.
3. Access point (AP): allows devices to connect to the WLAN.
- Associate
4. Station (STA): a device that has access to the WLAN system and allows transmission and reception of data.
When a terminal device is associated with a valid hotspot, it can communicate with the AP. A device (STA) can set up a connection with only one AP at a time.
5. mac80211: defines MAC-layer APIs for underlying drivers.
### Working Principles
6. Bus: provides a unified bus abstract interface for the upper layer. It shields the differences between different kernels by calling the Secure Digital Input Output (SDIO) interfaces provided by the platform layer and encapsulating the adapted USB and PCIe interfaces. It also encapsulates different types of bus operations in a unified manner to shield differences between different chipsets. The complete bus driving capabilities provided by the bus module help simplify and streamline the development of different chip vendors.
This document describes how to develop WLAN functions based on the HDF. The following figure shows the WLAN framework.
7. NetDevice: creates dedicated network devices to shield differences between OSs, provides unified interfaces for Wi-Fi drivers, unified HDF NetDevice data structure, and unified management, registration, and deregistration capabilities, and connects to the Linux network device layer on mini-, small-, standard, and large-system devices.
8. NetBuf: encapsulates the unified data structure of the Linux or LiteOS native network data buffer and the operation interfaces for network data.
1. The upper-layer service calls a hardware device interface (HDI) based on service requirements to deliver user-mode messages to the client through the Wi-Fi Protected Access (WPA) layer or hardware abstraction layer (HAL). The WPA layer provides interfaces for setting the encryption mode, associating with a hotspot, setting a channel, and hiding the hotspot. As a supplement to the WPA layer, the HAL provides APIs for setting the country code or MAC address and obtaining channel information.
9. FlowCtl: processes data based on the priority when the data volume is too large.
2. The Message module distributes user-mode messages to modules, such as the AP and STA, by component.
10. HCC-CFG: configures WLAN parameters, including the board configuration, driver configuration, and module configuration.
3. Hdf_Mac80211 defines MAC-layer interfaces for underlying drivers. The command field is delivered to Hdf_Mac80211 and then sent to the WLAN chip firmware through the Bus module.
The relationships between the main modules are as follows:
4. The Bus module provides unified bus abstraction interfaces for the upper layer. It shields the differences between kernels by calling the Secure Digital Input Output (SDIO) interfaces provided by the platform layer and encapsulating the USB and PCIe interfaces. The Bus module also encapsulates different types of bus operations in a unified manner to shield differences between chipsets. The interfaces provided by the Bus module simplify and streamline the development of different chip vendors.
1. The WLAN driver works with HCC-CFG and WLAN Configuration Core to parse and load configuration files.
5. Extensible Authentication Protocol (EAP) over LAN (EAPOL) is a LAN-based extended authentication protocol. It is used to transmit EAP packets between a client and a device (access device or server) so that EAP packets can be transmitted on a LAN to complete the authentication process and enable the device to go online.
2. The WLAN Message module distributes user-mode messages to the AP and STA by component.
6. NetDevice creates dedicated network devices to shield differences between OSs. It provides unified interfaces for Wi-Fi drivers, unified HDF NetDevice data structs, and unified management, registration, and deregistration capabilities, and connects to the Linux network device layer on OpenHarmony devices.
3. Commands are delivered to mac80211, and then forwarded by the Bus module to the WLAN chip firmware.
7. NetBuf encapsulates the unified data structure of the Linux or LiteOS native network data buffer and the operation interfaces for network data.
4. The protocol stack works with the NetDevice, NetBuf, and FlowCtl modules to exchange data flows.
8. The protocol stack works with the NetDevice and NetBuf modules to exchange data flows.
## How to Develop
### Constraints
### Available APIs
The WLAN driver provides basic capability interfaces for upper-layer WLAN services. The HDI interfaces apply to the standard system, and the HAL interfaces apply to mini and small systems.
The WLAN module provides the following types of APIs:
## Development Guidelines
1. HDI and Hardware Abstraction Layer (HAL) APIs for upper-layer services
### When to Use
2. APIs for vendors
The WLAN driver provides basic capability interfaces for upper-layer WLAN services to ensure that users can easily access the wireless network and transmit and share data. Refer to the following when you adapt your WLAN module to OpenHarmony.
- The WLAN module provides HAL APIs for upper-layer services (applicable to small and mini systems). **Table 1** and **Table 2** describe some APIs.
3. WLAN APIs directly called by drivers
- This interfaces provided by the WLAN Driver module for upper-layer services can be used to create or destroy an IWiFi object, and set MAC addresses or transmit power. Table 1 and Table 2 list the C function interfaces generated based on the IDL interface description. For details about the interface declaration, see the IDL files (**/drivers/interface/wlan/v1_1/**).
**Table 1** wifi_hal.h
| API| Description|
| -------- | -------- |
| int32_t WifiConstruct(struct IWiFi \*\*wifiInstance)| Creates an **IWiFi** instance with basic capabilities.|
| int32_t WifiDestruct(struct IWiFi \*\*wifiInstance)| Destroys an **IWiFi** instance.|
| int32_t (\*start)(struct IWiFi \*)| Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.|
| int32_t (\*stop)(struct IWiFi \*)| Stops the channel between the HAL and the driver.|
| int32_t WifiConstruct(struct IWiFi \*\*wifiInstance) | Creates an **IWiFi** instance with basic capabilities.|
| int32_t WifiDestruct(struct IWiFi \*\*wifiInstance) | Destroys an **IWiFi** instance.|
| int32_t (\*start)(struct IWiFi \*) | Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.|
| int32_t (\*stop)(struct IWiFi \*) | Stops the channel between the HAL and the driver.|
**Table 2** wifi_hal_base_feature.h
| API| Description|
| -------- | -------- |
| int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*)| Obtains the feature type.|
| int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Sets the MAC address.|
| int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Obtains the device MAC address.|
| int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*) | Obtains the feature type.|
| int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Sets the MAC address.|
| int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Obtains the device MAC address.|
| int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t) | Sets the transmit power.|
- The WLAN Driver module also provides APIs that you need to fill in the implementation. **Table 3** describes some APIs.
- The WLAN Driver module also provides APIs that you need to fill in the implementation. These APIs can be used to initialize or deregister a network device, open or stop a network device, and obtain network device status. Table 3 describes some APIs.
**Table 3** net_device.h
| API| Description|
| -------- | -------- |
| int32_t (\*init)(struct NetDevice \*netDev)| Initializes a network device.|
| struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev)| Obtains the state of a network device.|
| int32_t (\*setMacAddr)(struct NetDevice \*netDev, void \*addr)| Sets the MAC address.|
| void (\*deInit)(struct NetDevice \*netDev)| Deinitializes a network device.|
| int32_t (\*open)(struct NetDevice \*netDev)| Opens a network device.|
| int32_t (\*stop)(struct NetDevice \*netDev)| Stops a network device.|
| int32_t (\*init)(struct NetDevice \*netDev) | Initializes a network device.|
| struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev) | Obtains the state of a network device.|
| int32_t (\*setMacAddr)(struct NetDevice \*netDev, void \*addr) | Sets the MAC address.|
| void (\*deInit)(struct NetDevice \*netDev) | Deinitializes a network device.|
| int32_t (\*open)(struct NetDevice \*netDev) | Opens a network device.|
| int32_t (\*stop)(struct NetDevice \*netDev) | Stops a network device.|
- The WLAN Driver module provides APIs that you can directly use to create or release a **WifiModule**, connect to or disconnect from a WLAN hotspot, request or release a **NetBuf**, and convert between the **pbuf** structure of Lightweight IP (lwIP) and a **NetBuf**.
- The WLAN Driver module provides APIs that you can directly use to create or release a **WifiModule**, connect to or disconnect from a WLAN hotspot, request or release a **NetBuf**, and convert between the **pbuf** struct of Lightweight IP (lwIP) and a **NetBuf**.
The following tables describe the APIs.
Tables 4 to 6 list the APIs that can be directly called.
**Table 4** wifi_module.h
| API| Description|
| -------- | -------- |
| struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config)| Creates a **WifiModule**.|
| void WifiModuleDelete(struct WifiModule \*module)| Deletes a **WifiModule** and releases its data.|
| int32_t DelFeature(struct WifiModule \*module, uint16_t featureType)| Deletes a feature from a **WifiModule**.|
| int32_t AddFeature(struct WifiModule \*module, uint16_t featureType,<br> struct WifiFeature \*featureData)| Adds a feature to a **WifiModule**.|
| struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config) | Creates a **WifiModule**.|
| void WifiModuleDelete(struct WifiModule \*module) | Deletes a **WifiModule** and releases its data.|
| int32_t DelFeature(struct WifiModule \*module, uint16_t featureType) | Deletes a feature from a **WifiModule**.|
| int32_t AddFeature(struct WifiModule \*module, uint16_t featureType,<br> struct WifiFeature \*featureData) | Adds a feature to a **WifiModule**.|
**Table 5** wifi_mac80211_ops.h
| API| Description|
| -------- | -------- |
| int32_t (\*startAp)(NetDevice \*netDev)| Starts an AP.|
| int32_t (\*stopAp)(NetDevice \*netDev)| Stops an AP.|
| int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param)| Connects to a hotspot.|
| int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode)| Disconnects from a hotspot.|
| int32_t (\*startAp)(NetDevice \*netDev) | Starts an AP.|
| int32_t (\*stopAp)(NetDevice \*netDev) | Stops an AP.|
| int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param) | Connects to a hotspot.|
| int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode) | Disconnects from a hotspot.|
| struct NetBuf \*NetBufAlloc(uint32_t size)| Allocates a **NetBuf**.|
| void NetBufFree(struct NetBuf \*nb)| Releases a **NetBuf**.|
| struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf)| Converts the **pbuf** structure of lwIP to a **NetBuf**.|
| struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb)| Converts a **NetBuf** to the **pbuf** structure of lwIP.|
### Development Procedure
#### WLAN Framework Adaptation
The WLAN driver framework developed based on the HDF and Platform framework provides a unified driver model regardless of the OS and system on a chip (SoC). When developing your WLAN driver, you need to configure data based on the WLAN driver framework.
**Development Procedure**
1. Configure hardware (such as modules and chips) parameters in the **wlan_platform.hcs** file. The HDF parses the file to generate structure objects with full configuration.
2. Implement initialization and deinitialization of the WLAN module (such as initialize and deinitialize the WLAN chip and WLAN chip driver).
3. Implement the delivery of control flow commands.
4. Implement event reporting.
| static inline void NetBufQueueInit(struct NetBufQueue \*q) | Initializes a **NetBuf** queue.|
| struct NetBuf \*NetBufAlloc(uint32_t size) | Allocates a **NetBuf**.|
| void NetBufFree(struct NetBuf \*nb) | Releases a **NetBuf**.|
| struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | Converts the **pbuf** structure of lwIP to a **NetBuf**.|
| struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | Converts a **NetBuf** to the **pbuf** structure of lwIP.|
**Development Example**
### How to Develop
The following uses the Hi3881 WLAN chip as an example to describe how to initialize a WLAN module.
The WLAN driver framework developed based on the HDF and Platform framework provides a unified driver model for vendors regardless of the OS and system on a chip (SoC). When developing your WLAN driver based on the WLAN driver framework, you need to make adaptation. The following uses the Hi3881 WLAN chip as an example.
1. Configure the HDF configuration source (HCS) for the driver.
#### Configuring the HCS for the Driver
The HCS includes device configuration and component configuration.
The HDF configuration source (HCS) includes device configuration and component configuration.
- Device configuration
...
...
@@ -223,8 +211,9 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
}
```
2. Hook the **init** and **deinit** functions of the WLAN chip and WLAN chip driver.
- Implementing the driver adaptation entry function
#### Initializing and deinitializing the WLAN Chip and WLAN Chip Driver
- Implement the driver adaptation entry function
Define a variable of the HdfDriverEntry type based on the chip to hook functions of **Bind()**, **Init()**, and **Release()**. Call **HDF_INIT** to register the driver entry with the HDF. During driver loading, the HDF calls the **Bind** function and then the **Init** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources.
```c
...
...
@@ -239,7 +228,7 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
HDF_INIT(g_hdfHisiChipEntry);
```
- Registering the functions for initializing the chip and chip driver
- Register the functions for initializing the chip and chip driver
Hook the chip initialization function to **InitChip()** and the chip deinitialization function to **DeinitChip()**.
...
...
@@ -278,7 +267,8 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
@@ -470,7 +462,7 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
.init = oal_net_device_init,
.deInit = oal_net_free_netdev,
...
......
};
...
...
@@ -485,10 +477,12 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
}
```
3. Bind the commands to be delivered, including setting the MAC address and transmit power, implement STA connection and scan, start APs, and setting the country code.
#### Modifying the MAC Layer Interfaces
After the user-mode message is delivered to the driver, the driver calls the corresponding MAC-layer capability interfaces.
```c
/* Implement the basic capabilities of the MAC layer. */
/* Define the functions for implementing the basic capabilities in the MAC layer for the driver. */
staticstructHdfMac80211BaseOpsg_baseOps={
.SetMode=WalSetMode,
.AddKey=WalAddKey,
...
...
@@ -501,7 +495,7 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
.GetHwCapability=WalGetHwCapability
};
/* Implement the STA capabilities of the MAC layer. */
/* Define the functions for implementing the STA capabilities in the MAC layer for the driver. */
staticstructHdfMac80211STAOpsg_staOps={
.Connect=WalConnect,
.Disconnect=WalDisconnect,
...
...
@@ -510,7 +504,7 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
.SetScanningMacAddress=WalSetScanningMacAddress,
};
/* Implement the AP capabilities of the MAC layer. */
/* Define the functions for implementing the AP capabilities in the MAC layer for the driver. */
staticstructHdfMac80211APOpsg_apOps={
.ConfigAp=WalConfigAp,
.StartAp=WalStartAp,
...
...
@@ -546,7 +540,11 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
}
```
4. Invoke the event reporting APIs. <br>The WLAN framework provides the event reporting APIs. For details, see hdf_wifi_event.c. <br>For example, call **HdfWiFiEventNewSta AP** to report information about the newly associated STA.
#### Configuring Event Reporting
The WLAN framework provides interfaces for event reporting. For details, see **hdf_wifi_event.c**.
The following presents how to use **HdfWiFiEventNewSta()** to report information about a newly associated STA.
@@ -567,7 +565,10 @@ The following uses the Hi3881 WLAN chip as an example to describe how to initial
returnHI_SUCCESS;
}
```
**Verification**
### Debugging and Verification
#### Driver Adaptation Verification
Develop test cases in the WLAN module unit test to verify the basic features of the WLAN module. The following uses Hi3516D V300 standard system as an example.
...
...
@@ -644,7 +645,9 @@ Develop test cases in the WLAN module unit test to verify the basic features of
exit 0
```
- Create a **udhcpd.conf** file (used to start the **udhcpd**) and copy the following content to the file. <br>In the following, **opt dns** *x.x.x.x* *x.x.x.x* indicates two DNS servers configured. You can configure DNS servers as required.
- Create the **udhcpd.conf** file and copy the following content to the file.
In the following example, "opt dns x.x.x.x x.x.x.x" indicates two DNS servers configured. You can configure DNS servers as required.
```text
start 192.168.12.2
...
...
@@ -698,7 +701,7 @@ Develop test cases in the WLAN module unit test to verify the basic features of
busybox udhcpd /vendor/etc/udhcpd.conf
```
4. On the mobile phone, select the network named **test** in the available Wi-Fi list and enter the password. <br>The network name and password are configured in the **hostapd.conf** file. You can see that network name in the connected Wi-Fi list if the connection is successful.
4. On the mobile phone, select the network named **test** in the available Wi-Fi list and enter the password. (The network name and password are configured in the **hostapd.conf** file.) You can see that network name in the connected Wi-Fi list if the connection is successful.
5. Ping the test terminal from the development board.
...
...
@@ -706,11 +709,11 @@ Develop test cases in the WLAN module unit test to verify the basic features of
busybox ping xxx.xxx.xxx.xxx
```
In the command, *xxx.xxx.xxx.xxx* indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
- Verify basic STA features.
- Verify basic STA functions
1. Start the STA on the development board, and enable the hotspot on the test terminal. <br>The hotspot name and password are configured in the **hostapd.conf** file. The hotspot name is **test**, and the password is **12345678**.
1. Start the STA on the development board, and enable the hotspot on the test terminal. (The hotspot name and password are configured in the **hostapd.conf** file. The hotspot name is **test**, and the password is **12345678**.)
2. Run the following command in the **cmd** window:
...
...
@@ -737,8 +740,9 @@ Develop test cases in the WLAN module unit test to verify the basic features of
In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally.
#### **API Invocation**
The WLAN driver module provides two types of capability interfaces for the upper layer: HDI interface and HAL interface.
#### API Usage Example
The WLAN Driver module provides two types of capability interfaces for the upper layer: HDI APIs and HAL APIs.
- HDI API invocation
The following uses **GetSupportFeature** as an example to describe the development procedure:
...
...
@@ -753,7 +757,7 @@ The WLAN driver module provides two types of capability interfaces for the upper
5. Call **WlanInterfaceRelease()** to destroy the WLAN service instance.
The sample code is as follows:
Example:
```c
#include "v1_0/iwlan_interface.h"
#include "wlan_callback_impl.h"
...
...
@@ -848,7 +852,7 @@ The WLAN driver module provides two types of capability interfaces for the upper
7. Call **WifiDestruct()** to destroy the **IWiFi** instance.
The sample code is as follows:
Example:
```c
#include "wifi_hal.h"
...
...
@@ -947,17 +951,16 @@ The WLAN driver module provides two types of capability interfaces for the upper
- Code paths:
Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi**
Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network**
- Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi**
Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver: **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi**
- Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network**
Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
- Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver: **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi**
External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
- Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
HDF network model APIs: **//drivers/hdf_core/framework/include/net**
- External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
WLAN HDI server implementation: **//drivers/peripheral/wlan**
- HDF network model APIs: **//drivers/hdf_core/framework/include/net**
- WLAN HDI server implementation: **//drivers/peripheral/wlan**