Linux之USB串口option驱动简介

概述

在Linux内核中,option 驱动(源码位于 drivers/usb/serial/option.c)是最重要、最常用的USB串口驱动之一。它最初是为了支持GSM/CDMA调制解调器(Modem)而开发的,但现在广泛用于支持各种 3G/4G/5G 蜂窝网络模块(如移远、广和通、华为、中兴、SIMCom等)以及部分工业USB转串口设备,它是 Linux 移动宽带生态的基石。


一、 option 驱动的核心作用

option 驱动的主要任务是将USB蜂窝模块的串行通信接口映射为Linux系统中的字符设备(通常是 /dev/ttyUSBx/dev/ttyACMx)。
通过这些串口,用户空间程序(如 pppd, ModemManager, minicom)可以:

  1. 发送 AT 指令控制模块(拨号、查询信号、发短信)。
  2. 进行 PPP 拨号上网(传统方式)。
  3. 抓取模块的底层 Debug 日志(DM/DIAG 口)。
  4. 读取 GPS NMEA 数据。

二、 核心匹配机制 (Device Matching)

option 驱动如何知道该接管哪个USB设备?它依赖以下三种机制:

1. 静态匹配 (VID/PID 白名单)

在内核源码的 option_ids[] 数组中,硬编码了大量已知模块的 Vendor ID (VID) 和 Product ID (PID)。当USB设备插入时,内核会比对VID/PID,如果命中则加载 option 驱动。

2. 动态匹配 (Dynamic ID)

如果你的模块是新产品,内核中没有它的VID/PID,可以通过 sysfs 动态添加,无需重新编译内核

# 假设你的模块 VID 是 2c7c,PID 是 0125 (移远 EC20)
echo "2c7c 0125" > /sys/bus/usb-serial/drivers/option1/new_id

注:重启后失效,需写入 udev 规则实现持久化。

3. 接口类匹配 (Class/SubClass/Protocol)

某些模块不依赖具体的VID/PID,而是通过USB接口描述符中的 Class(通常为 0xFF Vendor Specific)、SubClass 和 Protocol 来匹配。


三、 多端口 (Multi-port) 与 接口过滤

现代4G/5G模块通常是 **USB复合设备 (Composite Device)**,包含多个USB接口(Interface)。一个模块可能同时暴露出 串口、网卡、存储(CD-ROM)等。

1. 端口功能区分

option 驱动接管串口后,通常会生成多个 /dev/ttyUSBx 节点。常见的端口功能如下(具体顺序因模块而异):

  • **DM / DIAG (Diagnostic)**:用于高通 QXDM 等工具抓取底层 Log。
  • GPS / NMEA:输出 GPS 定位数据。
  • **AT (AT Command)**:用于发送 AT 指令,控制模块。
  • Modem / PPP:用于传统的 PPP 数据拨号。
  • ADB:Android 调试桥端口(针对运行 Android 系统的模块)。

2. 黑名单机制 (Blacklist)

这是 option 驱动中最关键的设计之一。
模块中的某些接口(如 QMI, MBIM, ECM, RNDIS 网络接口)绝对不能option 接管,否则会导致无法上网。
option 驱动内部维护了一个 option_blacklist。在 probe 阶段,如果检测到当前接口是网络接口,option 会返回 -ENODEV,从而把该接口让给 qmi_wwancdc_mbimcdc_ether 等网络驱动。


四、 实战操作与调试指南

1. 查看驱动是否加载及设备状态

# 查看 option 驱动是否加载
lsmod | grep option

# 查看内核日志,确认设备识别和端口分配
dmesg | grep -i option
dmesg | grep -i ttyUSB

典型的 dmesg 输出:

usb 1-1: new high-speed USB device number 4 using xhci_hcd
option 1-1:1.0: GSM modem (1-port) converter detected
usb 1-1:1.0: converter now attached to ttyUSB0
option 1-1:1.2: GSM modem (1-port) converter detected
usb 1-1:1.2: converter now attached to ttyUSB2

2. 区分哪个是 AT 口?

如果你面对 /dev/ttyUSB0, 1, 2 不知道哪个是 AT 口,可以使用以下方法:

# 依次向每个端口发送 AT 指令,有 "OK" 返回的就是 AT 口
echo -e "AT\r\n" > /dev/ttyUSB0 && cat /dev/ttyUSB0 &
# 或者使用 microcom / minicom 工具连接测试
microcom -s 115200 /dev/ttyUSB0

3. 查看蜂窝网络模组的各种接口及驱动状态

cat /sys/kernel/debug/usb/devices 

五、 常见“坑”与解决方案

1. 设备识别为 CD-ROM (usb_modeswitch)

现象:插入模块后,lsusb 显示为 Mass Storage(U盘),没有生成 ttyUSB
原因:很多模块默认启动为 “CD-ROM 模式”(里面装有 Windows 驱动),需要先发送特定的 USB 控制传输将其切换为 “Modem 模式”。
解决:安装并使用 usb-modeswitch

sudo usb_modeswitch -W -v 2c7c -p 0125 -M '555343...' # 具体参数查阅模块手册或 modeswitch 数据库

2. 网络接口被 option 错误接管 (无法上网)

现象:模块识别出了很多 ttyUSB,但是 wwan0usb0 网卡没有出现,导致 QMI/MBIM 拨号失败。
原因:内核版本较老,option 驱动的黑名单不全,把网络接口也当成串口接管了。
解决

  1. 升级 Linux 内核(推荐 4.14 以上,最好 5.x)。
  2. 如果是特定接口被占用,可以通过 sysfs 强制解绑(不推荐,治标不治本):
    # 假设 ttyUSB3 是网络口被错误接管
    echo "1-1:1.4" > /sys/bus/usb-serial/drivers/option1/unbind

六、 option 与其他 USB 驱动的区别

在 Linux 中,处理 USB 串口/网络的驱动有很多,需根据场景选择:

驱动名称 适用场景 说明
option 3G/4G/5G 蜂窝模块的串口 (AT/DM/PPP) 最核心的 Modem 串口驱动,支持多端口和复杂接口过滤。
ch341 / cp210x / ftdi_sio 特定的 USB 转串口芯片 针对 CH340, CP2102, FT232 等桥接芯片的专用驱动。
cdc_acm 标准 CDC-ACM 设备 (如 Arduino, 普通 USB 转串口) 遵循 USB-IF 标准协议的设备。如果模块配置为标准 ACM,会被此驱动接管。
qmi_wwan 4G/5G 模块的 QMI 网络接口 配合 option 使用,option 管串口,qmi_wwan 管上网(生成 wwan0)。
cdc_mbim / cdc_ncm 4G/5G 模块的 MBIM/NCM 网络接口 用于较新的 4G/5G 模块的高速网络接口。