0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

WLAN驱动架构的组成和各部件的功能

电子工程师 来源:OpenAtom OpenHarmony 作者:徐赛 2021-09-05 10:46 次阅读

作者:徐赛

WLAN驱动概述

WLAN 是基于 HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移、自适应器件差异、模块化拼装编译等功能。从而降低 WLAN 驱动开发的难度,减少 WLAN 驱动移植和开发的工作量。

本文主要分析 WLAN 驱动架构的组成和各部件的功能,WLAN 芯片厂商通过本框架如何进行各自驱动的开发,以及如何使用 HAL 接口

WLAN驱动架构介绍

驱动架构主要由 Module、NetDevice、NetBuf、BUS、HAL、Client 和 Message 这七个部分组成。

Module

Module 基于 HDF 驱动框架实现 WLAN 框架的启动加载、配置文件的解析、设备驱动的初始化和芯片驱动的初始化等功能,根据 WLAN 的功能特性,划分 Base、AP、STA 等部件,对控制流的命令和事件进行统一管理。

NetDevice

NetDevice 用于建立专属网络设备,屏蔽不同 OS 的差异,对 WIFI 驱动提供统一接口,提供统一的 HDF NetDevice 数据结构,及其统一管理、注册、去注册能力;对接富设备上的 Linux 的网络设备层;对接轻设备上的 Linux 的网络设备层。

NetBuf

NetBuf 部件为 WLAN 驱动提供 Linux 或者 LiteOS 原生的网络数据缓冲的统一数据结构的封装以及对网络数据的操作接口的封装

BUS

BUS 驱动模块向上提供统一的总线抽象接口。通过向下调用 Platform 层提供的 sdio 接口和封装适配 usb、pcie 接口,屏蔽不同操作系统的差异;通过对不同类型的总线操作进行统一封装,屏蔽不同芯片差异,能够对不同芯片厂商提供完备的总线驱动功能,不同厂商共用此模块接口,从而使厂商的开发更为便捷和统一,

HAL

HAL 部件对 WiFiService 模块提供标准的 WIFI-HDI 接口和数据格式定义,提供能力如下:设置 MAC 地址、设置发射功率、获取设备的 MAC 地址等。

Client

Client 部件实现用户态与内核态的交互,通过对 sbuf 及 nl80211 做不同适配,根据产品做配置化编译,从而实现对上提供统一的接口调用,框架如下图所示:

2a93cd46-0da6-11ec-8fb8-12bb97331649.png

图4 Client框架图

Message

Message 部件为每个服务单独提供业务接口,每个服务也可依赖其他服务形成组合业务接口,此模块支持在用户态、内核态和 MCU 环境运行,实现了组件间的充分解耦。

2aa584a0-0da6-11ec-8fb8-12bb97331649.png

图5 当前WLAN服务关系图

WLAN驱动开发步骤与实例

各 WLAN 厂商驱动开发人员可根据 WLAN 模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭 WLAN 热点、扫描、关联 WLAN 热点等;

下面以 hi3881 WLAN 芯片为例,进行 WLAN 驱动开发过程的详解。

配置WLAN芯片的硬件参数

1)根据硬件参数,通过 wlan_platform.hcs 配置平台相关参数。

hisi :& deviceList { device0 :: deviceInst { deviceInstId = 0; powers { power0 { powerSeqDelay = 0; /* 电源序列延时 */ powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ gpioId = 1; /* GPIO管脚号 */ activeLevel=1; /* 有效电平:0--低;1--高 */ } power1 { powerSeqDelay = 0; /* 电源序列延时 */ powerType = 0; /* 电源类型:0--总是打开;1--GPIO */ } } reset { resetType = 0; /* 复位类型:0--不管理;1--GPIO */ gpioId = 2; /* GPIO管脚号 */ activeLevel=1; /* 有效电平:0--低;1--高 */ resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ } bootUpTimeout = 30; /* 启动超时时间(ms) */ bus { busType = 0; /* 总线类型:0-sdio */ busId = 2; /* 总线号 */ funcNum = [1]; /* SDIO功能号 */ timeout = 1000; /* 读/写数据的超时时间 */ blockSize = 512; /* 读/写数据的块大小 */ }}}

2)为 WLAN 块芯片添加配置文件 wlan_chip_《芯片名》.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。

