diff --git a/en/device-dev/driver/driver-peripherals-external-des.md b/en/device-dev/driver/driver-peripherals-external-des.md index 4c75f57c50e2ad762001fbce49128f66c3bcf6c7..9435835d0393685b2d6af55c5dde3cd5ab424df2 100644 --- a/en/device-dev/driver/driver-peripherals-external-des.md +++ b/en/device-dev/driver/driver-peripherals-external-des.md @@ -64,491 +64,929 @@ The relationships between the main modules are as follows: The WLAN module provides the following types of APIs: -- WLAN APIs that can be directly called by drivers +1. Hardware Device Interface (HDI) and Hardware Abstraction Layer (HAL) APIs for upper-layer services -- APIs for vendors - -- APIs for the HDI layer +2. APIs for vendors +3. WLAN APIs directly called by drivers **Figure 3** WLAN driver APIs ![image](figures/WLAN_driver_APIs.png "WLAN Driver APIs") -- 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**. - - Tables 1 to 3 describe these APIs. +- The WLAN module provides HDI APIs for upper-layer services (applicable to the standard system). **Table 1** describes the major APIs. - **Table 1** wifi_module.h (HDF-based WLAN driver development) + **Table 1** IWlanInterface.idl | API| Description| | -------- | -------- | - | struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config) | Creates a **WifiModule**.| - | void WifiModuleDelete(struct WifiModule \*module) | Deletes a **WifiModule** and releases its data.| - | int32_t DelFeature(struct WifiModule \*module, uint16_t featureType) | Deletes a feature from a **WifiModule**.| - | int32_t AddFeature(struct WifiModule \*module, uint16_t featureType, struct WifiFeature \*featureData) | Adds a feature to a **WifiModule**.| + | CreateFeature([in] int type, [out] struct HdfFeatureInfo ifeature);| Creates an **ifeature** instance.| + | DestroyFeature([in] struct HdfFeatureInfo ifeature);| Destroys an **ifeature** instance.| + | GetPowerMode([in] struct HdfFeatureInfo ifeature, [out] unsigned char mode);| Obtains the power mode.| + | SetPowerMode([in] struct HdfFeatureInfo ifeature, [in] unsigned char mode);| Sets the power mode.| - **Table 2** wifi_mac80211_ops.h +- The WLAN module provides HAL APIs for upper-layer services (applicable to small and mini systems). **Table 2** and **Table 3** describe some APIs. + + **Table 2** wifi_hal.h | API| Description| | -------- | -------- | - | int32_t (\*startAp)(NetDevice \*netDev) | Starts an AP.| - | int32_t (\*stopAp)(NetDevice \*netDev) | Stops an AP.| - | int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param) | Connects to a hotspot.| - | int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode) | Disconnects from a hotspot.| + | int32_t WifiConstruct(struct IWiFi \*\*wifiInstance)| Creates an **IWiFi** instance with basic capabilities.| + | int32_t WifiDestruct(struct IWiFi \*\*wifiInstance)| Destroys an **IWiFi** instance.| + | int32_t (\*start)(struct IWiFi \*)| Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.| + | int32_t (\*stop)(struct IWiFi \*)| Stops the channel between the HAL and the driver.| - **Table 3** hdf_netbuf.h + **Table 3** wifi_hal_base_feature.h | API| Description| | -------- | -------- | - | static inline void NetBufQueueInit(struct NetBufQueue \*q) | Initializes a **NetBuf** queue.| - | struct NetBuf \*NetBufAlloc(uint32_t size) | Allocates a **NetBuf**.| - | void NetBufFree(struct NetBuf \*nb) | Releases a **NetBuf**.| - | struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | Converts the **pbuf** structure of lwIP to a **NetBuf**.| - | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | Converts a **NetBuf** to the **pbuf** structure of lwIP.| + | int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*)| Obtains the feature type.| + | int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Sets the MAC address.| + | int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t)| Obtains the device MAC address.| + | int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t)| Sets the transmit power.| -- The WLAN Driver module also provides APIs that you need to fill in the implementation. This type of APIs can be used to initialize/deinitialize a **NetDevice**, opening/stopping a **NetDevice**, and obtaining the **NetDevice** status. Table 4 describes some of these APIs. +- The WLAN Driver module also provides APIs that you need to fill in the implementation. **Table 4** describes some APIs. **Table 4** net_device.h | API| Description| | -------- | -------- | - | int32_t (\*init)(struct NetDevice \*netDev) | Initializes a **NetDevice**.| - | struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev) | Obtains the state of a **NetDevice**.| + | int32_t (\*init)(struct NetDevice \*netDev) | Initializes a network device.| + | struct NetDevStats \*(\*getStats)(struct NetDevice \*netDev) | Obtains the state of a network device.| | int32_t (\*setMacAddr)(struct NetDevice \*netDev, void \*addr) | Sets the MAC address.| - | void (\*deInit)(struct NetDevice \*netDev) | Deinitializes a **NetDevice**.| - | int32_t (\*open)(struct NetDevice \*netDev) | Opens a **NetDevice**.| - | int32_t (\*stop)(struct NetDevice \*netDev) | Stops a **NetDevice**.| + | void (\*deInit)(struct NetDevice \*netDev) | Deinitializes a network device.| + | int32_t (\*open)(struct NetDevice \*netDev) | Opens a network device.| + | int32_t (\*stop)(struct NetDevice \*netDev) | Stops a network device.| -- The WLAN Driver module also provides APIs to the HDI layer for creating and destroying an **IWiFi** object and setting the MAC address. Tables 5 and 6 describe some of the APIs. +- 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**. - **Table 5** wifi_hal.h + Tables 5 to 7 describe the APIs. + + **Table 5** wifi_module.h | API| Description| | -------- | -------- | - | int32_t WifiConstruct(struct IWiFi \*\*wifiInstance) | Creates an **IWiFi** object with basic capabilities.| - | int32_t WifiDestruct(struct IWiFi \*\*wifiInstance) | Destroys an **IWiFi** object.| - | int32_t (\*start)(struct IWiFi \*) | Creates a channel between the HAL and the driver and obtains the NICs supported by the driver.| - | int32_t (\*stop)(struct IWiFi \*) | Stops the channel between the HAL and the driver.| + | struct WifiModule \*WifiModuleCreate(const struct HdfConfigWifiModuleConfig \*config) | Creates a **WifiModule**.| + | void WifiModuleDelete(struct WifiModule \*module) | Deletes a **WifiModule** and releases its data.| + | int32_t DelFeature(struct WifiModule \*module, uint16_t featureType) | Deletes a feature from a **WifiModule**.| + | int32_t AddFeature(struct WifiModule \*module, uint16_t featureType, struct WifiFeature \*featureData) | Adds a feature to a **WifiModule**.| - **Table 6** wifi_hal_base_feature.h + **Table 6** wifi_mac80211_ops.h | API| Description| | -------- | -------- | - | int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*) | Obtains the feature type.| - | int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Sets the MAC address.| - | int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | Obtains the device MAC address.| - | int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t) | Sets the transmit power.| + | int32_t (\*startAp)(NetDevice \*netDev) | Starts an AP.| + | int32_t (\*stopAp)(NetDevice \*netDev) | Stops an AP.| + | int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param) | Connects to a hotspot.| + | int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode) | Disconnects from a hotspot.| + **Table 7** hdf_netbuf.h + + | API| Description| + | -------- | -------- | + | static inline void NetBufQueueInit(struct NetBufQueue \*q) | Initializes a **NetBuf** queue.| + | struct NetBuf \*NetBufAlloc(uint32_t size) | Allocates a **NetBuf**.| + | void NetBufFree(struct NetBuf \*nb) | Releases a **NetBuf**.| + | struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | Converts the **pbuf** structure of lwIP to a **NetBuf**.| + | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | Converts a **NetBuf** to the **pbuf** structure of lwIP.| ### How to Develop The WLAN driver module developed based on the HDF and Platform frameworks provides a unified driver model for WLAN modules of different vendors regardless of the OS and system on a chip (SoC). + 1. Configure hardware (such as modules and chips) parameters in the **wlan_platform.hcs** file. This file can be parsed by the APIs in the HDF to generate structure objects with full configuration. -1. Configure hardware (such as modules and chips) parameters in the **wifi_config.hcs** file. This configuration file is parsed by the corresponding API in the HDF to generate a structure object for full configuration. - -2. Initialize and create a module. + 2. Implement initialization and deinitialization of the WLAN module (such as initialize and deinitialize the WLAN chip and WLAN chip driver). -3. Attach and initialize the chip. + 3. Implement the delivery of control flow commands. -4. Implement the upper-layer Wi-Fi Protected Access (WPA) service. + 4. Implement event reporting. ### Development Example -This example describes how to initialize a WLAN module. The following uses the Hi3881 WLAN chip as an example: - - 1. Set parameters for the WLAN module based on hardware attributes. - -``` -/* Set parameters in the wlan_platform.hcs file based on hardware attributes. The following is an example of the WLAN platform configuration. */ -hisi :& deviceList { - device0 :: deviceInst { - deviceInstId = 0; - powers { - power0 { - powerSeqDelay = 0; /* Power sequence delay. */ - powerType = 1; /* Power supply type. The value 0 indicates that the device is always powered on, and 1 indicates power supply through general-purpose input/output (GPIO). */ - gpioId = 1; /* GPIO pin number. */ - activeLevel=1; /* Active level. The value 0 indicates low level, and 1 indicates high level. */ +The following uses the Hi3881 WLAN chip as an example to describe how to initialize a WLAN module. + +1. Configure hardware parameters. + + ```text + /* Configure parameters in wlan_platform.hcs based on the hardware you use. The following is an example of WLAN platform configuration. */ + hisi :& deviceList { + device0 :: deviceInst { + deviceInstId = 0; + powers { + power0 { + powerSeqDelay = 0; /* Power sequence delay. */ + powerType = 1; /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */ + gpioId = 1; /* GPIO pin number. */ + activeLevel=1; /* Active level. The value 0 indicates low level, and 1 indicates high level. */ + } + power1 { + powerSeqDelay = 0; /* Power sequence delay. */ + powerType = 0; /* Power supply type. The value 0 indicates that the device is always on. The value 1 indicates power supply through GPIO. */ + } } - power1 { - powerSeqDelay = 0; /* Power sequence delay. */ - powerType = 0; /* The value 0 indicates that the device is always powered on, and 1 indicates power supply through GPIO. */ + reset { + resetType = 0; /* Reset type. The value 0 indicates that reset is dynamically determined, and 1 indicates reset through GPIO. */ + gpioId = 2; /* GPIO pin number. */ + activeLevel=1; /* Active level. The value 0 indicates low level, and 1 indicates high level. */ + resetHoldTime = 30; /* Hold time (ms) after a reset. */ + } + bootUpTimeout = 30; /* Boot timeout duration (ms). */ + bus { + busEnable = 1; /* Whether to initialize the bus. The value 1 means to initialize the bus; the value 0 means the opposite. */ + busType = 0; /* Bus type. The value 0 indicates SDIO. */ + busId = 2; /* Bus number. */ + funcNum = [1]; /* SDIO function number. */ + timeout = 1000; /* Timeout duration for data read/write. */ + blockSize = 512; /* Size of the data block to read or write. */ } - } - reset { - resetType = 0; /* Reset type. The value 0 indicates that reset is dynamically determined, and value 1 indicates reset through GPIO. */ - gpioId = 2; /* GPIO pin number. */ - activeLevel=1; /* Active level. The value 0 indicates low level, and 1 indicates high level. */ - resetHoldTime = 30; /* Hold time (ms) after a reset. */ - } - bootUpTimeout = 30; /* Boot timeout duration (ms). */ - bus { - busType = 0; /* Bus type. The value 0 indicates SDIO. */ - busId = 2; /* Bus number. */ - funcNum = [1]; /* SDIO function number. */ - timeout = 1000; /* Timeout duration for data read/write. */ - blockSize = 512; /* Size of the data block to read or write. */ } } -} -/* Add the configuration file wlan_chip_.hcs (for example, wlan_chip_hi3881.hcs) for each chip and set parameters. The following uses the Hi3881 chip as an example. */ -root { - wlan_config { - hi3881 :& chipList { - chipHi3881 :: chipInst { - match_attr = "hdf_wlan_chips_hi3881"; /* Attribute used to match the chip. */ - chipName = "hi3881"; /* WLAN chip name. */ - sdio { - vendorId = 0x0296; /* Vendor ID. */ - deviceId = [0x5347]; /* Device ID. */ + /* Add the configuration file wlan_chip_.hcs (for example, wlan_chip_hi3881.hcs) for each chip and set parameters. The following uses the Hi3881 chip as an example. */ + root { + wlan_config { + hi3881 :& chipList { + chipHi3881 :: chipInst { + match_attr = "hdf_wlan_chips_hi3881"; /* Attribute used to match the chip. */ + chipName = "hi3881"; /* WLAN chip name. */ + bus { + vendorId = 0x0296; /* Vendor ID. */ + deviceId = [0x5347]; /* Device ID. */ + } } } } } -} -``` - - 2. Hook the **init** and **deinit** functions of the WLAN chip and WLAN chip driver. - -``` -/* Process of implementing WLAN module initialization. */ -#include "hdf_device_desc.h" -#include "hdf_wifi_product.h" -#include "hdf_log.h" -#include "osal_mem.h" -#include "hdf_wlan_chipdriver_manager.h" -#include "securec.h" -#include "wifi_module.h" -#include "hi_wifi_api.h" -#include "hi_types_base.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* Functions for initializing and deinitializing a WLAN chip. */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device); -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); -/* Functions for initializing and deinitializing a WLAN chip driver. */ -int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); -int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); - -/* Initialize mac80211 by hooking the functions of the chip. */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); - -static const char* const HI3881_DRIVER_NAME = "hisi"; - -/* Hook the functions of the WLAN chip driver, mac80211, and chip. */ -static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) -{ - struct HdfChipDriver *specificDriver = NULL; - if (device == NULL) { - HDF_LOGE("%s fail : channel is NULL", __func__); - return NULL; - } - (void)device; - (void)ifIndex; - specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); - if (specificDriver == NULL) { - HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); - return NULL; - } - if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { - HDF_LOGE("%s fail: memset_s fail!", __func__); - OsalMemFree(specificDriver); - return NULL; - } - - if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { - HDF_LOGE("%s fail : strcpy_s fail", __func__); - OsalMemFree(specificDriver); - return NULL; - } - specificDriver->init = Hi3881Init; - specificDriver->deinit = Hi3881Deinit; + ``` + +2. Hook the **init** and **deinit** functions of the WLAN chip and WLAN chip driver. + + ```c + #include "hdf_device_desc.h" + #include "hdf_wifi_product.h" + #include "hdf_log.h" + #include "osal_mem.h" + #include "hdf_wlan_chipdriver_manager.h" + #include "securec.h" + #include "wifi_module.h" + #include "hi_wifi_api.h" + #include "hi_types_base.h" + + #define HDF_LOG_TAG Hi3881Driver + + /* Functions for initializing and deinitializing a WLAN chip. */ + int32_t InitHi3881Chip(struct HdfWlanDevice *device); + int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); + /* Functions for initializing and deinitializing a WLAN chip driver. */ + int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); + int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); + + /* Initialize mac80211 by hooking the functions of the chip. */ + hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); + + static const char* const HI3881_DRIVER_NAME = "hisi"; + + /* Hook the functions of the WLAN chip driver, mac80211, and chip. */ + static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) + { + struct HdfChipDriver *specificDriver = NULL; + if (device == NULL) { + HDF_LOGE("%s fail: channel is NULL!", __func__); + return NULL; + } + (void)ifIndex; + specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); + if (specificDriver == NULL) { + HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); + return NULL; + } + if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { + HDF_LOGE("%s fail: memset_s fail!", __func__); + OsalMemFree(specificDriver); + return NULL; + } - HiMac80211Init(specificDriver); + if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { + HDF_LOGE("%s fail: strcpy_s fail!", __func__); + OsalMemFree(specificDriver); + return NULL; + } + specificDriver->init = Hi3881Init; + specificDriver->deinit = Hi3881Deinit; - return specificDriver; -} + HiMac80211Init(specificDriver); -/* Release the WLAN chip driver. */ -static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - return; + return specificDriver; } - if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { - HDF_LOGE("%s:Not my driver!", __func__); - return; + + /* Release the WLAN chip driver. */ + static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) + { + if (chipDriver == NULL) { + return; + } + if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { + HDF_LOGE("%s:Not my driver!", __func__); + return; + } + OsalMemFree(chipDriver); } - OsalMemFree(chipDriver); -} - -static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { - (void)factory; - return 1; -} - -/* Register WLAN chip functions. */ -static int32_t HDFWlanRegHisiDriverFactory(void) -{ - static struct HdfChipDriverFactory tmpFactory = { 0 }; - struct HdfChipDriverManager *driverMgr = NULL; - driverMgr = HdfWlanGetChipDriverMgr(); - if (driverMgr == NULL && driverMgr->RegChipDriver != NULL) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; + + static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { + (void)factory; + return 1; } - tmpFactory.driverName = HI3881_DRIVER_NAME; - tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; - tmpFactory.InitChip = InitHi3881Chip; - tmpFactory.DeinitChip = DeinitHi3881Chip; - tmpFactory.Build = BuildHi3881Driver; - tmpFactory.Release = ReleaseHi3881Driver; - tmpFactory.ReleaseFactory = NULL; - if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; + + /* Register WLAN chip functions. */ + static int32_t HDFWlanRegHisiDriverFactory(void) + { + static struct HdfChipDriverFactory tmpFactory = { 0 }; + struct HdfChipDriverManager *driverMgr = NULL; + driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr == NULL) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + tmpFactory.driverName = HI3881_DRIVER_NAME; + tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; + tmpFactory.InitChip = InitHi3881Chip; + tmpFactory.DeinitChip = DeinitHi3881Chip; + tmpFactory.Build = BuildHi3881Driver; + tmpFactory.Release = ReleaseHi3881Driver; + tmpFactory.ReleaseFactory = NULL; + if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; } - return HDF_SUCCESS; -} - -static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) -{ - (void)device; - return HDFWlanRegHisiDriverFactory(); -} - -struct HdfDriverEntry g_hdfHisiChipEntry = { - .moduleVersion = 1, - .Init = HdfWlanHisiChipDriverInit, - .moduleName = "HDF_WLAN_CHIPS" -}; - -HDF_INIT(g_hdfHisiChipEntry); -``` - - -``` -#include "hdf_wifi_product.h" -#include "hi_wifi_api.h" -#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) -#include "oal_thread.h" -#include "osal_time.h" -#endif -#include "wifi_mac80211_ops.h" -#include "wal_cfg80211.h" -#include "net_adapter.h" -#include "hdf_wlan_utils.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* Function for initializing the WLAN chip. */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device) -{ - uint8_t maxPortCount = 1; - int32_t ret = HI_SUCCESS; - uint8_t maxRetryCount = 2; - if (device == NULL) { - HDF_LOGE("%s:NULL ptr!", __func__); - return HI_FAIL; + static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) + { + (void)device; + return HDFWlanRegHisiDriverFactory(); } - do { - if (ret != HI_SUCCESS) { - if (device->reset != NULL && device->reset->Reset != NULL) { - device->reset->Reset(device->reset); + struct HdfDriverEntry g_hdfHisiChipEntry = { + .moduleVersion = 1, + .Bind = HdfWlanHisiDriverBind, + .Init = HdfWlanHisiChipDriverInit, + .Release = HdfWlanHisiChipRelease, + .moduleName = "HDF_WLAN_CHIPS" + }; + + HDF_INIT(g_hdfHisiChipEntry); + ``` + + For details about initialization of the chip and chip driver, see hdfinit_3881.c. The functions are as follows: + + ```c + #include "hdf_wifi_product.h" + #include "hi_wifi_api.h" + #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) + #include "oal_thread.h" + #include "osal_time.h" + #endif + #include "wifi_mac80211_ops.h" + #include "wal_cfg80211.h" + #include "net_adapter.h" + #include "hdf_wlan_utils.h" + + #define HDF_LOG_TAG Hi3881Driver + + /* Initialize the WLAN chip. */ + int32_t InitHi3881Chip(struct HdfWlanDevice *device) + { + uint8_t maxPortCount = 3; + int32_t ret = HI_SUCCESS; + uint8_t maxRetryCount = 3; + if (device == NULL || device->bus == NULL) { + HDF_LOGE("%s:NULL ptr!", __func__); + return HI_FAIL; + } + + do { + if (ret != HI_SUCCESS) { + if (device->reset != NULL && device->reset->Reset != NULL) { + device->reset->Reset(device->reset); + } + HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); } - HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); + ret = hi_wifi_init(maxPortCount, device->bus); + } while (ret != 0 && --maxRetryCount > 0); + + if (ret != 0) { + HDF_LOGE("%s:Init hi3881 driver failed!", __func__); + return ret; } - ret = hi_wifi_init(maxPortCount); - } while (ret != 0 && --maxRetryCount > 0); + return HI_SUCCESS; + } - if (ret != 0) { - HDF_LOGE("%s:Init hi3881 driver failed!", __func__); + /* Deinitializing the WLAN chip. */ + int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) + { + (void)device; + int32_t ret = hi_wifi_deinit(); + if (ret != 0) { + HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); + } return ret; } - return HI_SUCCESS; -} - -/* Function for deinitializing the WLAN chip. */ -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) -{ - (void)device; - int32_t ret = hi_wifi_deinit(); - if (ret != 0) { - HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); + + /* Initializing the WLAN chip driver. */ + int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) + { + hi_u16 mode; + int32_t ret; + nl80211_iftype_uint8 type; + (void)chipDriver; + HDF_LOGI("%s: start...", __func__); + mode = wal_get_vap_mode(); + if (mode >= WAL_WIFI_MODE_BUTT) { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + if (mode == WAL_WIFI_MODE_STA) { + type = NL80211_IFTYPE_STATION; + #ifdef _PRE_WLAN_FEATURE_P2P + if (InitNetdev(netDevice, NL80211_IFTYPE_P2P_DEVICE) != HI_SUCCESS) { + return HI_FAIL; + } + #endif + } else if (mode == WAL_WIFI_MODE_AP) { + type = NL80211_IFTYPE_AP; + } else { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); + if (ret != HI_SUCCESS) { + oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); + } + return ret; } - return ret; -} - -/* Function for initializing the WLAN chip driver. */ -int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - HDF_LOGI("%s: start...", __func__); - hi_u16 mode = wal_get_vap_mode(); - int32_t ret; - nl80211_iftype_uint8 type; - (void)chipDriver; - - if (mode >= WAL_WIFI_MODE_BUTT) { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); - return HI_FAIL; + + /* Deinitializing the WLAN chip driver. */ + int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) + { + int32_t ret; + (void)chipDriver; + ret = DeinitNetdev(NL80211_IFTYPE_P2P_DEVICE); + if (ret != HI_SUCCESS) { + oam_error_log1(0, OAM_SF_ANY, "Hi3881Deinit: DeinitNetdev p2p device fail, ret = %d\n", ret); + return ret; + } + return wal_deinit_drv_wlan_netdev(netDevice); } - if (mode == WAL_WIFI_MODE_STA) { - type = NL80211_IFTYPE_STATION; - } else if (mode == WAL_WIFI_MODE_AP) { - type = NL80211_IFTYPE_AP; - } else { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + ``` + + 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**. + + ```c + hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, oal_net_device_stru *netdev) + { + hi_char *ac_mode_str = NULL; + hi_s32 ret; + if (oal_unlikely(netdev == HI_NULL)) { + oam_error_log0(0, OAM_SF_ANY, "{netdev is null!}"); + return HI_ERR_CODE_PTR_NULL; + } + + do { + /* Initialize the network device. */ + ret = wal_init_netdev(type, netdev); + if (ret != HI_SUCCESS) { + break; + } + + ret = wal_init_netif(type, netdev); + if (ret != HI_SUCCESS) { + break; + } + ac_mode_str = "11bgn"; + if (mode == WAL_PHY_MODE_11G) { + ac_mode_str = "11bg"; + } else if (mode == WAL_PHY_MODE_11B) { + ac_mode_str = "11b"; + } + + ret = wal_ioctl_set_mode(netdev, ac_mode_str); + } while (false); + + if (ret != HI_SUCCESS) { + wal_deinit_wlan_vap(netdev); + oal_net_unregister_netdev(netdev); + oal_net_clear_netdev(netdev); return HI_FAIL; } + + return HI_SUCCESS; + } - ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); - if (ret != HI_SUCCESS) { - oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); + /* Hook function pointers of netdev. For details, see NetDeviceInterFace. */ + oal_net_device_ops_stru g_wal_net_dev_ops = + { + .getStats = wal_netdev_get_stats, + .open = wal_netdev_open, + .stop = wal_netdev_stop, + .xmit = hmac_bridge_vap_xmit, + .ioctl = wal_net_device_ioctl, + .changeMtu = oal_net_device_change_mtu, + .init = oal_net_device_init, + .deInit = oal_net_free_netdev, + #if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) + .selectQueue = wal_netdev_select_queue, + #endif + .setMacAddr = wal_netdev_set_mac_addr, + #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) + .netifNotify = HI_NULL, + #endif + .specialEtherTypeProcess = SpecialEtherTypeProcess, + }; + + hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) + { + /* Add the network device to the protocol stack. */ + hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); + + ... + return HI_SUCCESS; } - return ret; -} - -/* Function for deinitializing the WLAN chip driver. */ -int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - (void)chipDriver; - int32_t ret = wal_deinit_drv_wlan_netdev(netDevice); - if (ret != HDF_SUCCESS) { - return ret; + ``` + +3. Bind the commands to be delivered, including setting the MAC address and transmit power, implement STA connection and scan, start APs, and setting the country code. + + ```c + /* Implement the basic capabilities of the MAC layer. */ + static struct HdfMac80211BaseOps g_baseOps = { + .SetMode = WalSetMode, + .AddKey = WalAddKey, + .DelKey = WalDelKey, + .SetDefaultKey = WalSetDefaultKey, + .GetDeviceMacAddr = WalGetDeviceMacAddr, + .SetMacAddr = WalSetMacAddr, + .SetTxPower = WalSetTxPower, + .GetValidFreqsWithBand = WalGetValidFreqsWithBand, + .GetHwCapability = WalGetHwCapability + }; + + /* Implement the STA capabilities of the MAC layer. */ + static struct HdfMac80211STAOps g_staOps = { + .Connect = WalConnect, + .Disconnect = WalDisconnect, + .StartScan = WalStartScan, + .AbortScan = WalAbortScan, + .SetScanningMacAddress = WalSetScanningMacAddress, + }; + + /* Implement the AP capabilities of the MAC layer. */ + static struct HdfMac80211APOps g_apOps = { + .ConfigAp = WalConfigAp, + .StartAp = WalStartAp, + .StopAp = WalStopAp, + .ConfigBeacon = WalChangeBeacon, + .DelStation = WalDelStation, + .SetCountryCode = WalSetCountryCode, + .GetAssociatedStasCount = WalGetAssociatedStasCount, + .GetAssociatedStasInfo = WalGetAssociatedStasInfo + }; + + static struct HdfMac80211P2POps g_p2pOps = { + .RemainOnChannel = WalRemainOnChannel, + .CancelRemainOnChannel = WalCancelRemainOnChannel, + .ProbeReqReport = WalProbeReqReport, + .AddIf = WalAddIf, + .RemoveIf = WalRemoveIf, + .SetApWpsP2pIe = WalSetApWpsP2pIe, + .GetDriverFlag = WalGetDriverFlag + }; + + /* Initialize mac80211 and hook functions of the chip. */ + void HiMac80211Init(struct HdfChipDriver *chipDriver) + { + if (chipDriver == NULL) { + HDF_LOGE("%s:input is NULL!", __func__); + return; + } + chipDriver->ops = &g_baseOps; + chipDriver->staOps = &g_staOps; + chipDriver->apOps = &g_apOps; + chipDriver->p2pOps = &g_p2pOps; + } + ``` + +4. Invoke the event reporting APIs. + + The WLAN framework provides the event reporting APIs. For details, see **hdf_wifi_event.c**. + + For example, call **HdfWiFiEventNewSta AP** to report information about the newly associated STA. + + ```c + hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len, + oal_station_info_stru *station_info, oal_gfp_enum_uint8 en_gfp) + { + #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX) + cfg80211_new_sta(net_device, mac_addr, station_info, en_gfp); + hi_unref_param(addr_len); + #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX) + struct StationInfo info = { 0 }; + info.assocReqIes = station_info->assoc_req_ies; + info.assocReqIesLen = station_info->assoc_req_ies_len; + HdfWifiEventNewSta(net_device, mac_addr, WLAN_MAC_ADDR_LEN, &info); + hi_unref_param(en_gfp); + hi_unref_param(addr_len); + #endif + + return HI_SUCCESS; } - return ReleasePlatformNetDevice(netDevice); -} -``` + ``` +## Verification + +Develop test cases in the WLAN module unit test to verify the basic features of the WLAN module. The following uses Hi3516D V300 standard system as an example. + +1. Set up the test environment. + + - Create a **hostapd.conf** file (used to start the AP) and copy the following content to the file: + + ```text + interface=wlan0 + driver=hdf wifi + ctrl_interface=udp + #Wi-Fi name + ssid=test + hw_mode=g + channel=1 + ignore_broadcast_ssid=0 + wpa=2 + rsn_pairwise=CCMP + # Wi-Fi password. + wpa_passphrase=12345678 + ``` + + - Create a **wpa_supplicant.conf** file (used to start the STA) and copy the following content to the file: + + ```text + country=GB + + network={ + #Hotspot name + ssid="test" + #Hotspot password + psk="12345678" + } + ``` + + - 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: + + ```shell + #!/system/bin/sh + [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 + + RESOLV_CONF="/etc/resolv.conf" + [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" + [ -n "$subnet" ] && NETMASK="netmask $subnet" + + case "$1" in + deconfig) + /system/bin/ifconfig $interface 0.0.0.0 + ;; + + renew|bound) + /system/bin/ifconfig $interface $ip $BROADCAST $NETMASK + + if [ -n "$router" ] ; then + echo "deleting routers" + while busybox route del default gw 0.0.0.0 dev $interface ; do + : + done + + for i in $router ; do + busybox route add default gw $i dev $interface + done + fi + + echo -n > $RESOLV_CONF + [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF + for i in $dns ; do + echo adding dns $i + echo nameserver $i >> $RESOLV_CONF + done + ;; + esac - 3. 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**. + exit 0 + ``` -``` -hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) -{ - oal_net_device_stru *netdev = HI_NULL; + - Create a **udhcpd.conf** file (used to start the **udhcpd**) and copy the following content to the file. 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. - ...... - /* Initialize the network device and obtain the initialized instance. */ - netdev = NetDeviceInit(ifname, *len, LITE_OS); - oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); - ret = wal_init_netif(type, netdev, wdev); + ```text + start 192.168.12.2 + end 192.168.12.100 + interface wlan0 #default: eth0 + max_leases 20 #default: 254 + remaining yes #default: yes + auto_time 7200 #default: 7200 (2 hours) + decline_time 3600 #default: 3600 (1 hour) + conflict_time 3600 #default: 3600 (1 hour) + offer_time 60 #default: 60 (1 minute) + min_lease 60 #defult: 60 + lease_file /vendor/etc/udhcpd.leases + opt dns x.x.x.x x.x.x.x + option subnet 255.255.255.0 + opt router 192.168.12.1 + ``` - ...... + - Run the following commands to push the files required for the test to the development board: - return HI_SUCCESS; -} -/* Hook pointers of NetDeviceInterFace(). */ -oal_net_device_ops_stru g_wal_net_dev_ops = -{ - .getStats = wal_netdev_get_stats, - .open = wal_netdev_open, - .stop = wal_netdev_stop, - .xmit = hmac_bridge_vap_xmit, - .ioctl = wal_net_device_ioctl, - .changeMtu = oal_net_device_change_mtu, - .init = oal_net_device_init, - .deInit = oal_net_free_netdev, -#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) - .selectQueue = wal_netdev_select_queue, -#endif - .setMacAddr = wal_netdev_set_mac_addr, -#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) - .netifNotify = HI_NULL, -#endif - .specialEtherTypeProcess = SpecialEtherTypeProcess, -}; - -hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) -{ - /* Add the network device to a protocol stack. */ - hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); - - ...... + ```shell + hdc shell "mount -o rw,remount /" + timeout /T 1 + hdc file send dhcpc.sh /system/lib/ + hdc shell "chmod 777 /system/lib/dhcpc.sh" + hdc file send wpa_supplicant.conf / + hdc shell "mount -o rw,remount /vendor" + hdc file send hostapd.conf / + hdc file send udhcpd.conf /vendor/etc + hdc shell "touch /vendor/etc/udhcpd.leases" + hdc shell "chmod 777 /vendor/etc/udhcpd.leases" + ``` + +2. Verify basic Wi-Fi features. + + - Verify basic AP features. + + 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. + + 2. Run the following command in the **cmd** window: + ```shell + hdc shell + hostapd ./hostapd.conf + ``` + + 3. Run the following commands in another **cmd** window: + + ```shell + hdc shell + ifconfig wlan0 192.168.12.1 netmask 255.255.255.0 + busybox udhcpd /vendor/etc/udhcpd.conf + ``` + + 4. On the mobile phone, select the network named **test** in the available Wi-Fi list and enter the password. + + The network name and password are configured in the **hostapd.conf** file. You can see the network name in the connected Wi-Fi list if the connection is successful. + + 5. Ping the test terminal from the development board. + + ```shell + busybox ping xxx.xxx.xxx.xxx + ``` + + In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally. + + - Verify basic STA features. + + 1. Start the STA on the development board, and enable the hotspot on the test terminal. (The hotspot name and password are configured in the **hostapd.conf** file. The hotspot name is **test**, and the password is **12345678**.) + + 2. Run the following command in the **cmd** window: + + ```shell + hdc shell + wpa_supplicant -i wlan0 -d -c wpa_supplicant.conf + ``` + + 3. Run the following commands in another **cmd** window: + + ```shell + hdc shell + mount -o rw,remount / + mount -o rw,remount /vendor + busybox udhcpc -i wlan0 -s system/lib/dhcpc.sh + ``` + The IP addresses of the board and test terminal are displayed if the command is successful. + + 4. Ping the test terminal from the development board. + + ```shell + busybox ping xxx.xxx.xxx.xxx + ``` + + In the command, xxx.xxx.xxx.xxx indicates the IP address of the test terminal. If the test terminal can be pinged, the WLAN driver provides basic features normally. - return HI_SUCCESS; -} -``` - -4. Hook functions of **WifiMac80211Ops**. - - -``` -/* Hook function pointers of mac80211. */ - -/* Define the functions for implementing the basic capabilities in the MAC layer for the driver. */ -static struct HdfMac80211BaseOps g_baseOps = { - .SetMode = WalSetMode, - .AddKey = WalAddKey, - .DelKey = WalDelKey, - .SetDefaultKey = WalSetDefaultKey, - .GetDeviceMacAddr = WalGetDeviceMacAddr, - .SetMacAddr = WalSetMacAddr, - .SetTxPower = WalSetTxPower, - .GetValidFreqsWithBand = WalGetValidFreqsWithBand, - .GetHwCapability = WalGetHwCapability -}; - -/* Define the functions for implementing the STA capabilities in the MAC layer for the driver. */ -static struct HdfMac80211STAOps g_staOps = { - .Connect = WalConnect, - .Disconnect = WalDisconnect, - .StartScan = WalStartScan, - .AbortScan = WalAbortScan, - .SetScanningMacAddress = WalSetScanningMacAddress, -}; - -/* Define the functions for implementing the AP capabilities in the MAC layer for the driver. */ -static struct HdfMac80211APOps g_apOps = { - .ConfigAp = WalConfigAp, - .StartAp = WalStartAp, - .StopAp = WalStopAp, - .ConfigBeacon = WalChangeBeacon, - .DelStation = WalDelStation, - .SetCountryCode = WalSetCountryCode, - .GetAssociatedStasCount = WalGetAssociatedStasCount, - .GetAssociatedStasInfo = WalGetAssociatedStasInfo -}; - -/* Initialize mac80211 and hook functions of the chip. */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - oam_error_log(0, OAM_SF_ANY, "%s:input is NULL!", __func__); - return; +3. Verify the unit test cases. + + To test a specified interface of the HDI module, perform the following steps: + + 1. Call **WlanInterfaceGetInstance()** to obtain a WLAN service instance. + + 2. Call **Start()** to create a channel between the HAL and the driver and obtain information about the driver network interface card (NIC). + + 3. Call **GetSupportFeature()** to obtain the WLAN features supported by the device. + + 4. Call **Stop()** to destroy the channel between the HAL and the driver + + 5. Call **WlanInterfaceRelease()** to destroy the WLAN service instance. + + The sample code is as follows: + + ```c + #include "v1_0/iwlan_interface.h" + #include "wlan_callback_impl.h" + #include "wlan_impl.h" + + #define PROTOCOL_80211_IFTYPE_NUM 11; + #define HDF_SUCCESS 0 + #define HDF_FAILURE (-1) + + static int32_t hdi_main() + { + int32_t rc; + const char *WLAN_SERVICE_NAME = "wlan_hal_c_service"; + static struct IWlanInterface *g_wlanObj = NULL; + uint8_t supType[PROTOCOL_80211_IFTYPE_NUM + 1] = {0}; + uint32_t supTypeLen = PROTOCOL_80211_IFTYPE_NUM + 1; + + /* Obtain the WLAN service instance. */ + g_wlanObj = WlanInterfaceGetInstance(WLAN_SERVICE_NAME); + if (g_wlanObj == NULL) + { + return HDF_FAILURE; + } + + /* Create a channel between the HAL and the driver and obtain the driver NIC information. */ + rc = g_wlanObj->Start(g_wlanObj); + if (rc != HDF_SUCCESS) + { + return HDF_FAILURE; + } + + /* Obtain the WLAN features supported by the device irrespective of the device status (AP, STA, or P2P). + rc = g_wlanObj->GetSupportFeature(g_wlanObj, supType, &supTypeLen); + if (rc != HDF_SUCCESS) + { + return HDF_FAILURE; + } + + /* Destroy the channel between the HAL and the driver. */ + rc = g_wlanObj->Stop(g_wlanObj); + if (rc != HDF_SUCCESS) + { + return HDF_FAILURE; + } + + /* Destroy the WLAN service instance. */ + rc = WlanInterfaceRelease(g_wlanObj); + if (rc != HDF_SUCCESS) + { + return HDF_FAILURE; + } + return rc; } - chipDriver->ops = &g_baseOps; - chipDriver->staOps = &g_staOps; - chipDriver->apOps = &g_apOps; -} -``` + ``` + + To test a specified interface of the HAL module, perform the following steps: + + 1. Call **WifiConstruct()** to create an **IWiFi** instance. + + 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. + + 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. + + 4. Call related APIs, for example, call **setMacAddress()** to set the MAC address and call **getDeviceMacAddress()** to obtain the device MAC address. + + 5. Call **destroyFeature()** to destroy the **apFeature** instance. + + 6. Call **stop()** to destroy the channel between the HAL and the driver. + + 7. Call **WifiDestruct()** to destroy the **IWiFi** instance. + + The sample code is as follows: + + ```c + #include "wifi_hal.h" + #include "wifi_hal_sta_feature.h" + #include "wifi_hal_ap_feature.h" + #include "wifi_hal_cmd.h" + #include "wifi_hal_event.h" + + #define MAC_LEN 6 + #define HDF_SUCCESS 0 + #define HDF_FAILURE (-1) + ``` + + ``` + static int32_t hal_main() + { + int32_t ret; + struct IWiFi *wifi; + + /* Create a WiFi instance. */ + ret = WifiConstruct(&wifi); + if (ret != HDF_SUCCESS || wifi == NULL) { + return HDF_FAILURE; + } + + /* Create a channel between the HAL and the driver and obtain the driver NIC information. */ + ret = wifi->start(wifi); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* Create an apFeature instance. */ + ret = wifi->createFeature(PROTOCOL_80211_IFTYPE_AP, (struct IWiFiBaseFeature **)&apFeature); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* Obtain the MAC address of the device. */ + unsigned char mac[MAC_LEN] = {0}; + ret = apFeature->baseFeature.getDeviceMacAddress((struct IWiFiBaseFeature *)apFeature, mac, MAC_LEN); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* Destroy the apFeature instance. */ + ret = wifi->destroyFeature((struct IWiFiBaseFeature *)apFeature); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* Destroy the channel between the HAL and the driver. */ + ret = wifi->stop(wifi); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* Destroy the IWiFi instance. */ + ret = WifiDestruct(&wifi); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + return ret; + } + ``` + +4. Verify the test cases. + 1. Push the test cases to the development board. + + ```shell + hdc file send /xxx /data + ``` + + In the command, xxx indicates the path of the test cases of the development board. + + 2. Modify the permissions on the test cases and execute the test cases. + + ```shell + hdc shell + cd data + chmod 777 Test_case_name + ./ Test case name. + ``` + + 3. Check the test case execution result. + ## Reference - Code repositories: - [drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core) + **[drivers\_hdf\_core](https://gitee.com/openharmony/drivers_hdf_core)** [drivers\_peripheral](https://gitee.com/openharmony/drivers_peripheral) + [drivers\_interface](https://gitee.com/openharmony/drivers_interface) + - Code paths: - Adaptation of WLAN FlowCtl component on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi** + - Adaptation of WLAN FlowCtl component on LiteOS: + + **//drivers/hdf_core/adapter/khdf/liteos/model/network/wifi** - Adaptation of HDF network model on LiteOS: **//drivers/hdf_core/adapter/khdf/liteos/model/network** + - Adaptation of HDF network model on LiteOS: - 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/liteos/model/network** - **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi** + - Adaptation of WLAN FlowCtl component on Linux, build of the HDF WLAN model, and build of the vendor's WLAN driver: - Core code for implementing the WLAN module: **//drivers/hdf_core/framework/model/network/wifi** + **//drivers/hdf_core/adapter/khdf/linux/model/network/wifi** - External APIs of the WLAN module: **//drivers/hdf_core/framework/include/wifi** + - Core code for implementing the WLAN module: - HDF network model APIs: **//drivers/hdf_core/framework/include/net** + **//drivers/hdf_core/framework/model/network/wifi** - WLAN HDI APIs and implementation: **//drivers/peripheral/wlan** + - External APIs of the WLAN module: + + **//drivers/hdf_core/framework/include/wifi** + + - HDF network model APIs: + + **//drivers/hdf_core/framework/include/net** + + - WLAN HDI server implementation: + + **//drivers/peripheral/wlan** + + - External APIs of the WLAN HDI: + + **//out/{product_name}/gen/drivers/interface/wlan/v1_0**