OpenHarmony HDF WIFI之WLAN Message 原创 精华

杀手来过
发布于 2022-4-9 09:49
浏览
1收藏

@[toc]

WLAN message

来自HDI client端的命令主要分三个类型:BaseCommands、APCommands、STACommands。

针对不同类型的CMD,也有三个服务来响应这些命令,分别是base feature、ap feature、sta feature。这三个feature定义在/drivers/framework/model/network/wifi/core/components下。

一、ServiceDef

驱动设计了一套message机制来响应来自HDI的命令,我们先把HDI的命令理解为message,才能使用这套机制,本文用于了解wlan message。

MessageDef:把HDI client命令理解成message,其成员MessageHandler是函数指针,指向处理命令的函数,pri是函数参数。

struct MessageDef {
    MessageHandler handler;
    uint8_t pri;
};

在wlan 驱动中定义了三个MessageDef数组,分别用于处理三种类型的HDI message。例如sta.c中定义了5个成员的数组,用于处理5个具体的sta命令。

//messagedef of servicedef
static struct MessageDef g_wifiStaFeatureCmds[] = {
    //DUEMessage(index,MessageHandler,pri)
    DUEMessage(CMD_STA_CONNECT, WifiCmdAssoc, 0),
    DUEMessage(CMD_STA_DISCONNECT, WifiCmdDisconnect, 0),
    DUEMessage(CMD_STA_SCAN, WifiCmdScan, 0),
    DUEMessage(CMD_STA_ABORT_SCAN, WifiCmdAbortScan, 0),
    DUEMessage(CMD_STA_SET_SCAN_MAC_ADDR, WifiCmdSetScanningMacAddress, 0)
};

同时还要注意到g_wifiStaFeatureCmds下方有一句宏定义:将该宏定义展开,可得到函数CreateServiceSTAService(),该函数创建了一个ServiceDef结构体,并调用InitService()函数

ServiceDefine(STAService, STA_SERVICE_ID, g_wifiStaFeatureCmds);
/**               
    Service *CreateServiceSTAService(const ServiceCfg *cfg)                
    {                                                                         
        static struct ServiceDef serviceDef = {                               
            .serviceId = STA_SERVICE_ID,                                          
            .messagesLength = sizeof(g_wifiStaFeatureCmds) / sizeof(struct MessageDef), 
            .messages = g_wifiStaFeatureCmds                                            
        };                                                                    
        return InitService(&serviceDef, cfg);                                 
    }
 */

这里就引入了ServiceDef对象,他不仅包含MessageDef,还有ServiceId,以及messagesLength。整个驱动一共有三个ServiceDef,分别为三种类型的message提供服务响应。

struct ServiceDef {
    ServiceId serviceId;	//DispatcherId dispatcherId,用于指示是baseservice,staservice,apservice
    uint8_t messagesLength;
    struct MessageDef *messages;
};

二、RemoteService()

InitService()函数在sidecar.c中,其主要作用就是创建Service结构体,调用RegistLocalService()

//create sidecar service and remote service,the cfg is defaultid 
Service *InitService(struct ServiceDef *def, const ServiceCfg *cfg)
{
    Service *service = (Service *)OsalMemCalloc(sizeof(Service));
	//init some funcs
    service->SendAsyncMessage = SideCarSendAsyncMessage;
    service->SendSyncMessage = SideCarSendSyncMessage;
    service->SendOneWayMessage = SideCarSendOneWayMessage;
    service->Destroy = DestroyService;

    SideCarPrivateData *privateData = (SideCarPrivateData *)OsalMemCalloc(sizeof(SideCarPrivateData));
    privateData->serviceId = def->serviceId;
    privateData->dispatcherId = cfg->dispatcherId;
    service->privateData = (void *)privateData;
    privateData = NULL;

    //init remote service
    ErrorCode errCode = RegistLocalService(cfg->dispatcherId, def);
    return service;
}

RegistLocalService调用RegistServiceInner。主要完成RemoteService的创建。

