GK 平台 OpenHarmony 6.1 适配兆通微 9612U WiFi 模组案例总结
| 项目 | 内容 |
|---|---|
| 文档版本 | V1.0 |
| 目标平台 | GK6780V100 / OpenHarmony 6.1 |
| WiFi 模组 | 兆通微 9612U(USB 接口,WiFi + 蓝牙 combo) |
| 厂商驱动包 | ZTOP_ACEV100_Android16_wifi_bt_20260417171536_V312D |
摘要
GK 平台系统由 OpenHarmony 5.1 升级至 6.1 后,原有 WiFi 模组驱动与框架接口发生较大变化。为满足无线网络连接及个人热点业务需求,项目选用兆通微 9612U USB WiFi 模组,基于厂商 ZTOP V312D 驱动源码完成内核模块编译、系统镜像集成及框架层适配。
本次适配依次攻克 HDF 设备注册、进程权限、热点 HDF 节点缺失、DHCP OFFER 报文不合规等问题,最终实现:STA 模式扫描/连接/DHCP/上网全流程贯通,以及系统级个人热点(SoftAP)多终端接入并自动获取 IP。本文档对调试过程、根因分析与修改方案进行系统归纳,供同类 USB WiFi 模组在 OH 6.1 上的移植参考。
1. 背景与目标
1.1 升级背景
OpenHarmony 6.1 相较 5.1,在 WiFi 子系统上主要变化包括:
- HDF 设备模型:WLAN 能力通过libwifi_hdi_c_device.z.so、libwpa_hdi_c_device.z.so、libhostapd_hdi_c_device.z.so等 C 语言 HDI 设备对外暴露,由wifi_host等 Host 进程承载。
- 服务分层:wifi_manager_service负责上层业务;WPA/Hostapd 通过 HDF 接口与框架交互。
- 组件演进:上游部分版本已移除独立 wifi_hal_service 二进制,目录创建等初始化逻辑需通过 init 配置保留,避免 WPA 框架依赖路径缺失。
在上述架构下,厂商 Linux 驱动需重新对接 nl80211/cfg80211,并完成 HDF、init、SELinux 等多层配置。
1.2 模组选型
| 属性 | 说明 |
|---|---|
| 型号 | 兆通微 9612U |
| 接口 | USB |
| 能力 | STA / AP 并发,支持 P2P 虚拟接口 |
| 驱动 | ZTOP 系列,ztop_wifi_driver.ko + zt9612_fw.bin固件 |
1.3 验收目标
- 开机自动加载驱动,出现 wlan0(及 p2p0、wlan1等虚拟接口)。
- STA:扫描、连接、DHCP 获址、访问外网。
- SoftAP:系统设置中开启个人热点,手机可搜索、连接、通过 DHCP 获 IP 并上网。
2. 系统架构
个人热点与 STA 在 OH 6.1 上的主要调用关系如下:


说明:STA 走 wpa_interface_service + wpa_supplicant;SoftAP 走 hostapd_interface_service + 系统 dhcp_server,不再依赖独立的 dnsmasq手动方案(早期验证曾用手动 hostapd,最终交付以框架方案为准)。
3. 调试时间线
| 阶段 | 日期 | 日志目录 | 主要问题 |
|---|---|---|---|
| WiFi 打开失败 | 05-12 | log/hilog_6.1_wifi_open_fail01 ~ fail06 | HDF 未注册、配置权限、CAP_NET_ADMIN |
| 热点无法启动 | 05-18 | log/hilog_6.1_softap_fail01 ~ fail03 | hostapd_interface_service 未注册 |
| 关联后无 IP | 05-18 ~ 05-20 | log/hilog_6.1_softap_dhcp_fail01 ~ fail06 | DHCP OFFER 报文非法 |
| 全链路通过 | 05-20 | log/hilog_6.1_softap_dhcp_ok01 | DISCOVER → OFFER → REQUEST → ACK 完整 |
4. 驱动编译与集成
4.1 环境准备
| 项目 | 配置 |
|---|---|
| 开发主机 | Ubuntu 22.04 |
| 工具链 | OHOS 6.1 LLVM(clang)+ 交叉编译前缀 |
| 内核 | Linux 5.10(GK6780V100 OH 6.1 适配版) |
| 驱动源码 | 厂商包解压至 ZTOP_V312D/wifi_driver/ |
4.2 编译脚本关键参数
修改 ZTOP_V312D/wifi_driver/build/build_linux.sh:
| 配置项 | 配置值 | 说明 |
|---|---|---|
| KSRC | {OHOS_ROOT}/out/kernel/OBJ/linux-5.10 | 须指向已编译内核树(含 .config、Module.symvers) |
| CROSS_COMPILE | prebuilts/gcc/.../aarch64-linux-gnu- | 交叉工具链前缀 |
| Clang | prebuilts/clang/ohos/linux-x86_64/llvm/bin/ | LLVM 编译器路径 |
| ANDROID | 1 | 使能 Android 兼容宏,创建 p2p0 接口,避免 P2P 状态机异常 |
ANDROID=1同时影响厂商驱动中 AP 模式相关编译选项;ZTOP V312D 驱动默认编译完整 mac80211 栈并支持 NL80211_IFTYPE_AP;gk6780 平台编译时需保持 build_linux.sh gk6780 中 ANDROID=1(用于 p2p0 等接口)。ZTOP V312D 驱动源码中不存在 CONFIG_AP_MODE宏,AP 能力由内置 mac80211 栈默认提供。