root { wlan_config { hi3881 :& chipList { chipHi3881 :: chipInst { match_attr = “hdf_wlan_chips_hi3881”; /* 配置匹配标识 */ chipName = “hi3881”; /* WLAN芯片的名称 */ sdio { vendorId = 0x0296; /* 厂商Id */ deviceId = [0x5347]; /* 设备Id */ } } } }}

WLAN初始化相关适配开发

1)适配挂接 WLAN 芯片的初始化和去初始化、WLAN 芯片驱动的初始化和去初始化。详情见 hdf_driver_register.c,分析如下:

#include “hdf_device_desc.h”#include “hdf_wifi_product.h”#include “hdf_log.h”#include “osal_mem.h”#include “hdf_wlan_chipdriver_manager.h”#include “securec.h”#include “wifi_module.h”#include “hi_wifi_api.h”#include “hi_types_base.h”

#define HDF_LOG_TAG Hi3881Driver

/* WLAN芯片的初始化和去初始化函数 */int32_t InitHi3881Chip(struct HdfWlanDevice *device);int32_t DeinitHi3881Chip(struct HdfWlanDevice *device);/* WLAN芯片驱动的初始化和去初始化函数 */int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice);int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice);/* 初始化mac80211与芯片侧的函数挂接,包括开始扫描,连接,设置国家码等,详情见3.2 */hi_void HiMac80211Init(struct HdfChipDriver *chipDriver);

static const char * const HI3881_DRIVER_NAME = “hisi”;/* WLAN芯片驱动挂接以及mac80211与芯片侧的函数挂接 */static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex){ struct HdfChipDriver *specificDriver = NULL; if (device == NULL) { HDF_LOGE(“%s fail : channel is NULL”, __func__); return NULL; } (void)device; (void)ifIndex; specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); if (specificDriver == NULL) { HDF_LOGE(“%s fail: OsalMemCalloc fail!”, __func__); return NULL; } if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { HDF_LOGE(“%s fail: memset_s fail!”, __func__); OsalMemFree(specificDriver); return NULL; }

if (strcpy_s(specificDriver-》name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { HDF_LOGE(“%s fail : strcpy_s fail”, __func__); OsalMemFree(specificDriver); return NULL; } specificDriver-》init = Hi3881Init; specificDriver-》deinit = Hi3881Deinit; HiMac80211Init(specificDriver);

return specificDriver;}/* 释放WLAN芯片驱动 */static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver){ if (chipDriver == NULL) { return; } if (strcmp(chipDriver-》name, HI3881_DRIVER_NAME) != 0) { HDF_LOGE(“%s:Not my driver!”, __func__); return; } OsalMemFree(chipDriver);}

static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory){ (void)factory; return 1;}

/* WLAN芯片相关函数的注册 */static int32_t HDFWlanRegHisiDriverFactory(void){ static struct HdfChipDriverFactory tmpFactory = { 0 }; struct HdfChipDriverManager *driverMgr = NULL; driverMgr = HdfWlanGetChipDriverMgr(); if (driverMgr == NULL) { HDF_LOGE(“%s fail: driverMgr is NULL!”, __func__); return HDF_FAILURE; } tmpFactory.driverName = HI3881_DRIVER_NAME; tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; tmpFactory.InitChip = InitHi3881Chip; tmpFactory.DeinitChip = DeinitHi3881Chip; tmpFactory.Build = BuildHi3881Driver; tmpFactory.Release = ReleaseHi3881Driver; tmpFactory.ReleaseFactory = NULL; if (driverMgr-》RegChipDriver(&tmpFactory) != HDF_SUCCESS) { HDF_LOGE(“%s fail: driverMgr is NULL!”, __func__); return HDF_FAILURE; }

return HDF_SUCCESS;}

static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device){ (void)device; return HDFWlanRegHisiDriverFactory();}

static int HdfWlanHisiDriverBind(struct HdfDeviceObject *dev){ (void)dev; return HDF_SUCCESS;}

static void HdfWlanHisiChipRelease(struct HdfDeviceObject *object){ (void)object;}

struct HdfDriverEntry g_hdfHisiChipEntry = { .moduleVersion = 1, .Bind = HdfWlanHisiDriverBind, .Init = HdfWlanHisiChipDriverInit, .Release = HdfWlanHisiChipRelease, .moduleName = “HDF_WLAN_CHIPS”};/* HDF的驱动加载入口,先执行Bind,再执行Init */HDF_INIT(g_hdfHisiChipEntry);

