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 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 AddFeature(struct WifiModule \*module, uint16_t featureType,<br> struct WifiFeature \*featureData) | Adds a feature to a **WifiModule**.| 125 126 **Table 5** wifi_mac80211_ops.h 127 128 | API| Description| 129 | -------- | -------- | 130 | int32_t (\*startAp)(NetDevice \*netDev) | Starts an AP.| 131 | int32_t (\*stopAp)(NetDevice \*netDev) | Stops an AP.| 132 | int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param) | Connects to a hotspot.| 133 | int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode) | Disconnects from a hotspot.| 134 135 **Table 6** hdf_netbuf.h 136 137 | API| Description| 138 | -------- | -------- | 139 | static inline void NetBufQueueInit(struct NetBufQueue \*q) | Initializes a **NetBuf** queue.| 140 | struct NetBuf \*NetBufAlloc(uint32_t size) | Allocates a **NetBuf**.| 141 | void NetBufFree(struct NetBuf \*nb) | Releases a **NetBuf**.| 142 | struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | Converts the **pbuf** structure of lwIP to a **NetBuf**.| 143 | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*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