OpenHarmony HDF WIFI之WLAN_Core 原创 精华

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

@[toc]

WIFI Core

在WLAN HDI 的那篇文章中,命令最终被发送到HDF WIFI驱动模块,该驱动的实现就在hdf_wifi_core.c中:

struct HdfDriverEntry g_hdfWifiEntry = {
    .moduleVersion = 1,
    .Bind = HdfWifiDriverBind,
    .Init = HdfWlanMainInit,
    .Release = HdfWlanDriverRelease,
    .moduleName = "HDF_WIFI"
};
HDF_INIT(g_hdfWifiEntry);

WIFI Core 驱动对消息的处理流程如图:

OpenHarmony HDF WIFI之WLAN_Core-开源基础软件社区OpenHarmony HDF WIFI之WLAN_Core-开源基础软件社区

由于WIFI Core所涉及的对象多且复杂,最好先来了解这些对象是如何生成的,再看他们是如何使用。

一、LocalNodeService

展开宏定义后的LocalNodeService,根据上图可了解到LocalNodeService有三个,分别用于响应base、sta、ap消息,于是就有三个文件对应实现。

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;

以sta.c为例子,学习LocalNodeService是如何被创建的:

sta.c中定义了三个MessageDef数组,分别用于处理三种类型的HDI message。例如sta.c中定义了5个成员的数组,用于处理5个具体的sta命令,例如WifiCmdAssoc()是用于响应wifi连接命令的。

static struct MessageDef g_wifiStaFeatureCmds[] = {
    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()函数.同时在StaInit()在调用该函数:

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);                                 
    }
 */
int32_t StaInit(struct WifiFeature *feature)
{
    (void)feature;
    if (g_staService == NULL) {
        ServiceCfg cfg = {
            .dispatcherId = DEFAULT_DISPATCHER_ID
        };
        //g_staService = CreateServiceSTAService(&cfg);
        g_staService = CreateService(STAService, &cfg);
        if (g_staService == NULL) {
            return HDF_FAILURE;
        }
    }
    return HDF_SUCCESS;
}

InitService()函数在sidecar.c中,其最重要的部分是调用RegistLocalService(),而RegistLocalService简单的调用RegistServiceInner():

该函数的目的是创建LocalNodeService,但创建LocalNodeServic需要使用到MessageNode,这里先暂时不管。

//主要是创建LocalNodeServic
static ErrorCode RegistServiceInner(const NodeId nodeId, const DispatcherId dispatcherId, struct ServiceDef *mapper)
{
    HDF_STATUS status = OsalMutexTimedLock(&g_routerMutex, HDF_WAIT_FOREVER);
    //获取default node(非重点)
    MessageNode *node = RefMessageNode(nodeId, false);
    
    RemoteService *remoteService = NULL;
    MessageDispatcher *dispatcher = NULL;
    do {
        //获取default dispatcher
        dispatcher = RefDispatcherInner(dispatcherId, false);
		//重要:调用CreateLocalNodeService(node,dispatcher, mapper)
        remoteService = node->CreateRemoteService(node, dispatcher, mapper);
        errCode = NotifyAllNodesServiceAdd(nodeId, mapper);
		//把remoteService添加到g_servicesIndex[]
        errCode = DoRegistService(nodeId, dispatcherId, remoteService);

    } while (false);
    return errCode;
}

CreateLocalNodeService() 创建了LocalNodeService对象。

RemoteService *CreateLocalNodeService(MessageNode *node, MessageDispatcher *dispatcher, struct ServiceDef *mapper)
{
    //create local node service
    LocalNodeService *service = (LocalNodeService *)OsalMemCalloc(sizeof(LocalNodeService));
    do {
        service->status = ME_STATUS_RUNNING;
        //填充函数:处理请求消息
        service->ExecRequestMsg = HandleRequestMessage;
        service->ExecResponseMsg = HandleResponseMessage;
        service->SendMessage = SendMessageLocalNode;
        service->Shutdown = ShutdownLocalService;
        service->serviceId = mapper->serviceId;
        //把sta.c中定义的ServiceDef 赋值给 LocalNodeService
        service->mapper = mapper;
        service->dispatcher = dispatcher->Ref(dispatcher);
    } while (false);
    return (RemoteService *)service;
}

总结一下,调用sta.c,ap.c,wifi_base.c中的初始化函数,就能创建上图所示的LocalNodeService。

二、消息传递流程

了解了LocalNodeService是如何创建的,我们就能轻松的了解消息的传递流程。