//create remote service
static ErrorCode RegistServiceInner(const NodeId nodeId, const DispatcherId dispatcherId, struct ServiceDef *mapper)
{
    HDF_STATUS status = OsalMutexTimedLock(&g_routerMutex, HDF_WAIT_FOREVER);

    //get default message node
    MessageNode *node = RefMessageNode(nodeId, false);
    
    RemoteService *remoteService = NULL;
    MessageDispatcher *dispatcher = NULL;

    do {
        //get default dispatch
        dispatcher = RefDispatcherInner(dispatcherId, false);
		// CreateLocalNodeService(node,dispatcher, mapper)
        remoteService = node->CreateRemoteService(node, dispatcher, mapper);

        errCode = NotifyAllNodesServiceAdd(nodeId, mapper);
		//add remoteService to g_servicesIndex[]
        errCode = DoRegistService(nodeId, dispatcherId, remoteService);

    } while (false);

    status = OsalMutexUnlock(&g_routerMutex);
    if (dispatcher != NULL && dispatcher->Disref != NULL) {
        //realease dispatcher
        dispatcher->Disref(dispatcher);
    }
    if (node != NULL && node->Disref != NULL) {
        node->Disref(node);
    }
    return errCode;
}

这里一个新的重要的结构体 RemoteService,但我们先暂时按下不表,来看他是如何被创建的。

2.1、MessageNode

创建 RemoteService的方式是调用node->CreateRemoteService()函数,所以这个函数执行的前提是MessageNode先被创建出来,我们需要先知道MessageNode是如何被创建的,才能知道RemoteService被创建时的参数。

MessageNode的创建函数是CreateLocalNode(),定义在local_node.c中,这里我们仅需要关注CreateRemoteService函数指针的实现:CreateLocalNodeService()

ErrorCode CreateLocalNode(MessageNode **node)
{
    LocalMessageNode *newNode = (LocalMessageNode *)OsalMemCalloc(sizeof(LocalMessageNode));
    do {
        newNode->status = ME_STATUS_STOPPED;
        newNode->Init = InitLocalNode;
        //创建remote service的方法
        newNode->CreateRemoteService = CreateLocalNodeService;
        newNode->SyncService = NULL;
        newNode->NotifyServiceAdd = NULL;
        newNode->NotifyServiceDel = NULL;
    } while (false);
    return errCode;
}

2.2、LocalNodeService

CreateLocalNodeService()创建了RemoteService的超集LocalNodeService。这里实现了RemoteService中的许多函数,并把之前定义的ServiceDef,和dispatch赋值给LocalNodeService。(dispatch在后面介绍)

RemoteService *CreateLocalNodeService(MessageNode *node, MessageDispatcher *dispatcher, struct ServiceDef *mapper)
{
    //create local node service
    LocalNodeService *service = (LocalNodeService *)OsalMemCalloc(sizeof(LocalNodeService));

    ErrorCode errCode;
    do {
        //realize some funcs
        service->status = ME_STATUS_RUNNING;
        //重点
        service->ExecRequestMsg = HandleRequestMessage;
        service->ExecResponseMsg = HandleResponseMessage;
        service->SendMessage = SendMessageLocalNode;
        service->Shutdown = ShutdownLocalService;
        service->serviceId = mapper->serviceId;
        service->mapper = mapper;
        service->dispatcher = dispatcher->Ref(dispatcher);
    } while (false);
    return (RemoteService *)service;
}

LocalNodeService 展开宏定义后,可见LocalNodeService 就是RemoteService再加上MessageDispatcher和ServiceDef。

所以本质上也是创建RemoteService。

//展开宏定义后
typedef struct LocalNodeService {
    enum MessageEngineStatus status;                
    OsalAtomic refCount;                            
    struct RemoteService *(*Ref)(struct RemoteService * obj); 
    void (*Disref)(struct RemoteService * obj);          
    void (*Destroy)(struct RemoteService * obj);
    //发送请求消息
    void (*ExecRequestMsg)(const struct RemoteService *service, MessageContext *context);  
    //发送响应消息
    void (*ExecResponseMsg)(const struct RemoteService *service, MessageContext *context);  
    //发送消息
    ErrorCode (*SendMessage)(const struct RemoteService *service, MessageContext *context); 
    void (*Shutdown)(struct RemoteService * service);   
    //service类型:base、ap、sta
    ServiceId serviceId;    
    //dispatch用于缓存消息
    MessageDispatcher *dispatcher;
    //响应消息的服务
    struct ServiceDef *mapper;
} LocalNodeService;

