OpenHarmony HDF WIFI之WLAN_HDI(中) 原创 精华

发布于 2022-4-9 09:48
浏览
0收藏

下面就以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};

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