4.3 编译与部署步骤
步骤 1:编译内核(生成模块依赖树)
cd {OHOS_ROOT}
./build.sh --product-name=gk6780v100 -T kernel
步骤 2:编译 WiFi 驱动
cd {OHOS_ROOT}/ZTOP_V312D/wifi_driver/build
sudo ./build_linux.sh gk6780
产物:build/output/ztop_wifi_driver.ko、fw/zt9612_fw.bin。
步骤 3:拷贝至 vendor 预置目录
cp build/output/ztop_wifi_driver.ko \
vendor/goke/gk6780v100/wifi/firmware/ztop_wifi_driver.ko
cp fw/zt9612_fw.bin \
vendor/goke/gk6780v100/wifi/firmware/zt9612_fw.bin
由 vendor/goke/gk6780v100/wifi/BUILD.gn 打包安装至镜像:
- Ko:/vendor/etc/ko/ztop_wifi_driver.ko
- 固件:/vendor/firmware/zt9612_fw.bin
步骤 4:Strip(可选)
$(CROSS_COMPILE)strip --strip-debug --strip-unneeded ztop_wifi_driver.ko
4.4 开机加载
在 device/board/goke/gk6780v100/tv/customize/gk6780v100/etc/vendor/init.taishan.cfg 的 boot job 中增加:
insmod /vendor/etc/ko/ztop_wifi_driver.ko
加载成功后 ifconfig -a 可见 wlan0、p2p0、wlan1 等节点(MAC 示例:60:58:01:xx:xx:xx)。
5. WiFi STA 功能调通(2026-05-12)
5.1 问题汇总
| # | 现象 | 根因 | 修复方案 | 关键证据 |
|---|---|---|---|---|
| 1 | 打开 WiFi 立即失败 | wpa_interface_service 未写入 HDF 设备表 | 在 device_info.hcs 的 wlan::host 下增加 wpa_c_device,preload = 2 | device wpa_interface_service not in configed device list |
| 2 | 启动报 wifi_hal_service 无效 | OH 6.1 镜像无 /system/bin/wifi_hal_service | 删除 post-fs 中 start wifi_hal_service 及 services 定义;保留 early-boot 中目录创建命令 | kmsg: ServiceStart pathArgs invalid |
| 3 | wpa_supplicant 无法读配置 | wifi_host 进程缺少 wifi_group | wifi_standard.cfg 为 wifi_manager_service 增加 wifi_group gid(与目录属组一致) | Failed to open config file ... Permission denied |
| 4 | 无法将 wlan0 置 UP | wifi_host 缺少 NET_ADMIN / NET_RAW | device_info.hcs 增加 caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH", "NET_ADMIN", "NET_RAW"] | Could not set interface wlan0 flags (UP): Operation not permitted |
| 5 | 启动早期 P2P 状态机报错 | 驱动未创建 p2p0 | 编译脚本设置 ANDROID=1 | P2P state machine does not process messages: [200] |
5.1.1 HDF 配置示例(wlan::host)
路径:vendor/goke/gk6780v100/hdf_config/uhdf/device_info.hcs
wlan :: host {
hostName = "wifi_host";
priority = 50;
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH", "NET_ADMIN", "NET_RAW"];
gid = ["wifi_host", "wifi_group"];
wifi_device :: device { ... wlan_interface_service ... }
chip_device :: device { ... chip_interface_service ... }
wpa_c_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
preload = 2;
moduleName = "libwpa_hdi_c_device.z.so";
serviceName = "wpa_interface_service";
}
}
hostapd_device :: device { ... hostapd_interface_service ... }
}
说明:preload = 2(DEVICE_PRELOAD_DISABLE)表示设备进入 DevMgr 动态设备列表,框架在需要时通过 LoadDevice 加载;未配置则动态加载必然失败。
5.1.2 wifi_hal_service 处理说明
调试阶段发现 init 仍尝试启动已不存在的 wifi_hal_service 二进制。处理原则:
- 保留 early-boot 中对 /data/service/el1/public/wifi、wpa_supplicant、sockets、dhcp 等目录的 mkdir 与 restorecon;
- 移除对不存在二进制的 start 与 services 条目。
GK6780V100 产品另可通过 vendor/goke/gk6780v100/patch/foundation/communication/wifi/0008-support_dynamic_wifi.patch 扩展 HAL 层动态 insmod 能力;本案例最终采用 init.taishan.cfg 在 boot 阶段直接 insmod,与上述 patch 可并存,文档以实际生效的 init 加载路径为准。
5.2 STA 功能验证
| 测试项 | 操作 | 预期 | 结果(05-12 后) |
|---|---|---|---|
| 扫描 | 进入设置 → 无线局域网,开启WiFi开关 | 列出周边 AP | 通过 |
| 连接 | 选择目标AP,输入密码,点击连接 | 关联成功 | 通过 |
| DHCP | 框架自动 DHCP | 获取有效 IP | 通过 |
| 上网 | ping 外网域名 | 连通 | 通过 |
6. 个人热点(SoftAP)调通(2026-05-18 ~ 05-20)
OH 6.1 个人热点由 hostapd(HDF)+ dhcp_server 实现,用户在设置中打开热点后,由 WifiApService 驱动完整状态机。
6.1 热点无法启动(05-18)
现象
设置中开启个人热点后很快关闭,其他设备扫描不到 SSID。
根因
WifiApService 通过 DevMgr 动态加载 hostapd_interface_service,但 GK6780V100 的 device_info.hcs 中:
- 缺少 hostapd_interface_service 节点;或
- moduleName 错误(如写成 libhostapd_interface);或
- 未设置 preload = 2,不在动态设备列表内。
对比同平台已量产配置 vendor/goke/gk6320/hdf_config/uhdf/device_info.hcs,gk6320 在独立 hostapd::host 下正确声明了 libhostapd_hdi_c_device.z.so 与 preload = 2。gk6780v100 属于配置遗漏。
关键日志
DevmgrServiceStubDispatchLoadDevice:load service hostapd_interface_service
device hostapd_interface_service not in configed device list
HdiStartAp: HdiApStart failed.
enter ApstartedState is failed.
修复
在 wlan::host(或独立 hostapd host,与产品策略一致)中增加:
hostapd_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
preload = 2;
moduleName = "libhostapd_hdi_c_device.z.so";
serviceName = "hostapd_interface_service";
}
}
serviceName 与 HDI_AP_SERVICE_NAME 一致;moduleName 与 drivers/peripheral/wlan/hostapd 的 BUILD.gn 产物一致。
验证
热点可正常拉起,驱动日志可见 VIF 切换为 AP 模式(vif_type:3),wpa_supplicant 侧有 AP-STA-CONNECTED 等事件。
6.2 客户端关联但无法获取 IP(05-18 ~ 05-20)
本阶段为本次适配的核心难点:热点 SSID 可见、手机可关联并完成 WPA 四次握手,但始终拿不到 IP,一直重复 DHCP DISCOVER。
6.2.1 排查过程