在hdf_wifi_core.c中的HdfWifiDriverBind函数定义了HDF_WIFI驱动所提供的服务,并启动MessageRouter来创建MessageNode,创建dispatch,MessageNode和Dispatch正是我们前面创建LocalNodeService所需要的。

static int32_t HdfWifiDriverBind(struct HdfDeviceObject *dev)
{
    static struct IDeviceIoService wifiService = {
        .object.objectId = 1,
        .Dispatch = DispatchToMessage,
    };
    errCode = StartMessageRouter(MESSAGE_NODE_CONFIG_DEFAULT);
    errCode = EnableDefaultDispatcher();
    dev->service = &wifiService;
    return HDF_SUCCESS;
}

这里我们重点关注DispatchToMessage():

该函数定义在sidecar.c中。sidecar.c封装了LocalNodeService,提供接口给HDF_WIFI驱动使用,起到中介的作用。要注意到,驱动的命令是以id+HdfSBuf的形式传递进来的,需要转换成messagecontext。

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;
    //从HDI发送过来的是REQ
    context->requestType = MESSAGE_TYPE_SYNC_REQ;
    context->client = client;
    RemoteService *targetService = NULL;
    do {
        //获取特定的 LocalNodeService
        targetService = RefRemoteService(serviceId);
        //SendMessage就是在LocalNodeService创建时设置的 SendMessageLocalNode()
        errCode = targetService->SendMessage(targetService, context);
    } while (false);
}

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

  • sync:同步类消息需要马上处理
  • async:异步类消息由RunDispatcher线程稍后处理
ErrorCode SendMessageLocalNode(const RemoteService *service, MessageContext *context)
{
    //MESSAGE_TYPE_SYNC_REQ 来自HDI的同步请求,马上处理并回复
    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 {
        //异步请求,交给dispatch缓存处理
        return localService->dispatcher->AppendMessage(localService->dispatcher, pri, context);
    }
}

HandleRequestMessage()获取定义在sta.c、wifi_base.c、ap.c的messageDef,然后指定handler函数,例如:WifiCmdAssoc()

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);
}

让我们重新回到sta.c中,看看messageDef[]中的handler函数是如何处理消息的。还是以WifiCmdAssoc()为线索:

static int32_t WifiCmdAssoc(const RequestContext *context, struct HdfSBuf *reqData, struct HdfSBuf *rspData)
{
    struct WlanConnectParams params = { 0 };
    WifiAssociateParams assoc = { 0 };
    struct NetDevice *netdev = NULL;
    ifName = HdfSbufReadString(reqData);
    //设置连接参数
    if (WifiFillAssocParams(&assoc, reqData) != HDF_SUCCESS) {
        return HDF_FAILURE;
    }
	//获取netdev
    if ((netdev = NetDeviceGetInstByName(ifName)) == NULL) {
        HDF_LOGE("%s:netdev not found!ifName=%s", __func__, ifName);
        return HDF_FAILURE;
    }
    //设置连接参数
    if (WifiSetAssocParams(&assoc, netdev, &params) != HDF_SUCCESS) {
        return HDF_FAILURE;
    }
    do {
        params.centerFreq = assoc.freq;
		//开始连接wifi
        ret = Connect(netdev, &params);
    } while (false);

}

Connect()使用 chipDriver 对象提供的接口进行连接:

inline static int32_t Connect(struct NetDevice *netDev, struct WlanConnectParams *param)
{
    //获取chip driver
    struct HdfChipDriver *chipDriver = GetChipDriver(netDev);
    RETURN_IF_CHIPOPS_NOT_IMPLEMENT(chipDriver->staOps, Connect);
    //chip driver 开始连接
    return chipDriver->staOps->Connect(netDev, param);
}

至此 WIFI Core 的任务就完成了。

三、HDF WIFI 初始化

首先来看HdfWlanMainInit函数,这是驱动的初始化函数,负责生成上图所用到的所有对象。

HDF_WIFI的初始化分为三个部分:

  • HdfWlanGetConfig是获取配置文件的配置信息,暂不分析。
  • HdfWlanInitProduct:调用InitWifiModule 初始化wifi module(本质是初始化三个LocalNodeService)
  • HdfWlanScanAndInitThread:初始化硬件
