参考:
现代Linux下的wifi框架-CSDN博客
Linux下wifi子系统的数据流-CSDN博客
mac80211基础知识总结-CSDN博客
cfg80211简介
cfg80211可以看作是Linux 内核中所有 Wi-Fi 设备的“通用配置管理员”。它位于用户态命令(如
iw,wpa_supplicant)和驱动程序(如aic8800_fdrv.ko或mac80211)之间,核心目标是统一管理、简化驱动。它的主要职责可以概括为以下四点:
🎛️ 1. 统一配置与用户空间接口 (nl80211)
这是
cfg80211最核心的职能。
替代旧方案:它使用全新的
nl80211命令集和标准工具iw来替代老旧的Wireless Extensions(iwconfig),提供更丰富、更直观的管理方式。向后兼容:为了兼容旧程序,
cfg80211内部会自动将老的iwconfig请求转换为nl80211命令,对驱动和用户程序都屏蔽了这种差异。🧠 2. 内核中的“注册中心”与能力声明 (
wiphy)驱动程序在初始化时,必须向
cfg80211注册一个核心结构体:wiphy(Wireless Physical Device)。这就像硬件向系统递交的一份“简历”,详细说明自己的能力,包括:
支持的频段(2.4 GHz/5 GHz)和信道。
支持的速率。
是否支持 HT (802.11n)、VHT (802.11ac) 等特性。
驱动通过填充
struct wiphy并实现struct cfg80211_ops里的回调函数,来响应上层的配置请求(如扫描、连接等)。⚖️ 3. 全球频谱法规强制执行 (Regulatory)
不同国家对 Wi-Fi 信道和功率有严格限制。
cfg80211集成了全球法规数据库,负责强制执行这些规则。例如,它会检查你所用的信道 (
struct ieee80211_channel) 是否允许,若不允许则标记IEEE80211_CHAN_DISABLED或要求进行雷达检测 (IEEE80211_CHAN_RADAR),确保设备合法合规。🔧 4. 提供通用工具函数
为了减少驱动开发的重复劳动,
cfg80211提供了一系列工具,例如将 802.11 帧转换为以太网帧的ieee80211_data_to_8023函数,帮助开发者避免重写标准逻辑。🧱 关键数据结构
wiphy(无线物理设备):代表物理无线网卡(如AIC8800)。
wireless_dev(无线虚拟设备):代表虚拟接口(如wlan0或p2p0),挂在wiphy之下。
cfg80211_ops(回调操作集):驱动需要实现的操作函数。当你在用户态输入iw wlan0 scan时,最终会调用到驱动中的.scan函数指针。💎 总结:它在架构中的位置
结合之前的图示,
cfg80211的位置和作用就非常清晰了:总结来说,
cfg80211是驱动开发的“标准框架”。驱动开发者只需关注如何实现cfg80211_ops里的回调,而无需操心用户态通信和法规限制。这也是为什么所有现代 Linux 无线驱动都绕不开它的原因。
注意:cfg80211不参与网络数据收发
在网络数据收发(即传输用户的实际数据,如网页浏览、视频流)时,数据不经过
cfg80211。cfg80211是一个配置与管理框架,不参与高速数据路径。数据走的是另一条更直接的路径,而
cfg80211和mac80211在数据路径中的角色可以这样区分:1.
cfg80211:配置面/控制面
作用:用于配置、管理和控制Wi-Fi 设备,属于慢路径。
功能:扫描、连接、断开、设置功率、调节天线、查询状态等。
数据流向:用户态命令(
iw,wpa_supplicant)通过netlink套接字发给cfg80211,cfg80211再调用驱动(或mac80211)的回调函数。数据路径中的角色:完全不参与实际数据包的收发。
2.
mac80211:部分数据路径(对 SoftMAC 设备)
作用:对SoftMAC设备,
mac80211确实在数据路径中。功能:实现 802.11 数据帧的封装/解封装、加密/解密、MSDU 聚合等。
数据流向:上层协议栈(TCP/IP)的 skb 进入
mac80211,处理后交给驱动发送;接收路径相反。数据路径中的角色:核心数据处理器。
3. 对 HardMAC 设备(如 AIC8800)
数据路径基本不经过
mac80211。驱动(
aic8800_fdrv)直接从网络栈接收 skb,通过私有接口发给固件处理(如rwnx_msg_tx.c等)。固件内部完成 802.11 封装、加密等操作。
📊 数据路径图解
下面是数据收发时的简化路径,可以清晰看到
cfg80211被完全绕开:发送路径 (TX)
应用程序 (浏览器) ↓ write() TCP/IP 协议栈 (内核) ↓ skb 网络设备子系统 (netif_submit) ↓ ndo_start_xmit() AIC8800 驱动 (aic8800_fdrv) ↓ 驱动私有接口 AIC8800 固件 (运行在 Cortex-M4F) ↓ 硬件 Wi-Fi 信号发出接收路径 (RX)
Wi-Fi 信号到达 ↓ 硬件 AIC8800 固件 (运行在 Cortex-M4F) ↓ 驱动私有接口 (中断/轮询) AIC8800 驱动 (aic8800_fdrv) ↓ netif_rx() / napi_gro_receive() 网络设备子系统 ↓ skb TCP/IP 协议栈 ↓ read() 应用程序可以看到,在整个数据传输过程中,完全没有
cfg80211的身影。💎 类比总结
cfg80211:就像汽车的仪表盘和中控台。你用它来拧钥匙启动、挂挡、打转向灯——这些都是控制和配置。但你真正在高速行驶时,不经过中控台,而是通过方向盘、油门、刹车直接控制机械部件。数据路径:就像发动机到轮子的传动系统。一旦配置好(挂上 D 挡),数据传输就走这个专用高速通道,和配置路径完全分离。
这种“控制面与数据面分离”的设计,是网络设备驱动的经典架构,保证了数据收发的高效率,同时让配置管理接口更清晰、更安全。
wifi也归网络子系统的管理
WiFi 驱动是通过
wiphy_new、wiphy_register和add_virtual_intf等cfg80211接口来管理的。但是,这些接口的底层,最终还是会调用到alloc_netdev和register_netdev来创建真正的网络设备。cfg80211框架是对通用网络设备框架的一个更高层次的封装和扩展。下面我们来详细拆解一下这个过程。
核心概念:
wiphy与net_device的分工这两者代表了不同层次的概念:
概念 代表含义 管理框架 类比 wiphy(Wireless phy)一个物理无线网卡。它描述了这个硬件设备的能力,如支持的频率、信道、加密方式等。 cfg80211一个“物理网卡硬件” net_device一个网络接口。它是内核网络协议栈看到的逻辑设备,可以收发数据包。是通用的网络设备抽象层。 内核核心网络子系统 一个“网络接口” (如 eth0,wlan0)关键点在于:一个
wiphy可以对应多个net_device。这就是为什么你的手机连接WiFi时可以同时开启“热点模式”——同一个物理网卡(同一个
wiphy)可以创建两个虚拟接口(两个net_device),一个作为客户端(wlan0),一个作为热点(ap0)。cfg80211框架的主要职责之一就是管理这种一对多的关系。源码中的直接证据:
alloc_netdev和register_netdev确实存在搜索资料可以直接证明,在
cfg80211的底层实现中,net_device的分配和注册是必不可少的一步。
alloc_netdev的身影
一份较老的cfg80211示例代码清晰地展示了这一完整流程。在通过wiphy_new创建wiphy和wiphy_register注册之后,代码接着调用了alloc_netdev_mqs(即alloc_netdev) 来分配一个网络设备,并为其指定名称"my_dev",最后调用register_netdev将它注册到内核网络系统中。// 示例代码片段 [citation:1] wdev->netdev = alloc_netdev_mqs(..., "my_dev", ..., ether_setup, ...); // ... ret = register_netdev(wdev->netdev);
register_netdev的封装形式
在现代的cfg80211驱动(以mwifiex为例)中,你不会直接看到register_netdevice,而是会看到一个封装函数cfg80211_register_netdevice。但这恰恰证明了其底层实现。// mwifiex 驱动中的实际代码 [citation:2][citation:7] // 在创建虚拟接口的回调函数中 if (cfg80211_register_netdevice(dev)) { // ... }该函数是内核开发者为了管理RTNL锁而引入的封装,其文档明确说明,它最终的效果等同于
register_netdevice。官方文档也规定,驱动需要在add_virtual_intf回调函数中创建并注册这个net_device。
add_virtual_intf:连接两个世界的“桥梁”你提到的
add_virtual_intf正是连接cfg80211世界和通用网络设备世界的关键。
它是
struct cfg80211_ops中的一个回调函数。当用户空间通过nl80211命令请求创建一个新的虚拟接口(比如一个sta模式的wlan0)时,cfg80211内核子系统就会调用驱动注册的这个函数。这个函数的职责就是创建一个
net_device。驱动开发者需要在这个函数内部,调用alloc_netdev或cfg80211_register_netdevice来完成net_device的创建和注册。所以,完整的流程是这样的:
[用户空间] iw wlan0 create | (nl80211命令) ↓ [内核 cfg80211] 收到命令,找到对应的 wiphy 和其 ops | (调用) ↓ [驱动] .add_virtual_intf = 驱动自定义函数 | (内部调用) ↓ [驱动] alloc_netdev() / register_netdev() [或 cfg80211_register_netdevice()] | (创建) ↓ [内核网络子系统] 一个新的 net_device (如 wlan0) 诞生了总结
可以把
cfg80211和通用网络设备框架的关系理解成这样:
通用网络设备框架:提供了最基础的“骨架”——
net_device结构体和register_netdev()等接口。所有网络设备(ETH、PPP、WiFi)都必须基于它构建。
cfg80211框架:为WiFi这个复杂的外设,在这个通用骨架上增加了一套“神经系统”和“肌肉组织”。wiphy描述硬件能力,cfg80211_ops定义操作,但它最终需要通过add_virtual_intf等接口,利用通用的net_device骨架来创建出系统可见的网络接口。所以,你观察到的现象是API层面的差异,但底层原理是统一的。WiFi驱动开发者使用
cfg80211框架提供的更专业、更方便的API,这些API在内部依然依赖并正确使用了通用网络设备框架提供的基础设施。
struct wiphy
struct wiphy是 Linux 内核cfg80211框架中描述一个物理无线设备的核心结构体。你可以把它理解为该物理 Wi-Fi 芯片在内核中的“身份证”或“简历”。它由驱动分配并注册到内核,主要职责是向
cfg80211子系统声明它所代表的硬件具备哪些能力,并为上层的配置和管理提供基础。1. 核心定位:物理硬件的抽象
struct wiphy代表的是一个物理无线网卡 (PHY),比如你系统里的一块 AIC8800 芯片。
与
net_device的区别:struct net_device(如wlan0) 是系统看到的逻辑网络接口。一个wiphy可以对应多个net_device,例如一个物理网卡可以同时创建出用于连接 Wi-Fi 的wlan0和用于发射热点的ap0。与
ieee80211_hw的关系:对于使用mac80211框架的 SoftMAC 驱动,其核心结构体struct ieee80211_hw内部就包含了一个指向struct wiphy的指针。2. 关键成员:硬件能力的“简历”
struct wiphy包含了大量的成员变量,驱动在注册它之前需要填充这些字段,以告知内核该硬件的各项能力。
分类 关键成员 作用 基础信息 perm_addr设备的永久 MAC 地址。 工作模式 interface_modes支持的接口模式,如工作站 (STA)、热点 (AP) 等。 频谱/信道 bands[]极其重要。指向一个数组,定义了硬件支持的每一个频段(如 2.4 GHz、5 GHz),包括该频段下的所有可用信道、每个信道的最大发射功率、以及支持的 802.11 速率。 特性标志 features,flags用位掩码表示的硬件特性,例如是否支持 WPA3、省电模式等。 固件/版本 fw_version固件版本信息,用于 ethtool等工具查询。操作函数集 (在 wiphy_new时传入)驱动实现的 struct cfg80211_ops函数指针集,是连接用户空间命令(如扫描、连接)和硬件固件操作的桥梁。私有数据 priv可变长度数组,驱动可以将其强制转换为自己定义的私有数据结构,存放硬件上下文。 3. 生命周期管理:关键 API
驱动程序通过以下标准函数来管理
struct wiphy的生命周期:
wiphy_new():驱动初始化时调用。该函数会分配一个wiphy结构体的内存(包括后面的priv私有数据空间),并将驱动实现的cfg80211_ops函数集与它关联起来。填充成员:在调用注册函数之前,驱动需要填充
wiphy的上述关键成员,如perm_addr、bands、interface_modes等,以声明硬件能力。
wiphy_register():将填充好的wiphy注册到内核的cfg80211子系统中。注册成功后,该设备才会在系统中可见(如在/sys/class/ieee80211/下出现对应的目录)。
wiphy_unregister()与wiphy_free():驱动卸载时调用,执行与注册相反的操作,从系统中移除并释放wiphy结构体占用的内存。
struct cfg80211_ops
struct cfg80211_ops超详细详解(Linux 无线驱动核心)一、它是什么?
struct cfg80211_ops是Linux 内核 cfg80211 子系统的核心回调函数集合。简单说:它就是无线驱动(WiFi)告诉内核 “我能做什么、怎么做” 的函数表。内核的无线协议栈(nl80211 /cfg80211)→ 调用
cfg80211_ops→ 你的硬件驱动它是mac80211 软 AP / station / 扫描 / 认证 / 关联一切功能的入口。
二、定义位置
#include <net/cfg80211.h>三、核心作用(一句话)
内核想让 WiFi 做任何操作,都会调用 cfg80211_ops 里的函数。驱动必须实现这些函数,硬件才能工作。
四、结构体全貌(精简关键版)
我只保留最常用、必须理解的成员,去掉废弃 / 极少用的:
struct cfg80211_ops { /* 扫描 WLAN 网络 */ int (*scan)(struct wiphy *wiphy, struct cfg80211_scan_request *request); /* 认证(Authentication) */ int (*auth)(struct wiphy *wiphy, struct station_info *si, struct cfg80211_auth_request *req); /* 关联(Association) */ int (*assoc)(struct wiphy *wiphy, struct station_info *si, struct cfg80211_assoc_request *req); /* 断开连接 */ int (*deauth)(struct wiphy *wiphy, struct station_info *si, struct cfg80211_deauth_request *req); /* 启动 AP */ int (*start_ap)(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_ap_settings *settings); /* 停止 AP */ int (*stop_ap)(struct wiphy *wiphy, struct wireless_dev *wdev); /* 加入 IBSS(Ad-hoc) */ int (*join_ibss)(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_ibss_params *params); /* station 信息获取 */ int (*get_station)(struct wiphy *wiphy, struct station_info *si); /* 设置信道 */ int (*set_channel)(struct wiphy *wiphy, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); /* 发送 mgmt 帧 */ int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_mgmt_tx_params *params); /* 切换网卡模式(station / ap / monitor) */ int (*set_interface_mode)(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_iftype type); /* 发送数据帧 */ netdev_tx_t (*xmit)(struct sk_buff *skb, struct net_device *dev); };五、最关键函数功能详解(驱动开发必考)
1.
scan作用:扫描周围 WiFi 热点内核调用 → 驱动控制硬件扫描 → 驱动把扫描结果上报内核
2.
auth作用:802.11 认证(开放 / 共享密钥)连接 WiFi 的第一步。
3.
assoc作用:关联 AP连接 WiFi 的第二步,成功后才算连上。
4.
deauth作用:断开 WiFi 连接
5.
start_ap作用:开启 SoftAP 热点设置 SSID、密码、信道、加密方式。
6.
stop_ap作用:关闭 AP
7.
set_channel作用:设置 WiFi 工作信道(1~14 等)
8.
set_interface_mode作用:切换模式
- station(客户端)
- AP(热点)
- monitor(监听)
- P2P(点对点)
9.
mgmt_tx作用:发送管理帧(Probe、Beacon、Auth、Assoc 等)
10.
xmit作用:发送普通数据帧最底层发送函数。
六、它和谁配合工作?
1.
struct wiphy代表无线硬件设备每个 WiFi 芯片对应一个 wiphy。
2.
struct wireless_dev代表无线虚拟接口(wlan0、ap0 等)
3.
net_deviceLinux 标准网络设备
调用关系:
用户空间(iw / hostapd / wpa_supplicant) ↓ 内核 nl80211/cfg80211 ↓ 调用 cfg80211_ops 函数 ↓ 驱动操作硬件七、驱动如何使用?(最简示例)
/* 1. 定义你的 ops */ static struct cfg80211_ops my_wifi_ops = { .scan = my_scan, .auth = my_auth, .assoc = my_assoc, .start_ap = my_start_ap, .set_channel = my_set_channel, /* ... 其他函数 ... */ }; /* 2. 注册 wiphy 时绑定 */ wiphy = wiphy_new(&my_wifi_ops, sizeof(struct my_wifi_priv));八、一句话总结(最核心)
cfg80211_ops = WiFi 驱动的 “功能菜单”,内核点菜,驱动做菜。不实现它,WiFi 芯片啥也干不了。
struct wireless_dev
struct wireless_dev(简称wdev)是 cfg80211 子系统里代表一个无线逻辑接口的核心结构体,比如wlan0(STA)、ap0(AP)、p2p0(P2P)。简单一句话:wiphy 是物理无线硬件;wireless_dev 是硬件上跑的一个无线接口实例。一、头文件 & 定义位置
#include <net/cfg80211.h>二、结构体精简核心成员(内核 5.x/6.x 通用)
struct wireless_dev { struct wiphy *wiphy; // 所属物理无线设备 enum nl80211_iftype iftype; // 接口模式:STA/AP/MONITOR/P2P等 struct net_device *netdev; // 绑定的Linux网络设备 u8 address[ETH_ALEN]; // 本接口MAC地址 u8 bssid[ETH_ALEN]; // 连接的AP的BSSID(STA模式用) /* 连接状态、认证关联信息 */ struct cfg80211_bss *current_bss; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len; /* 加密/安全参数 */ struct cfg80211_crypto_settings crypto; /* AP模式参数 */ struct cfg80211_ap_settings *ap_settings; /* 状态标记 */ bool connected; // 是否已连接AP bool operational; enum nl80211_auth_type auth_type; /* 内核内部锁、状态机、工作队列 */ spinlock_t lock; struct work_struct disconnect_work; /* 私有数据指针,驱动可扩展 */ void *drv_priv; };三、关键字段逐行详解(驱动开发重点)
1.
wiphy指向所属物理无线设备,一个
wiphy可以挂载多个 wireless_dev(多接口)。2.
iftype—— 最重要字段接口类型,决定这个 wdev 是干嘛的:
enum nl80211_iftype { NL80211_IFTYPE_STATION, // 普通WiFi客户端(wlan0) NL80211_IFTYPE_AP, // 热点模式(SoftAP) NL80211_IFTYPE_MONITOR, // 监听模式 NL80211_IFTYPE_P2P_CLIENT, // P2P客户端 NL80211_IFTYPE_P2P_GO, // P2P热点 NL80211_IFTYPE_ADHOC, // 自组网IBSS ... };内核通过此字段调用
cfg80211_ops中对应回调。3.
netdev绑定 Linux 标准网络设备,收发数据最终走
netdev。4.
address本接口 MAC;
bssid= 连上的路由器 MAC。5.
ssid / current_bssSTA 模式:保存当前连接的 WiFi 名称、BSS 信息。
6.
crypto加密配置:WPA2/WPA3、密钥、算法,驱动读取配置。
7.
ap_settingsAP 模式专用:SSID、信道、加密、带宽、beacon 间隔。
8.
connected状态位:true = 已成功关联 AP;false = 未连接 / 断开。
9.
drv_priv驱动私有数据,驱动自定义扩展,存硬件状态、固件信息等。
wireless_dev到底是干啥的,没太理解。。。。。。。。。。。。
理解
wireless_dev的关键,在于分清"物理硬件"和"虚拟接口"这两个概念。简单来说,
wireless_dev就是一个虚拟的、纯软件的无线网络接口。它代表了你通过iw命令在同一个物理网卡 (wiphy) 上创建出来的一个逻辑设备。概念区分:一张网卡,多个身份
为了帮你理解,我们先区分两个概念:
wiphy(物理设备):代表你电脑或手机里那块实实在在的Wi-Fi 芯片,比如 AIC8800。它非常强大,但它只是一个硬件。
net_device(通用网络接口):这是内核网络子系统看到的网络接口,比如eth0。它主要负责数据的收发。
wireless_dev(无线设备):它是net_device在无线领域的"专业增强版"。它包含了net_device的所有基本功能,同时又额外添加了无线通信特有的"状态信息"和"配置参数",比如当前连接到了哪个 Wi-Fi、加密方式是什么、信号强度如何等。假设你有一台物理服务器(
wiphy),它有强大的计算能力。你可以在这台服务器上创建多个虚拟机(wireless_dev),每个虚拟机都有自己的操作系统和 IP 地址(net_device)。一个虚拟机可以作为客户端去访问别人(wlan0),另一个虚拟机可以作为服务器提供热点服务(ap0)。wireless_dev就是这些虚拟机的蓝图。
wireless_dev的核心价值可以这样理解:
一个
wiphy可以创建出多个wireless_dev,每个wireless_dev都对应着一个供内核使用的net_device,并用无线相关的状态信息对后者进行了补充。这个设计,使得一块强大的物理无线网卡(
wiphy)能被虚拟成多个功能各异的逻辑设备,完美支持了Wi-Fi的各种复杂应用场景。例如,一台支持AP+STA并发模式的设备,其内部逻辑就是:
一个
wiphy(代表物理芯片)。它下面创建了两个
wireless_dev:iftype为NL80211_IFTYPE_STATION(客户端) 和NL80211_IFTYPE_AP(热点)。每个
wireless_dev都关联着自己的net_device(wlan0和ap0)。这两个
net_device各自维护一个完整的网络协议栈,可以独立地进行网络通信。生命周期:代码协作示例
在内核文档的示例中,
wireless_dev的生命周期通过cfg80211_ops中的两个关键回调函数来管理:/* file: drivers/net/wireless/cfg80211/mydrv_main.c */ static int mydrv_add_virtual_intf(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, enum nl80211_iftype type, struct vif_params *params) { struct mydrv_priv *priv = wiphy_priv(wiphy); struct wireless_dev *wdev; struct net_device *ndev; // 1. 分配一个 net_device,并返回它内部的 wireless_dev 指针 ndev = alloc_netdev_mqs(sizeof(*wdev), name, name_assign_type, ether_setup, 1, 1); wdev = ndev->ieee80211_ptr; // 拿到 wireless_dev wdev->wiphy = wiphy; // 设置所属 wiphy wdev->iftype = type; // 设置模式 (STA/AP) // 2. 注册 net_device (此时 wireless_dev 也随之对内核可见) if (register_netdevice(ndev)) { free_netdev(ndev); return -EINVAL; } return 0; } static int mydrv_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) { struct net_device *ndev = wdev->netdev; // 执行无线特有的清理工作... // ... // 3. 删除接口 unregister_netdevice(ndev); free_netdev(ndev); return 0; } static struct cfg80211_ops mydrv_ops = { .add_virtual_intf = mydrv_add_virtual_intf, .del_virtual_intf = mydrv_del_virtual_intf, // ... 其他回调 };这个流程清晰地展示了
wireless_dev如何通过add_virtual_intf回调被创建,并与net_device关联。总结
维度 wiphy(物理设备)wireless_dev(无线设备)net_device(网络接口)本质 代表物理硬件 代表虚拟接口 代表网络协议栈的抽象端口 关系 一个硬件包含一个 一个 wiphy拥有多个一个 wireless_dev关联一个 (1:1)作用 声明硬件能力 管理无线状态和配置 管理数据包收发 类比 一部高端智能手机 手机运行的"副系统"(工作空间) 副系统打开的微信/QQ聊天窗口 所以,回到你的问题:"
wireless_dev到底是干啥的?"它的核心使命就是:作为一个功能更强大的
net_device集无线专有状态于一身,使得一个物理网卡(wiphy)能够被灵活地虚拟成多个具有不同无线功能(如工作站或热点)的逻辑接口(wlan0,ap0等),从而完美支持各种复杂的无线应用场景。具体说明:wiphy/wireless_dev/net_device之间是啥关系??
cfg80211一般开发步骤
cfg80211的使用主要面向驱动开发者,而非普通用户。如果你是要为 AIC8800 这样的芯片开发或移植驱动,那么了解其在内核中的标准使用步骤至关重要。这些步骤的核心是:驱动向内核注册一个
wiphy(无线物理设备)对象,并实现cfg80211_ops中的操作函数。以下是典型的标准使用流程:
步骤一:注册
wiphy设备这是驱动初始化的第一步。驱动需要分配、初始化并注册一个
wiphy结构体,向系统声明一个无线网卡的存在。// 1. 分配 wiphy 结构体 struct wiphy *wiphy = wiphy_new(&my_cfg80211_ops, sizeof(struct my_priv)); // 2. 设置 wiphy 的能力标志 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); wiphy->bands[NL80211_BAND_2GHZ] = &my_band_2ghz; // 支持2.4G频段 // 3. 注册 wiphy 到系统 int ret = wiphy_register(wiphy);这对应到 AIC8800 驱动的实际代码中,你应该能在
aic8800_fdrv的初始化函数中找到类似的wiphy_new()和wiphy_register()调用。步骤二:实现
cfg80211_ops回调函数这是最核心的一步。驱动需要实现
struct cfg80211_ops中定义的操作。用户空间通过nl80211发送的命令,最终都会映射到这里。static struct cfg80211_ops my_cfg80211_ops = { .scan = my_scan, // 处理扫描请求 .connect = my_connect, // 处理连接请求 (WPA supplicant调用) .disconnect = my_disconnect, // 处理断开请求 .add_key = my_add_key, // 添加加密密钥 .set_power_mgmt = my_set_power, // 设置省电模式 // ... 更多回调 };对于 HardMAC 设备(如 AIC8800),这些函数的具体工作通常是:将命令打包,通过IPC 消息(如
rwnx_msg_tx.c中的函数)发送给芯片固件执行。步骤三:创建虚拟接口 (Net Device)
注册
wiphy后,系统还没有可用的网络接口。需要通过nl80211命令或驱动内部调用ieee80211_add_virtual_interface()来创建像wlan0这样的网络设备。驱动通常需要实现
add_virtual_intf回调,该回调负责分配并注册一个net_device,并将其与wiphy关联。// 在 cfg80211_ops 中实现 static int my_add_interface(struct wiphy *wiphy, struct wireless_dev *wdev) { // 初始化 net_device 并关联到 wdev // 设置 netdev_ops 指向驱动的数据收发函数 }步骤四:处理数据路径(绕过 cfg80211)
如前所述,配置完成后,实际的数据收发就走另一条路了:
发送:内核网络栈调用驱动的
ndo_start_xmit回调,驱动将数据交给固件发送。接收:固件上报数据,驱动调用
netif_rx()或napi_gro_receive()将数据送入内核网络栈。步骤五:注销与清理
当驱动卸载时,需要按相反顺序清理:
// 1. 删除虚拟接口 // 2. 注销 wiphy wiphy_unregister(wiphy); // 3. 释放 wiphy wiphy_free(wiphy);💎 总结
cfg80211的使用核心就是围绕以下三点展开:
注册与声明:让内核知道硬件存在及其能力。
实现回调:定义如何响应上层的配置命令。
交由框架管理生命周期:利用内核提供的 API 完成注册与注销。
通过这个标准框架,无线驱动开发得以规范化,开发者可以聚焦在芯片特有的通信逻辑(如 AIC8800 的消息机制),而无需操心用户空间通信细节和法规约束。
aic8800如何使用cfg80211
一、初始化流程:注册到cfg80211
1
2
3
二、cfg80211_ops回调实现
三、典型流程分析
1
2
3
四、事件上报机制
五、完整交互架构图
更多