OpenHarmony HDF WIFI之WLAN Message 原创 精华
@[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 硬件的行为。