/* main init process including config, powers, load the factory, and chip init */
static int32_t HdfWlanMainInit(struct HdfDeviceObject *device)
{
    //获取配置文件的配置信息
    if (HdfWlanGetConfig(device) != HDF_SUCCESS) {
        HDF_LOGE("%s:HdfWlanGetConfig get wlan config failed!", __func__);
        return HDF_FAILURE;
    }
    rootConfig = HdfWlanGetModuleConfigRoot();
    moduleConfig = &rootConfig->wlanConfig.moduleConfig;
    //初始化Modules
    if (HdfWlanInitProduct(device, moduleConfig) != HDF_SUCCESS) {
        HDF_LOGE("%s:HdfWlanInitProduct failed!", __func__);
        return HDF_FAILURE;
    }
    //初始化硬件
    if (HdfWlanScanAndInitThread(device) != HDF_SUCCESS) {
        HDF_LOGE("%s: LoadChipFactoryThread failed, the load process failed!", __func__);
        return HDF_FAILURE;
    }
}

int HdfWlanInitProduct(struct HdfDeviceObject *device, const struct HdfConfigWlanModuleConfig *config)
{
    g_hdfWlanProductData = OsalMemCalloc(sizeof(struct HdfWifiProductData));
    ret = InitWifiModule(&(g_hdfWlanProductData->module), config);
}

3.1、HdfWlanInitProduct

初始化WIFI Module,其根本目的是为了创建三个LocalNodeService,分别是:BASE、STA、AP LocalNodeService

函数调用流程是:InitWifiModule()->InitFeatures(),其中分别调用BaseInit()、StaInit()、ApInit()来创建LocalNodeService

static int32_t InitFeatures(struct WifiModule *module)
{
    //初始化 BASE LocalNodeService
    ret = BaseInit();
    //获取 ApFeature、staFeature
    module->feList.fe[HDF_WIFI_FEATURE_AP] = GetWifiApFeature();
    module->feList.fe[HDF_WIFI_FEATURE_STA] = GetWifiStaFeature();

    for (i = 0; i < HDF_WIFI_FEATURE_NUM; i++) {
        if ((module->moduleConfig.hslConfig->featureMap & (1 << i)) && module->feList.fe[i] != NULL) {
            //调用StaInit() ApInit()
            module->feList.fe[i]->init(module->feList.fe[i]);
        }
    }
    return HDF_SUCCESS;
}

3.2、HdfWlanScanAndInitThread

HdfWlanScanAndInitThread会回调HdfWlanInitThread函数,在其中初始化硬件,如sdio控制器,芯片电源引脚,复位引脚,驱动程序。

static int32_t HdfWlanInitThread(void *para)
{
    struct HdfDeviceObject *device = (struct HdfDeviceObject *)para;
    OsalSleep(initDelaySec);
    devList = HdfWlanGetDeviceList();
    for (i = 0; i < devList->deviceListSize; i++) {
        //sdio config
        ret = HdfWlanConfigSDIO(devList->deviceInst[i].bus.busIdx);
        // init hardware
        wlanDevice = ProbeDevice(&(devList->deviceInst[i]));
        ret = HdfWlanAddDevice(wlanDevice);
        // Load chip driver
        (void)DevSvcManagerClntSubscribeService(wlanDevice->driverName, callback);
        (void)HdfWifiInitDevice(wlanDevice);
    }
}

HdfWlanInitThread也分为三个部分:

  • HdfWlanConfigSDIO:由驱动开发者实现,配置sdio控制器外设
  • ProbeDevice:初始化硬件
  • HdfWifiInitDevice:初始化硬件驱动程序
3.2.1、HdfWlanConfigSDIO

由驱动开发者实现,配置sdio控制器外设,以海思的芯片为例:

int32_t HdfWlanConfigSDIO(uint8_t busId)
{
    struct HdfConfigWlanRoot *config = HdfWlanGetModuleConfigRoot();
    if (strcmp("hi3516dv300", config->wlanConfig.hostChipName) == 0) {
        return ConfigHi3516DV300SDIO(busId);
    }
    if (strcmp("hi3518ev300", config->wlanConfig.hostChipName) == 0) {
        return ConfigHi3518EV300SDIO(busId);
    }
    HDF_LOGE("%s: platform chip not supported!", __func__);
    return HDF_FAILURE;
}

