# WLAN Development Example This section describes how to initialize the WLAN module on a Hi3881 WLAN chip. 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 supply sequencing delay */ powerType = 1; /* Power supply type. Value 0 indicates that the power supply is always on, and value 1 indicates power supply through general-purpose input/output (GPIO). */ gpioId = 1; /* GPIO pin ID */ activeLevel=1; /* Active level. Value 0 indicates a low level, and value 1 indicates a high level. */ } power1 { powerSeqDelay = 0; /* Power supply sequencing delay */ powerType = 0; /* Power supply type. Value 0 indicates that the power supply is always on, and value 1 indicates power supply through GPIO. */ } } reset { resetType = 0; /* Reset type. Value 0 indicates that reset is not supported, and value 1 indicates reset through GPIO. */ gpioId = 2; /* GPIO pin ID */ activeLevel=1; /* Active level. Value 0 indicates a low level, and value 1 indicates a high level. */ resetHoldTime = 30; /* Hold time (ms) for a reset */ } bootUpTimeout = 30; /* Boot timeout duration (ms) */ bus { busType = 0; /* Bus type. Value 0 indicates secure digital input/output (SDIO). */ busId = 2; /* Bus ID */ 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 configuration file wlan_chip_.hcs (for example, wlan_chip_hi3881.hcs) for each chip and set parameters. The following takes the Hi3881 chip as an example. */ root { wlan_config { hi3881 :& chipList { chipHi3881 :: chipInst { match_attr = "hdf_wlan_chips_hi3881"; /* Match attribute */ chipName = "hi3881"; /* WLAN chip name */ sdio { vendorId = 0x0296; /* Vendor ID */ deviceId = [0x5347]; /* Device ID */ } } } } } ``` 2. Mount the **init** and **deinit** functions of the WLAN chip and WLAN chip driver. ``` /* WLAN module initialization and mount process */ #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 the WLAN chip */ int32_t InitHi3881Chip(struct HdfWlanDevice *device); int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); /* Functions for initializing and deinitializing the WLAN chip driver */ int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); /* Initialize mac80211 and mount functions of the chip. */ hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); static const char* const HI3881_DRIVER_NAME = "hisi"; /* Mount the WLAN chip driver and the functions of mac80211 and the 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; HiMac80211Init(specificDriver); return specificDriver; } /* 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); } static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { (void)factory; return 1; } /* Register functions related to the WLAN chip. */ 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; } 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; } 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_adpater.h" #include "hdf_wlan_utils.h" #define HDF_LOG_TAG Hi3881Driver /* Initialize 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; } 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); } ret = hi_wifi_init(maxPortCount); } while (ret != 0 && --maxRetryCount > 0); if (ret != 0) { HDF_LOGE("%s:Init hi3881 driver failed!", __func__); return ret; } return HI_SUCCESS; } /* Deinitialize 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; } /* Initialize 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; } 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); 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; } /* Deinitialize 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; } return ReleasePlatformNetDevice(netDevice); } ``` 3. During the chip initialization, call the **NetDeviceInit\(\)** function to initialize a network device, call the **NetDeviceAdd\(\)** function to add the network device to a protocol stack, and implement some function pointers of **netdev**. ``` 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; ...... /* 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); ...... return HI_SUCCESS; } /* Mount some function pointers of {@link 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); ...... return HI_SUCCESS; } ``` 4. Implement functions of **WifiMac80211Ops**. ``` /* Mount some function pointers of mac80211. */ /* MAC-layer APIs for basic capabilities that need to be implemented by 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 }; /* MAC-layer APIs for station capabilities that need to be implemented by the driver */ static struct HdfMac80211STAOps g_staOps = { .Connect = WalConnect, .Disconnect = WalDisconnect, .StartScan = WalStartScan, .AbortScan = WalAbortScan, .SetScanningMacAddress = WalSetScanningMacAddress, }; /* MAC-layer APIs for AP capabilities that need to be implemented by 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 mount 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; } chipDriver->ops = &g_baseOps; chipDriver->staOps = &g_staOps; chipDriver->apOps = &g_apOps; } ```