产品没有网口,需求是:手机直连设备的 WiFi 热点,用 DLNA 把音乐投送到播放器出声。一天多时间从零搭通全栈,板验时四连修——每修好一个,下一个才露头,又是一次"叠罗汉"。这篇记录集成路径和四个坑。

一、全栈构成

1
2
3
4
RTL8188EUS(out-of-tree 内核模块,内核 5.4)
  → hostapd(SoftAP,2.4G)
  → udhcpd / dnsmasq(DHCP + DNS)
  → upmpdcli(UPnP/DLNA renderer → MPD)

手机连上热点后,任何 DLNA 投送 App(手机音乐 App 的投送、或第三方 DLNA 控制端)都能把这条设备当渲染器选歌推送。

out-of-tree WiFi 驱动进 Tina 构建是第一道坎:模块要跟内核同源同配置编译,单独 make 出来的 .ko 一载入就洗出一屏 ARM 架构符号错误——先确认 ARCH=arm、交叉工具链和内核源码树三个参数都对,再谈别的。

二、板验四连修

台架通电后依次炸出四个问题,一个都没想到、一个都躲不掉:

① hostapd 起不来:allowed_bw 配置。 照模板抄的 hostapd 配置里信道带宽声明与驱动能力不匹配,hostapd 直接拒绝启动。日志里一行报错,改配置即过——但它过了才轮到下一个。

② 驱动私有 ioctl 崩溃:wext 0x1C 槽位 NULL 无回落。 hostapd 初始化时探测无线扩展(wext),0x1C 这条命令在驱动的 wext 处理表里是 NULL 槽位,而且没有"不支持的命令就返回 -EOPNOTSUPP"的回落分支——一探就内核崩。主线 cfg80211 驱动都有回落,这种 out-of-tree 老驱动全靠自觉。补上回落分支,探测变成"礼貌拒绝"。

③ upmpdcli 硬编码运行用户。 源码里编译期写死了一个运行用户,精简 rootfs 上根本没有这个账号——进程起不来。这类"桌面发行版假设"(用户存在、路径存在、服务存在)在嵌入式 rootfs 上全是雷,逐个拆。

④ DHCP 抢端口:udhcpd 与 dnsmasq 同抢 67。 udhcpd 的租约文件路径配置和 dnsmasq 的 DHCP 功能撞在一起,两边抢 67 端口,输的那个静默退出——手机连上热点拿不到 IP。服务起不来看端口占用,这条铁律又应验了。DHCP 职责划给一边,另一边关掉对应功能。

四连修完,手机连热点、DLNA 投送、出声——验收完成。

三、方法论沉淀

  1. 集成类问题的排障顺序 = 栈的物理启动顺序:驱动 → AP → DHCP → renderer。下层不通时上层的一切症状都没有意义,别被上层报错带跑。
  2. out-of-tree 驱动 + 老内核 = 缝里全是坑:私有 ioctl、wext 老接口、无回落分支——这些不是"配置问题",是要做好打源码补丁的心理准备。
  3. 精简 rootfs 的雷区清单:硬编码用户、假定路径、假定服务存在。移植任何带桌面基因的软件先 grep 这三样。
  4. 端口冲突要主动查:netstat -tulpn(或 /proc/net/udp)一秒钟的事,两个 daemon 静默互踩能浪费一下午。

尾注

2.4G 热点通了之后,5G 频段的备胎方案(8812CU 芯片)也预研完毕:驱动源码选型时踩了一个"8821cu ≠ 8812cu"的型号陷阱——两家名字只差一位数字,源码树完全不同,选错编译也过、装载也过,就是不干活。模块还没到货,到货先 lsusb 验 VID:PID 再继续。教训先记下:外购芯片选驱动源码,先核对 USB ID,别信名字。