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