• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# WLAN
2
3
4## Overview
5
6### WLAN
7
8The 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.
9
10### Working Principles
11
12You can modify your driver code based on the unified APIs provided by the WLAN module. The WLAN module provides:
13
14- 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.
15- 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.
16
17The 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).
18
19  **Figure 1** WLAN architecture
20
21  ![image](figures/WLAN_architecture.png "WLAN architecture")
22
23  The following figure shows the WLAN driver architecture.
24
25  **Figure 2** WLAN driver architecture
26
27  ![image](figures/WLAN_driver_architecture.png "WLAN driver architecture")
28
29The WLAN driver consists of the following modules:
30
311. 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.
32
332. WLAN Configuration Core: parses WLAN configuration files.
34
353. Access point (AP): allows devices to connect to the WLAN.
36
374. Station (STA): a device that has access to the WLAN system and allows transmission and reception of data.
38
395. mac80211: defines MAC-layer APIs for underlying drivers.
40
416. 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.
42
437. 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.
44
458. NetBuf: encapsulates the unified data structure of the Linux or LiteOS native network data buffer and the operation interfaces for network data.
46
479. FlowCtl: processes data based on the priority when the data volume is too large.
48
4910. HCC-CFG: configures WLAN parameters, including the board configuration, driver configuration, and module configuration.
50
51The relationships between the main modules are as follows:
52
531. The WLAN driver works with HCC-CFG and WLAN Configuration Core to parse and load configuration files.
54
552. The WLAN Message module distributes user-mode messages to the AP and STA by component.
56
573. Commands are delivered to mac80211, and then forwarded by the Bus module to the WLAN chip firmware.
58
594. The protocol stack works with the NetDevice, NetBuf, and FlowCtl modules to exchange data flows.
60
61## How to Develop
62
63### Available APIs
64
65The WLAN module provides the following types of APIs:
66
671. HDI and Hardware Abstraction Layer (HAL) APIs for upper-layer services
68
692. APIs for vendors
70
713. WLAN APIs directly called by drivers
72
73  **Figure 3** WLAN driver APIs
74
75  ![image](figures/WLAN_driver_APIs.png "WLAN Driver APIs")
76
77
78- The WLAN module provides HAL APIs for upper-layer services (applicable to small and mini systems). **Table 1** and **Table 2** describe some APIs.
79
80    **Table 1** wifi_hal.h
81
82  | API| Description|
83  | -------- | -------- |
84  | int32_t WifiConstruct(struct IWiFi \*\*wifiInstance)| Creates an **IWiFi** instance with basic capabilities.|
85  | int32_t WifiDestruct(struct IWiFi \*\*wifiInstance)| Destroys an **IWiFi** instance.|
86  | int32_t (\*start)(struct IWiFi \*)| Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.|
87  | int32_t (\*stop)(struct IWiFi \*)| Stops the channel between the HAL and the driver.|
88
89    **Table 2** wifi_hal_base_feature.h
90
91  | API| Description|
92  | -------- | -------- |
93  | int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*)| Obtains the feature type.|
94  | int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Sets the MAC address.|
95  | int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Obtains the device MAC address.|
96  | int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t)| Sets the transmit power.|
97
98- The WLAN Driver module also provides APIs that you need to fill in the implementation. **Table 3** describes some APIs.
99
100    **Table 3** net_device.h
101
102  | API| Description|
103  | -------- | -------- |
104  | int32_t (\*init)(struct NetDevice \*netDev)| Initializes a network device.|
105  | struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev)| Obtains the state of a network device.|
106  | int32_t (\*setMacAddr)(struct NetDevice \*netDev, void \*addr)| Sets the MAC address.|
107  | void (\*deInit)(struct NetDevice \*netDev)| Deinitializes a network device.|
108  | int32_t (\*open)(struct NetDevice \*netDev)| Opens a network device.|
109  | int32_t (\*stop)(struct NetDevice \*netDev)| Stops a network device.|
110
111- 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**.
112
113  The following tables describe the APIs.
114
115    **Table 4** wifi_module.h
116
117  | API| Description|
118  | -------- | -------- |
119  | struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config)| Creates a **WifiModule**.|
120  | void WifiModuleDelete(struct WifiModule \*module)| Deletes a **WifiModule** and releases its data.|
121  | int32_t DelFeature(struct WifiModule \*module, uint16_t featureType)| Deletes a feature from a **WifiModule**.|
122  | int32_t AddFeature(struct WifiModule \*module, uint16_t featureType,<br> struct WifiFeature \*featureData)| Adds a feature to a **WifiModule**.|
123
124    **Table 5** wifi_mac80211_ops.h
125
126  | API| Description|
127  | -------- | -------- |
128  | int32_t (\*startAp)(NetDevice \*netDev)| Starts an AP.|
129  | int32_t (\*stopAp)(NetDevice \*netDev)| Stops an AP.|
130  | int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param)| Connects to a hotspot.|
131  | int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode)| Disconnects from a hotspot.|
132
133    **Table 6** hdf_netbuf.h
134
135  | API| Description|
136  | -------- | -------- |
137  | static inline void NetBufQueueInit(struct NetBufQueue \*q)| Initializes a **NetBuf** queue.|
138  | struct NetBuf \*NetBufAlloc(uint32_t size)| Allocates a **NetBuf**.|
139  | void NetBufFree(struct NetBuf \*nb)| Releases a **NetBuf**.|
140  | struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf)| Converts the **pbuf** structure of lwIP to a **NetBuf**.|
141  | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb)| Converts a **NetBuf** to the **pbuf** structure of lwIP.|
142
143### Development Procedure
144#### WLAN Framework Adaptation
145
146The 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.
147**Development Procedure**
148
1491. 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.
150
1512. Implement initialization and deinitialization of the WLAN module (such as initialize and deinitialize the WLAN chip and WLAN chip driver).
152
1533. Implement the delivery of control flow commands.
154
1554. Implement event reporting.
156
157**Development Example**
158
159The following uses the Hi3881 WLAN chip as an example to describe how to initialize a WLAN module.
160
1611. Configure the HDF configuration source (HCS) for the driver.
162
163   The HCS includes device configuration and component configuration.
164
165   - Device configuration
166
167     The configuration file contains the power supply, reset, and bus configuration.
168
169     Configuration file path: **vendor/<vendor name>/<device name >/hdf_config/khdf/wifi**
170
171     Configure device parameters in **wlan_platform.hcs** based on the device you use. The following is an example of WLAN platform configuration.
172        ```text
173        hisi :& deviceList {
174            device0 :: deviceInst {
175                deviceInstId = 0;
176                powers {
177                    power0 {
178                        powerSeqDelay = 0;  /* Power sequence delay. */
179                        powerType = 1;      /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */
180                        gpioId = 1;         /* GPIO pin number. */
181                        activeLevel=1;      /* Active level. The value 0 indicates low level, and 1 indicates high level. */
182                    }
183                    power1 {
184                        powerSeqDelay = 0;  /* Power sequence delay. */
185                        powerType = 0;      /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */
186                    }
187                }
188                reset {
189                    resetType = 0;          /* Reset type. The value 0 indicates that reset is dynamically determined, and 1 indicates reset through GPIO. */
190                    gpioId = 2;             /* GPIO pin number. */
191                    activeLevel=1;          /* Active level. The value 0 indicates low level, and 1 indicates high level. */
192                    resetHoldTime = 30;     /* Hold time (ms) after a reset. */
193                }
194                bootUpTimeout = 30;         /* Boot timeout duration (ms). */
195                bus {
196                    busEnable = 1;          /* Whether to initialize the bus. The value 1 means to initialize the bus; the value 0 means the opposite. */
197                    busType = 0;            /* Bus type. The value 0 indicates SDIO. */
198                    busId = 2;              /* Bus number. */
199                    funcNum = [1];          /* SDIO function number. */
200                    timeout = 1000;         /* Timeout duration for data read/write. */
201                    blockSize = 512;        /* Size of the data block to read or write. */
202                }
203            }
204        }
205        ```
206   - Component configuration
207
208     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.
209        ```text
210        root {
211            wlan_config {
212                hi3881 :& chipList {
213                    chipHi3881 :: chipInst {
214                        match_attr = "hdf_wlan_chips_hi3881"; /* Attribute used to match the chip. */
215                        chipName = "hi3881";                  /* WLAN chip name. */
216                        bus {
217                            vendorId = 0x0296;                /* Vendor ID. */
218                            deviceId = [0x5347];              /* Device ID. */
219                        }
220                    }
221                }
222            }
223        }
224        ```
225
2262. Hook the **init** and **deinit** functions of the WLAN chip and WLAN chip driver.
227   - Implementing the driver adaptation entry function
228
229     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.
230     ```c
231     struct HdfDriverEntry g_hdfHisiChipEntry = {
232        .moduleVersion = 1,
233        .Bind = HdfWlanHisiDriverBind,
234        .Init = HdfWlanHisiChipDriverInit,
235        .Release = HdfWlanHisiChipRelease,
236        .moduleName = "HDF_WLAN_CHIPS"
237     };
238
239     HDF_INIT(g_hdfHisiChipEntry);
240     ```
241
242   - Registering the functions for initializing the chip and chip driver
243
244     Hook the chip initialization function to **InitChip()** and the chip deinitialization function to **DeinitChip()**.
245
246     Hook the chip driver initialization function to **Build()** and the chip driver deinitialization function to **Release()**.
247
248     ```c
249     /* Register WLAN chip functions. */
250     static int32_t HDFWlanRegHisiDriverFactory(void)
251     {
252         static struct HdfChipDriverFactory tmpFactory = { 0 };
253         struct HdfChipDriverManager *driverMgr = NULL;
254         driverMgr = HdfWlanGetChipDriverMgr();
255         if (driverMgr == NULL) {
256             HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
257             return HDF_FAILURE;
258         }
259         tmpFactory.driverName = HI3881_DRIVER_NAME;
260         tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount;
261         tmpFactory.InitChip = InitHi3881Chip;
262         tmpFactory.DeinitChip = DeinitHi3881Chip;
263         tmpFactory.Build = BuildHi3881Driver;
264         tmpFactory.Release = ReleaseHi3881Driver;
265         tmpFactory.ReleaseFactory = NULL;
266         if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) {
267             HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
268             return HDF_FAILURE;
269         }
270
271         return HDF_SUCCESS;
272     }
273
274     static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device)
275     {
276         (void)device;
277         return HDFWlanRegHisiDriverFactory();
278     }
279     ```
280
281   - Initializing and deinitializing the chip
282     ```c
283     /* Function for initializing the WLAN chip. */
284     int32_t InitHi3881Chip(struct HdfWlanDevice *device)
285     {
286         uint8_t maxPortCount = 3;
287         int32_t ret = HI_SUCCESS;
288         uint8_t maxRetryCount = 3;
289         if (device == NULL || device->bus == NULL) {
290             HDF_LOGE("%s:NULL ptr!", __func__);
291             return HI_FAIL;
292         }
293
294         do {
295             if (ret != HI_SUCCESS) {
296                 if (device->reset != NULL && device->reset->Reset != NULL) {
297                     device->reset->Reset(device->reset);
298                 }
299                 HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret);
300             }
301             ret = hi_wifi_init(maxPortCount, device->bus);
302         } while (ret != 0 && --maxRetryCount > 0);
303
304         if (ret != 0) {
305             HDF_LOGE("%s:Init hi3881 driver failed!", __func__);
306             return ret;
307         }
308         return HI_SUCCESS;
309     }
310
311     /* Function for deinitializing the WLAN chip. */
312     int32_t DeinitHi3881Chip(struct HdfWlanDevice *device)
313     {
314         (void)device;
315         int32_t ret = hi_wifi_deinit();
316         if (ret != 0) {
317             HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret);
318         }
319         return ret;
320     }
321     ```
322   - Initializing and deinitializing the chip driver
323     ```c
324     /* Hook the functions of the WLAN chip driver, mac80211, and chip. */
325     static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex)
326     {
327         struct HdfChipDriver *specificDriver = NULL;
328         if (device == NULL) {
329             HDF_LOGE("%s fail: channel is NULL!", __func__);
330             return NULL;
331         }
332         (void)ifIndex;
333         specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver));
334         if (specificDriver == NULL) {
335             HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__);
336             return NULL;
337         }
338         if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) {
339             HDF_LOGE("%s fail: memset_s fail!", __func__);
340             OsalMemFree(specificDriver);
341             return NULL;
342         }
343
344         if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) {
345             HDF_LOGE("%s fail: strcpy_s fail!", __func__);
346             OsalMemFree(specificDriver);
347             return NULL;
348         }
349         specificDriver->init = Hi3881Init;
350         specificDriver->deinit = Hi3881Deinit;
351
352         HiMac80211Init(specificDriver);
353
354         return specificDriver;
355     }
356
357     /* Release the WLAN chip driver. */
358     static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
359     {
360         if (chipDriver == NULL) {
361             return;
362         }
363         if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) {
364             HDF_LOGE("%s:Not my driver!", __func__);
365             return;
366         }
367         OsalMemFree(chipDriver);
368     }
369
370     /* Function for initializing the WLAN chip driver. */
371     int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
372     {
373         hi_u16 mode;
374         int32_t ret;
375         nl80211_iftype_uint8 type;
376         (void)chipDriver;
377         HDF_LOGI("%s: start...", __func__);
378         mode = wal_get_vap_mode();
379         if (mode >= WAL_WIFI_MODE_BUTT) {
380             oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode);
381             return HI_FAIL;
382         }
383         if (mode == WAL_WIFI_MODE_STA) {
384             type = NL80211_IFTYPE_STATION;
385     #ifdef _PRE_WLAN_FEATURE_P2P
386             if (InitNetdev(netDevice, NL80211_IFTYPE_P2P_DEVICE) != HI_SUCCESS) {
387                 return HI_FAIL;
388             }
389     #endif
390         } else if (mode == WAL_WIFI_MODE_AP) {
391             type = NL80211_IFTYPE_AP;
392         } else {
393             oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode);
394             return HI_FAIL;
395         }
396         ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice);
397         if (ret != HI_SUCCESS) {
398             oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret);
399         }
400         return ret;
401     }
402
403     /* Function for deinitializing the WLAN chip driver. */
404     int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
405     {
406         int32_t ret;
407         (void)chipDriver;
408         ret = DeinitNetdev(NL80211_IFTYPE_P2P_DEVICE);
409         if (ret != HI_SUCCESS) {
410             oam_error_log1(0, OAM_SF_ANY, "Hi3881Deinit: DeinitNetdev p2p device fail, ret = %d\n",  ret);
411             return ret;
412         }
413         return wal_deinit_drv_wlan_netdev(netDevice);
414     }
415
416     ```
417
418     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**.
419
420     ```c
421     hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, oal_net_device_stru *netdev)
422     {
423         hi_char *ac_mode_str = NULL;
424         hi_s32 ret;
425         if (oal_unlikely(netdev == HI_NULL)) {
426             oam_error_log0(0, OAM_SF_ANY, "{netdev is null!}");
427             return HI_ERR_CODE_PTR_NULL;
428         }
429
430         do {
431             /* Initialize the network device. */
432             ret = wal_init_netdev(type, netdev);
433             if (ret != HI_SUCCESS) {
434                 break;
435             }
436
437             ret = wal_init_netif(type, netdev);
438             if (ret != HI_SUCCESS) {
439                 break;
440             }
441             ac_mode_str = "11bgn";
442             if (mode == WAL_PHY_MODE_11G) {
443                 ac_mode_str = "11bg";
444             } else if (mode == WAL_PHY_MODE_11B) {
445                 ac_mode_str = "11b";
446             }
447
448             ret = wal_ioctl_set_mode(netdev, ac_mode_str);
449         } while (false);
450
451         if (ret != HI_SUCCESS) {
452             wal_deinit_wlan_vap(netdev);
453             oal_net_unregister_netdev(netdev);
454             oal_net_clear_netdev(netdev);
455             return HI_FAIL;
456         }
457
458         return HI_SUCCESS;
459     }
460
461     /* Hook function pointers of netdev. For details, see NetDeviceInterFace. */
462     oal_net_device_ops_stru g_wal_net_dev_ops =
463     {
464        .getStats          = wal_netdev_get_stats,
465        .open               = wal_netdev_open,
466        .stop               = wal_netdev_stop,
467        .xmit         = hmac_bridge_vap_xmit,
468        .ioctl           = wal_net_device_ioctl,
469        .changeMtu         = oal_net_device_change_mtu,
470        .init              = oal_net_device_init,
471        .deInit            = oal_net_free_netdev,
472
473        ...
474
475     };
476
477     hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev)
478     {
479         /* Add the network device to the protocol stack. */
480         hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type);
481
482         ...
483
484         return HI_SUCCESS;
485     }
486     ```
487
4883. 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.
489
490    ```c
491    /* Implement the basic capabilities of the MAC layer. */
492    static struct HdfMac80211BaseOps g_baseOps = {
493        .SetMode = WalSetMode,
494        .AddKey = WalAddKey,
495        .DelKey = WalDelKey,
496        .SetDefaultKey = WalSetDefaultKey,
497        .GetDeviceMacAddr = WalGetDeviceMacAddr,
498        .SetMacAddr = WalSetMacAddr,
499        .SetTxPower = WalSetTxPower,
500        .GetValidFreqsWithBand = WalGetValidFreqsWithBand,
501        .GetHwCapability = WalGetHwCapability
502    };
503
504    /* Implement the STA capabilities of the MAC layer. */
505    static struct HdfMac80211STAOps g_staOps = {
506        .Connect = WalConnect,
507        .Disconnect = WalDisconnect,
508        .StartScan = WalStartScan,
509        .AbortScan = WalAbortScan,
510        .SetScanningMacAddress = WalSetScanningMacAddress,
511    };
512
513    /* Implement the AP capabilities of the MAC layer. */
514    static struct HdfMac80211APOps g_apOps = {
515        .ConfigAp = WalConfigAp,
516        .StartAp = WalStartAp,
517        .StopAp = WalStopAp,
518        .ConfigBeacon = WalChangeBeacon,
519        .DelStation = WalDelStation,
520        .SetCountryCode = WalSetCountryCode,
521        .GetAssociatedStasCount = WalGetAssociatedStasCount,
522        .GetAssociatedStasInfo = WalGetAssociatedStasInfo
523    };
524
525    static struct HdfMac80211P2POps g_p2pOps = {
526        .RemainOnChannel = WalRemainOnChannel,
527        .CancelRemainOnChannel = WalCancelRemainOnChannel,
528        .ProbeReqReport = WalProbeReqReport,
529        .AddIf = WalAddIf,
530        .RemoveIf = WalRemoveIf,
531        .SetApWpsP2pIe = WalSetApWpsP2pIe,
532        .GetDriverFlag = WalGetDriverFlag
533    };
534
535    /* Initialize mac80211 and hook functions of the chip. */
536    void HiMac80211Init(struct HdfChipDriver *chipDriver)
537    {
538        if (chipDriver == NULL) {
539            HDF_LOGE("%s:input is NULL!", __func__);
540            return;
541        }
542        chipDriver->ops = &g_baseOps;
543        chipDriver->staOps = &g_staOps;
544        chipDriver->apOps = &g_apOps;
545        chipDriver->p2pOps = &g_p2pOps;
546    }
547    ```
548
5494. 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.
550
551    ```c
552    hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len,
553        oal_station_info_stru *station_info, oal_gfp_enum_uint8 en_gfp)
554    {
555    #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX)
556        cfg80211_new_sta(net_device, mac_addr, station_info, en_gfp);
557        hi_unref_param(addr_len);
558    #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
559        struct StationInfo info = { 0 };
560        info.assocReqIes = station_info->assoc_req_ies;
561        info.assocReqIesLen = station_info->assoc_req_ies_len;
562        HdfWifiEventNewSta(net_device, mac_addr, WLAN_MAC_ADDR_LEN, &info);
563        hi_unref_param(en_gfp);
564        hi_unref_param(addr_len);
565    #endif
566
567        return HI_SUCCESS;
568    }
569    ```
570**Verification**
571
572Develop 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.
573
5741. Set up the test environment.
575
576   - Create a **hostapd.conf** file (used to start the AP) and copy the following content to the file:
577
578        ```text
579        interface=wlan0
580        driver=hdf wifi
581        ctrl_interface=udp
582        #Wi-Fi name
583        ssid=test
584        hw_mode=g
585        channel=1
586        ignore_broadcast_ssid=0
587        wpa=2
588        rsn_pairwise=CCMP
589        # Wi-Fi password.
590        wpa_passphrase=12345678
591        ```
592
593    - Create a **wpa_supplicant.conf** file (used to start the STA) and copy the following content to the file:
594
595        ```text
596        country=GB
597
598        network={
599            #Hotspot name
600            ssid="test"
601            #Hotspot password
602            psk="12345678"
603        }
604        ```
605
606    - 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:
607
608        ```shell
609        #!/system/bin/sh
610        [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
611
612        RESOLV_CONF="/etc/resolv.conf"
613        [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
614        [ -n "$subnet" ] && NETMASK="netmask $subnet"
615
616        case "$1" in
617            deconfig)
618            /system/bin/ifconfig $interface 0.0.0.0
619            ;;
620
621            renew|bound)
622            /system/bin/ifconfig $interface $ip $BROADCAST $NETMASK
623
624            if [ -n "$router" ] ; then
625                echo "deleting routers"
626                while busybox route del default gw 0.0.0.0 dev $interface ; do
627                :
628                done
629
630                for i in $router ; do
631                busybox route add default gw $i dev $interface
632                done
633            fi
634
635            echo -n > $RESOLV_CONF
636            [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
637            for i in $dns ; do
638                echo adding dns $i
639                echo nameserver $i >> $RESOLV_CONF
640            done
641            ;;
642        esac
643
644        exit 0
645        ```
646
647    -  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.
648
649        ```text
650        start 192.168.12.2
651        end 192.168.12.100
652        interface wlan0 #default: eth0
653        max_leases 20 #default: 254
654        remaining yes #default: yes
655        auto_time 7200 #default: 7200 (2 hours)
656        decline_time 3600 #default: 3600 (1 hour)
657        conflict_time 3600 #default: 3600 (1 hour)
658        offer_time 60 #default: 60 (1 minute)
659        min_lease 60 #defult: 60
660        lease_file /vendor/etc/udhcpd.leases
661        opt dns x.x.x.x x.x.x.x
662        option subnet 255.255.255.0
663        opt router 192.168.12.1
664        ```
665
666    - Run the following commands to push the files required for the test to the development board:
667
668        ```shell
669        hdc shell "mount -o rw,remount /"
670        timeout /T 1
671        hdc file send dhcpc.sh /system/lib/
672        hdc shell "chmod 777 /system/lib/dhcpc.sh"
673        hdc file send wpa_supplicant.conf /
674        hdc shell "mount -o rw,remount /vendor"
675        hdc file send hostapd.conf /
676        hdc file send udhcpd.conf /vendor/etc
677        hdc shell "touch /vendor/etc/udhcpd.leases"
678        hdc shell "chmod 777 /vendor/etc/udhcpd.leases"
679        ```
680
6812. Verify basic Wi-Fi features.
682
683   - Verify basic AP features.
684
685     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.
686
687     2. Run the following command in the **cmd** window:
688        ```shell
689        hdc shell
690        hostapd ./hostapd.conf
691        ```
692
693     3. Run the following commands in another **cmd** window:
694
695        ```shell
696        hdc shell
697        ifconfig wlan0 192.168.12.1 netmask 255.255.255.0
698        busybox udhcpd /vendor/etc/udhcpd.conf
699        ```
700
701     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.
702
703     5. Ping the test terminal from the development board.
704
705        ```shell
706        busybox ping xxx.xxx.xxx.xxx
707        ```
708
709        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.
710
711   - Verify basic STA features.
712
713     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**.
714
715     2. Run the following command in the **cmd** window:
716
717        ```shell
718        hdc shell
719        wpa_supplicant -i wlan0 -d -c wpa_supplicant.conf
720        ```
721
722     3. Run the following commands in another **cmd** window:
723
724        ```shell
725        hdc shell
726        mount -o rw,remount /
727        mount -o rw,remount /vendor
728        busybox udhcpc -i wlan0 -s system/lib/dhcpc.sh
729        ```
730        The IP addresses of the board and test terminal are displayed if the command is successful.
731
732     4. Ping the test terminal from the development board.
733
734        ```shell
735        busybox ping xxx.xxx.xxx.xxx
736        ```
737
738        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.
739
740#### **API Invocation**
741The WLAN driver module provides two types of capability interfaces for the upper layer: HDI interface and HAL interface.
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   The sample code is as follows:
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   The sample code is as follows:
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: **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi**
955
956  Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi**
957
958  External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi**
959
960  HDF network model APIs: **//drivers/hdf_core/framework/include/net**
961
962  WLAN HDI server implementation: **//drivers/peripheral/wlan**
963
964