2)芯片初始化和芯片驱动初始化相关内容详见 hdfinit_3881.c,分解如下:

int32_t InitHi3881Chip(struct HdfWlanDevice *device){ int32_t ret = HI_SUCCESS; …… ret = hi_wifi_init(maxPortCount, device-》bus); // 实现芯片的初始化,包括frw机制、平台和host初始化等等 ……}int32_t DeinitHi3881Chip(struct HdfWlanDevice *device){ ……int32_t ret = hi_wifi_deinit(); // 实现芯片的去初始化……}

3)芯片驱动的初始化与去初始化,主要针对网络设备相关的配置和加载

int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice){ ……ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice);……}

int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice){ return wal_deinit_drv_wlan_netdev(netDevice);}

4)在网络设备进行初始化时,挂接 NetDevice 中提供的数据发送、设置 mac 地址、打开 NetDev 等功能接口。

oal_net_device_ops_stru g_wal_net_dev_ops = { .getStats = wal_netdev_get_stats, .open = wal_netdev_open, .stop = wal_netdev_stop, .xmit = hmac_bridge_vap_xmit, .ioctl = wal_net_device_ioctl, .changeMtu = oal_net_device_change_mtu, .init = oal_net_device_init, .deInit = oal_net_free_netdev,#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) .selectQueue = wal_netdev_select_queue,#endif

.setMacAddr = wal_netdev_set_mac_addr,#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) .netifNotify = HI_NULL,#endif .specialEtherTypeProcess = SpecialEtherTypeProcess,};oal_net_device_ops_stru *wal_get_net_dev_ops(hi_void){ return &g_wal_net_dev_ops;}

hi_s32 wal_init_netdev(nl80211_iftype_uint8 type, oal_net_device_stru *netdev){ ……netdev-》netDeviceIf = wal_get_net_dev_ops();……}

控制流命令下发和事件上报的适配

1)命令下发绑定,包括具有公共能力的设置 mac 地址、设置发射功率等;STA 相关的连接、扫描等;AP 相关的启动 ap、设置国家码等。

static struct HdfMac80211BaseOps g_baseOps = { .SetMode = WalSetMode, .AddKey = WalAddKey, .DelKey = WalDelKey, .SetDefaultKey = WalSetDefaultKey, .GetDeviceMacAddr = WalGetDeviceMacAddr, .SetMacAddr = WalSetMacAddr, .SetTxPower = WalSetTxPower, .GetValidFreqsWithBand = WalGetValidFreqsWithBand, .GetHwCapability = WalGetHwCapability};static struct HdfMac80211STAOps g_staOps = { .Connect = WalConnect, .Disconnect = WalDisconnect, .StartScan = WalStartScan, .AbortScan = WalAbortScan, .SetScanningMacAddress = WalSetScanningMacAddress,};static struct HdfMac80211APOps g_apOps = { .ConfigAp = WalConfigAp, .StartAp = WalStartAp, .StopAp = WalStopAp, .ConfigBeacon = WalChangeBeacon, .DelStation = WalDelStation, .SetCountryCode = WalSetCountryCode, .GetAssociatedStasCount = WalGetAssociatedStasCount, .GetAssociatedStasInfo = WalGetAssociatedStasInfo};hi_void HiMac80211Init(struct HdfChipDriver *chipDriver){ if (chipDriver == NULL) { oam_error_log(0, OAM_SF_ANY, “%s:input is NULL!”, __func__); return; } chipDriver-》ops = &g_baseOps; chipDriver-》staOps = &g_staOps; chipDriver-》apOps = &g_apOps;}

2)事件上报接口调用,WLAN 框架提供了 event 事件的上报接口,详情见 hdf_wifi_event.c,例:调用 HdfWifiEventNewSta AP 上报新关联的某个 STA 的情况

