RK3588 kernel-6.1 drivers/usb/serial 代码功能与实现原理

RK3588 kernel-6.1 drivers/usb/serial 代码功能与实现原理

1. 子系统定位

USB Serial 在内核里为 USB 通信设备类(CDC)以外的「USB ↔ 串口/VCP」 设备(以及大量厂商专有 Bulk 协议)提供统一框架:

  • 对上:暴露 /dev/ttyUSBn(主设备号 188,见 USB_SERIAL_TTY_MAJOR
  • 对下:通过 usb_interface → usb_serial_driver → bulk/int URB 与硬件交互

架构文档:Documentation/usb/usb-serial.rst


2. 模块划分(Makefile

目标 组成 作用
usbserialCONFIG_USB_SERIAL usb-serial.ogeneric.obus.o,可选 console.o 核心:TTY、usb_serial 生命周期、generic 读写完、usb-serial 伪总线
*_SERIAL_* ftdi_sio.opl2303.och341.o 芯片专用:probe、open/read_bulk/write_bulkioctl

专用驱动 depends on usbserial,由 MODULE_DEVICE_TABLE(usb, …) 触发 modprobe 加载 usbserial


3. 核心数据结构(概念)

  • struct usb_serial_driver<linux/usb/serial.h>):一种芯片/协议的「模板」,包含 usb_driver(绑定 usb_serial_probe)、id_table端口数calc_num_portsopen/closebulk/int callbackattach/release 等。
  • struct usb_serial:一次 USB 设备 probe 对应的 逻辑适配器,持有 devinterface、端口指针数组、type
  • struct usb_serial_port:单个 TTY 端口,内含 tty_portminor、bulk/int URB 缓冲serial 反向指针

minoridrserial_minors)分配,范围受 USB_SERIAL_TTY_MINORS(512) 限制。


4. 绑定与初始化:usb_serial_probeusb-serial.c

usbcore 匹配到某 usb_serial_driver

  1. search_serial_device 选出 type(持 table_lock)。
  2. create_serial 分配 usb_serialusb_serial_port
  3. 调用 type->probe(serial, id)(可选):子驱动拒绝则退出。
  4. find_endpoints:扫描接口 bulk in/out、interrupt,必要时包含 sibling 接口。
  5. 校验端点数量 ≥ type->num_bulk_* 等要求。
  6. calc_num_ports 或固定 type->num_ports 决定 tty 端口个数
  7. allocate_minorssetup_port_bulk_* / setup_port_interrupt_* 填充 URB
  8. device_add 注册 端口设备,使其落到 usb_serial_bus_type 上。

原理USB 接口驱动只做「发现资源 + 建 usb_serial」;真正注册 ttyUSB 发生在 端口 bus 的 probe(见下)。


5. usb_serial_bus_typebus.c

自定义 struct bus_typeusb-serial

  • match端口已绑定 port->serial->type,与 usb_serial_driver 一一对应。
  • probeusb_serial_device_probe:调用 driver->port_probe(可选),再 tty_port_register_device,打印 ttyUSB%d
  • removetty_unregister_deviceport_remove

原理:把 「端口」做成独立 device,便于 sysfs、电源管理与 TTY 设备节点 生命周期对齐。


6. TTY 路径(usb-serial.c

  • usb_serial_tty_drivertty_drivermajor 188
  • serial_installminor → usb_serial_port_get_by_minortty->driver_data = port,可选 init_termios
  • serial_opentty_port_openserial_port_activatetype->open(tty, port)(通常 usb_serial_generic_open + 提交 读 URB)。
  • serial_port_shutdowntype->closeusb_autopm_put_interface
  • 写路径serial_write → 子驱动或 generic 把数据塞进 bulk out URB
  • 读路径bulk in completetty_insert_flip_stringtty_flip_buffer_push

电源usb_autopm_get/put_interfaceruntime PM 绑定,避免休眠与 URB 竞态。


7. generic.c:默认 Bulk 读写

usb_serial_generic_open:提交 bulk IN URBusb_serial_generic_submit_read_urbs)。
usb_serial_generic_write_bulk_callback / read_bulk_callback:维护 环形缓冲/链表,与 TTY 层对接。
多数简单设备 不重写 read/write,仅靠 generic + 正确端点探测 即可工作。

CONFIG_USB_SERIAL_GENERIC:调试用的 「generic」驱动,仅绑定模块参数 vendor/product不推荐量产设备依赖


8. 专用驱动模式(以常见芯片为例)

ftdi_siopl2303ch341 等通常实现:

  • probe:波特率表、流控、私有 EEPROM/寄存器初始化。
  • open波特率、parity → USB 厂商命令 → 再 generic open
  • *自定义 read_int_callback*:调制解调器状态线 CTS/DCDtty_port_tty_wakeup / tty_schedule_flip

usb-serial-simple.c:宏批量生成 仅 VID/PID + 固定端口数usb_serial_driver,无专有协议。


9. 与其它子系统的关系

边界 说明
drivers/usb/class/cdc-acm.c CDC ACM 走另一套 TTY(/dev/ttyACM),不经过 usb-serial 核心
usbcore 枚举、URB;usb-serial 是普通 usb_driver
drivers/usb/core/file.c USB 字符设备 minor 与 ttyUSB 无关(后者由 tty_driver 注册)

10. 数据流简图

1
2
3
4
5
6
7
8
9
10
用户 read/write / termios


tty_io ──► usb_serial_tty_driver(major 188)


serial_open/write ──► usb_serial_driver::open/write


generic 或 ftdi/pl2303… ──URB──► usbcore ──► HCD

11. 延伸阅读(本仓库)

文档
drivers-usb-core详细分析.md
USB总线枚举匹配与数据传输分析.md

基于 rk3588/kernel-6.1/drivers/usb/serial 源码归纳。

文章互动

阅读 --

留言

0 条留言

正在加载留言…