| 排查手段 | 发现 |
|---|---|
| hilog C01565 | 仅有 DISCOVER / OFFER,无 REQUEST / ACK |
| 强制广播补丁后 | broadCastFlag: 1 已生效,仍无 REQUEST |
| tcpdump / Wireshark | OFFER 标记为 Malformed Packet;option 54 之后截断,缺少 END 0xff |
6.2.2 根因与修复(三轮)
第一轮:DHCP 广播与选项基础修复
| 问题 | 根因 | 修复文件 |
|---|---|---|
| 单播 OFFER 手机收不到 | SoftAP 接口上未强制广播 | dhcp_s_server.cpp:IsWifiApInterface() + force broadcast |
| failed to create option node | END_OPTION(255) 长度为 0 时 CreateOptionNode 拒绝 | dhcp_option.cpp:允许 code=255 && length=0 |
| giaddr 异常 | 客户端 giaddr=0 时仍填入网关地址 | dhcp_s_server.cpp:FillReply 仅在收到非 0 giaddr 时回填 |
| sendto 误判成功 | 使用 if (!ret) 将 -1 当作成功 | 改为 if (ret < 0) |
修复后仍只有 DISCOVER/OFFER 循环,OFFER 长度仍为 304 字节。
第二轮:报文长度错误(决定性根因)
| 项目 | 错误值 | 正确值(RFC 2131) |
|---|---|---|
| DHCP_MSG_HEADER_SIZE |
234 | 236(BOOTP 固定头至 options 前) |
| 实际发送长度 | 304 = 234 + 70 | 306 = 236 + 4(magic cookie)+ 66(options 含 END) |
ParseReplyOptions() 中 reply->length = DHCP_MSG_HEADER_SIZE + replyOptsLength 少算 2 字节,导致 sendto() 在 option 区尾部截断,DNS option(option 6)少发 1 字节且缺少 END,Wireshark 报 Malformed,手机丢弃 OFFER。
修复:
- dhcp_message.h:#define DHCP_MSG_HEADER_SIZE 236
- dhcp_s_server.cpp:ParseReplyOptions() 写入前检查 remainingSize,避免静默截断
第三轮:验证通过
成功日志(log/hilog_6.1_softap_dhcp_ok01):
Discover reply offer
send reply offer, length:306
==> Received DHCPREQUEST message.
Request reply ack!
send reply ack, size:306
手机获得 192.168.62.x 网段地址(以实际 dhcpd 配置为准),可正常上网。
6.2.3 DHCP 修复要点对照表
| 修改点 | 文件 | 作用 |
|---|---|---|
| DHCP_MSG_HEADER_SIZE 236 | dhcp_message.h | 报文总长度与 RFC 一致 |
| END option 零长度 | dhcp_option.cpp | 选项区合法结束 |
| END 单字节 0xFF 写入 | dhcp_s_server.cpp | 符合 TLV 解析规则 |
| giaddr 条件填充 | dhcp_s_server.cpp | 直连 SoftAP 场景 giaddr 保持 0 |
| WiFi AP 强制广播 | dhcp_s_server.cpp | 提高 OFFER/ACK 到达率 |
| sendto 返回值判断 | dhcp_s_server.cpp | 发送失败可感知 |
6.3 SoftAP 验证结果
| 验证项 | 操作 | 结果 |
|---|---|---|
| 热点可见 | 手机搜索 WiFi | SSID 正常广播 |
| 连接 | 输入 WPA2 密码 | 关联成功 |
| 获 IP | 查看手机网络详情 | 192.168.x.x(DHCP) |
| 上网 | 浏览器访问外网 | 正常 |
7. 驱动层补充说明
7.1 P2P 接口与 ANDROID 宏
编译时未设置 ANDROID=1 时,驱动不创建 p2p0,wifi_manager_service 在启动早期向 P2P 状态机发送消息会失败,可能间接影响 SoftAP 并发或切换。设置后可见 p2p0 接口,P2P 相关告警消除。
7.2 AP 模式与 SoftAP 驱动侧说明
9612U 硬件支持 STA/AP 并发。本案例使用的 ZTOP V312D 驱动(ztop_wifi_driver.ko)无需、也不存在 CONFIG_AP_MODE 开关——该描述适用于其他厂商驱动(如 Realtek rtw_ap 方案),勿照搬。
ZTOP 驱动 AP 能力的实际来源如下:
| 机制 | 位置 | 说明 |
|---|---|---|
| mac80211 全栈编译 | wifi_driver/build/Makefile 中 MAC80211_COMPILE=1 | 默认编入 cfg.c、iface.c、tx.c 等,含 AP 相关逻辑 |
| AP 接口类型注册 | src/core/rwnx_main.c | NL80211_IFTYPE_AP 已在 rwnx_limits 中声明 |
| gk6780 编译参数 | build/build_linux.sh → ANDROID=1 | 创建 p2p0、启用 android_if_*.c,与 P2P/接口创建相关 |
| 固件 | zt9612_fw.bin | 随 Ko 一并部署至 /vendor/firmware/ |
gk6780 平台编译命令:./build_linux.sh gk6780(须先完成内核编译)。产物拷贝至 vendor/goke/gk6780v100/wifi/firmware/ 后打包进镜像。
框架层 SoftAP 还需完成 HDF hostapd_interface_service 等配置(见第 6 章);驱动侧只要 Ko 能创建 AP VIF(日志中 vif_type:3)即可。本案例实测 SoftAP 已调通,说明当前预置 Ko 已具备 AP 能力,无需额外打开 CONFIG_AP_MODE。
8. 变更文件清单(附录 A)
| 子系统 | 文件路径 | 变更说明 |
|---|---|---|
| HDF | vendor/goke/gk6780v100/hdf_config/uhdf/device_info.hcs | 补全 wlan/wpa/hostapd 节点、caps、preload |
| Init | device/board/goke/.../init.taishan.cfg | boot 阶段 insmod WiFi/BT Ko |
| WiFi 服务 | foundation/communication/wifi/.../wifi_standard.cfg | wifi_manager_service 增加 wifi_group |
| WiFi Init | foundation/communication/wifi/.../wifi_hal_service.cfg | 移除无效 wifi_hal_service 启动(调试方案) |
| DHCP | foundation/communication/dhcp/.../dhcp_message.h | DHCP_MSG_HEADER_SIZE → 236 |
| DHCP | foundation/communication/dhcp/.../dhcp_option.cpp | 允许 END_OPTION 零长度节点 |
| DHCP | foundation/communication/dhcp/.../dhcp_s_server.cpp | 广播、giaddr、长度、sendto 等修复 |
| Vendor | vendor/goke/gk6780v100/wifi/BUILD.gn | 预置 Ko 与固件 |
| Vendor | vendor/goke/gk6780v100/wifi/firmware/* | ztop_wifi_driver.ko、zt9612_fw.bin 等 |
| 驱动源码 | ZTOP_V312D/wifi_driver/build/build_linux.sh | KSRC、工具链、ANDROID=1 |
| 可选 Patch | vendor/goke/gk6780v100/patch/.../0008-support_dynamic_wifi.patch | HAL 动态 insmod(产品可选) |
9. 经验总结
9.1 关键成果
- 在 OH 6.1 上完成兆通微 9612U 驱动编译、镜像集成与框架适配。
- STA 模式:扫描、连接、DHCP、上网全流程可用。
- SoftAP:系统级个人热点可被发现、连接,客户端 DHCP 完整交互(OFFER 306 字节 / ACK 306 字节)。
9.2 OH 6.1 WiFi 模组适配 Checklist
- HDF 三件套:wlan_interface_service、wpa_interface_service、hostapd_interface_service 均需注册,动态加载须 preload = 2。
- wifi_host 权限:caps 含 NET_ADMIN、NET_RAW;gid 含 wifi_group;配置目录属主与进程 gid 一致。
- init 与上游差异:确认 wifi_hal_service 二进制是否存在,勿启动无效服务;保留 data 分区目录初始化。
- 驱动编译:gk6780 须用 ./build_linux.sh gk6780 且 ANDROID=1(p2p0);ZTOP 驱动 AP 由 mac80211 默认支持,无 CONFIG_AP_MODE。
- DHCP:SoftAP 场景用 Wireshark 校验 OFFER 长度与 option 完整性;DHCP_MSG_HEADER_SIZE 必须为 236。
- SELinux:失败时优先检索 avc: denied(本次以权限与 HDF 为主,SELinux 为辅助排查项)。
10. 参考日志目录
完整调试日志位于工程log/ 目录:
- hilog_6.1_wifi_open_fail01 ~ fail06 — WiFi 打开(05-12)
- hilog_6.1_softap_fail01 ~ fail03 — 热点启动(05-18)
- hilog_6.1_softap_dhcp_fail01 ~ fail06— DHCP 问题(05-18 ~ 05-20)
- hilog_6.1_softap_dhcp_ok01 — 最终通过(05-20)
文档结束
更多推荐
所有评论(0)