hi_u32 oal_cfg80211_new_sta(oal_net_device_stru *net_device, const hi_u8 *mac_addr, hi_u8 addr_len, oal_station_info_stru *station_info, oal_gfp_enum_uint8 en_gfp){#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX) cfg80211_new_sta(net_device, mac_addr, station_info, en_gfp); hi_unref_param(addr_len);#elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX) struct StationInfo info = { 0 }; info.assocReqIes = station_info-》assoc_req_ies; info.assocReqIesLen = station_info-》assoc_req_ies_len; HdfWifiEventNewSta(net_device, mac_addr, WLAN_MAC_ADDR_LEN, &info); hi_unref_param(en_gfp); hi_unref_param(addr_len);#endif return HI_SUCCESS;}

使用HAL的开发步骤与实例

HAL模块使用步骤

2ac48152-0da6-11ec-8fb8-12bb97331649.png

图6 HAL使用流程

1)使用 WifiConstruct 创建一个 WiFi 实体。

2)用创建的 WiFi 实体调用 start 开启 HAL 和驱动之间的通道,获得驱动网卡信息

3)通过 createFeature 一个 apFeature 或者 staFeature。后面可通过这些 Feature 去调用具体的实现接口,下面基于创建的 apFeature。

4)调用和使用相关接口:如 setMacAddress 设置 MAC 地址、getDeviceMacAddress 获取设备的 MAC 地址等。

5)调用 destroyFeature,销毁掉创建的这个 Feature。

6)调用 stop 销毁创建的通道。

7)执行 WifiDestruct 销毁创建的 WiFi 实体。

HAL使用实例

#include “wifi_hal.h”#include “wifi_hal_sta_feature.h”#include “wifi_hal_ap_feature.h”#include “wifi_hal_cmd.h”#include “wifi_hal_event.h”

#define MAC_LEN 6

static void *hal_main(){ int ret; struct IWiFi *wifi;

/* 创建一个WiFi实体 */ ret = WifiConstruct(&wifi); if (ret != 0 || wifi == NULL) { return; }

/* 开启HAL和驱动之间的通道 */ ret = wifi-》start(wifi); if (ret != 0) { return; }

/* 创建apFeature */ ret = wifi-》createFeature(PROTOCOL_80211_IFTYPE_AP, (struct IWiFiBaseFeature **)&apFeature); if (ret != 0) { return; }

/* 获取设备的MAC地址 */ unsigned char mac[MAC_LEN] = {0}; ret = apFeature-》baseFeature.getDeviceMacAddress((struct IWiFiBaseFeature *)apFeature, mac, MAC_LEN); if (ret != 0) { return; }

/* 销毁掉创建的这个Feature */ ret = wifi-》destroyFeature((struct IWiFiBaseFeature *)apFeature); if (ret != 0) { return; }

/* 销毁创建的通道 */ ret = wifi-》stop(wifi); if (ret != 0) { return; }

/* 销毁创建的WiFi实体 */ ret = WifiDestruct(&wifi); if (ret != 0) { return; } return;}

总结

以上是基于 WLAN 框架开发所涉及的所有核心适配,重点介绍了 WLAN 框架的各部件的详情,以 3881 为例进行了 WLAN 芯片开发过程的详细讲解,希望通过本次的文档,您能初步掌握开发 WLAN 的步骤和方法,接下来就在 HDF WLAN 框架下尽情的开发和释放热情吧!

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • WLAN
    +关注

    关注

    2

    文章

    652

    浏览量

    73007
  • 驱动
    +关注

    关注

    12

    文章

    1824

    浏览量

    85169
  • HarmonyOS
    +关注

    关注

    79

    文章

    1967

    浏览量

    29997

原文标题:OpenHarmony HDF WLAN驱动分析与使用

