• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# WLAN
2
3
4## Overview
5
6### Function
7
8A 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.
9
10### Basic Concepts
11
12Before development, you need to understand the following basic concepts related to WLAN:
13
14- AP
15
16  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.
17
18- STA
19
20  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.
21
22- SSID
23
24  A service set identifier (SSID) identifies a wireless network. Each WLAN has its SSID.
25
26- bssid
27
28  A basic service set identifier (BSSID) is a 48-bit MAC address that uniquely identifies a basic service set on a WLAN.
29
30- Scan
31
32  A terminal device scans the wireless network to obtain visible wireless network information, including the hotspot SSID, operating frequency band, and signal strength.
33
34- Associate
35
36  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.
37
38### Working Principles
39
40This document describes how to develop WLAN functions based on the HDF. The following figure shows the WLAN framework.
41
42![image](figures/WLAN-driver-framework.png "WLAN Framework")
43
441. 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.
45
462. The Message module distributes user-mode messages to modules, such as the AP and STA, by component.
47
483. 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.
49
504. 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.
51
525. 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.
53
546. 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.
55
567. NetBuf encapsulates the unified data structure of the Linux or LiteOS native network data buffer and the operation interfaces for network data.
57
588. The protocol stack works with the NetDevice and NetBuf modules to exchange data flows.
59
60### Constraints
61
62The 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.
63
64## Development Guidelines
65
66### When to Use
67
68The 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.
69
70### Available APIs
71
72The WLAN module provides the following APIs:
73
741. HDI and HAL APIs for upper-layer services
75
762. APIs for vendors
77
783. WLAN APIs directly called by drivers
79
80- 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/).
81
82    **Table 1** wifi_hal.h
83
84  | API| Description|
85  | -------- | -------- |
86  | int32_t WifiConstruct(struct IWiFi \*\*wifiInstance) | Creates an **IWiFi** instance with basic capabilities.|
87  | int32_t WifiDestruct(struct IWiFi \*\*wifiInstance) | Destroys an **IWiFi** instance.|
88  | int32_t (\*start)(struct IWiFi \*) | Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.|
89  | int32_t (\*stop)(struct IWiFi \*) | Stops the channel between the HAL and the driver.|
90
91    **Table 2** wifi_hal_base_feature.h
92
93  | API| Description|
94  | -------- | -------- |
95  | int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*) | Obtains the feature type.|
96  | int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Sets the MAC address.|
97  | int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Obtains the device MAC address.|
98  | int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t) | Sets the transmit power.|
99
100- 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.
101
102    **Table 3** net_device.h
103
104  | API| Description|
105  | -------- | -------- |
106  | int32_t (\*init)(struct NetDevice \*netDev) | Initializes a network device.|
107  | struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev) | Obtains the state of a network device.|
108  | int32_t (\*setMacAddr)(struct NetDevice \*netDev, void \*addr) | Sets the MAC address.|
109  | void (\*deInit)(struct NetDevice \*netDev) | Deinitializes a network device.|
110  | int32_t (\*open)(struct NetDevice \*netDev) | Opens a network device.|
111  | int32_t (\*stop)(struct NetDevice \*netDev) | Stops a network device.|
112
113- 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**.
114
115  Tables 4 to 6 list the APIs that can be directly called.
116
117    **Table 4** wifi_module.h
118
119  | API| Description|
120  | -------- | -------- |
121  | struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config) | Creates a **WifiModule**.|
122  | void WifiModuleDelete(struct WifiModule \*module) | Deletes a **WifiModule** and releases its data.|
123  | int32_t DelFeature(struct WifiModule \*module, uint16_t featureType) | Deletes a feature from a **WifiModule**.|
124  | int32_t&nbsp;AddFeature(struct&nbsp;WifiModule&nbsp;\*module,&nbsp;uint16_t&nbsp;featureType,<br>&nbsp;struct&nbsp;WifiFeature&nbsp;\*featureData) | Adds a feature to a **WifiModule**.|
125
126    **Table 5** wifi_mac80211_ops.h
127
128  | API| Description|
129  | -------- | -------- |
130  | int32_t&nbsp;(\*startAp)(NetDevice&nbsp;\*netDev) | Starts an AP.|
131  | int32_t&nbsp;(\*stopAp)(NetDevice&nbsp;\*netDev) | Stops an AP.|
132  | int32_t&nbsp;(\*connect)(NetDevice&nbsp;\*netDev,&nbsp;WifiConnectParams&nbsp;\*param) | Connects to a hotspot.|
133  | int32_t&nbsp;(\*disconnect)(NetDevice&nbsp;\*netDev,&nbsp;uint16_t&nbsp;reasonCode) | Disconnects from a hotspot.|
134
135    **Table 6** hdf_netbuf.h
136
137  | API| Description|
138  | -------- | -------- |
139  | static&nbsp;inline&nbsp;void&nbsp;NetBufQueueInit(struct&nbsp;NetBufQueue&nbsp;\*q) | Initializes a **NetBuf** queue.|
140  | struct&nbsp;NetBuf&nbsp;\*NetBufAlloc(uint32_t&nbsp;size) | Allocates a **NetBuf**.|
141  | void&nbsp;NetBufFree(struct&nbsp;NetBuf&nbsp;\*nb) | Releases a **NetBuf**.|
142  | struct&nbsp;NetBuf&nbsp;\*Pbuf2NetBuf(const&nbsp;struct&nbsp;NetDevice&nbsp;\*netdev,&nbsp;struct&nbsp;pbuf&nbsp;\*lwipBuf) | Converts the **pbuf** structure of lwIP to a **NetBuf**.|
143  | struct&nbsp;pbuf&nbsp;\*NetBuf2Pbuf(const&nbsp;struct&nbsp;NetBuf&nbsp;\*nb) | Converts a **NetBuf** to the **pbuf** structure of lwIP.|
144
145### How to Develop
146
147The 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.
148
149#### Configuring the HCS for the Driver
150
151   The HDF configuration source (HCS) includes device configuration and component configuration.
152
153   - Device configuration
154
155     The configuration file contains the power supply, reset, and bus configuration.
156
157     Configuration file path: **vendor/<vendor name>/<device name >/hdf_config/khdf/wifi**
158
159     Configure device parameters in **wlan_platform.hcs** based on the device you use. The following is an example of WLAN platform configuration.
160        ```text
161        hisi :& deviceList {
162            device0 :: deviceInst {
163                deviceInstId = 0;
164                powers {
165                    power0 {
166                        powerSeqDelay = 0;  /* Power sequence delay. */
167                        powerType = 1;      /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */
168                        gpioId = 1;         /* GPIO pin number. */
169                        activeLevel=1;      /* Active level. The value 0 indicates low level, and 1 indicates high level. */
170                    }
171                    power1 {
172                        powerSeqDelay = 0;  /* Power sequence delay. */
173                        powerType = 0;      /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */
174                    }
175                }
176                reset {
177                    resetType = 0;         /* Reset type. The value 0 indicates that reset is dynamically determined, and 1 indicates reset through GPIO. */
178                    gpioId = 2;           /* GPIO pin number. */
179                    activeLevel=1;      /* Active level. The value 0 indicates low level, and 1 indicates high level. */
180                    resetHoldTime = 30;    /* Hold time (ms) after a reset. */
181                }
182                bootUpTimeout = 30;  /* Boot timeout duration (ms). */
183                bus {
184                    busEnable = 1;   /* Whether to initialize the bus. The value 1 means to initialize the bus; the value 0 means the opposite. */
185                    busType = 0;     /* Bus type. The value 0 indicates SDIO. */
186                    busId = 2;      /* Bus number. */
187                    funcNum = [1];   /* SDIO function number. */
188                    timeout = 1000;  /* Timeout duration for data read/write. */
189                    blockSize = 512; /* Size of the data block to read or write. */
190                }
191            }
192        }
193        ```
194   - Component configuration
195
196     Add a configuration file **wlan_chip_.hcs** for each chip, for example, **wlan_chip_hi3881.hcs**, and configure related parameters. The following is a configuration example of hi3881.
197        ```text
198        root {
199            wlan_config {
200                hi3881 :& chipList {
201                    chipHi3881 :: chipInst {
202                        match_attr = "hdf_wlan_chips_hi3881"; /* Attribute used to match the chip. */
203                        chipName = "hi3881";                   /* WLAN chip name. */
204                        bus {
205                            vendorId = 0x0296;    /* Vendor ID. */
206                            deviceId = [0x5347];  /* Device ID. */
207                        }
208                    }
209                }
210            }
211        }
212        ```
213
214#### Initializing and deinitializing the WLAN Chip and WLAN Chip Driver
215
216   - Implementing the driver adaptation entry function
217
218     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.
219     ```c
220     struct HdfDriverEntry g_hdfHisiChipEntry = {
221        .moduleVersion = 1,
222        .Bind = HdfWlanHisiDriverBind,
223        .Init = HdfWlanHisiChipDriverInit,
224        .Release = HdfWlanHisiChipRelease,
225        .moduleName = "HDF_WLAN_CHIPS"
226     };
227
228     HDF_INIT(g_hdfHisiChipEntry);
229     ```
230
231   - Registering the functions for initializing the chip and chip driver
232
233     Hook the chip initialization function to **InitChip()** and the chip deinitialization function to **DeinitChip()**.
234
235     Hook the chip driver initialization function to **Build()** and the chip driver deinitialization function to **Release()**.
236
237     ```c
238     /* Register WLAN chip functions. */
239     static int32_t HDFWlanRegHisiDriverFactory(void)
240     {
241         static struct HdfChipDriverFactory tmpFactory = { 0 };
242         struct HdfChipDriverManager *driverMgr = NULL;
243         driverMgr = HdfWlanGetChipDriverMgr();
244         if (driverMgr == NULL) {
245             HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
246             return HDF_FAILURE;
247         }
248         tmpFactory.driverName = HI3881_DRIVER_NAME;
249         tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount;
250         tmpFactory.InitChip = InitHi3881Chip;
251         tmpFactory.DeinitChip = DeinitHi3881Chip;
252         tmpFactory.Build = BuildHi3881Driver;
253         tmpFactory.Release = ReleaseHi3881Driver;
254         tmpFactory.ReleaseFactory = NULL;
255         if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) {
256             HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
257             return HDF_FAILURE;
258         }
259
260         return HDF_SUCCESS;
261     }
262
263     static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device)
264     {
265         (void)device;
266         return HDFWlanRegHisiDriverFactory();
267     }
268     ```
269
270     1. Initializing and deinitializing the chip
271
272      ```c
273      /* Function for initializing the WLAN chip. */
274      int32_t InitHi3881Chip(struct HdfWlanDevice *device)
275      {
276          uint8_t maxPortCount = 3;
277          int32_t ret = HI_SUCCESS;
278          uint8_t maxRetryCount = 3;
279          if (device == NULL || device->bus == NULL) {
280              HDF_LOGE("%s:NULL ptr!", __func__);
281              return HI_FAIL;
282          }
283
284          do {
285              if (ret != HI_SUCCESS) {
286                  if (device->reset != NULL && device->reset->Reset != NULL) {
287                      device->reset->Reset(device->reset);
288                  }
289                  HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret);
290              }
291              ret = hi_wifi_init(maxPortCount, device->bus);
292          } while (ret != 0 && --maxRetryCount > 0);
293
294          if (ret != 0) {
295              HDF_LOGE("%s:Init hi3881 driver failed!", __func__);
296              return ret;
297          }
298          return HI_SUCCESS;
299      }
300
301      /* Function for deinitializing the WLAN chip. */
302      int32_t DeinitHi3881Chip(struct HdfWlanDevice *device)
303      {
304          (void)device;
305          int32_t ret = hi_wifi_deinit();
306          if (ret != 0) {
307              HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret);
308          }
309          return ret;
310      }
311      ```
312
313     2. Initializing and deinitializing the chip driver
314
315      ```c
316      /* Hook the functions of the WLAN chip driver, mac80211, and chip. */
317      static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex)
318      {
319          struct HdfChipDriver *specificDriver = NULL;
320          if (device == NULL) {
321              HDF_LOGE("%s fail: channel is NULL!", __func__);
322              return NULL;
323          }
324          (void)ifIndex;
325          specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver));
326          if (specificDriver == NULL) {
327              HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__);
328              return NULL;
329          }
330          if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) {
331              HDF_LOGE("%s fail: memset_s fail!", __func__);
332              OsalMemFree(specificDriver);
333              return NULL;
334          }
335
336          if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) {
337              HDF_LOGE("%s fail: strcpy_s fail!", __func__);
338              OsalMemFree(specificDriver);
339              return NULL;
340          }
341          specificDriver->init = Hi3881Init;
342          specificDriver->deinit = Hi3881Deinit;
343
344          HiMac80211Init(specificDriver);
345
346          return specificDriver;
347      }
348
349      /* Release the WLAN chip driver. */
350      static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
351      {
352          if (chipDriver == NULL) {
353              return;
354          }
355          if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) {
356              HDF_LOGE("%s:Not my driver!", __func__);
357              return;
358          }
359          OsalMemFree(chipDriver);
360      }
361
362      /* Function for initializing the WLAN chip driver. */
363      int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
364      {
365          hi_u16 mode;
366          int32_t ret;
367          nl80211_iftype_uint8 type;
368          (void)chipDriver;
369          HDF_LOGI("%s: start...", __func__);
370          mode = wal_get_vap_mode();
371          if (mode >= WAL_WIFI_MODE_BUTT) {
372              oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode);
373              return HI_FAIL;
374          }
375          if (mode == WAL_WIFI_MODE_STA) {
376              type = NL80211_IFTYPE_STATION;
377      #ifdef _PRE_WLAN_FEATURE_P2P
378               if (InitNetdev(netDevice, NL80211_IFTYPE_P2P_DEVICE) != HI_SUCCESS) {
379                  return HI_FAIL;
380              }
381      #endif
382          } else if (mode == WAL_WIFI_MODE_AP) {
383              type = NL80211_IFTYPE_AP;
384          } else {
385              oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode);
386              return HI_FAIL;
387          }
388          ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice);
389          if (ret != HI_SUCCESS) {
390              oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret);
391          }
392          return ret;
393      }
394
395      /* Function for deinitializing the WLAN chip driver. */
396      int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
397      {
398          int32_t ret;
399          (void)chipDriver;
400          ret = DeinitNetdev(NL80211_IFTYPE_P2P_DEVICE);
401          if (ret != HI_SUCCESS) {
402              oam_error_log1(0, OAM_SF_ANY, "Hi3881Deinit: DeinitNetdev p2p device fail, ret = %d\n",  ret);
403              return ret;
404          }
405          return wal_deinit_drv_wlan_netdev(netDevice);
406      }
407
408      ```
409
410      During the chip initialization process, call **NetDeviceInit()** to initialize a network device, call **NetDeviceAdd()** to add the network device to a protocol stack, and hook function pointers of **netdev**.
411
412      ```c
413      hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, oal_net_device_stru *netdev)
414      {
415          hi_char *ac_mode_str = NULL;
416          hi_s32 ret;
417          if (oal_unlikely(netdev == HI_NULL)) {
418              oam_error_log0(0, OAM_SF_ANY, "{netdev is null!}");
419              return HI_ERR_CODE_PTR_NULL;
420          }
421
422          do {
423              /* Initialize the network device. */
424              ret = wal_init_netdev(type, netdev);
425              if (ret != HI_SUCCESS) {
426                  break;
427              }
428
429              ret = wal_init_netif(type, netdev);
430              if (ret != HI_SUCCESS) {
431                  break;
432              }
433              ac_mode_str = "11bgn";
434              if (mode == WAL_PHY_MODE_11G) {
435                  ac_mode_str = "11bg";
436              } else if (mode == WAL_PHY_MODE_11B) {
437                  ac_mode_str = "11b";
438              }
439
440              ret = wal_ioctl_set_mode(netdev, ac_mode_str);
441          } while (false);
442
443          if (ret != HI_SUCCESS) {
444              wal_deinit_wlan_vap(netdev);
445              oal_net_unregister_netdev(netdev);
446              oal_net_clear_netdev(netdev);
447              return HI_FAIL;
448          }
449
450          return HI_SUCCESS;
451      }
452
453      /* Hook function pointers of netdev. For details, see NetDeviceInterFace. */
454      oal_net_device_ops_stru g_wal_net_dev_ops =
455      {
456         .getStats          = wal_netdev_get_stats,
457         .open               = wal_netdev_open,
458         .stop               = wal_netdev_stop,
459         .xmit         = hmac_bridge_vap_xmit,
460         .ioctl           = wal_net_device_ioctl,
461         .changeMtu         = oal_net_device_change_mtu,
462         .init              = oal_net_device_init,
463         .deInit            = oal_net_free_netdev,
464
465         ......
466
467      };
468
469      hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev)
470      {
471          /* Add the network device to the protocol stack. */
472          hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type);
473
474          ......
475
476          return HI_SUCCESS;
477      }
478      ```
479
480#### Modifying the MAC Layer Interfaces
481
482   After the user-mode message is delivered to the driver, the driver calls the corresponding MAC-layer capability interfaces.
483
484   ```c
485   /* Define the functions for implementing the basic capabilities in the MAC layer for the driver. */
486   static struct HdfMac80211BaseOps g_baseOps = {
487       .SetMode = WalSetMode,
488       .AddKey = WalAddKey,
489       .DelKey = WalDelKey,
490       .SetDefaultKey = WalSetDefaultKey,
491       .GetDeviceMacAddr = WalGetDeviceMacAddr,
492       .SetMacAddr = WalSetMacAddr,
493       .SetTxPower = WalSetTxPower,
494       .GetValidFreqsWithBand = WalGetValidFreqsWithBand,
495       .GetHwCapability = WalGetHwCapability
496   };
497
498   /* Define the functions for implementing the STA capabilities in the MAC layer for the driver. */
499   static struct HdfMac80211STAOps g_staOps = {
500       .Connect = WalConnect,
501       .Disconnect = WalDisconnect,
502       .StartScan = WalStartScan,
503       .AbortScan = WalAbortScan,
504       .SetScanningMacAddress = WalSetScanningMacAddress,
505   };
506
507   /* Define the functions for implementing the AP capabilities in the MAC layer for the driver. */
508   static struct HdfMac80211APOps g_apOps = {
509       .ConfigAp = WalConfigAp,
510       .StartAp = WalStartAp,
511       .StopAp = WalStopAp,
512       .ConfigBeacon = WalChangeBeacon,
513       .DelStation = WalDelStation,
514       .SetCountryCode = WalSetCountryCode,
515       .GetAssociatedStasCount = WalGetAssociatedStasCount,
516       .GetAssociatedStasInfo = WalGetAssociatedStasInfo
517   };
518
519   static struct HdfMac80211P2POps g_p2pOps = {
520       .RemainOnChannel = WalRemainOnChannel,
521       .CancelRemainOnChannel = WalCancelRemainOnChannel,
522       .ProbeReqReport = WalProbeReqReport,
523       .AddIf = WalAddIf,
524       .RemoveIf = WalRemoveIf,
525       .SetApWpsP2pIe = WalSetApWpsP2pIe,
526       .GetDriverFlag = WalGetDriverFlag
527   };
528
529   /* Initialize mac80211 and hook functions of the chip. */
530   void HiMac80211Init(struct HdfChipDriver *chipDriver)
531   {
532       if (chipDriver == NULL) {
533           HDF_LOGE("%s:input is NULL!", __func__);
534           return;
535       }
536       chipDriver->ops = &g_baseOps;
537       chipDriver->staOps = &g_staOps;
538       chipDriver->apOps = &g_apOps;
539       chipDriver->p2pOps = &g_p2pOps;
540   }
541   ```
542
543#### Configuring Event Reporting
544
545   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.
546
547   ```c
548   hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len,
549       oal_station_info_stru *station_info, oal_gfp_enum_uint8 en_gfp)
550   {
551   #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX)
552       cfg80211_new_sta(net_device, mac_addr, station_info, en_gfp);
553       hi_unref_param(addr_len);
554   #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
555       struct StationInfo info = { 0 };
556       info.assocReqIes = station_info->assoc_req_ies;
557       info.assocReqIesLen = station_info->assoc_req_ies_len;
558       HdfWifiEventNewSta(net_device, mac_addr, WLAN_MAC_ADDR_LEN, &info);
559       hi_unref_param(en_gfp);
560       hi_unref_param(addr_len);
561   #endif
562
563       return HI_SUCCESS;
564   }
565   ```
566
567### Debugging and Verification
568
569#### Driver Adaptation Verification
570
571Develop 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.
572
5731. Set up the test environment.
574
575   - Create a **hostapd.conf** file (used to start the AP) and copy the following content to the file:
576
577        ```text
578        interface=wlan0
579        driver=hdf wifi
580        ctrl_interface=udp
581        #Wi-Fi name
582        ssid=test
583        hw_mode=g
584        channel=1
585        ignore_broadcast_ssid=0
586        wpa=2
587        rsn_pairwise=CCMP
588        # Wi-Fi password.
589        wpa_passphrase=12345678
590        ```
591
592    - Create a **wpa_supplicant.conf** file (used to start the STA) and copy the following content to the file:
593
594        ```text
595        country=GB
596
597        network={
598            #Hotspot name
599            ssid="test"
600            #Hotspot password
601            psk="12345678"
602        }
603        ```
604
605    - Create a **dhcpc.sh** file (used to write the IP address allocated by the udhcpc to the device) and copy the following content to the file:
606
607        ```shell
608        #!/system/bin/sh
609        [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
610
611        RESOLV_CONF="/etc/resolv.conf"
612        [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
613        [ -n "$subnet" ] && NETMASK="netmask $subnet"
614
615        case "$1" in
616            deconfig)
617            /system/bin/ifconfig $interface 0.0.0.0
618            ;;
619
620            renew|bound)
621            /system/bin/ifconfig $interface $ip $BROADCAST $NETMASK
622
623            if [ -n "$router" ] ; then
624                echo "deleting routers"
625                while busybox route del default gw 0.0.0.0 dev $interface ; do
626                :
627                done
628
629                for i in $router ; do
630                busybox route add default gw $i dev $interface
631                done
632            fi
633
634            echo -n > $RESOLV_CONF
635            [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
636            for i in $dns ; do
637                echo adding dns $i
638                echo nameserver $i >> $RESOLV_CONF
639            done
640            ;;
641        esac
642
643        exit 0
644        ```
645
646    - 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.
647
648        ```text
649        start 192.168.12.2
650        end 192.168.12.100
651        interface wlan0 #default: eth0
652        max_leases 20 #default: 254
653        remaining yes #default: yes
654        auto_time 7200 #default: 7200 (2 hours)
655        decline_time 3600 #default: 3600 (1 hour)
656        conflict_time 3600 #default: 3600 (1 hour)
657        offer_time 60 #default: 60 (1 minute)
658        min_lease 60 #defult: 60
659        lease_file /vendor/etc/udhcpd.leases
660        opt dns x.x.x.x x.x.x.x
661        option subnet 255.255.255.0
662        opt router 192.168.12.1
663        ```
664
665    - Run the following commands to push the files required for the test to the development board:
666
667        ```shell
668        hdc shell "mount -o rw,remount /"
669        timeout /T 1
670        hdc file send dhcpc.sh /system/lib/
671        hdc shell "chmod 777 /system/lib/dhcpc.sh"
672        hdc file send wpa_supplicant.conf /
673        hdc shell "mount -o rw,remount /vendor"
674        hdc file send hostapd.conf /
675        hdc file send udhcpd.conf /vendor/etc
676        hdc shell "touch /vendor/etc/udhcpd.leases"
677        hdc shell "chmod 777 /vendor/etc/udhcpd.leases"
678        ```
679
6802. Verify basic Wi-Fi features.
681
682   - Verify basic AP features.
683
684     1. Start the AP on the development board and enable Wi-Fi on the test terminal. For example, choose **Settings** > **WLAN** and turn on Wi-Fi on a mobile phone.
685
686     2. Run the following command in the **cmd** window:
687        ```shell
688        hdc shell
689        hostapd ./hostapd.conf
690        ```
691
692     3. Run the following commands in another **cmd** window:
693
694        ```shell
695        hdc shell
696        ifconfig wlan0 192.168.12.1 netmask 255.255.255.0
697        busybox udhcpd /vendor/etc/udhcpd.conf
698        ```
699
700     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.
701
702     5. Ping the test terminal from the development board.
703
704        ```shell
705        busybox ping xxx.xxx.xxx.xxx
706        ```
707
708        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.
709
710   - Verify basic STA functions
711
712     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**.)
713
714     2. Run the following command in the **cmd** window:
715
716        ```shell
717        hdc shell
718        wpa_supplicant -i wlan0 -d -c wpa_supplicant.conf
719        ```
720
721     3. Run the following commands in another **cmd** window:
722
723        ```shell
724        hdc shell
725        mount -o rw,remount /
726        mount -o rw,remount /vendor
727        busybox udhcpc -i wlan0 -s system/lib/dhcpc.sh
728        ```
729        The IP addresses of the board and test terminal are displayed if the command is successful.
730
731     4. Ping the test terminal from the development board.
732
733        ```shell
734        busybox ping xxx.xxx.xxx.xxx
735        ```
736
737        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.
738
739#### API Usage Example
740
741The WLAN Driver module provides two types of capability interfaces for the upper layer: HDI APIs and HAL APIs.
742- HDI API invocation
743
744   The following uses **GetSupportFeature** as an example to describe the development procedure:
745
746   1. Call **WlanInterfaceGetInstance()** to obtain a WLAN service instance.
747
748   2. Call **Start()** to create a channel between the HAL and the driver and obtain information about the driver network interface card (NIC).
749
750   3. Call **GetSupportFeature()** to obtain the WLAN features supported by the device.
751
752   4. Call **Stop()** to destroy the channel between the HAL and the driver
753
754   5. Call **WlanInterfaceRelease()** to destroy the WLAN service instance.
755
756   HDI API invocation development example:
757   ```c
758   #include "v1_0/iwlan_interface.h"
759   #include "wlan_callback_impl.h"
760   #include "wlan_impl.h"
761
762   #define PROTOCOL_80211_IFTYPE_NUM 11
763   #define HDF_SUCCESS 0
764   #define HDF_FAILURE (-1)
765
766   static int32_t hdi_main()
767   {
768       int32_t rc;
769       const char *WLAN_SERVICE_NAME = "wlan_hal_c_service";
770       static struct IWlanInterface *g_wlanObj = NULL;
771       uint8_t supType[PROTOCOL_80211_IFTYPE_NUM + 1] = {0};
772       uint32_t supTypeLen = PROTOCOL_80211_IFTYPE_NUM + 1;
773
774        /* Obtain the WLAN service instance. */
775        g_wlanObj = WlanInterfaceGetInstance(WLAN_SERVICE_NAME);
776        if (g_wlanObj == NULL)
777        {
778            return HDF_FAILURE;
779        }
780
781        /* Create a channel between the HAL and the driver and obtain the driver NIC information. */
782        rc = g_wlanObj->Start(g_wlanObj);
783        if (rc != HDF_SUCCESS)
784        {
785            return HDF_FAILURE;
786        }
787
788        /* Obtain the WLAN features supported by the device irrespective of the device status (AP, STA, or P2P).
789        rc = g_wlanObj->GetSupportFeature(g_wlanObj, supType, &supTypeLen);
790        if (rc != HDF_SUCCESS)
791        {
792            return HDF_FAILURE;
793        }
794
795        /* Destroy the channel between the HAL and the driver. */
796        rc = g_wlanObj->Stop(g_wlanObj);
797        if (rc != HDF_SUCCESS)
798        {
799            return HDF_FAILURE;
800        }
801
802        /* Destroy the WLAN service instance. */
803        rc = WlanInterfaceRelease(g_wlanObj);
804        if (rc != HDF_SUCCESS)
805        {
806            return HDF_FAILURE;
807        }
808        return rc;
809    }
810
811   ```
812
813   Building:
814
815   1. Add the dependent library file to the build script.
816
817      ```text
818      deps = [
819        "//drivers/peripheral/wlan/hdi_service:hdi_wlan_service",
820      ]
821      ```
822   2. Add the dependent header files to the build script.
823      ```text
824      include_dirs = [
825        "//drivers/peripheral/wlan/interfaces/include",
826        "//drivers/peripheral/wlan/hdi_service",
827        "//drivers/peripheral/wlan/client/include",
828        "//drivers/peripheral/wlan/hal/include",
829      ]
830      ```
831   3. Run the build script and check whether the build is successful.
832
833- HAL API invocation
834
835   To test a specified interface of the HAL module, perform the following steps:
836
837   1. Call **WifiConstruct()** to create an **IWiFi** instance.
838
839   2. Use the created **IWiFi** instance to call **start()** to create a channel between the HAL and the driver and obtain the driver NIC information.
840
841   3. Call **createFeature()** to create an **apFeature** or **staFeature**. These features can be used to invoke specific APIs. The following uses the **apFeature** instance as an example.
842
843   4. Call related APIs, for example, call **setMacAddress()** to set the MAC address and call **getDeviceMacAddress()** to obtain the device MAC address.
844
845   5. Call **destroyFeature()** to destroy the **apFeature** instance.
846
847   6. Call **Stop()** to destroy the channel between the HAL and the driver.
848
849   7. Call **WifiDestruct()** to destroy the **IWiFi** instance.
850
851   HAL API invocation development example:
852
853   ```c
854    #include "wifi_hal.h"
855    #include "wifi_hal_sta_feature.h"
856    #include "wifi_hal_ap_feature.h"
857    #include "wifi_hal_cmd.h"
858
859    #define MAC_LEN 6
860    #define HDF_SUCCESS 0
861    #define HDF_FAILURE (-1)
862
863    static int32_t hal_main()
864    {
865        int32_t ret;
866        struct IWiFi *wifi;
867        struct IWiFiAp *apFeature;
868
869        /* Create an IWiFi instance. */
870        ret = WifiConstruct(&wifi);
871        if (ret != HDF_SUCCESS || wifi == NULL) {
872            return HDF_FAILURE;
873        }
874
875        /* Create a channel between the HAL and the driver and obtain the driver NIC information. */
876        ret = wifi->start(wifi);
877        if (ret != HDF_SUCCESS) {
878            return HDF_FAILURE;
879        }
880
881        /* Create an apFeature instance. */
882        ret = wifi->createFeature(PROTOCOL_80211_IFTYPE_AP, (struct IWiFiBaseFeature **)&apFeature);
883        if (ret != HDF_SUCCESS) {
884            return HDF_FAILURE;
885        }
886
887        /* Obtain the MAC address of the device. */
888        unsigned char mac[MAC_LEN] = {0};
889        ret = apFeature->baseFeature.getDeviceMacAddress((struct IWiFiBaseFeature *)apFeature, mac, MAC_LEN);
890        if (ret != HDF_SUCCESS) {
891            return HDF_FAILURE;
892        }
893
894        /* Destroy the apFeature instance. */
895        ret = wifi->destroyFeature((struct IWiFiBaseFeature *)apFeature);
896        if (ret != HDF_SUCCESS) {
897            return HDF_FAILURE;
898        }
899
900        /* Destroy the channel between the HAL and the driver. */
901        ret = wifi->stop(wifi);
902        if (ret != HDF_SUCCESS) {
903            return HDF_FAILURE;
904        }
905
906        /* Destroy the IWiFi instance. */
907        ret = WifiDestruct(&wifi);
908        if (ret != HDF_SUCCESS) {
909            return HDF_FAILURE;
910        }
911        return ret;
912    }
913   ```
914   Building:
915   1. Add the dependent library file to the build script.
916
917      ```text
918      deps = [
919        "//drivers/peripheral/wlan/client:wifi_driver_client",
920        "//drivers/peripheral/wlan/hal:wifi_hal",
921      ]
922      ```
923
924   2. Add the dependent header files to the build script.
925      ```text
926      include_dirs = [
927        "//drivers/peripheral/wlan/interfaces/include",
928        "//drivers/peripheral/wlan/hdi_service",
929        "//drivers/peripheral/wlan/client/include",
930        "//drivers/peripheral/wlan/hal/include",
931      ]
932      ```
933   3. Run the build script and check whether the build is successful.
934
935
936
937
938## Reference
939
940- Code repositories:
941
942  **[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)**
943
944  [drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral)
945
946  [drivers\_interface](https://gitee.com/openharmony/drivers_interface)
947
948- Code paths:
949
950  Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi**
951
952  Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network**
953
954  Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver:
955
956  //drivers/hdf_core/adapter/khdf/linux/model/network/wifi
957
958  Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
959
960  External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
961
962  HDF network model APIs: **//drivers/hdf_core/framework/include/net**
963
964  WLAN HDI server implementation: **//drivers/peripheral/wlan**
965