Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
d40c475d
D
Docs
项目概览
OpenHarmony
/
Docs
1 年多 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d40c475d
编写于
8月 25, 2022
作者:
C
chenbotong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
docs:Modify the wlan document
Signed-off-by:
N
chenbotong
<
chenbotong1@huawei.com
>
上级
dfed36f1
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
796 addition
and
378 deletion
+796
-378
zh-cn/device-dev/driver/driver-peripherals-external-des.md
zh-cn/device-dev/driver/driver-peripherals-external-des.md
+796
-378
未找到文件。
zh-cn/device-dev/driver/driver-peripherals-external-des.md
浏览文件 @
d40c475d
...
...
@@ -65,48 +65,46 @@ WLAN Driver框架主要由如下模块组成:
WLAN模块有三部分对外开放的API接口,如下图所示:
1.
驱动直接调用WLAN模块
能力接口。
1.
对上层服务提供HDI以及HAL
能力接口。
2.
提供给各厂商实现的能力接口。
3.
对HDI层提供的能力接口
3.
驱动直接调用WLAN模块能力接口。
**图3**
WLAN驱动接口框架图
!
[
image
](
figures/WLAN驱动接口框架图.png
"WLAN驱动接口框架图"
)
-
WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。
可直接调用的接口如表1、表2和表3所示。
-
WLAN驱动模块对上层服务提供的HDI能力接口(适用于标准系统),主要功能有:创建/销毁ifeature对象、设置/获取功率模式等。提供的部分接口说明如表1所示:
**表1**
wifi_module.h
**表1**
IWlanInterface.idl
| 接口名称 | 功能描述 |
| -------- | -------- |
|
struct
WifiModule
\*WifiModuleCreate(const
struct
HdfConfigWifiModuleConfig
\*
config) | 基于HDF开发WLAN驱动时,创建一个WifiModule
。 |
|
void
WifiModuleDelete(struct
WifiModule
\*
module) | 基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据
。 |
|
int32_t
DelFeature(struct
WifiModule
\*module,
uint16_t
featureType) | 基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件
。 |
|
int32_t
AddFeature(struct
WifiModule
\*module,
uint16_t
featureType,
<br>
struct
WifiFeature
\*
featureData) | 基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule
。 |
|
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); | 设置功率模式
。 |
**表2** wifi_mac80211_ops.h
-
WLAN驱动模块对上层服务提供的HAL能力接口(适用于小型系统及轻量系统),主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如表2、表3所示:
**表2** wifi_hal.h
| 接口名称 | 功能描述 |
| -------- | -------- |
| int32_t
(\*startAp)(NetDevice
\*
netDev) | 启动AP
。 |
| int32_t
(\*stopAp)(NetDevice
\*
netDev) | 停止AP
。 |
| int32_t
(\*
connect)(NetDevice
\*netDev,
WifiConnectParams
\*
param) | 开始关联
。 |
| int32_t
(\*
disconnect)(NetDevice
\*netDev,
uint16_t
reasonCode) | 取消关联
。 |
| int32_t
WifiConstruct(struct
IWiFi
\*\*
wifiInstance) | 创建IWiFi对象,提供IWiFi基本能力
。 |
| int32_t
WifiDestruct(struct
IWiFi
\*\*
wifiInstance) | 销毁IWiFi对象
。 |
| int32_t
(\*
start)(struct
IWiFi
\*
) | 创建HAL和驱动之间的通道及获取驱动支持的网卡信息
。 |
| int32_t
(\*
stop)(struct
IWiFi
\*
) | 销毁通道
。 |
**表3**
hdf_netbuf
.h
**表3**
wifi_hal_base_feature
.h
| 接口名称 | 功能描述 |
| -------- | -------- |
| static
inline
void
NetBufQueueInit(struct
NetBufQueue
\*
q) | 初始化NetBuf队列。 |
| struct
NetBuf
\*NetBufAlloc(uint32_t
size) | 申请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。 |
| int32_t
(\*getFeatureType)(const
struct
IWiFiBaseFeature
\*
) | 获取特性的类型。 |
| int32_t
(\*setMacAddress)(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) | 设置发射功率。 |
-
WLAN驱动模块也提供了需要驱动开发人员自行去填充具体实现内容的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如表4所示:
...
...
@@ -121,133 +119,142 @@ WLAN模块有三部分对外开放的API接口,如下图所示:
| int32_t
(\*open)(struct
NetDevice
\*
netDev) | 打开NetDevice。 |
| int32_t
(\*stop)(struct
NetDevice
\*
netDev) | 关闭NetDevice。 |
-
WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如表5、表6所示:
-
WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。
可直接调用的接口如表5、表6和表7所示。
**表5** wifi_
hal
.h
**表5** wifi_
module
.h
| 接口名称 | 功能描述 |
| -------- | -------- |
|
int32_t
WifiConstruct(struct
IWiFi
\*\*
wifiInstance) | 创建IWiFi对象,提供IWiFi基本能力
。 |
|
int32_t
WifiDestruct(struct
IWiFi
\*\*
wifiInstance) | 销毁IWiFi对象
。 |
| int32_t
(\*start)(struct
IWiFi
\*
) | 创建HAL和驱动之间的通道及获取驱动支持的网卡信息
。 |
| int32_t
(\*stop)(struct
IWiFi
\*
) | 销毁通道
。 |
|
struct
WifiModule
\*WifiModuleCreate(const
struct
HdfConfigWifiModuleConfig
\*
config) | 基于HDF开发WLAN驱动时,创建一个WifiModule
。 |
|
void
WifiModuleDelete(struct
WifiModule
\*
module) | 基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据
。 |
| int32_t
DelFeature(struct
WifiModule
\*module,
uint16_t
featureType) | 基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件
。 |
| int32_t
AddFeature(struct
WifiModule
\*module,
uint16_t
featureType,
<br>
struct
WifiFeature
\*
featureData) | 基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule
。 |
**表6** wifi_
hal_base_feature
.h
**表6** wifi_
mac80211_ops
.h
| 接口名称 | 功能描述 |
| -------- | -------- |
| int32_t
(\*
getFeatureType)(const
struct
IWiFiBaseFeature
\*
) | 获取特性的类型
。 |
| int32_t
(\*s
etMacAddress)(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
(\*
startAp)(NetDevice
\*
netDev) | 启动AP
。 |
| int32_t
(\*s
topAp)(NetDevice
\*
netDev) | 停止AP
。 |
| int32_t
(\*
connect)(NetDevice
\*netDev,
WifiConnectParams
\*
param) | 开始关联
。 |
| int32_t
(\*
disconnect)(NetDevice
\*netDev,
uint16_t
reasonCode) | 取消关联
。 |
**表7** hdf_netbuf.h
### 开发步骤
| 接口名称 | 功能描述 |
| -------- | -------- |
| static
inline
void
NetBufQueueInit(struct
NetBufQueue
\*
q) | 初始化NetBuf队列。 |
| struct
NetBuf
\*NetBufAlloc(uint32_t
size) | 申请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驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。
### 开发步骤
WLAN驱动基于HDF框架和Platform框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。
1.
通过wifi_config.hcs文件,配置硬件(例如module、芯片等)相关的参数。此配置文件
通过HDF框架中对应的接口解析后,生成全量配置的结构体对象。
1.
配置硬件(例如module、芯片等)相关的参数。在wlan_platform.hcs文件中对参数进行配置,该文件会
通过HDF框架中对应的接口解析后,生成全量配置的结构体对象。
2.
Module初始化,创建Module
。
2.
初始化和去初始化WLAN模块相关适配(如WLAN芯片初始化和去初始化、WLAN芯片驱动初始化和去初始化)
。
3.
挂接Chip,初始化Chip
。
3.
控制流命令下发的适配
。
4.
挂接上层WPA(Wi-Fi Protected Access)业务
。
4.
事件上报的调用
。
### 开发实例
本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以Hi3881WLAN芯片为例):
1、根据硬件,
修改配置参数。
1.
根据硬件具体情况
修改配置参数。
```
/* 根据硬件参数,通过wlan_platform.hcs
配置相关参数,以下是WLAN平台配置的示例 */
hisi :& deviceList {
```text
/* 根据硬件具体情况,在wlan_platform.hcs中
配置相关参数,以下是WLAN平台配置的示例 */
hisi :& deviceList {
device0 :: deviceInst {
deviceInstId = 0;
powers {
power0 {
powerSeqDelay = 0; /* 电源序列延时 */
powerType = 1; /* 电源类型:0--总是打开;1--
GPIO */
powerType = 1; /* 电源类型,0表示总是打开;1表示
GPIO */
gpioId = 1; /* GPIO管脚号 */
activeLevel=1; /* 有效电平:0--低;1--高
*/
activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效
*/
}
power1 {
powerSeqDelay = 0; /* 电源序列延时 */
powerType = 0; /* 电源类型:0--总是打开;1--
GPIO */
powerType = 0; /* 电源类型,0表示总是打开;1表示
GPIO */
}
}
reset {
resetType = 0; /* 复位类型:0--不管理;1--
GPIO */
resetType = 0; /* 复位类型,0表示不管理;1表示
GPIO */
gpioId = 2; /* GPIO管脚号 */
activeLevel=1; /* 有效电平:0--低;1--高
*/
activeLevel=1; /* 有效电平,0表示低电平有效;1表示高电平有效
*/
resetHoldTime = 30; /* 复位配置后的等待时间(ms) */
}
bootUpTimeout = 30; /* 启动超时时间(ms) */
bus {
busType = 0; /* 总线类型:0-sdio */
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_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */
root {
wlan_config {
hi3881 :& chipList {
chipHi3881 :: chipInst {
match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */
chipName = "hi3881"; /* WLAN芯片的名称 */
sdio
{
vendorId = 0x0296; /* 厂商Id
*/
deviceId = [0x5347]; /* 设备Id
*/
bus
{
vendorId = 0x0296; /* 厂商ID
*/
deviceId = [0x5347]; /* 设备ID
*/
}
}
}
}
}
```
2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。
```
/* WLAN初始化挂接流程 */
#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)
{
}
```
2.
适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化。
```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__);
HDF_LOGE("%s fail: channel is NULL!
", __func__);
return NULL;
}
(void)device;
(void)ifIndex;
specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver));
if (specificDriver == NULL) {
...
...
@@ -261,7 +268,7 @@ static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uin
}
if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) {
HDF_LOGE("%s fail : strcpy_s fail
", __func__);
HDF_LOGE("%s fail: strcpy_s fail!
", __func__);
OsalMemFree(specificDriver);
return NULL;
}
...
...
@@ -271,11 +278,11 @@ static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uin
HiMac80211Init(specificDriver);
return specificDriver;
}
}
/* 释放WLAN芯片驱动
*/
static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
{
/* 释放WLAN芯片驱动。
*/
static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
{
if (chipDriver == NULL) {
return;
}
...
...
@@ -284,20 +291,20 @@ static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver)
return;
}
OsalMemFree(chipDriver);
}
}
static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) {
static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) {
(void)factory;
return 1;
}
}
/* WLAN芯片相关函数的注册
*/
static int32_t HDFWlanRegHisiDriverFactory(void)
{
/* WLAN芯片相关函数的注册。
*/
static int32_t HDFWlanRegHisiDriverFactory(void)
{
static struct HdfChipDriverFactory tmpFactory = { 0 };
struct HdfChipDriverManager *driverMgr = NULL;
driverMgr = HdfWlanGetChipDriverMgr();
if (driverMgr == NULL && driverMgr->RegChipDriver !
= NULL) {
if (driverMgr =
= NULL) {
HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
return HDF_FAILURE;
}
...
...
@@ -314,45 +321,48 @@ static int32_t HDFWlanRegHisiDriverFactory(void)
}
return HDF_SUCCESS;
}
}
static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device)
{
static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device)
{
(void)device;
return HDFWlanRegHisiDriverFactory();
}
}
struct HdfDriverEntry g_hdfHisiChipEntry = {
struct HdfDriverEntry g_hdfHisiChipEntry = {
.moduleVersion = 1,
.Bind = HdfWlanHisiDriverBind,
.Init = HdfWlanHisiChipDriverInit,
.Release = HdfWlanHisiChipRelease,
.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
/* WLAN芯片的初始化函数 */
int32_t InitHi3881Chip(struct HdfWlanDevice *device)
{
uint8_t maxPortCount = 1;
};
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 = 2
;
if (device
== NULL) {
uint8_t maxRetryCount = 3
;
if (device == NULL || device->bus
== NULL) {
HDF_LOGE("%s:NULL ptr!", __func__);
return HI_FAIL;
}
...
...
@@ -364,7 +374,7 @@ int32_t InitHi3881Chip(struct HdfWlanDevice *device)
}
HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret);
}
ret = hi_wifi_init(maxPortCount
);
ret = hi_wifi_init(maxPortCount, device->bus
);
} while (ret != 0 && --maxRetryCount > 0);
if (ret != 0) {
...
...
@@ -372,81 +382,113 @@ int32_t InitHi3881Chip(struct HdfWlanDevice *device)
return ret;
}
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();
if (ret != 0) {
HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret);
}
return ret;
}
}
/* WLAN芯片驱动的初始化函数 */
int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
{
HDF_LOGI("%s: start...", __func__);
hi_u16 mode = wal_get_vap_mode();
/* 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)
{
/* WLAN芯片驱动的去初始化函数。 */
int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice)
{
int32_t ret;
(void)chipDriver;
int32_t ret = wal_deinit_drv_wlan_netdev(netDevice);
if (ret != HDF_SUCCESS) {
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 ReleasePlatformNetDevice(netDevice);
}
```
return wal_deinit_drv_wlan_netdev(netDevice);
}
3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接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;
在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针。
......
/* 初始化网络设备,获取对应的实例 */
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);
```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的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */
oal_net_device_ops_stru g_wal_net_dev_ops =
{
}
/* 挂接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,
...
...
@@ -455,35 +497,32 @@ oal_net_device_ops_stru g_wal_net_dev_ops =
.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))
#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL))
.selectQueue = wal_netdev_select_queue,
#endif
#endif
.setMacAddr = wal_netdev_set_mac_addr,
#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
.netifNotify = HI_NULL,
#endif
#endif
.specialEtherTypeProcess = SpecialEtherTypeProcess,
};
};
hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev)
{
/* 添加网络设备到协议栈
*/
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;
}
```
4、WifiMac80211Ops中的函数挂接实现。
}
```
```
/* 挂接mac80211的一些函数指针 */
3.
命令下发绑定,包括具有公共能力的设置MAC地址、设置发射功率等;STA相关的连接、扫描等;AP相关的启动AP、设置国家码等。
/* 驱动需要实现的MAC层基本能力的控制接口 */
static struct HdfMac80211BaseOps g_baseOps = {
```c
/* 驱动需要实现的MAC层基本能力的控制接口。 */
static struct HdfMac80211BaseOps g_baseOps = {
.SetMode = WalSetMode,
.AddKey = WalAddKey,
.DelKey = WalDelKey,
...
...
@@ -493,19 +532,19 @@ static struct HdfMac80211BaseOps g_baseOps = {
.SetTxPower = WalSetTxPower,
.GetValidFreqsWithBand = WalGetValidFreqsWithBand,
.GetHwCapability = WalGetHwCapability
};
};
/* 驱动需要实现的MAC层STA能力的控制接口
*/
static struct HdfMac80211STAOps g_staOps = {
/* 驱动需要实现的MAC层STA能力的控制接口。
*/
static struct HdfMac80211STAOps g_staOps = {
.Connect = WalConnect,
.Disconnect = WalDisconnect,
.StartScan = WalStartScan,
.AbortScan = WalAbortScan,
.SetScanningMacAddress = WalSetScanningMacAddress,
};
};
/* 驱动需要实现的MAC层AP能力的控制接口
*/
static struct HdfMac80211APOps g_apOps = {
/* 驱动需要实现的MAC层AP能力的控制接口。
*/
static struct HdfMac80211APOps g_apOps = {
.ConfigAp = WalConfigAp,
.StartAp = WalStartAp,
.StopAp = WalStopAp,
...
...
@@ -514,35 +553,412 @@ static struct HdfMac80211APOps g_apOps = {
.SetCountryCode = WalSetCountryCode,
.GetAssociatedStasCount = WalGetAssociatedStasCount,
.GetAssociatedStasInfo = WalGetAssociatedStasInfo
};
/* 初始化mac80211与芯片侧的函数挂接 */
hi_void HiMac80211Init(struct HdfChipDriver *chipDriver)
{
};
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) {
oam_error_log(0, OAM_SF_ANY,
"%s:input is NULL!", __func__);
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标准系统为例)。
1.
测试验证环境准备。
-
新建hostapd.conf文件(启动AP配置文件)并将以下内容复制到该文件中。
```text
interface=wlan0
driver=hdf wifi
ctrl_interface=udp
#WiFi名称
ssid=test
hw_mode=g
channel=1
ignore_broadcast_ssid=0
wpa=2
rsn_pairwise=CCMP
# WiFi密码
wpa_passphrase=12345678
```
- 新建wpa_supplicant.conf文件(启动STA配置文件)并将以下内容复制到该文件中。
```text
country=GB
network={
#热点名称
ssid="test"
#热点密码
psk="12345678"
}
```
- 新建dhcpc.sh文件(将UDHCPC分配的IP地址等写入到设备中)并将以下内容复制到该文件中。
```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
exit 0
```
- 新建udhcpd.conf文件(启动UDHCPD配置文件)并将以下内容复制到该文件中。
```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 10.221.0.11 8.8.8.8
option subnet 255.255.255.0
opt router 192.168.12.1
```
- 执行下列命令将测试所需文件推送到开发板。
```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.
验证WiFi基本功能。
-
验证AP基本功能
1. 开发板启动AP,测试终端(例如手机)打开WiFi开关(设置 -> WLAN -> 打开WiFi开关)。
2. 使用cmd窗口输入如下命令。
```shell
hdc shell
hostapd ./hostapd.conf
```
3. 使用另一个cmd窗口执行下列命令。
```shell
hdc shell
ifconfig wlan0 192.168.12.1 netmask 255.255.255.0
busybox udhcpd /vendor/etc/udhcpd.conf
```
4. 在手机的WiFi列表中找到对应名称为test的网络,并输入密码(网络名称及密码均在在hostapd.conf中进行配置,成功连接后,手机上可看到已连接)。
5. 使用开发板ping测试终端。
```shell
busybox ping xxx.xxx.xxx.xxx
```
上述xxx.xxx.xxx.xxx为当前测试终端的IP地址,若测试能够ping通测试终端则表示,WLAN驱动基本功能正常。
-
验证STA基本功能
1. 开发板启动STA,测试终端(例如手机)打开热点(网络名称及密码均在在hostapd.conf中进行配置,热点名称为test,密码为12345678)。
2. 使用cmd窗口输入如下命令。
```shell
hdc shell
wpa_supplicant -i wlan0 -d -c wpa_supplicant.conf
```
3. 使用另一个cmd窗口执行下列命令。
```shell
hdc shell
mount -o rw,remount /
mount -o rw,remount /vendor
busybox udhcpc -i wlan0 -s system/lib/dhcpc.sh
```
上述命令执行成功后,回显信息中可以看到单板及测试终端IP地址。
4. 使用开发板ping测试终端。
```shell
busybox ping xxx.xxx.xxx.xxx
```
上述xxx.xxx.xxx.xxx为当前测试终端的IP地址,若测试能够ping通测试终端则表示,WLAN驱动基本功能正常。
3.
验证单元测试用例
HDI模块用例开发步骤(需要测试HDI模块指定接口时,可采用下列步骤):
-
使用WlanInterfaceGetInstance获取WLAN服务对象。
-
使用Start创建HAL和驱动之间的通道及获取驱动网卡信息。
-
通过GetSupportFeature获取该设备支持的WLAN特性。
-
调用Stop,销毁HAL和驱动之间的通道。
-
执行WlanInterfaceRelease销毁WLAN服务对象。
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;
/
* 获取WLAN服务对象。*
/
g_wlanObj = WlanInterfaceGetInstance(WLAN_SERVICE_NAME);
if (g_wlanObj == NULL)
{
return HDF_FAILURE;
}
/
* 创建HAL和驱动之间的通道及获取驱动网卡信息。 *
/
rc = g_wlanObj->Start(g_wlanObj);
if (rc != HDF_SUCCESS)
{
return HDF_FAILURE;
}
/
* 获取该设备支持的WLAN特性(不考虑当前的使用状态)。 *
/
rc = g_wlanObj->GetSupportFeature(g_wlanObj, supType,
&supTypeLen);
if (rc != HDF_SUCCESS)
{
return HDF_FAILURE;
}
/
* 销毁HAL和驱动之间的通道。 *
/
rc = g_wlanObj->Stop(g_wlanObj);
if (rc != HDF_SUCCESS)
{
return HDF_FAILURE;
}
/
* 销毁WLAN服务对象。 *
/
rc = WlanInterfaceRelease(g_wlanObj);
if (rc != HDF_SUCCESS)
{
return HDF_FAILURE;
}
return rc;
}
```
HAL模块用例开发步骤(需要测试HAL模块指定接口时,可采用下列步骤):
- 使用WifiConstruct创建一个WiFi实体。
- 用创建的WiFi实体调用start开启HAL和驱动之间的通道,获得驱动网卡的信息。
- 通过createFeature创建一个apFeature或者staFeature。后面可通过这些Feature去调用具体的实现接口,下面基于创建的apFeature为例进行介绍。
- 调用和使用相关接口:如setMacAddress设置MAC地址、getDeviceMacAddress获取设备的MAC地址等。
- 调用destroyFeature,销毁掉创建的apFeature。
- 调用stop销毁创建的通道。
- 执行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;
/* 创建一个wifi实体。 */
ret = WifiConstruct(&wifi);
if (ret != HDF_SUCCESS || wifi == NULL) {
return HDF_FAILURE;
}
/* 开启HAL和驱动之间的通道,获得驱动网卡的信息。 */
ret = wifi->start(wifi);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
/* 创建apFeature。 */
ret = wifi->createFeature(PROTOCOL_80211_IFTYPE_AP, (struct IWiFiBaseFeature **)&apFeature);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
/* 获取设备MAC地址。 */
unsigned char mac[MAC_LEN] = {0};
ret = apFeature->baseFeature.getDeviceMacAddress((struct IWiFiBaseFeature *)apFeature, mac, MAC_LEN);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
/* 销毁创建的apFeature。 */
ret = wifi->destroyFeature((struct IWiFiBaseFeature *)apFeature);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
/* 销毁HAL和驱动之间的通道。 */
ret = wifi->stop(wifi);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
/* 销毁创建的WiFi实体。 */
ret = WifiDestruct(&wifi);
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
return ret;
}
```
4.
验证测试用例方法如下
1.
将测试用例推送到单板。
```shell
hdc file send /xxx /data
```
xxx表示需要推送到单板根目录的测试用例路径。
2.
修改测试用例权限并执行该用例。
```shell
hdc shell
cd data
chmod 777 测试用例名称
./测试用例名称
```
查看测试用例执行结果是否正确。
## 参考
-
代码仓库如下:
[
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
)
-
代码路径如下:
WLAN模块流控组件liteos适配://drivers/hdf_core/adapter/khdf/liteos/model/network/wifi
HDF网络模型liteos适配://drivers/hdf_core/adapter/khdf/liteos/model/network
WLAN模块流控组件Linux适配、HDF WLAN模型
及
VENDOR WLAN驱动编译:
WLAN模块流控组件Linux适配、HDF WLAN模型
、
VENDOR WLAN驱动编译:
//drivers/hdf_core/adapter/khdf/linux/model/network/wifi
...
...
@@ -552,4 +968,6 @@ hi_void HiMac80211Init(struct HdfChipDriver *chipDriver)
HDF网络模型接口://drivers/hdf_core/framework/include/net
WLAN HDI接口及具体实现://drivers/peripheral/wlan
WLAN HDI服务端实现://drivers/peripheral/wlan
WLAN HDI对外接口://out/{product_name}/gen/drivers/interface/wlan/v1_0
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录