文章出处:【微信号:gh_e4f28cfa3159,微信公众号:OpenAtom OpenHarmony】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    计算机系统的硬件组成和主要部件

    计算机系统的硬件组成是计算机运行的基础,它包含了多个关键部件,这些部件相互协作,共同实现计算机的各种功能
    的头像 发表于 09-10 11:41 1541次阅读

    集成运放电路的组成各部分的作用是什么

    等领域。集成运放电路的组成各部分的作用是理解其工作原理和应用的关键。 集成运放电路的组成 输入级 :通常由差分放大器构成,用于接收输入信号并提供高输入阻抗。 中间级 :可以是共源放大器、共栅放大器或共基放大器,用于提供增益。
    的头像 发表于 09-03 09:22 610次阅读

    LED显示屏各大组成部件及安装要点

    、电源、控制卡、连线 单元板背面、单元板正面、开关电源和LED条屏控制卡。下面我们分别来看看各个组成部分及其安装要点: 1. 单元板 单元板是LED的显示核心部件之一,单元板的好坏,直接影响到显示效果的。单元板由LED模块,驱动
    的头像 发表于 07-29 09:33 457次阅读

    功率驱动装置的组成部件

    功率驱动装置是一种将电能转换为机械能的设备,广泛应用于工业、交通、医疗等领域。以下是功率驱动装置的主要组成部件及其功能: 电源模块:电源模块
    的头像 发表于 07-17 15:17 315次阅读

    伺服压机各部功能介绍

    伺服压机是一种高效、节能、精密的压装设备,广泛应用于汽车、电子、航空、航天、机械制造等行业。本文将介绍伺服压机的各部功能。 一、伺服压机概述 伺服压机是一种采用伺服电机作为动力源的压装设备。与传统
    的头像 发表于 07-13 10:07 756次阅读

    cpu控制器和运算器组成部件有哪些

    CPU(中央处理器)是计算机的核心部件,负责执行程序指令和处理数据。CPU主要由控制器和运算器组成,这两个部件共同完成计算机的运算任务。下面详细介绍CPU控制器和运算器组成
    的头像 发表于 06-30 11:01 1537次阅读

    控制器的组成部件以及各部件功能

    控制器是计算机系统的核心部件之一,它负责协调和管理计算机系统中的各种硬件和软件资源,以实现计算机系统的正常运行。控制器的组成部件各部件功能
    的头像 发表于 06-30 10:05 2149次阅读

    数控铣床由哪些部分组成的?各部分有什么关系

    数控铣床是一种高度自动化的机床,广泛应用于机械加工、模具制造、航空航天等领域。它由多个部分组成各部分之间相互协作,共同完成加工任务。以下是对数控铣床各部分的详细介绍: 床身:床身是数控铣
    的头像 发表于 06-07 10:39 1846次阅读

    数控铣床由哪些部分组成的?各部分的主要作用是什么?

    数控铣床是一种高精度、高效率的自动化机床,广泛应用于机械加工领域。它由多个部分组成,每个部分都有其特定的功能和作用。以下是对数控铣床各部分的详细介绍: 床身(Base) 床身是数控铣床的基础部分
    的头像 发表于 06-07 10:35 3820次阅读

    村田电容各部件的功用解析

    村田电容代理-村田电容各部件的功用解析 说到贴片式电容,村田贴片式电容在领域内应当不以生疏,做为先前最高的处于被动元器件生产商,村田(murata)贴片式电容运用的十分普遍。与此同时贴片式电容作为
    的头像 发表于 04-19 14:15 497次阅读
    村田电容<b class='flag-5'>各部件</b>的功用解析

    鸿蒙实战开发:【WLAN使用】

    在eTS中WLAN的基本使用,包括禁用和启用WLANWLAN扫描和获取扫描结果、WLAN状态监听、WiFi连接状态监听、获取IP信息、获取国家码、判断设备是否支持
    的头像 发表于 03-07 15:36 514次阅读
    鸿蒙实战开发:【<b class='flag-5'>WLAN</b>使用】

    WLAN是什么网 wlan与wifi有什么区别

    WLAN是无线局域网(Wireless Local Area Network)的缩写。它是一种将计算机设备和其他电子设备通过无线电波进行通信的技术。与传统的有线局域网相比,WLAN能够提供更高
    的头像 发表于 01-22 14:48 6186次阅读

    电流探头校准装置由哪些部件组成

    电流探头校准装置由哪些部件组成? 电流探头校准装置是一种用于校准电流探头的设备,主要用于保证电流测量的准确性和可靠性。它由多个部件组成,每个部件
    的头像 发表于 01-08 15:55 488次阅读

    什么是WLAN直连?WLAN直连的优势包括哪些?

    什么是WLAN直连?WLAN直连的优势包括哪些?WLAN直连与蓝牙技术相比  WLAN直连是指通过无线局域网技术(WLAN)直接连接两台或多
    的头像 发表于 01-04 15:29 4181次阅读

    什么是WLAN直连?常见的WLAN直连方式 WLAN直连的优势包括哪些

    相互通信和共享资源,进一步扩展了无线网络的功能和灵活性。 有多种常见的WLAN直连方式,包括点对点连接、Ad-hoc模式和Wi-Fi Direct。 1. 点对点连接(Point-to-Point):两个设备通过WLAN直接连接
    的头像 发表于 12-27 16:11 6482次阅读