文章目录
WLAN_HDI
关于WLAN HDI的介绍,可见官网文档,其结构可如图所示:
WLAN HDI 目的是提供接口给 Wi-Fi Service调用,其提供的功能有:启动/关闭WLAN,查看连接状态,注册回调函数,启动wlan扫描等。
一、WILAN HAL
WLAN HAL模块作为HDI的中间层,提供给Wi-Fi service IWiFi 对象,以及IWiFiSta、IWiFiAp、IWiFiBaseFeature对象来发送和接受WLAN 命令。
struct IWiFi {
//打开hal层和driver的通道
int32_t (*start)(struct IWiFi *iwifi);
//关闭hal层和driver的通道
int32_t (*stop)(struct IWiFi *iwifi);
//获取wifi驱动支持的feature
int32_t (*getSupportFeature)(uint8_t *supType, uint32_t size);
//获取wifi驱动支持的feature组合
int32_t (*getSupportCombo)(uint64_t *combo, uint32_t size);
//创建一个feature
int32_t (*createFeature)(int32_t type, struct IWiFiBaseFeature **ifeature);
int32_t (*getFeatureByIfName)(const char *ifName, struct IWiFiBaseFeature **ifeature);
//注册回调函数监听 wifi event
int32_t (*registerEventCallback)(CallbackFunc cbFunc, const char *ifName);
int32_t (*unregisterEventCallback)(CallbackFunc cbFunc, const char *ifName);
int32_t (*destroyFeature)(struct IWiFiBaseFeature *ifeature);
//复位芯片驱动程序
int32_t (*resetDriver)(const uint8_t chipId, const char *ifName);
//get net device infos.
int32_t (*getNetDevInfo)(struct NetDeviceInfoResult *netDeviceInfoResult);
};
1.1、IWiFi
WifiConstruct用于创建 IWiFi 对象,并对其函数赋值。开发者就可以调用IWiFi对象的方法创建IWiFiSta、IWiFiAp、IWiFiBaseFeature对象。再通过这三个对象发送具体的WIFI命令
int32_t WifiConstruct(struct IWiFi **wifiInstance)
{
static bool isInited = false;
static struct IWiFi singleWifiInstance;
if (!isInited) {
if (HalMutexInit() != HDF_SUCCESS) {
HDF_LOGE("%s: HalMutexInit failed, line: %d\n", __FUNCTION__, __LINE__);
return HDF_FAILURE;
}
//给函数赋值
singleWifiInstance.start = Start;
singleWifiInstance.stop = Stop;
singleWifiInstance.getSupportFeature = GetSupportFeature;
singleWifiInstance.getSupportCombo = GetSupportCombo;
singleWifiInstance.createFeature = CreateFeature;
singleWifiInstance.getFeatureByIfName = GetFeatureByIfName;
singleWifiInstance.destroyFeature = DestroyFeature;
singleWifiInstance.registerEventCallback = HalRegisterEventCallback;
singleWifiInstance.unregisterEventCallback = HalUnregisterEventCallback;
singleWifiInstance.resetDriver = ResetDriver;
singleWifiInstance.getNetDevInfo = GetNetDevInfo;
InitIWiFiList();
isInited = true;
}
(*wifiInstance) = &singleWifiInstance;
return HDF_SUCCESS;
}
1.2、IWiFiBaseFeature
IWiFiSta、IWiFiAp都是基于IWiFiBaseFeature的扩展,我们以IWiFiSta 为例,了解HAL层是如何发送命令的。
struct IWiFiSta {
//继承了IWiFiBaseFeature
struct IWiFiBaseFeature baseFeature;
//扫描指定的mac地址
int32_t (*setScanningMacAddress)(const struct IWiFiSta *staFeature, unsigned char *scanMac, uint8_t len);
//开始扫描
int32_t (*startScan)(const char *ifName, WifiScan *scan);
};
struct IWiFiBaseFeature {
char ifName[IFNAME_MAX_LEN];
int32_t type;
//获取网卡名称
const char *(*getNetworkIfaceName)(const struct IWiFiBaseFeature *baseFeature);
//获取feature类型
int32_t (*getFeatureType)(const struct IWiFiBaseFeature *baseFeature);
//设置mac地址
int32_t (*setMacAddress)(const struct IWiFiBaseFeature *baseFeature, unsigned char *mac, uint8_t len);
//获取设备mac地址
int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *baseFeature, unsigned char *mac, uint8_t len);
//获取wifi带宽
int32_t (*getValidFreqsWithBand)(const struct IWiFiBaseFeature *baseFeature, int32_t band, int32_t *freqs,
uint32_t count, uint32_t *num);
//设置发送电源
int32_t (*setTxPower)(const struct IWiFiBaseFeature *baseFeature, int32_t power);
//获取芯片id
int32_t (*getChipId)(const struct IWiFiBaseFeature *baseFeature, uint8_t *chipId);
//获取网口名称
int32_t (*getIfNamesByChipId)(const uint8_t chipId, char **ifNames, uint32_t *num);
};
首先是创建IWiFiSta,需要调用 IWiFi 对象的createFeature()方法创建,具体的内容就是填充IWiFiSta对象中的方法。
下面就以createFeature()为例,学习feature的函数是如何发送命令到wifi驱动的。
//createFeature调用CreateFeatureInner
static int32_t CreateFeatureInner(int32_t type, struct IWiFiBaseFeature **ifeature)
{
//init feature
ret = InitFeatureByType(type, ifeature);
ret = FindValidNetwork(type, ifeature);
return HDF_SUCCESS;
}
//根据不同类型的feature,调用不同的接口
static int32_t InitFeatureByType(int32_t type, struct IWiFiBaseFeature **ifeature)
{
int32_t ret;
switch (type) {
case PROTOCOL_80211_IFTYPE_AP:
*ifeature = (struct IWiFiBaseFeature *)malloc(sizeof(struct IWiFiAp));
(void)memset_s(*ifeature, sizeof(struct IWiFiAp), 0, sizeof(struct IWiFiAp));
ret = InitApFeature((struct IWiFiAp **)ifeature);
break;
case PROTOCOL_80211_IFTYPE_STATION:
*ifeature = (struct IWiFiBaseFeature *)malloc(sizeof(struct IWiFiSta));
(void)memset_s(*ifeature, sizeof(struct IWiFiSta), 0, sizeof(struct IWiFiSta));
ret = InitStaFeature((struct IWiFiSta **)ifeature);
break;
default:
HDF_LOGE("%s: type not support, line: %d", __FUNCTION__, __LINE__);
return HDF_FAILURE;
}
return ret;
}
首先调用InitBaseFeature()来初始化basefeature,再添加IWiFiSta独有的函数。
int32_t InitStaFeature(struct IWiFiSta **fe)
{
if (InitBaseFeature((struct IWiFiBaseFeature **)fe) != HDF_SUCCESS) {
HDF_LOGE("%s: init base feature, line: %d", __FUNCTION__, __LINE__);
return HDF_FAILURE;
}
(*fe)->setScanningMacAddress = SetScanningMacAddress;
(*fe)->startScan = StartScan;
return HDF_SUCCESS;
}
创建完成IWiFiSta,就可以使用其接口来发送WIFI命令。
下面就以startScan命令为例子,加上互斥锁是因为wifi芯片同一时间只能响应一个命令。
static int32_t StartScan(const char *ifName, WifiScan *scan)
{
//加互斥锁,不能被其他命令打断执行
HalMutexLock();
//StartScanInner()最终调用sbuf_cmd_adapter.c中的WifiCmdScan()
int32_t ret = StartScanInner(ifName, scan);
HalMutexUnlock();
return ret;
}
StartScanInner()最终调用sbuf_cmd_adapter.c中的WifiCmdScan():
int32_t WifiCmdScan(const char *ifName, WifiScan *scan)
{
int32_t ret;
struct HdfSBuf *data = NULL;
data = HdfSBufObtainDefaultSize();
bool isSerializeFailed = false;
isSerializeFailed = isSerializeFailed || !HdfSbufWriteString(data, ifName);
if (scan->bssid == NULL) {
isSerializeFailed = isSerializeFailed || !HdfSbufWriteBuffer(data, scan->bssid, 0);
} else {
isSerializeFailed = isSerializeFailed || !HdfSbufWriteBuffer(data, scan->bssid, ETH_ADDR_LEN);
}
isSerializeFailed =
isSerializeFailed || !HdfSbufWriteBuffer(data, scan->ssids, sizeof(scan->ssids[0]) * scan->numSsids);
isSerializeFailed = isSerializeFailed || !HdfSbufWriteBuffer(data, scan->extraIes, scan->extraIesLen);
isSerializeFailed =
isSerializeFailed || !HdfSbufWriteBuffer(data, scan->freqs, sizeof(scan->freqs[0]) * scan->numFreqs);
isSerializeFailed = isSerializeFailed || !HdfSbufWriteUint8(data, scan->prefixSsidScanFlag);
isSerializeFailed = isSerializeFailed || !HdfSbufWriteUint8(data, scan->fastConnectFlag);
if (isSerializeFailed) {
HILOG_ERROR(LOG_DOMAIN, "%s: Serialize failed!", __FUNCTION__);
ret = RET_CODE_FAILURE;
} else {
//发送命令给WLAN 驱动
ret = SendCmdSync(WIFI_WPA_CMD_SCAN, data, NULL);
}
HdfSBufRecycle(data);
return ret;
}
sbuf_cmd_adapter.c中的函数把所有的WIFI命令封装成sbuf类型,并调用 HDF 驱动的消息机制给 HDF_WIFI驱动发送命令。
static int32_t SendCmdSync(const uint32_t cmd, struct HdfSBuf *reqData, struct HdfSBuf *respData)
{
int32_t ret = g_wifiService->dispatcher->Dispatch(&g_wifiService->object, cmd, reqData, respData);
return ret;
}
1.3、Client
SendCmdSync()函数中使用了 g_wifiService 变量,该变量是 HdfIoService类型,在调用IWiFi的start方法时,会初始化该变量:
int32_t WifiDriverClientInit(void)
{
int32_t ret;
if (g_wifiService == NULL) {
//绑定 hdfwifi 服务
g_wifiService = HdfIoServiceBind(DRIVER_SERVICE_NAME);
}
//注册回调函数
g_wifiDevEventListener.onReceive = OnWiFiEvents;
return ret;
}
除了绑定服务,向服务发送消息外,还注册了回调函数OnWiFiEvents(),在该函数中,根据eventId调用不同的函数来处理驱动上报的消息,把消息从sbuf转换成普通的类型数据。(如何注册回调函数看最后)
int OnWiFiEvents(struct HdfDevEventlistener *listener,struct HdfIoService *service, uint32_t eventId, struct HdfSBuf *data)
{
const char *ifName = HdfSbufReadString(data);
//处理不同的wifi事件
switch (eventId) {
case WIFI_EVENT_NEW_STA:
WifiEventNewStaProcess(ifName, eventId, data);
break;
case WIFI_EVENT_DEL_STA:
WifiEventDelStaProcess(ifName, eventId, data);
break;
......
default:
break;
}
}
//以WifiEventNewStaProcess为例子
static void WifiEventNewStaProcess(const char *ifName, uint32_t event, struct HdfSBuf *reqData)
{
WifiNewStaInfo staInfo;
//提取reqData的数据到staInfo
if (!HdfSbufReadInt32(reqData, &staInfo.reassoc)) {
HILOG_ERROR(LOG_DOMAIN, "%s: fail to get reassoc", __FUNCTION__);
return;
}
if (!HdfSbufReadBuffer(reqData, (const void **)(&staInfo.ie), &staInfo.ieLen)) {
HILOG_ERROR(LOG_DOMAIN, "%s: fail to get ie", __FUNCTION__);
return;
}
if (!HdfSbufReadBuffer(reqData, (const void **)(&staInfo.macAddr), &len) || (len != ETH_ADDR_LEN)) {
HILOG_ERROR(LOG_DOMAIN, "%s: fail to get macAddr", __FUNCTION__);
return;
}
//上报到IWiFi
WifiEventReport(ifName, event, &staInfo);
}
WifiEventReport()调用HAL 层注册的回调函数:
void WifiEventReport(const char *ifName, uint32_t event, void *data)
{
uint32_t i;
//IWiFi 注册的回调函数保存在g_callbackEventMap
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_callbackEventMap[i] != NULL && (strcmp(g_callbackEventMap[i]->ifName, ifName) == 0) &&
(((1 << event) & g_callbackEventMap[i]->eventType) != 0)) {
//调用回调函数 通知事件的发送
g_callbackEventMap[i]->onRecFunc(event, data, ifName);
}
}
}
二、HDI Service
HAL层的上一层是HDI Service,他将WLAN HAL层的IWiFiSta、IWiFiAp、IWiFiBaseFeature封装到一个对象 IWifiInterface 中,使其更方便用户使用。
HDI Service 分为两个部分:
- Services:作为HDF驱动模块,调用WLAN HAL 提供的对象,并提供服务给IWifiInterface。
- IWifiInterface:订阅 HDI Service驱动服务,提供统一接口给用户。
2.1、Service
作为一个HDF驱动模块,他必须有初始化函数,bind函数:
struct HdfDriverEntry g_wlanHdiDriverEntry = {
.moduleVersion = 1,
.moduleName = "wlan_device",
.Bind = HdfWlanHdiDriverBind,
.Init = HdfWlanHdiDriverInit,
.Release = HdfWlanHdiDriverRelease,
};
HDF_INIT(g_wlanHdiDriverEntry);
重点是dispatch()函数的实现:WlanHdiServiceDispatch()
在WlanHdiServiceOnRemoteRequest()中根据命令id调用不同的函数,这些函数最终都会调用WLAN HAL层提供的接口。
static int32_t WlanHdiServiceDispatch(struct HdfDeviceIoClient *client, int cmdId,
struct HdfSBuf *data, struct HdfSBuf *reply)
{
return WlanHdiServiceOnRemoteRequest(client, cmdId, data, reply);
}
int32_t WlanHdiServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId,
struct HdfSBuf *data, struct HdfSBuf *reply)
{
switch (cmdId) {
case WLAN_SERVICE_CONSTRUCT:
return HdiWifiConstruct(client, data, reply);
case WLAN_SERVICE_DECONSTRUCT:
return HdiWifiDeConstruct(client, data, reply);
case WLAN_SERVICE_START:
return WlanServiceStubStart(client, data, reply);
......
default:
HDF_LOGW("SampleServiceDispatch: not support cmd %d", cmdId);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
例如:WlanServiceStubStart()
static int32_t WlanServiceStubStart(struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
ret = g_wifi->start(g_wifi);
return ret;
}
2.2、IWifiInterface
IWifiInterface对象通过订阅HDI Service驱动服务,把所有的WIFI命令整合到一起,相比直接使用HAL 层接口更加简单方便。
调用HdIWifiInterfaceGet会帮我们创建IWifiInterface对象:
struct IWifiInterface *HdIWifiInterfaceGet(const char *serviceName)
{
struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
//绑定hdi service
struct HdfRemoteService *remote = serviceMgr->GetService(serviceMgr, serviceName);
//create IWifiInterface
struct IWifiInterface *wlanClient = (struct IWifiInterface *)OsalMemAlloc(sizeof(struct IWifiInterface));
wlanClient->remote = remote;
IwifiConstruct(wlanClient);
return wlanClient;
}
//构建IWifiInterface对象
static void IwifiConstruct(struct IWifiInterface *inst)
{
inst->construct = WlanConstruct;
inst->destruct = WlanDestruct;
......
inst->getNetDevInfo = WlanGetNetDevInfo;
inst->startScan = WlanStartScan;
}
IWifiInterface 使用HDF 驱动消息机制 来和service通信,以WlanStart命令为例子:
static int32_t WlanStart(struct IWifiInterface *self)
{
int32_t ec = HDF_FAILURE;
//创建sbuf
struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC);
struct HdfSBuf *reply = HdfSBufTypedObtain(SBUF_IPC);
//发送WLAN_SERVICE_START命令
ec = WlanProxyCall(self, WLAN_SERVICE_START命令, data, reply);
}
static int32_t WlanProxyCall(struct IWifiInterface *self, int32_t id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
//给 hdi service驱动服务发送消息
return self->remote->dispatcher->Dispatch(self->remote, id, data, reply);
}
三、注册WLAN回调函数
HAL 层提供了回调函数来监听wifi event。具体的实现是在wifi_driver_client.c
HalRegisterEventCallback()实现将onRecFunc函数赋值到全局变量g_callbackEventMap[];
static int32_t HalRegisterEventCallback(OnReceiveFunc onRecFunc, const char *ifName)
{
HalMutexLock();
int32_t ret = RegisterEventCallbackInner(onRecFunc, ifName);
HalMutexUnlock();
return ret;
}
static int32_t RegisterEventCallbackInner(OnReceiveFunc onRecFunc, const char *ifName)
{
if (WifiRegisterEventCallback(onRecFunc, WIFI_KERNEL_TO_HAL_CLIENT, ifName) != HDF_SUCCESS) {
HDF_LOGE("%s: callback function has been registered, line: %d", __FUNCTION__, __LINE__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t WifiRegisterEventCallback(OnReceiveFunc onRecFunc, uint32_t eventType, const char *ifName)
{
uint32_t i;
struct CallbackEvent *callbackEvent = NULL;
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
//checkout event type and ifname
if (g_callbackEventMap[i] != NULL && g_callbackEventMap[i]->eventType == eventType &&
(strcmp(g_callbackEventMap[i]->ifName, ifName) == 0) && g_callbackEventMap[i]->onRecFunc == onRecFunc)
{
HILOG_INFO(LOG_DOMAIN, "%s the onRecFunc has been registered!", __FUNCTION__);
return RET_CODE_SUCCESS;
}
}
//create new callbackEvent
callbackEvent = (struct CallbackEvent *)malloc(sizeof(struct CallbackEvent));
//config callbackEvent
callbackEvent->eventType = eventType;
if (strcpy_s(callbackEvent->ifName, IFNAMSIZ, ifName) != RET_CODE_SUCCESS) {
free(callbackEvent);
return RET_CODE_FAILURE;
}
callbackEvent->onRecFunc = onRecFunc;
//add onRecFunc to the g_callbackEventMap[]
for (i = 0; i < MAX_CALL_BACK_COUNT; i++) {
if (g_callbackEventMap[i] == NULL) {
g_callbackEventMap[i] = callbackEvent;
return RET_CODE_SUCCESS;
}
}
free(callbackEvent);
HILOG_ERROR(LOG_DOMAIN, "%s fail: register onRecFunc num more than %d!", __FUNCTION__, MAX_CALL_BACK_COUNT);
return RET_CODE_FAILURE;
}
g_callbackEventMap[]是固定长度的数组,其中存放所有wifi事件的回调函数,wifi event的类型定义在wifi_common_cmd.h中。
struct CallbackEvent {
uint32_t eventType; //eventmap
char ifName[IFNAMSIZ + 1];
OnReceiveFunc onRecFunc;
};
static struct CallbackEvent *g_callbackEventMap[MAX_CALL_BACK_COUNT] = {
NULL};
今天的文章OpenHarmony WLAN HDI 源码学习「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89208.html