static int32_t ConfigHi3516DV300SDIO(uint8_t busId)
{
    if (busId == 2) {
        HDF_LOGE("%s: Config Hi3516DV300 SDIO bus %d", __func__, busId);
        const uint32_t PMC_REG_ADDR_REG0 = 0x12090000;
        const uint32_t PIN_REG_ADDR_CLK = 0x112F0008;
        const uint32_t PIN_REG_ADDR_CMD = 0x112F000C;
        const uint32_t PIN_REG_ADDR_DATA0 = 0x112F0010;
        const uint32_t PIN_REG_ADDR_DATA1 = 0x112F0014;
        const uint32_t PIN_REG_ADDR_DATA2 = 0x112F0018;
        const uint32_t PIN_REG_ADDR_DATA3 = 0x112F001C;

        REG_SET_BITS(PMC_REG_ADDR_REG0, 0x0080);
        REG_WRITE(PIN_REG_ADDR_CLK, 0x601);
        REG_WRITE(PIN_REG_ADDR_CMD, 0x501);
        REG_WRITE(PIN_REG_ADDR_DATA0, 0x501);
        REG_WRITE(PIN_REG_ADDR_DATA1, 0x501);
        REG_WRITE(PIN_REG_ADDR_DATA2, 0x501);
        REG_WRITE(PIN_REG_ADDR_DATA3, 0x501);
        return HDF_SUCCESS;
    }

    HDF_LOGE("%s: SDIO bus ID %d not supportted!", __func__, busId);
    return HDF_FAILURE;
}
3.2.2、ProbeDevice()

初始化 HdfWlanDevice结构体,并调用HdfWlanDevice的方法初始化 硬件wifi芯片,如上电、复位、连接总线。

static struct HdfWlanDevice *ProbeDevice(struct HdfConfigWlanDevInst *deviceConfig)
{
    struct HdfWlanDevice *device = NULL;
    device = (struct HdfWlanDevice *)OsalMemCalloc(sizeof(struct HdfWlanDevice));
    do {
        //create PowerManage and ResetManage 
        device->powers = HdfWlanCreatePowerManager(&deviceConfig->powers);
        device->reset = HdfWlanCreateResetManager(&deviceConfig->reset, deviceConfig->bootUpTimeOut);
		//上电
        ret = HdfWlanPowerOnProcess(device->powers);
		//复位 
        ret = HdfWlanResetProcess(device->reset);
		//init sdio bus 
        ret = HdfWlanBusInit(device, &deviceConfig->bus);
    } while (false);
}

HdfWlanDevice 是来描述所有wlan设备的硬件属性:例如驱动名称,芯片名称、电源、复位、连接到主控的总线

struct HdfWlanDevice {
    uint8_t id;
    const char *driverName;                     /**< Driver name */
    const char *chipName;                       /**< Chip name */
    uint32_t netIfMap;                          /**< WLAN device bitmap */
    struct HdfWlanManufacturer manufacturer;    /**< WLAN device manufacturer */
    struct ResetManager *reset;                 /**< Chip reset management API */
    struct PowerManager *powers;                /**< Chip power management APIs */
    struct BusDev *bus;
};
struct ResetManager {
    int32_t (*Reset)(struct ResetManager *resetManager);//Resets the WLAN module using a specified reset manager
    int32_t (*Release)(struct ResetManager *resetMgr);    //Releases a specified reset manager.
};
struct PowerManager {
    int32_t (*On)(struct PowerManager *powerMgr);	//Powers on the device using a specified power manager.
    int32_t (*Off)(struct PowerManager *powerMgr);	//Powers off the device using a specified power manager.
    int32_t (*Release)(struct PowerManager *powerMgr);	//Releases power using a specified power manager.
};
struct BusDev {
    void *devBase;
    struct DevOps ops;
    struct PrivateData priData;
};

调用HdfWlanCreatePowerManager()会初始化PowerManager,HdfWlanPowerOnProcess 会调用PowerManager->on(),即HdfWlanChipPowerOn(),通过设置gpio引脚来使能wlan芯片。

static int32_t HdfWlanChipPowerOn(struct PowerManager* powerMgr)
{
    powerMgrimpl = (struct PowerManagerImpl*)powerMgr;
    ret = HdfWlanSinglePowerActive(&powerMgrimpl->powerDatas.power0);
    ret = HdfWlanSinglePowerActive((struct HdfConfigWlanPower*)&powerMgrimpl->powerDatas.power1);
    return HDF_SUCCESS;
}
static int32_t HdfWlanSinglePowerActive(struct HdfConfigWlanPower* powerDate)
{
    //set gpio pin
    ret = GpioSetDir(powerDate->gpioId, 1);
    OsalMSleep(powerDate->powerSeqDelay);
    ret = GpioWrite(powerDate->gpioId, powerDate->activeLevel);
    return HDF_SUCCESS;
}

ResetManager的实现也是类似的

3.2.3、HdfWifiInitDevice()

