未验证 提交 f21e47ce 编写于 作者: O openharmony_ci 提交者: Gitee

!19155 feat:wlan develop guide optimization

Merge pull request !19155 from wangyanzhen/master
...@@ -5,65 +5,71 @@ ...@@ -5,65 +5,71 @@
### 功能简介 ### 功能简介
WLAN(Wireless Local Area Network)作为网络设备的一个重要特性,其驱动的开发也是设备开发过程中不可忽略的一部分。 无线局域网数据传输是端侧设备不可或缺的一部分,用户可以方便地接入到无线网络进行数据传输和共享,并且在无线网络覆盖区域自由移动,彻底摆脱有线的束缚。基于HDF(Hardware Driver Foundation)驱动框架开发的WLAN驱动,能够屏蔽硬件器件差异,为上层WLAN服务提供稳定的基础能力接口,包括启动扫描、关联/取消关联热点、获取MAC地址、设置MAC地址、获取链路信息等。
在OpenHarmony架构中,基于HDF(Hardware Driver Foundation)驱动框架开发的WLAN驱动模块,具备跨操作系统迁移、自适应器件差异、模块化拼装编译等特性。
### 运作机制 ### 基本概念
各WLAN设备厂商的驱动开发人员可根据WLAN模块提供的向下、向上的统一接口适配各自的驱动代码:
- 向下统一接口实现的能力包括:建立/关闭WLAN热点、扫描、关联WLAN热点等。
- 对HDI层向上提供能力包括:设置MAC地址、设置发射功率、获取设备的MAC地址等。
WLAN框架如图1所示,其中WLAN Driver模块主要提供启动加载、配置文件解析、提供总线抽象接口等能力,WLAN Chip Driver模块主要提供MAC子层管理实体等。
**图1** WLAN框架
![image](figures/WLAN框架.png "WLAN框架")
WLAN Driver框架如图2所示。
**图2** WLAN Driver框架 开发前,开发者应了解一下WLAN涉及的基本概念:
![zh-cn_image_0000001300092359](figures/zh-cn_image_0000001300092359.png) - AP
无线接入点(Access Point,简称AP),是网络的中心节点,提供无线接入服务。其它无线设备接入后,可以进行数据访问。
WLAN Driver框架主要由如下模块组成: - STA
站点(Station,简称STA),是无线局域网的最基本组成单元。每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。
1. WLAN Message:该部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和MCU环境运行,实现部件间的充分解耦。 - ssid
无线网络的名称,用来标识一个无线网络,每个无线网络都有自己的ssid。
2. WLAN Configuration Core:WLAN相关的配置文件进行解析。 - bssid
用于标识WLAN中的基本服务集,是唯一的48位MAC地址。
- Scan
3. AP:AP(Access Point)为WLAN终端提供外部接入入口的设备 终端设备扫描环境中的无线网络,获取到周围的无线网络信息。包括热点名称(ssid)、工作频带和信号强度等
4. STA:STA(Station)为接入WLAN系统的终端。 - Associate
5. Mac80211:定义底层驱动相关的MAC层接口 终端设备指定有效的热点进行连接,成功后即可与AP端数据通信。终端同一时刻只可以和一个AP建立链路
6. Bus:该驱动模块向上提供统一的总线抽象接口。通过向下调用Platform层提供的SDIO接口和封装适配USB、PCIE接口,屏蔽不同内核的差异;通过对不同类型的总线操作进行统一封装,屏蔽不同芯片差异,能够对不同芯片厂商提供完备的总线驱动能力,不同厂商共用此模块接口,从而使厂商的开发更为便捷和统一。 ### 运作机制
7. NetDevice:用于建立专属网络设备,屏蔽不同OS的差异,对WiFi驱动提供统一接口,提供统一的HDF NetDevice数据结构,及其统一管理、注册、去注册能力;对接轻设备及富设备上的Linux的网络设备层。
8. NetBuf:该部件为WLAN驱动提供Linux或者LiteOS原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装。
9. FlowCtl:流控模块,当数据量过大时按照优先级策略处理数据。 本文主要介绍基于HDF(Hardware Driver Foundation)驱动框架开发的WLAN功能。WLAN整体框架:
10. HCC-CFG:WLAN相关参数配置其中包括板级配置、驱动配置、Module配置。 ![image](figures/WLAN驱动接口框架图.png "WLAN框架图")
其中主要模块关系如下: 1. 上层服务基于业务需要调用HDI接口,将用户态消息通过WPA层或HAL层下发至Client层。WPA层接口提供设置加密方式、关联热点、设置信道、隐藏热点等功能,HAL层接口作为WPA接口的补充,提供设置国家码、设置MAC地址、获取信道信息等功能。
2. Message模块将用户态的消息按组件分发至AP、STA等模块。
3. Hdf_Mac80211定义底层驱动相关的MAC层接口。命令字段下发至Hdf_Mac80211,再通过Bus模块发送到WLAN芯片固件侧。
4. Bus模块向上提供统一的总线抽象接口。通过向下调用Platform层提供的SDIO接口和封装适配USB、PCIE接口,屏蔽不同内核的差异;通过对不同类型的总线操作进行统一封装,屏蔽不同芯片差异,能够对不同芯片厂商提供完备的总线驱动能力,不同厂商共用此模块接口,从而使厂商的开发更为便捷和统一。
5. EAPOL(Extensible Authentication Protocol Over LAN),基于局域网的扩展认证协议,主要用于在客户端和设备(接入设备、服务器)之间传送EAP协议报文,以允许EAP协议报文在LAN上传送,完成认证流程,实现设备上线功能。
6. NetDevice用于建立专属网络设备,屏蔽不同OS的差异,对WiFi驱动提供统一接口,提供统一的HDF NetDevice数据结构,及其统一管理、注册、去注册能力;对接轻设备及富设备上的Linux的网络设备层。
7. NetBuf为WLAN驱动提供Linux或者LiteOS原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装。
8. 协议栈与NetDevice模块、NetBuf模块共同协同完成数据流交互。
1. WLAN Driver通过HCC-CFG模块和WLAN Configuration Core模块进行配置文件的解析与加载。 ### 约束与限制
2. WLAN Message将用户态的消息按组件分发至AP、STA等模块 WLAN驱动为上层WLAN服务提供稳定的基础能力接口,HDI接口适用于标准系统,HAL接口适用于小型系统及轻量系统
3. 对于命令字段则下发至Mac80211,再通过Bus模块发送到WLAN芯片固件侧。 ## 开发指导
4. 协议栈与NetDevice模块、NetBuf模块、FlowCtl模块共同协同完成数据流交互。 ### 场景介绍
## 开发指导 WLAN驱动的主要工作是为上层WLAN服务提供稳定的基础能力接口,保证用户可以方便地接入到无线网络,实现数据传输和共享。不同WLAN模组需要适配OpenHarmony时,请参考如下的接口说明和开发步骤。
### 接口说明 ### 接口说明
WLAN模块有三部分对外开放的API接口,如下图所示 WLAN模块有三部分对外开放的API接口:
1. 对上层服务提供HDI以及HAL能力接口。 1. 对上层服务提供HDI以及HAL能力接口。
...@@ -71,12 +77,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: ...@@ -71,12 +77,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示:
3. 驱动直接调用WLAN模块能力接口。 3. 驱动直接调用WLAN模块能力接口。
**图3** WLAN驱动接口框架图 - WLAN驱动模块对上层服务提供的能力接口,主要功能有:创建/销毁IWiFi对象、设置MAC地址、设置发射功率等。以下接口列举的为IDL接口描述生成的对应C语言函数接口,如表1、表2所示。接口声明见idl文件(/drivers/interface/wlan/v1_1/)。
![image](figures/WLAN驱动接口框架图.png "WLAN驱动接口框架图")
- WLAN驱动模块对上层服务提供的HAL能力接口(适用于小型系统及轻量系统),主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如表2、表3所示:
**表1** wifi_hal.h **表1** wifi_hal.h
...@@ -94,9 +95,9 @@ WLAN模块有三部分对外开放的API接口,如下图所示: ...@@ -94,9 +95,9 @@ WLAN模块有三部分对外开放的API接口,如下图所示:
| int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*) | 获取特性的类型。 | | int32_t (\*getFeatureType)(const struct IWiFiBaseFeature \*) | 获取特性的类型。 |
| int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | 设置MAC地址。 | | int32_t (\*setMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | 设置MAC地址。 |
| int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | 获取设备持久化的MAC地址。 | | int32_t (\*getDeviceMacAddress)(const struct IWiFiBaseFeature \*, unsigned char \*, uint8_t) | 获取设备持久化的MAC地址。 |
| int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t) | 设置发射功率。 | | int32_t (\*setTxPower)(const struct IWiFiBaseFeature \*, int32_t) | 设置发射功率。 |
- WLAN驱动模块也提供了需要驱动开发人员自行去填充具体实现内容的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如表4所示: - WLAN驱动模块提供了需要驱动开发人员自行去填充具体实现内容的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如表3所示:
**表3** net_device.h **表3** net_device.h
...@@ -111,7 +112,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示: ...@@ -111,7 +112,7 @@ WLAN模块有三部分对外开放的API接口,如下图所示:
- WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。 - WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。
可直接调用的接口如表5、表6和表7所示。 可直接调用的接口如表4、表5和表6所示。
**表4** wifi_module.h **表4** wifi_module.h
...@@ -139,28 +140,13 @@ WLAN模块有三部分对外开放的API接口,如下图所示: ...@@ -139,28 +140,13 @@ WLAN模块有三部分对外开放的API接口,如下图所示:
| struct NetBuf \*NetBufAlloc(uint32_t size) | 申请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 NetBuf \*Pbuf2NetBuf(const struct NetDevice \*netdev, struct pbuf \*lwipBuf) | lwip的pbuf转换为NetBuf。 |
| struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | NetBuf转换为lwip的pbuf。 | | struct pbuf \*NetBuf2Pbuf(const struct NetBuf \*nb) | NetBuf转换为lwip的pbuf。 |
### 开发步骤 ### 开发步骤
#### 厂商适配WLAN框架
WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下开发流程适配WLAN驱动框架。
**开发流程**
1. 配置硬件(例如module、芯片等)相关的参数。wlan_platform.hcs文件中对参数进行配置后,HDF框架会对该文件进行解析,并生成全量配置的结构体对象。
2. 初始化和去初始化WLAN模块相关适配(如WLAN芯片初始化和去初始化、WLAN芯片驱动初始化和去初始化) WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下开发流程适配WLAN驱动框架。示例以Hi3881WLAN芯片为例
3. 控制流命令下发的适配。 #### 配置Driver的HCS文件
4. 事件上报的调用。
**开发实例**
本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以Hi3881WLAN芯片为例):
1. Driver的HCS配置。
HCS文件配置包括:device相关配置和组件配置。 HCS文件配置包括:device相关配置和组件配置。
...@@ -225,7 +211,8 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, ...@@ -225,7 +211,8 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,
} }
``` ```
2. 驱动适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。 #### 初始化和去初始化WLAN芯片、WLAN芯片驱动
- 驱动适配入口函数实现 - 驱动适配入口函数实现
根据各自的芯片定义一个HdfDriverEntry类型的变量,主要实现Bind、Init、Release接口的函数挂接。调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源。 根据各自的芯片定义一个HdfDriverEntry类型的变量,主要实现Bind、Init、Release接口的函数挂接。调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源。
...@@ -280,296 +267,306 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, ...@@ -280,296 +267,306 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,
} }
``` ```
- 芯片的初始化和去初始化 1. 芯片的初始化和去初始化
```c
/* WLAN芯片的初始化函数 */ ```c
int32_t InitHi3881Chip(struct HdfWlanDevice *device) /* WLAN芯片的初始化函数 */
{ int32_t InitHi3881Chip(struct HdfWlanDevice *device)
uint8_t maxPortCount = 3; {
int32_t ret = HI_SUCCESS; uint8_t maxPortCount = 3;
uint8_t maxRetryCount = 3; int32_t ret = HI_SUCCESS;
if (device == NULL || device->bus == NULL) { uint8_t maxRetryCount = 3;
HDF_LOGE("%s:NULL ptr!", __func__); if (device == NULL || device->bus == NULL) {
return HI_FAIL; HDF_LOGE("%s:NULL ptr!", __func__);
} return HI_FAIL;
}
do {
if (ret != HI_SUCCESS) { do {
if (device->reset != NULL && device->reset->Reset != NULL) { if (ret != HI_SUCCESS) {
device->reset->Reset(device->reset); 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); ret = hi_wifi_init(maxPortCount, device->bus);
} while (ret != 0 && --maxRetryCount > 0);
if (ret != 0) {
HDF_LOGE("%s:Init hi3881 driver failed!", __func__); if (ret != 0) {
return ret; HDF_LOGE("%s:Init hi3881 driver failed!", __func__);
} return ret;
return HI_SUCCESS; }
} return HI_SUCCESS;
}
/* WLAN芯片的去初始化函数 */
int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) /* WLAN芯片的去初始化函数 */
{ int32_t DeinitHi3881Chip(struct HdfWlanDevice *device)
(void)device; {
int32_t ret = hi_wifi_deinit(); (void)device;
if (ret != 0) { int32_t ret = hi_wifi_deinit();
HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); if (ret != 0) {
} HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret);
return 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芯片驱动 */ 2. 芯片驱动的初始化和去初始化
static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
{ ```c
if (chipDriver == NULL) { /* WLAN芯片驱动挂接以及Mac80211与芯片侧的函数挂接 */
return; static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex)
} {
if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { struct HdfChipDriver *specificDriver = NULL;
HDF_LOGE("%s:Not my driver!", __func__); if (device == NULL) {
return; HDF_LOGE("%s fail: channel is NULL!", __func__);
} return NULL;
OsalMemFree(chipDriver); }
} (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);
}
/* 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芯片驱动的去初始化函数 */ 在芯片驱动初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针。
int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
{ ```c
int32_t ret; hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, oal_net_device_stru *netdev)
(void)chipDriver; {
ret = DeinitNetdev(NL80211_IFTYPE_P2P_DEVICE); hi_char *ac_mode_str = NULL;
if (ret != HI_SUCCESS) { hi_s32 ret;
oam_error_log1(0, OAM_SF_ANY, "Hi3881Deinit: DeinitNetdev p2p device fail, ret = %d\n", ret); if (oal_unlikely(netdev == HI_NULL)) {
return ret; oam_error_log0(0, OAM_SF_ANY, "{netdev is null!}");
} return HI_ERR_CODE_PTR_NULL;
return wal_deinit_drv_wlan_netdev(netDevice); }
}
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,
.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,
......
``` };
在芯片驱动初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针。 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);
```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 { return HI_SUCCESS;
/* 初始化网络设备。 */ }
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,
.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,
......
}; #### 适配MAC层能力接口
hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) 用户态消息下发到驱动后,驱动会调用相应的MAC层能力接口。
{
/* 添加网络设备到协议栈 */
hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type);
...... ```c
/* 驱动需要实现的MAC层基本能力的控制接口 */
static struct HdfMac80211BaseOps g_baseOps = {
.SetMode = WalSetMode,
.AddKey = WalAddKey,
.DelKey = WalDelKey,
.SetDefaultKey = WalSetDefaultKey,
.GetDeviceMacAddr = WalGetDeviceMacAddr,
.SetMacAddr = WalSetMacAddr,
.SetTxPower = WalSetTxPower,
.GetValidFreqsWithBand = WalGetValidFreqsWithBand,
.GetHwCapability = WalGetHwCapability
};
/* 驱动需要实现的MAC层STA能力的控制接口 */
static struct HdfMac80211STAOps g_staOps = {
.Connect = WalConnect,
.Disconnect = WalDisconnect,
.StartScan = WalStartScan,
.AbortScan = WalAbortScan,
.SetScanningMacAddress = WalSetScanningMacAddress,
};
/* 驱动需要实现的MAC层AP能力的控制接口 */
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
};
/* 初始化Mac80211与芯片侧的函数挂接 */
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;
}
```
return HI_SUCCESS; #### 适配event事件上报
}
``` WLAN框架提供了event事件的上报接口,详情见hdf_wifi_event.c,例:调用HdfWiFiEventNewSta AP上报新关联的某个STA的情况。
3. 命令下发绑定,包括具有公共能力的设置MAC地址、设置发射功率等;STA相关的连接、扫描等;AP相关的启动AP、设置国家码等。 ```c
hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len,
```c oal_station_info_stru *station_info, oal_gfp_enum_uint8 en_gfp)
/* 驱动需要实现的MAC层基本能力的控制接口 */ {
static struct HdfMac80211BaseOps g_baseOps = { #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX)
.SetMode = WalSetMode, cfg80211_new_sta(net_device, mac_addr, station_info, en_gfp);
.AddKey = WalAddKey, hi_unref_param(addr_len);
.DelKey = WalDelKey, #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
.SetDefaultKey = WalSetDefaultKey, struct StationInfo info = { 0 };
.GetDeviceMacAddr = WalGetDeviceMacAddr, info.assocReqIes = station_info->assoc_req_ies;
.SetMacAddr = WalSetMacAddr, info.assocReqIesLen = station_info->assoc_req_ies_len;
.SetTxPower = WalSetTxPower, HdfWifiEventNewSta(net_device, mac_addr, WLAN_MAC_ADDR_LEN, &info);
.GetValidFreqsWithBand = WalGetValidFreqsWithBand, hi_unref_param(en_gfp);
.GetHwCapability = WalGetHwCapability hi_unref_param(addr_len);
}; #endif
/* 驱动需要实现的MAC层STA能力的控制接口 */ return HI_SUCCESS;
static struct HdfMac80211STAOps g_staOps = { }
.Connect = WalConnect, ```
.Disconnect = WalDisconnect,
.StartScan = WalStartScan,
.AbortScan = WalAbortScan,
.SetScanningMacAddress = WalSetScanningMacAddress,
};
/* 驱动需要实现的MAC层AP能力的控制接口 */
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
};
/* 初始化Mac80211与芯片侧的函数挂接 */
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. 事件上报接口调用,WLAN框架提供了event事件的上报接口,详情见hdf_wifi_event.c,例:调用HdfWiFiEventNewSta AP上报新关联的某个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;
}
```
**调测验证**
驱动开发完成后,在WLAN模块单元测试里面开发自测试用例以及验证WLAN模块基本功能。测试环境采用开发者自测试平台(这里以Hi3516DV300标准系统为例)。 驱动开发完成后,在WLAN模块单元测试里面开发自测试用例以及验证WLAN模块基本功能。测试环境采用开发者自测试平台(这里以Hi3516DV300标准系统为例)。
...@@ -739,7 +736,8 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台, ...@@ -739,7 +736,8 @@ WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,
上述xxx.xxx.xxx.xxx为当前测试终端的IP地址,若测试能够ping通测试终端则表示,WLAN驱动基本功能正常。 上述xxx.xxx.xxx.xxx为当前测试终端的IP地址,若测试能够ping通测试终端则表示,WLAN驱动基本功能正常。
#### 接口调用 #### 接口使用实例
WLAN驱动模块向上层提供两种能力接口:HDI接口和HAL接口。 WLAN驱动模块向上层提供两种能力接口:HDI接口和HAL接口。
- HDI接口调用 - HDI接口调用
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册