Linux 内核 E3C EC168 DVB-T USB 接收机支持:设备卡表(cardlist)与驱动源码解析
发布时间:2026/9/10 12:16:35 作者:尧图编辑部 阅读量:1,286
与驱动源码解析)
Linux 内核 E3C EC168 DVB-T USB 接收机支持设备卡表cardlist与驱动源码解析【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linuxEC168 是 E3CeMPIA? 不E3C Technology推出的 USB2.0 DVB-T 接收方案Linux 内核通过dvb-usb-v2框架中的 EC168 驱动对其提供支持。本文以内核文档 dvb-usb-ec168-cardlist.rst 中的设备卡表card list为主体结合 ec168.c、ec168.h 等源码完整说明该驱动支持哪些硬件按 USB ID 识别、底层如何工作、如何编译启用并验证设备是否被内核正确驱动。一、文档定位media 子系统的设备卡表体系在内核 Media Controllerdrivers/media文档体系中card list卡片清单用于把每一款被驱动支持的实际硬件与其厂商 VIDVendor ID/ 产品 PIDProduct ID组合逐条登记方便用户查询我手上的这个 USB 棒能不能被内核识别。卡表文档的规范索引见 cardlist.rst其中 USB 类设备统一由 usb-cardlist.rst 汇总跳转EC168 正是该体系下众多 DVB USB 卡表之一。dvb-usb-ec168-cardlist.rst 是面向 EC168 驱动的专属卡表。从源码驱动 ec168.c 的MODULE_DESCRIPTION(E3C EC168 driver)、ec168.h 的文件头注释以及固件名dvb-usb-ec168.fw可以确认驱动、文档与硬件方案一一对应。二、支持硬件清单E3C EC168 reference design卡表文档通过 reStructuredText 的flat-table指令定义了表格共两列Card name设备名与USB IDs支持的 USB 设备 ID 集合。当前版本内核中该卡表登记的设备如下Card name设备名USB IDsUSB 设备标识E3C EC168 reference design18b4:1689、18b4:fffa、18b4:fffb、18b4:1001、18b4:1002其中18b4是厂商 IDVID:后的四位十六进制数是产品 IDPID。也就是说只要 USB 设备枚举后返回的 idVendor 为0x18b4且 idProduct 落在上述五个取值之一内核的 EC168 驱动就会认领该设备。该表登记的是 E3C 官方 EC168 参考设计板卡市面上基于同一参考设计由 E3C 原厂或第三方贴牌出货的设备往往也复用这几组 ID因此这张表同时也是用户判断杂牌 DVB-T 棒是否 EC168 主控的快速清单。三、USB ID 在源码中的定义与匹配卡表文档中的五组 USB ID在源码中以宏形式集中定义在 USB ID 头文件 dvb-usb-ids.h第 44 行#define USB_VID_E3C 0x18b4VID第 211~215 行分别定义了五个 PID 宏USB_PID_E3C_EC168 0x1689USB_PID_E3C_EC168_2 0xfffaUSB_PID_E3C_EC168_3 0xfffbUSB_PID_E3C_EC168_4 0x1001USB_PID_E3C_EC168_5 0x1002这正好与卡表文档完全一一对应从源码结构看文档中列出的就是驱动ec168_id[]匹配表里全部条目印证了文档卡表 驱动实际支持的硬件集合这一约定。匹配表的真实落点在 ec168.c 中上述宏被组装进内核usb_device_id表static const struct usb_device_id ec168_id[] { { DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168, ec168_props, E3C EC168 reference design, NULL)}, { DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2, ec168_props, E3C EC168 reference design, NULL)}, { DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3, ec168_props, E3C EC168 reference design, NULL)}, { DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4, ec168_props, E3C EC168 reference design, NULL)}, { DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5, ec168_props, E3C EC168 reference design, NULL)}, {} }; MODULE_DEVICE_TABLE(usb, ec168_id);注意所有五条匹配记录共享同一个ec168_props设备属性描述和同一设备名字符串E3C EC168 reference design——这正是卡表文档中那唯一一行 Card name 的由来五种 USB ID 在驱动看来是同一款参考设计硬件的不同固件/批次变体不做功能区分。MODULE_DEVICE_TABLE(usb, ...)会把该表导出到模块的 USB id_table供modprobe等工具做基于 VID/PID 的自动装载。接着它注册了标准的usb_driver回调static struct usb_driver ec168_driver { .name KBUILD_MODNAME, .id_table ec168_id, .probe dvb_usbv2_probe, .disconnect dvb_usbv2_disconnect, .suspend dvb_usbv2_suspend, .resume dvb_usbv2_resume, .no_dynamic_id 1, .soft_unbind 1, };即USB 核心探测到匹配的18b4:xxxx设备后会调用dvb_usbv2_probe把设备交给通用的 dvb-usb-v2 框架再由ec168_props中注册的专属回调完成固件下载、前端demod与调谐器tuner的挂载。no_dynamic_id 1表示不允许运行时动态注入新的 VID/PID——意味着只有卡表/匹配表中列出的 ID 会被支持这正是该卡表文档具有权威性的技术前提。四、配套驱动源码EC168 硬件方案是怎么工作的卡片清单只是对号真正干活的是同一目录下的驱动实现。下面把 ec168.c 中反映出的硬件方案拆解开帮助你理解这块接收棒的内外结构。1. 整体架构片上解调 外挂调谐器解调器DemodEC168 主控芯片内部集成了 EC100 DVB-T 解调器。驱动在 ec168.c 中配置static struct ec100_config ec168_ec100_config { .demod_address 0xff, /* not real address, demod is integrated */ };注释明确说明0xff并非真实 I2C 地址——解调器是片内集成的走的是 USB 厂商命令而非外部 I2C。frontend_attach回调通过dvb_attach(ec100_attach, ...)挂载 EC100 前端。调谐器Tuner片外使用MXL5005S调谐器I2C 地址0xc6其详细配置见 ec168.c 的ec168_mxl5003s_config中频 4.57 MHz、晶振 16 MHz、ZIF 零中频、数字模式等。tuner_attach回调通过mxl5005s_attach把它与前端的 I2C 适配器绑定。USB 端点接口描述见ec168_props中.bInterfaceNumber 1与流配置DVB_USB_STREAM_BULK(0x82, 6, 32 * 512)——即接口 0 是 HID接口 1 才是 DVB-TTS 流通过批量端点0x82传输6 个 urb、每个 32×512 字节缓冲区。2. 厂商控制命令协议设备与主机之间的寄存器读写全部通过 USB vendor control transfer 完成。命令集合定义在 ec168.henum ec168_cmd { DOWNLOAD_FIRMWARE 0x00, /* 下载固件 */ CONFIG 0x01, DEMOD_RW 0x03, /* 读写片上解调器寄存器 */ GPIO 0x04, STREAMING_CTRL 0x10, /* 开启/停止 TS 流 */ READ_I2C 0x20, /* 经 USB 桥接读外部 I2C */ WRITE_I2C 0x21, /* 经 USB 桥接写外部 I2C */ HID_DOWNLOAD 0x30, GET_CONFIG, SET_CONFIG, READ_DEMOD, WRITE_DEMOD, };而每次传输的数据信封由struct ec168_reqec168.h承载struct ec168_req { u8 cmd; /* [1] */ u16 value; /* [2|3] */ u16 index; /* [4|5] */ u16 size; /* [6|7] */ u8 *data; };请求在 ec168.c 的ec168_ctrl_msg()中被翻译成一次usb_control_msg()调用并根据命令方向设置USB_DIR_IN/USB_DIR_OUT。实现细节上可以看到一个典型的嵌入式问题规避每次传输前强制msleep(1); /* avoid I2C errors */以等待器件内部状态稳定避免后续 I2C 访问出错。3. 桥接 I2C让 Linux I2C 子系统操作片外器件由于解调器和调谐器处于器件内部/外部总线上而主机只能访问 USB驱动实现了虚拟 I2C 适配器。在ec168_i2c_xfer()ec168.c中可以看到地址分派逻辑目标地址为片上解调器0xff虚拟地址→ 转为READ_DEMOD/WRITE_DEMOD把寄存器号编码进index 0xff00 reg其他 I2C 地址如调谐器0xc6→ 转为READ_I2C/WRITE_I2C厂商命令I2C 地址编码进index 0x0100 addr单条消息长度超过 1 或涉及多段消息时按num 2直接返回-EINVAL拒绝。最终通过ec168_i2c_algo注册为标准的i2c_algorithm使dvb-usb-v2框架与 EC100/MXL5005S 驱动可以透明地走i2c_transfer()访问硬件。4. 固件下载与状态机EC168 与绝大多数 DVB USB 方案一样遵循COLD/WARM 两阶段启动上电后器件处于 COLD 态无固件。ec168_identify_state()ec168.c通过GET_CONFIG命令读回状态字节0x01判为 WARM否则为 COLD。COLD 态下ec168_download_firmware()ec168.c把固件按每包最大 2048 字节分块下发#define LEN_MAX 2048 /* max packet size */随后发送SET_CONFIGset warm?、一次 GPIO 写源码注释坦承 really needed - no idea what does、以及一次激活调谐器 I2C 的WRITE_I2C0x00c6。固件文件名由 ec168.h 定义dvb-usb-ec168.fw并经MODULE_FIRMWARE()声明配合CONFIG_EXTRA_FIRMWARE或发行版固件包提供。这一大段源码即是对卡表文档的最好注解表中那些 USB ID 标识的reference design就是内置 EC100 解调、外挂 MXL5005S、需要下载dvb-usb-ec168.fw固件的一整套 dvb-usb-v2 设备。五、内核配置与模块装载要启用该设备支持在内核配置中打开对应选项即可。Kconfig 条目见 drivers/media/usb/dvb-usb-v2/Kconfigconfig DVB_USB_EC168 tristate E3C EC168 DVB-T USB2.0 support depends on DVB_USB_V2 select DVB_EC100 select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.它依赖DVB_USB_V2dvb-usb-v2 核心框架并且强制select DVB_EC100片上解调器驱动在开启MEDIA_SUBDRV_AUTOSELECT时自动选择 MXL5005S 调谐器驱动。Makefile将其编入模块后可手动装载# 编译内核时配置 CONFIG_DVB_USB_EC168m然后 modprobe dvb-usb-ec168装载成功后若再插入上表任一 VID/PID 的接收棒内核日志会打印设备识别信息modinfo dvb-usb-ec168可以查看模块声明支持的固件文件firmware: dvb-usb-ec168.fw与描述信息。六、实践验证如何确认你的 EC168 设备被驱动由于卡表以 USB ID 为唯一判据验证步骤非常直接以下命令依赖系统已安装 usbutils 等常规工具仅用于查看与确认不修改内核源码# 1. 查看 USB 总线上是否存在匹配的 VID:PID lsusb | grep -i 18b4 # 期望看到形如 Bus xxx Device xxx: ID 18b4:1689 ... 的输出 # 2. 查看驱动是否已认领该接口需以有权限的用户执行 lsusb -t # 查看 USB 设备树中该设备绑定的 driver # 3. 查看内核日志中的枚举与固件下载过程 dmesg | grep -iE ec168|dvb|18b4如果dmesg中出现 downloading firmware 之后报错或反复 COLD/WARM 切换最常见的根因是系统缺少/lib/firmware/dvb-usb-ec168.fw——该文件并非内核源码自带需从发行版固件包如linux-firmware或设备厂商渠道获取并放置到标准固件目录。七、小结围绕 dvb-usb-ec168-cardlist.rst 这张一行表格我们可以串联起完整的硬件支持链路卡表文档登记 E3C EC168 reference design 及其 5 个 USB ID18b4:1689/fffa/fffb/1001/1002这是硬件识别层面的官方清单dvb-usb-ids.h 以宏形式固化上述 IDec168.c 的ec168_id[]把它们映射到同一套设备属性并注册 USB 驱动驱动实现层面EC168 方案 片内 EC100 DVB-T 解调 片外 MXL5005S 调谐器 虚拟 I2C 桥 厂商控制命令下载dvb-usb-ec168.fw固件的 dvb-usb-v2 标准流程。对于开发者而言这张卡表既是改硬件/换固件时如何新增一个 PID 条目的参照入口也是排查USB 棒插上却没反应问题的第一张排查对照表。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考