diff --git a/zh-cn/device-dev/driver/driver-peripherals-external-des.md b/zh-cn/device-dev/driver/driver-peripherals-external-des.md index afe7362b616131bfc5a3ba749b89db1fb9ba77d2..889e18cfc090b7ac8dbba21e629d27cc5dcab2c3 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-external-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-external-des.md @@ -29,7 +29,7 @@ WLAN框架如图1所示,其中WLAN Driver模块主要提供启动加载、配 WLAN Driver框架主要由如下模块组成: -1. WLAN Message:该部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和MCU环境运行,实现组件间的充分解耦。 +1. WLAN Message:该部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和MCU环境运行,实现部件间的充分解耦。 2. WLAN Configuration Core:WLAN相关的配置文件进行解析。 @@ -45,7 +45,7 @@ WLAN Driver框架主要由如下模块组成: 8. NetBuf:该部件为WLAN驱动提供Linux或者LiteOS原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装。 -9. FlowCtl:流控模块。 +9. FlowCtl:流控模块,当数据量过大时按照优先级策略处理数据。 10. HCC-CFG:WLAN相关参数配置其中包括板级配置、驱动配置、Module配置。 @@ -75,20 +75,10 @@ WLAN模块有三部分对外开放的API接口,如下图所示: ![image](figures/WLAN驱动接口框架图.png "WLAN驱动接口框架图") -- WLAN驱动模块对上层服务提供的HDI能力接口(适用于标准系统),主要功能有:创建/销毁ifeature对象、设置/获取功率模式等。提供的部分接口说明如表1所示: - - **表1** IWlanInterface.idl - - | 接口名称 | 功能描述 | - | -------- | -------- | - | CreateFeature([in] int type, [out] struct HdfFeatureInfo ifeature); | 创建ifeature对象。 | - | DestroyFeature([in] struct HdfFeatureInfo ifeature); | 销毁ifeature对象。 | - | GetPowerMode([in] struct HdfFeatureInfo ifeature, [out] unsigned char mode); | 获取功率模式。 | - | SetPowerMode([in] struct HdfFeatureInfo ifeature, [in] unsigned char mode); | 设置功率模式。 | - WLAN驱动模块对上层服务提供的HAL能力接口(适用于小型系统及轻量系统),主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如表2、表3所示: - **表2** wifi_hal.h + **表1** wifi_hal.h | 接口名称 | 功能描述 | | -------- | -------- | @@ -97,7 +87,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: | int32_t (\*start)(struct IWiFi \*) | 创建HAL和驱动之间的通道及获取驱动支持的网卡信息。 | | int32_t (\*stop)(struct IWiFi \*) | 销毁通道。 | - **表3** wifi_hal_base_feature.h + **表2** wifi_hal_base_feature.h | 接口名称 | 功能描述 | | -------- | -------- | @@ -108,7 +98,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: - WLAN驱动模块也提供了需要驱动开发人员自行去填充具体实现内容的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如表4所示: - **表4** net_device.h + **表3** net_device.h | 接口名称 | 功能描述 | | -------- | -------- | @@ -123,7 +113,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: 可直接调用的接口如表5、表6和表7所示。 - **表5** wifi_module.h + **表4** wifi_module.h | 接口名称 | 功能描述 | | -------- | -------- | @@ -132,7 +122,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: | int32_t DelFeature(struct WifiModule \*module, uint16_t featureType) | 基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。 | | int32_t AddFeature(struct WifiModule \*module, uint16_t featureType,
 struct WifiFeature \*featureData) | 基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。 | - **表6** wifi_mac80211_ops.h + **表5** wifi_mac80211_ops.h | 接口名称 | 功能描述 | | -------- | -------- | @@ -141,354 +131,338 @@ WLAN模块有三部分对外开放的API接口,如下图所示: | int32_t (\*connect)(NetDevice \*netDev, WifiConnectParams \*param) | 开始关联。 | | int32_t (\*disconnect)(NetDevice \*netDev, uint16_t reasonCode) | 取消关联。 | - **表7** hdf_netbuf.h + **表6** hdf_netbuf.h | 接口名称 | 功能描述 | | -------- | -------- | | static inline void NetBufQueueInit(struct NetBufQueue \*q) | 初始化NetBuf队列。 | | struct NetBuf \*NetBufAlloc(uint32_t size) | 申请NetBuf。 | - | void NetBufFree(struct NetBuf \*nb) | 释放NetBuf | + | void NetBufFree(struct NetBuf \*nb) | 释放NetBuf。 | | struct NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | lwip的pbuf转换为NetBuf。 | | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | NetBuf转换为lwip的pbuf。 | ### 开发步骤 +#### 厂商适配WLAN框架 -WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 +WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下开发流程适配WLAN驱动框架。 - 1. 配置硬件(例如module、芯片等)相关的参数。在wlan_platform.hcs文件中对参数进行配置,该文件会通过HDF框架中对应的接口解析后,生成全量配置的结构体对象。 +**开发流程** - 2. 初始化和去初始化WLAN模块相关适配(如WLAN芯片初始化和去初始化、WLAN芯片驱动初始化和去初始化)。 +1. 配置硬件(例如module、芯片等)相关的参数。wlan_platform.hcs文件中对参数进行配置后,HDF框架会对该文件进行解析,并生成全量配置的结构体对象。 - 3. 控制流命令下发的适配。 +2. 初始化和去初始化WLAN模块相关适配(如WLAN芯片初始化和去初始化、WLAN芯片驱动初始化和去初始化)。 - 4. 事件上报的调用。 +3. 控制流命令下发的适配。 -### 开发实例 +4. 事件上报的调用。 -本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以Hi3881WLAN芯片为例): +**开发实例** -1. 根据硬件具体情况修改配置参数。 - - ```text - /* 根据硬件具体情况,在wlan_platform.hcs中配置相关参数,以下是WLAN平台配置的示例 */ - hisi :& deviceList { - device0 :: deviceInst { - deviceInstId = 0; - powers { - power0 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 1; /* 电源类型,0表示总是打开;1表示GPIO */ - gpioId = 1; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效 */ - } - power1 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 0; /* 电源类型,0表示总是打开;1表示GPIO */ - } - } - reset { - resetType = 0; /* 复位类型,0表示不管理;1表示GPIO */ - gpioId = 2; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效 */ - resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ - } - bootUpTimeout = 30; /* 启动超时时间(ms) */ - bus { - busEnable = 1; /* bus总线是否初始化,0-表示不初始化; 1表示初始化 */ - busType = 0; /* 总线类型,0表示sdio */ - busId = 2; /* 总线号 */ - funcNum = [1]; /* SDIO功能号 */ - timeout = 1000; /* 读/写数据的超时时间 */ - blockSize = 512; /* 读/写数据的块大小 */ - } - } - } - /* 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */ - root { - wlan_config { - hi3881 :& chipList { - chipHi3881 :: chipInst { - match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ - chipName = "hi3881"; /* WLAN芯片的名称 */ - bus { - vendorId = 0x0296; /* 厂商ID */ - deviceId = [0x5347]; /* 设备ID */ - } - } - } - } - } - ``` +本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以Hi3881WLAN芯片为例): -2. 适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。 +1. Driver的HCS配置。 - ```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 - - /* WLAN芯片的初始化和去初始化函数。 */ - int32_t InitHi3881Chip(struct HdfWlanDevice *device); - int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); - /* WLAN芯片驱动的初始化和去初始化函数。 */ - int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); - int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); - - /* 初始化Mac80211与芯片侧的函数挂接。 */ - hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); - - static const char* const HI3881_DRIVER_NAME = "hisi"; - - /* WLAN芯片驱动挂接以及Mac80211与芯片侧的函数挂接。 */ - 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; - } + HCS文件配置包括:device相关配置和组件配置。 - 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; + - device相关配置 - HiMac80211Init(specificDriver); + 配置文件内容包括:电源配置、复位配置和总线配置。 - return specificDriver; - } + 配置文件路径:vendor/<厂商名>/<设备名>/hdf_config/khdf/wifi。 - /* 释放WLAN芯片驱动。 */ - 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; + 根据硬件具体情况,在wlan_platform.hcs中配置相关参数,以下是WLAN平台配置的示例: + ```text + hisi :& deviceList { + device0 :: deviceInst { + deviceInstId = 0; + powers { + power0 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 1; /* 电源类型,0表示总是打开;1表示GPIO */ + gpioId = 1; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效 */ + } + power1 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 0; /* 电源类型,0表示总是打开;1表示GPIO */ + } + } + reset { + resetType = 0; /* 复位类型,0表示不管理;1表示GPIO */ + gpioId = 2; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效 */ + resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ + } + bootUpTimeout = 30; /* 启动超时时间(ms) */ + bus { + busEnable = 1; /* bus总线是否初始化,0-表示不初始化; 1表示初始化 */ + busType = 0; /* 总线类型,0表示sdio */ + busId = 2; /* 总线号 */ + funcNum = [1]; /* SDIO功能号 */ + timeout = 1000; /* 读/写数据的超时时间 */ + blockSize = 512; /* 读/写数据的块大小 */ + } + } } - OsalMemFree(chipDriver); - } - - static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { - (void)factory; - return 1; - } + ``` + - 组件配置 - /* WLAN芯片相关函数的注册。 */ - 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; + 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例: + ```text + root { + wlan_config { + hi3881 :& chipList { + chipHi3881 :: chipInst { + match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ + chipName = "hi3881"; /* WLAN芯片的名称 */ + bus { + vendorId = 0x0296; /* 厂商ID */ + deviceId = [0x5347]; /* 设备ID */ + } + } + } + } } + ``` - return HDF_SUCCESS; - } +2. 驱动适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。 + - 驱动适配入口函数实现 - static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) - { - (void)device; - return HDFWlanRegHisiDriverFactory(); - } - - struct HdfDriverEntry g_hdfHisiChipEntry = { + 根据各自的芯片定义一个HdfDriverEntry类型的变量,主要实现Bind、Init、Release接口的函数挂接。调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源。 + ```c + struct HdfDriverEntry g_hdfHisiChipEntry = { .moduleVersion = 1, .Bind = HdfWlanHisiDriverBind, .Init = HdfWlanHisiChipDriverInit, .Release = HdfWlanHisiChipRelease, .moduleName = "HDF_WLAN_CHIPS" - }; - - HDF_INIT(g_hdfHisiChipEntry); - ``` - - 芯片初始化和芯片驱动初始化相关内容详见hdfinit_3881.c,具体函数分解如下: - - ```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 - - /* WLAN芯片的初始化函数。 */ - 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); - } - 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; - } - return HI_SUCCESS; - } - - /* WLAN芯片的去初始化函数。 */ - 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; - } - - /* WLAN芯片驱动的初始化函数。 */ - 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; - } - - /* WLAN芯片驱动的去初始化函数。 */ - 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); - } - - ``` - - 在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接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 { - /* 初始化网络设备。 */ - 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; - } - - /* 挂接netdev的一些函数指针,详细挂接函数请参考NetDeviceInterFace。 */ - oal_net_device_ops_stru g_wal_net_dev_ops = - { + }; + + HDF_INIT(g_hdfHisiChipEntry); + ``` + + - 芯片初始化,芯片驱动初始化函数的注册 + + InitChip/DeinitChip接口挂接芯片初始化、去初始化的函数实现。 + + Build/Release接口挂接芯片驱动的初始化、去初始化函数实现。 + + ```c + /* WLAN芯片相关函数的注册 */ + 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; + } + + static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) + { + (void)device; + return HDFWlanRegHisiDriverFactory(); + } + ``` + + - 芯片的初始化和去初始化 + ```c + /* WLAN芯片的初始化函数 */ + 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); + } + 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; + } + return HI_SUCCESS; + } + + /* WLAN芯片的去初始化函数 */ + 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; + } + ``` + - 芯片驱动的初始化和去初始化 + ```c + /* WLAN芯片驱动挂接以及Mac80211与芯片侧的函数挂接 */ + 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; + } + + 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; + } + + /* 释放WLAN芯片驱动 */ + 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); + } + + /* WLAN芯片驱动的初始化函数 */ + 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; + } + + /* WLAN芯片驱动的去初始化函数 */ + 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); + } + + ``` + + 在芯片驱动初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接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 { + /* 初始化网络设备。 */ + 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; + } + + /* 挂接netdev的一些函数指针,详细挂接函数请参考NetDeviceInterFace */ + oal_net_device_ops_stru g_wal_net_dev_ops = + { .getStats = wal_netdev_get_stats, .open = wal_netdev_open, .stop = wal_netdev_stop, @@ -497,31 +471,26 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, .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) - { - /* 添加网络设备到协议栈。 */ - hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); + }; - ...... + hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) + { + /* 添加网络设备到协议栈 */ + hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); - return HI_SUCCESS; - } - ``` + ...... + + return HI_SUCCESS; + } + ``` 3. 命令下发绑定,包括具有公共能力的设置MAC地址、设置发射功率等;STA相关的连接、扫描等;AP相关的启动AP、设置国家码等。 ```c - /* 驱动需要实现的MAC层基本能力的控制接口。 */ + /* 驱动需要实现的MAC层基本能力的控制接口 */ static struct HdfMac80211BaseOps g_baseOps = { .SetMode = WalSetMode, .AddKey = WalAddKey, @@ -534,7 +503,7 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, .GetHwCapability = WalGetHwCapability }; - /* 驱动需要实现的MAC层STA能力的控制接口。 */ + /* 驱动需要实现的MAC层STA能力的控制接口 */ static struct HdfMac80211STAOps g_staOps = { .Connect = WalConnect, .Disconnect = WalDisconnect, @@ -543,7 +512,7 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, .SetScanningMacAddress = WalSetScanningMacAddress, }; - /* 驱动需要实现的MAC层AP能力的控制接口。 */ + /* 驱动需要实现的MAC层AP能力的控制接口 */ static struct HdfMac80211APOps g_apOps = { .ConfigAp = WalConfigAp, .StartAp = WalStartAp, @@ -565,7 +534,7 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, .GetDriverFlag = WalGetDriverFlag }; - /* 初始化Mac80211与芯片侧的函数挂接。 */ + /* 初始化Mac80211与芯片侧的函数挂接 */ void HiMac80211Init(struct HdfChipDriver *chipDriver) { if (chipDriver == NULL) { @@ -600,7 +569,7 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, return HI_SUCCESS; } ``` -## 调测验证 +**调测验证** 驱动开发完成后,在WLAN模块单元测试里面开发自测试用例以及验证WLAN模块基本功能。测试环境采用开发者自测试平台(这里以Hi3516DV300标准系统为例)。 @@ -770,38 +739,39 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, 上述xxx.xxx.xxx.xxx为当前测试终端的IP地址,若测试能够ping通测试终端则表示,WLAN驱动基本功能正常。 -3. 验证单元测试用例 - - HDI模块用例开发步骤(需要测试HDI模块指定接口时,可采用下列步骤): +#### 接口调用 +WLAN驱动模块向上层提供两种能力接口:HDI接口和HAL接口。 +- HDI接口调用 - - 使用WlanInterfaceGetInstance获取WLAN服务对象。 + HDI接口调用开发步骤(以GetSupportFeature为例): - - 使用Start创建HAL和驱动之间的通道及获取驱动网卡信息。 + 1. 使用WlanInterfaceGetInstance获取WLAN服务对象。 - - 通过GetSupportFeature获取该设备支持的WLAN特性。 + 2. 使用Start创建HAL和驱动之间的通道及获取驱动网卡信息。 - - 调用Stop,销毁HAL和驱动之间的通道。 + 3. 通过GetSupportFeature获取该设备支持的WLAN特性。 - - 执行WlanInterfaceRelease销毁WLAN服务对象。 + 4. 调用Stop,销毁HAL和驱动之间的通道。 - HDI模块用例开发实例: + 5. 执行WlanInterfaceRelease销毁WLAN服务对象。 - ```c - #include "v1_0/iwlan_interface.h" - #include "wlan_callback_impl.h" - #include "wlan_impl.h" + HDI接口调用开发实例: + ```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; + #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; /* 获取WLAN服务对象。*/ g_wlanObj = WlanInterfaceGetInstance(WLAN_SERVICE_NAME); @@ -839,42 +809,64 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, } return rc; } - ``` + + ``` + + HDI接口调用编译: - HAL模块用例开发步骤(需要测试HAL模块指定接口时,可采用下列步骤): + 1. 编译脚本中添加依赖的库文件: + + ```text + deps = [ + "//drivers/peripheral/wlan/hdi_service:hdi_wlan_service", + ] + ``` + 2. 编译脚本中添加依赖的头文件: + ```text + include_dirs = [ + "//drivers/peripheral/wlan/interfaces/include", + "//drivers/peripheral/wlan/hdi_service", + "//drivers/peripheral/wlan/client/include", + "//drivers/peripheral/wlan/hal/include", + ] + ``` + 3. 执行编译脚本,确认是否编译OK。 - - 使用WifiConstruct创建一个WiFi实体。 +- HAL接口调用 - - 用创建的WiFi实体调用start开启HAL和驱动之间的通道,获得驱动网卡的信息。 + HAL接口调用开发步骤(需要测试HAL模块指定接口时,可采用下列步骤): - - 通过createFeature创建一个apFeature或者staFeature。后面可通过这些Feature去调用具体的实现接口,下面基于创建的apFeature为例进行介绍。 + 1. 使用WifiConstruct创建一个WiFi实体。 - - 调用和使用相关接口:如setMacAddress设置MAC地址、getDeviceMacAddress获取设备的MAC地址等。 + 2. 用创建的WiFi实体调用start开启HAL和驱动之间的通道,获得驱动网卡的信息。 - - 调用destroyFeature,销毁掉创建的apFeature。 + 3. 通过createFeature创建一个apFeature或者staFeature。后面可通过这些Feature去调用具体的实现接口,下面基于创建的apFeature为例进行介绍。 - - 调用stop销毁创建的通道。 + 4. 调用和使用相关接口:如setMacAddress设置MAC地址、getDeviceMacAddress获取设备的MAC地址等。 - - 执行WifiDestruct销毁创建的WiFi实体。 + 5. 调用destroyFeature,销毁掉创建的apFeature。 - HAL模块用例开发实例: + 6. 调用stop销毁创建的通道。 - ```c + 7. 执行WifiDestruct销毁创建的WiFi实体。 + + HAL接口调用开发实例: + + ```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; + struct IWiFiAp *apFeature; /* 创建一个wifi实体。 */ ret = WifiConstruct(&wifi); @@ -920,27 +912,30 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, } return ret; } - ``` - -4. 验证测试用例方法如下 - 1. 将测试用例推送到单板。 - - ```shell - hdc file send /xxx /data - ``` - - xxx表示需要推送到单板根目录的测试用例路径。 - - 2. 修改测试用例权限并执行该用例。 - - ```shell - hdc shell - cd data - chmod 777 测试用例名称 - ./测试用例名称 - ``` + ``` + HAL接口调用编译: + 1. 编译脚本中添加依赖的库文件: + + ```text + deps = [ + "//drivers/peripheral/wlan/client:wifi_driver_client", + "//drivers/peripheral/wlan/hal:wifi_hal", + ] + ``` + + 2. 编译脚本中添加依赖的头文件: + ```text + include_dirs = [ + "//drivers/peripheral/wlan/interfaces/include", + "//drivers/peripheral/wlan/hdi_service", + "//drivers/peripheral/wlan/client/include", + "//drivers/peripheral/wlan/hal/include", + ] + ``` + 3. 执行编译脚本,确认是否编译OK。 + + - 查看测试用例执行结果是否正确。 ## 参考 @@ -970,4 +965,3 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, WLAN HDI服务端实现://drivers/peripheral/wlan - WLAN HDI对外接口://out/{product_name}/gen/drivers/interface/wlan/v1_0