OpenHarmony WLAN HDI 源码学习「建议收藏」

OpenHarmony WLAN HDI 源码学习「建议收藏」文章目录WLAN_HDI一、WILANHAL1.1、IWiFi1.2、IWiFiBaseFeature1.3、Client二、HDIService2.1、Service2.2、IWifiInter

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注