到此我们创建了一个响应HDI层命令所需的结构体。

三、MessageDispatcher

其作用主要是缓存message,实现的方法是使用优先级队列来缓存message,在RunDispatcher线程中处理message。

typedef struct MessageDispatcher {
    SHARED_OBJ(MessageDispatcher); 
    OSAL_DECLARE_MUTEX(mutex); 
    ErrorCode (*AppendMessage)(struct MessageDispatcher *, const uint8_t priority, MessageContext * context); 	//将message缓存
    ErrorCode (*Start)(struct MessageDispatcher * dispatcher);                        
    void (*Shutdown)(struct MessageDispatcher * dispatcher);                          
    PriorityQueue *messageQueue
} MessageDispatcher;

RunDispatcher线程:

static int RunDispatcher(void *para){
    while (dispatcher->status == ME_STATUS_RUNNING) {
        //pop message
        MessageContext *context = PopPriorityQueue(dispatcher->messageQueue, QUEUE_OPER_TIMEOUT);
        if (context == NULL) {
            continue;
        }
        HandleMessage(context);
    }
}

static void HandleMessage(MessageContext *context)
{
    if (context != NULL) {
        switch (context->requestType) {
            case MESSAGE_TYPE_SYNC_REQ:
            case MESSAGE_TYPE_ASYNC_REQ:
                HandleRequestMessage(context);
                break;
            case MESSAGE_TYPE_SYNC_RSP:
                HandleSyncResponse(context);
                break;
            case MESSAGE_TYPE_ASYNC_RSP:
                HandleAsyncResponse(context);
                break;
            default:
                HDF_LOGE("Unsupported message type %u", context->requestType);
        }
    }
}

static void HandleSyncResponse(MessageContext *context)
{
    HDF_STATUS status = OsalSemPost(&context->rspSemaphore);
    return;
}
//调用remoteservice->ExecRequestMsg和SendMessage
static void HandleRequestMessage(MessageContext *context)
{
    RemoteService *targetService = RefRemoteService(context->receiverId);
    do {
        targetService->ExecRequestMsg(targetService, context);
        // Convert to response message
        SetToResponse(context);
        rspService = RefRemoteService(context->receiverId);
        errCode = rspService->SendMessage(rspService, context);
    } while (false);
}

CreateLocalDispatcher用于创建MessageDispatcher,这里我们关注AppendMessage的实现:AppendToLocalDispatcher(),其本质就是将message推入指定的queue,然后在RunDispatcher线程中会弹出队列中的message,对message进行响应。

ErrorCode CreateLocalDispatcher(MessageDispatcher **dispatcher, const DispatcherConfig *config)
{
    LocalMessageDispatcher *localDispatcher = (LocalMessageDispatcher *)OsalMemCalloc(sizeof(LocalMessageDispatcher));
    ErrorCode errCode;
    do {
        //realize some func
        localDispatcher->status = ME_STATUS_STOPPED;
        localDispatcher->AppendMessage = AppendToLocalDispatcher;
        localDispatcher->Shutdown = ShutdownDispatcher;
        localDispatcher->Start = StartDispatcher;
		//create queues
        localDispatcher->messageQueue = CreatePriorityQueue(config->queueSize, config->priorityLevelCount);
    } while (false);
}

ErrorCode AppendToLocalDispatcher(MessageDispatcher *dispatcher, const uint8_t priority, MessageContext *context)
{
    return PushPriorityQueue(dispatcher->messageQueue, priority, context);
}

int32_t PushPriorityQueue(PriorityQueue *queue, const uint8_t priority, void *context)
{
    queueImpl = (PriorityQueueImpl *)queue;
    pri = priority;
    ret = PushQueue(queueImpl->queues[pri], context);
}