获取 HdfChipDriverFactory,并调用其InitChip()方法来初始化芯片硬件,调用HdfWlanInitInterfaces()初始化HdfChipDriver ;

int32_t HdfWifiInitDevice(struct HdfWlanDevice *device)
{
    struct  HdfChipDriverFactory *chipDriverFact = NULL;
	//获取 HdfChipDriverFactory 管理所有驱动程序
    chipDriverFact = HdfWlanGetDriverFactory(device->driverName);

    if (chipDriverFact->InitChip != NULL) {
        //初始化芯片
        ret = chipDriverFact->InitChip(device);
    }
    //创建wifi芯片的接口
    ret = HdfWlanInitInterfaces(device, chipDriverFact);
}

HdfChipDriverFactory结构体由硬件厂商实现,其最终目的是为了创建chip driver.

chip driver

HdfWlanInitInterfaces 创建对应芯片的HdfChipDriver ,创建netdevice,调用chipDriver->init()初始化芯片驱动程序(即由驱动开发者根据具体芯片实现的)

static int32_t HdfWlanInitInterface(struct HdfWlanDevice *device, struct HdfChipDriverFactory *factory, uint8_t index)
{
    NetDevice *netDev = NULL;
    struct HdfChipDriver *chipDriver = NULL;
    do {
        //创建 chip driver
        chipDriver = factory->Build(device, index);
        //创建 NetDev 
        netDev = AllocPlatformNetDevice(device);
        data = GetPlatformData(netDev);
        data->device = device;
        //call chipdriver to init the chip
        ret = chipDriver->init(chipDriver, netDev);
        //将netdev和chip driver 绑定
        data->chipDriver = chipDriver;
        chipDriver = NULL;
    } while (false);
}

HdfChipDriver 是直接操作wifi 芯片硬件的驱动,也必须由驱动厂商实现,其中HdfMac80211BaseOps、HdfMac80211STAOps、HdfMac80211STAOps都需要实现具体的硬件操作。

struct HdfChipDriver {
    uint16_t type;                          /**< Chip type */
    char name[MAX_WIFI_COMPONENT_NAME_LEN]; /**< Chip name */
    struct HdfMac80211BaseOps *ops;         
    struct HdfMac80211STAOps *staOps;       
    struct HdfMac80211STAOps *apOps;        
    void *priv;                             
	//Initializes a chip driver.
    int32_t (*init)(struct HdfChipDriver *chipDriver, NetDevice *netDev);
	//Deinitializes a chip driver.
    int32_t (*deinit)(struct HdfChipDriver *chipDriver, NetDevice *netDev);
};
struct HdfMac80211BaseOps {
	//设置wifi模式
    int32_t (*SetMode)(NetDevice *netDev, enum WlanWorkMode mode);
	//添加key
    int32_t (*AddKey)(struct NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr,
        struct KeyParams *params);
    int32_t (*DelKey)(struct NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr);

    int32_t (*SetDefaultKey)(struct NetDevice *netDev, uint8_t keyIndex, bool unicast, bool multicas);

    int32_t (*GetDeviceMacAddr)(NetDevice *netDev, int32_t type, uint8_t *mac, uint8_t len);
    int32_t (*SetMacAddr)(NetDevice *netDev, uint8_t *mac, uint8_t len);
    int32_t (*SetTxPower)(NetDevice *netDev, int32_t power);
	//获取芯片支持的带宽
    int32_t (*GetValidFreqsWithBand)(NetDevice *netDev, int32_t band, int32_t *freqs, uint32_t *num);
	//获取芯片的能力
    int32_t (*GetHwCapability)(NetDevice *netDev, struct WlanHwCapability **capability);

    int32_t (*RemainOnChannel)(NetDevice *netDev, WifiOnChannel *onChannel);

    int32_t (*CancelRemainOnChannel)(NetDevice *netDev);

    int32_t (*ProbeReqReport)(NetDevice *netDev, int32_t report);

    int32_t (*AddIf)(NetDevice *netDev, WifiIfAdd *ifAdd);

    int32_t (*RemoveIf)(NetDevice *netDev, WifiIfRemove *ifRemove);

    int32_t (*SetApWpsP2pIe)(NetDevice *netDev, WifiAppIe *appIe);

    int32_t (*GetDriverFlag)(struct NetDevice *netDev, WifiGetDrvFlags **params);

    int32_t (*SendAction)(struct NetDevice *netDev, WifiActionData *actionData);

    int32_t (*GetIftype)(struct NetDevice *netDev, uint8_t *iftype);
};

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