四、sidecar

创建完成以上结构体后,wifi驱动框架究竟如何来响应来自HDI层的命令呢?也就是说我们上面所做的一切为了什么?

在HDF_WIFI驱动的dispatch函数中,调用的是DispatchToMessage()函数,该函数定义在sidecar.c中。sidecar.c就是封装了上面的结构体,提供接口给HDF_WIFI驱动使用,起到连接中介的作用。要注意到,驱动的命令是以id+HdfSBuf的形式传递进来的,需要转换成我们之前一直提到的message,才能由message系统来处理。

HDI client下发的命令通过io-dispatch会传递到DispatchToMessage()函数:

DispatchToMessage首先创建message,获取之前创建的LocalNodeService结构体中的RemoteService,调用其SendMessage()函数

int32_t DispatchToMessage(struct HdfDeviceIoClient *client, int id, struct HdfSBuf *reqData, struct HdfSBuf *rspData)
{
    //create message
    context = CreateMessageContext(RESERVED_SERVICE_ID, serviceId, cmd, reqData);

    context->rspData = rspData;
    context->requestType = MESSAGE_TYPE_SYNC_REQ;
    context->client = client;
    RemoteService *targetService = NULL;
    do {
        //get LocalNodeService
        targetService = RefRemoteService(serviceId);
        //SendMessage = SendMessageLocalNode()
        errCode = targetService->SendMessage(targetService, context);
    } while (false);
    if (targetService != NULL && targetService->Disref != NULL) {
        targetService->Disref(targetService);
    }
    OsalMemFree(context);
    return errCode;
}

在创建LocalNodeService时我们已经指定了SendMessage()函数的实现:

SendMessage()根据message类型作不同的处理:

  • sync:同步类消息需要马上传递处理
  • async:异步类消息由RunDispatcher线程稍后处理
ErrorCode SendMessageLocalNode(const RemoteService *service, MessageContext *context)
{
    //sync req need respone
    if (!context->crossNode && context->requestType == MESSAGE_TYPE_SYNC_REQ) {
        HandleRequestMessage(service, context);
        SetToResponse(context);
        return context->responseStatus;
    } else if (context->requestType == MESSAGE_TYPE_SYNC_RSP) {
        (void)OsalSemPost(&context->rspSemaphore);
        return ME_SUCCESS;
    } else {
        //async,append to message
        return localService->dispatcher->AppendMessage(localService->dispatcher, pri, context);
    }
}

message类型还进一步可分为request和response,所有request类型message最终都会调用HandleRequestMessage()来响应请求:

对于所有的请求message,最终都会调用 LocalNodeService的ServiceDef中的MessageDef来处理。

static void HandleRequestMessage(const RemoteService *service, MessageContext *context)
{
    LocalNodeService *localNodeService = (LocalNodeService *)service;
	//根据commandID获取请求对应的messageDef
    struct MessageDef messageDef = { NULL, 0 };
    if (localNodeService->mapper != NULL && context->commandId < localNodeService->mapper->messagesLength) {
        messageDef = localNodeService->mapper->messages[context->commandId];
    }
	//调用messageDef的函数处理请求
    context->responseStatus = messageDef.handler((RequestContext *)context, context->reqData, context->rspData);
}

response类型message最终调用HandleResponseMessage()

static void HandleResponseMessage(const RemoteService *service, MessageContext *context)
{
    //sync
    if (context->requestType == MESSAGE_TYPE_SYNC_RSP) {
        HDF_STATUS status = OsalSemPost(&context->rspSemaphore);
    } else if (context->requestType == MESSAGE_TYPE_ASYNC_RSP) {
        //async
        if (context->callback != NULL) {
            context->callback((const RequestContext *)context, context->reqData, context->rspData,
                context->responseStatus);
        }
    } 
 
}

五、小结

WLAN Message定义了如何处理来自WIFI HDI层的命令,这些命令适用于控制WIFI 硬件的行为。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
3
收藏 1
回复
举报
回复
    相关推荐