Linux 内核 dvb-usb-pctv452e 驱动设备卡列表:PCTV HDTV USB 与 TT Connect S2-3600/S2-3650-CI 支持指南
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
本篇技术指南聚焦 Linux 内核 DVB 子系统中的dvb-usb-pctv452e驱动,完整呈现 Documentation/admin-guide/media/dvb-usb-pctv452e-cardlist.rst 所登记的三款 USB 卫星接收设备(PCTV HDTV USB、Technotrend TT Connect S2-3600、S2-3650-CI)及其 USB ID,并结合 pctv452e.c 驱动源码,深入讲解设备识别原理、内核配置方式、驱动内部硬件组成(STB0899 解调器 + STB6100 调谐器)、USB 命令协议、I2C 桥接以及 S2-3650-CI 的 Common Interface(CI)条件接收支持。读完本文,你将能够在内核配置中定位该驱动、用lsusb正确识别这些设备,并理解该驱动在源码层面的工作机理。
一、设备卡列表总览
dvb-usb-pctv452e是 Linux 内核媒体子系统(Media subsystem)中负责 Pinnacle PCTV 系列与 Technotrend TT Connect 系列 USB DVB-S/S2 接收棒的内核驱动,代码位于drivers/media/usb/dvb-usb/目录。内核官方文档以"设备卡列表"(card list)的形式登记了该驱动支持的所有硬件及其 USB Vendor ID/Product ID。
依据 dvb-usb-pctv452e-cardlist.rst,该驱动当前登记的卡片如下:
| Card name(设备名称) | USB IDs |
|---|---|
| PCTV HDTV USB | 2304:021f |
| Technotrend TT Connect S2-3600 | 0b48:3007 |
| Technotrend TT Connect S2-3650-CI | 0b48:300a |
其中:
- PCTV HDTV USB(
2304:021f):由 Pinnacle 设计制造,市场上以 "PCTV HDTV Pro USB" 品牌销售,是第一款受支持的设备; - Technotrend TT Connect S2-3600(
0b48:3007):Technotrend 出品的 DVB-S2 USB 接收器; - Technotrend TT Connect S2-3650-CI(
0b48:300a):在 S2-3600 基础上增加了 Common Interface 卡槽(用于条件接收 CAM 模块)的型号,同时还支持 MAC 地址读取。
驱动源码 pctv452e.c 中的设备枚举与 USB ID 表与之逐一对应:
enum { PINNACLE_PCTV_452E, TECHNOTREND_CONNECT_S2_3600, TECHNOTREND_CONNECT_S2_3650_CI, }; static const struct usb_device_id pctv452e_usb_table[] = { DVB_USB_DEV(PINNACLE, PINNACLE_PCTV_452E), DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2_3600), DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2_3650_CI), { } };模块描述也印证了这一点(pctv452e.c#L1112):
MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");二、USB ID 的定义与设备识别原理
2.1 内核中的 USB ID 常量
三款设备的 VID/PID 并非散落在驱动代码中,而是统一定义在 include/media/dvb-usb-ids.h,供整个 DVB USB 子系统共享:
#define USB_VID_PINNACLE 0x2304 #define USB_VID_TECHNOTREND 0x0b48 #define USB_PID_PINNACLE_PCTV_452E 0x021f #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a对照卡列表文档可见:
- 文档中
2304:021f即USB_VID_PINNACLE : USB_PID_PINNACLE_PCTV_452E(0x2304 = 2304、0x021f = 021f); - 文档中
0b48:3007、0b48:300a即USB_VID_TECHNOTREND : USB_PID_TECHNOTREND_CONNECT_S2_3600与USB_PID_TECHNOTREND_CONNECT_S2_3650_CI。
也就是说,卡列表文档中的三行记录就是上面三组内核常量的可读呈现,两者必须保持一致,否则驱动将无法匹配设备。
2.2 用 lsusb 识别设备
USB 设备通过 USB ID 被内核识别。Linux 下可使用lsusb命令查看当前总线上的 USB 设备及其 VID:PID:
$ lsusb ... Bus 001 Device 074: ID 2040:b131 Hauppauge Bus 001 Device 075: ID 2013:024f PCTV Systems nanoStick T2 290e ...需要说明的是,lsusb输出中的 ID 一律为小写十六进制且不带 0x 前缀。因此上述三款设备的实际lsusb显示形态为:
2304:021f (PCTV HDTV USB) 0b48:3007 (Technotrend TT Connect S2-3600) 0b48:300a (Technotrend TT Connect S2-3650-CI)文档中 PCTV HDTV USB 一行写作2304:021f正是这一形态,而另两行带0x前缀的写法属于文档的十六进制记法差异,与lsusb输出对照时应统一理解为十六进制数值。
2.3 warm-only 设备与匹配流程
从源码看,三款设备都是"仅热态"(warm-only)设备,即设备上电后不需要先经过固件下载(cold/warm 切换)流程,插上即可被驱动接管。pctv452e.c#L1014-L1019 中cold_ids均为NULL:
.devices = { { .name = "PCTV HDTV USB", .cold_ids = { NULL, NULL }, /* this is a warm only device */ .warm_ids = { &pctv452e_usb_table[PINNACLE_PCTV_452E], NULL } },而tt_connect_s2_3600_properties则登记了两个 device desc,分别对应 S2-3600 与 S2-3650-CI(pctv452e.c#L1066-L1077):
.num_device_descs = 2, .devices = { { .name = "Technotrend TT Connect S2-3600", .cold_ids = { NULL, NULL }, /* this is a warm only device */ .warm_ids = { &pctv452e_usb_table[TECHNOTREND_CONNECT_S2_3600], NULL } }, { .name = "Technotrend TT Connect S2-3650-CI", .cold_ids = { NULL, NULL }, .warm_ids = { &pctv452e_usb_table[TECHNOTREND_CONNECT_S2_3650_CI], NULL } }, { NULL }, }probe回调依次尝试用两套dvb_usb_device_properties初始化设备(pctv452e.c#L1088-L1098),USB 核心依据pctv452e_usb_table完成 VID/PID 匹配后进入该回调。
三、驱动在内核配置中的位置与编译
该驱动在内核 Kconfig 中的配置项为DVB_USB_PCTV452E,位于 drivers/media/usb/dvb-usb/Kconfig:
config DVB_USB_PCTV452E tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600" depends on DVB_USB select TTPCI_EEPROM select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT select DVB_LNBP22 if MEDIA_SUBDRV_AUTOSELECT select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT help Support for external USB adapter designed by Pinnacle, shipped under the brand name 'PCTV HDTV Pro USB'. Also supports TT Connect S2-3600/3650 cards. Say Y if you own such a device and want to use it.解读:
depends on DVB_USB:依赖 DVB USB 通用框架,必须先启用CONFIG_DVB_USB;select TTPCI_EEPROM:无条件选中 EEPROM 解码模块,用于从板上 EEPROM 读取/解码 MAC 地址;- 在开启
MEDIA_SUBDRV_AUTOSELECT(媒体子驱动自动选择)的前提下,自动选中DVB_ISL6423(PCTV 型号的 LNB 供电/DiSEqC 芯片)、DVB_LNBP22(S2-3650-CI 的 LNB 供电芯片)、DVB_STB0899(解调器)与DVB_STB6100(调谐器); - 编译产物为
dvb-usb-pctv452e.ko,对应构建规则见 drivers/media/usb/dvb-usb/Makefile:
obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o在内核配置界面中,该选项位于 "Device Drivers → Multimedia support → Media USB Adapters → Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600",可配置为y(内建)、m(模块)或n(禁用)。也可通过内核配置工具(make menuconfig/make xconfig等)或直接编辑.config来启用。
此外,Documentation/admin-guide/media/usb-cardlist.rst 的驱动总表中将该驱动登记为dvb-usb-pctv452e,描述为 "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600",与 Kconfig 的提示文本一致。
四、驱动的硬件组成与前端结构
pctv452e驱动并非简单的 USB 搬运工,它内部串起了完整的 DVB-S/S2 接收链路。从 pctv452e.c 的包含关系与配置结构可以还原出板载硬件:
| 组件 | 芯片 | I2C 地址 | 作用 |
|---|---|---|---|
| 解调器(Demodulator) | STB0899 | 0x68(0xd0>>1) | DVB-S/DVB-S2 信道解调 |
| 调谐器(Tuner) | STB6100 | 0x60(0xc0>>1) | 射频调谐,参考时钟 27 MHz |
| LNB 供电(PCTV 型号) | ISL6423 | 0x08 | LNB 电压/电流控制与 DiSEqC |
| LNB 供电(S2-3650-CI) | LNBP22 | 0x08(0x10>>1) | LNB 供电 |
| EEPROM | 24C16 / 24C64 | 0x50 / 0x51 | 存储 MAC 地址等出厂信息 |
(I2C 地址宏见 pctv452e.c#L49-L53。)
4.1 前端挂载:frontend_attach 与 tuner_attach
在pctv452e_frontend_attach(pctv452e.c#L913-L940)中,驱动先挂载 STB0899 解调器,再按设备型号差异化初始化:
a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config, &a->dev->i2c_adap); if (!a->fe_adap[0].fe) return -ENODEV; id = a->dev->desc->warm_ids[0]; if (id->idVendor == USB_VID_TECHNOTREND && id->idProduct == USB_PID_TECHNOTREND_CONNECT_S2_3650_CI) { if (dvb_attach(lnbp22_attach, ...) == NULL) { err("Cannot attach lnbp22\n"); } /* Error ignored. */ tt3650_ci_init(a); } else if (dvb_attach(isl6423_attach, ...) == NULL) { err("Cannot attach isl6423\n"); }这段代码清晰地区分了卡列表中的三款设备:
- S2-3650-CI(
0b48:300a):挂载 LNBP22 供电芯片,并初始化 CI(条件接收接口); - PCTV HDTV USB与S2-3600:挂载 ISL6423 供电/DiSEqC 芯片,不启用 CI。
调谐器挂载在pctv452e_tuner_attach(pctv452e.c#L942-L953)中完成,STB6100 的参考时钟为 27 MHz(与解调器晶振一致,见stb6100_config.refclock)。
4.2 STB0899 解调器配置
stb0899_config(pctv452e.c#L856-L900)给出了解调器的工作参数:晶振 27 MHz、IQ_SWAP_ON反转配置、TS 输出并行模式,以及一整套 DVB-S2 的捕获门限常量(如MISS_THRESHOLD、UWP_THRESHOLD_*、SOF_SEARCH_TIMEOUT、LDPC_MAX_ITER等)。驱动还通过postproc钩子(pctv45e_postproc)操作 STB0899 的 GPIO01,用以切换前面板 LED 的绿/橙指示(pctv452e.c#L62-L64):
#define PCTV_LED_GPIO STB0899_GPIO01 #define PCTV_LED_GREEN 0x82 #define PCTV_LED_ORANGE 0x024.3 MPEG2 TS 流传输参数
两种型号的 TS 流均以 USB 等时(isochronous)方式传输,但 URB 参数略有差异(pctv452e.c#L993-L1004 与 pctv452e.c#L1046-L1056):
| 属性 | PCTV HDTV USB / S2-3600 | S2-3650-CI |
|---|---|---|
| 传输类型 | USB_ISOC | USB_ISOC |
| URB 数量(count) | 4 | 4 |
| 端点(endpoint) | 0x02 | 0x02 |
| framesperurb | 4 | 64 |
| framesize | 940 | 940 |
| interval | 1 | 1 |
S2-3650-CI 将每个 URB 的帧数提高到 64,以适应 CI 解扰后的 TS 吞吐需求。
五、USB 命令协议与 I2C 桥接
三款设备共用同一套厂商私有 USB 命令协议,理解它有助于排查设备通信问题。
5.1 命令帧格式
驱动在 pctv452e.c#L37-L47 定义了协议关键常量:
#define ISOC_INTERFACE_ALTERNATIVE 3 #define SYNC_BYTE_OUT 0xaa #define SYNC_BYTE_IN 0x55 #define PCTV_CMD_RESET 0x15 /* 复位(推断自 ttusb-budget) */ #define PCTV_CMD_IR 0x1b /* 轮询红外遥控 */ #define PCTV_CMD_I2C 0x31 /* 透传 I2C 事务 */每次 USB 命令都以 4 字节头开始(tt3650_ci_msg与pctv452e_i2c_msg均遵循该格式):
| 偏移 | 内容 | 说明 |
|---|---|---|
| 0 | 0xaa | 输出同步字节(SYNC_BYTE_OUT) |
| 1 | id | 事务计数器,每次递增(state->c++,可回绕) |
| 2 | cmd | 命令码(0x15 复位 / 0x1b IR / 0x31 I2C,以及 0x40~0x45 的 CI 命令) |
| 3 | len | 后续负载长度(部分命令为发送长度) |
设备应答则以 0x55(SYNC_BYTE_IN)开头,并回显事务 id 用于校验:
if (SYNC_BYTE_IN != buf[0] || id != buf[1]) goto failed; /* TT USB 协议错误 */每次命令设备最多返回 64 字节(PCTV_ANSWER_LEN),命令等待超时为 1000 ms(PCTV_TIMEOUT,见 pctv452e.c#L56-L59)。
5.2 复位与上电初始化
pctv452e_power_ctrl(pctv452e.c#L516-L565)在设备上电时做一次性初始化:先通过usb_set_interface将接口 0 切换到备选设置 3(等时传输接口),然后连续发送两次PCTV_CMD_RESET复位命令,完成后置位state->initialized:
b0[0] = 0xaa; b0[1] = state->c++; b0[2] = PCTV_CMD_RESET; b0[3] = 1; b0[4] = 0; /* reset board */ ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0); ... b0[4] = 1; /* reset board (again?) */5.3 I2C 透传桥
由于 STB0899、STB6100、ISL6423/LNBP22 与 EEPROM 全部挂在设备的 I2C 总线上,驱动实现了完整的 I2C 适配器桥接(pctv452e_i2c_algo,pctv452e.c#L908-L911)。pctv452e_i2c_msg将一次 I2C 事务打包为命令 0x31:
buf[0] = SYNC_BYTE_OUT; buf[1] = id; buf[2] = PCTV_CMD_I2C; buf[3] = snd_len + 3; buf[4] = addr << 1; /* 7 位地址左移为 8 位总线地址 */ buf[5] = snd_len; buf[6] = rcv_len;应答中若buf[5] < snd_len || buf[6] < rcv_len,则判定为 I2C 设备未按预期响应(返回-EREMOTEIO)。驱动因此得以复用 Linux 标准 I2C 框架来驱动解调器、调谐器与 LNB 芯片——这也是 usb-cardlist.rst 中提到媒体驱动可能提供card=参数选择设备型号的机制基础:同类 VID/PID 复用场景下,可通过该参数强制指定正确的板卡配置。
5.4 MAC 地址读取(S2-3600/S2-3650-CI)
pctv452e_read_mac_address(pctv452e.c#L618-L653)通过 I2C 从板上 EEPROM(24C16,地址 0x50;若返回-EREMOTEIO则回退尝试 24C64,地址 0x51)读取 20 字节编码 MAC,再交给ttpci_eeprom_decode_mac解码为 6 字节 MAC 地址。读取失败时以零地址兜底(eth_zero_addr(mac))。这一特性在tt_connect_s2_3600_properties中通过.read_mac_address钩子启用(pctv452e.c#L1029),PCTV HDTV USB 属性块中则未设置该钩子。
六、S2-3650-CI 的 Common Interface 支持
卡列表中的第三款设备 S2-3650-CI 是驱动中最复杂的部分——它完整实现了 EN 50221 标准定义的 Common Interface(CI),用于对接条件接收模块(CAM,即智能卡模块)。
6.1 CI 命令集
驱动定义了 7 个 CI 专用命令(pctv452e.c#L73-L81):
enum { TT3650_CMD_CI_TEST = 0x40, /* 查询 CAM 状态 */ TT3650_CMD_CI_RD_CTRL, /* 读 CAM 控制寄存器 */ TT3650_CMD_CI_WR_CTRL, /* 写 CAM 控制寄存器 */ TT3650_CMD_CI_RD_ATTR, /* 读属性内存 */ TT3650_CMD_CI_WR_ATTR, /* 写属性内存 */ TT3650_CMD_CI_RESET, /* 复位 CAM */ TT3650_CMD_CI_SET_VIDEO_PORT /* 开启/关闭 TS 通路 */ };6.2 与 dvb_ca_en50221 框架的对接
驱动通过struct dvb_ca_en50221注册回调集合(pctv452e.c#L379-L413):
state->ca.owner = THIS_MODULE; state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem; state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem; state->ca.read_cam_control = tt3650_ci_read_cam_control; state->ca.write_cam_control = tt3650_ci_write_cam_control; state->ca.slot_reset = tt3650_ci_slot_reset; state->ca.slot_shutdown = tt3650_ci_slot_shutdown; state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable; state->ca.poll_slot_status = tt3650_ci_poll_slot_status; state->ca.data = d; ret = dvb_ca_en50221_init(&a->dvb_adap, &state->ca, /* flags */ 0, /* n_slots */ 1);关键流程:
- 槽位轮询:
tt3650_ci_poll_slot_status发送TT3650_CMD_CI_TEST,应答字节为 1 时返回DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY,向上层通报 CAM 在位且就绪; - 槽位复位:
tt3650_ci_slot_reset依次发送CI_RESET(参数 0)→ 等待 500 ms →CI_RESET(参数 1)→ 等待 500 ms →CI_SET_VIDEO_PORT(参数 0,FTA 状态); - TS 通路控制:
slot_ts_enable/slot_shutdown通过CI_SET_VIDEO_PORT打开/关闭解扰后的 TS 输出; - 并发保护:所有 CI 事务经由
state->ca_mutex串行化(tt3650_ci_msg_locked); - 卸载时
tt3650_ci_uninit(pctv452e.c#L355-L377)先关闭视频端口再释放 CI 资源。
此外,解调器 TS 输出寄存器STB0899_TSOUT在初始化表中被配置为0x69,源码注释标注/* 0x0d for CAM */(pctv452e.c#L802),说明解调器 TS 输出模式与 CI 通路存在联动关系,属于从配置表可以推断的硬件细节。
七、红外遥控与调试
三款设备都支持板载红外接收器,驱动通过rc_query轮询方式读取遥控按键:
- 轮询命令为
PCTV_CMD_IR(0x1b),轮询间隔 100 ms(rc_interval = 100); - 应答中
rx[3] == 9且rx[12] & 0x01表示一次"按下"事件,按键码按 RC5 协议解析为RC_SCANCODE_RC5(rx[7], rx[6])并上报(pctv452e.c#L601-L612); - PCTV HDTV USB 使用
RC_MAP_DIB0700_RC5_TABLE键位表,TT Connect 系列使用RC_MAP_TT_1500键位表(对应 Technotrend 遥控器); - 松开按键时上报
rc_keyup,并清空last_rc_key。
调试方面,驱动暴露了两个模块参数(pctv452e.c#L31-L35):
static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);debug:整型,加载时可用modprobe dvb-usb-pctv452e debug=N传入(debug > 2输出 RC 按键明细,debug > 3输出 IR 原始应答,见 pctv452e.c#L593-L599);adapter_nr:由 DVB 框架宏生成的适配器编号参数,用于指定 DVB 适配器的编号,支持按设备列表传入多个编号。
八、与其他文档的关联
本文所依据的卡列表是内核 USB DVB 设备文档体系的一部分。总览文档 Documentation/admin-guide/media/usb-cardlist.rst 说明了 USB ID 的识别方法(lsusb)、card=参数的用途,并列出全部受支持的 USB 媒体驱动;dvb-usb-pctv452e-cardlist.rst则通过toctree挂载于其下(见 usb-cardlist.rst#L128 的dvb-usb-pctv452e-cardlist条目)。
结语
dvb-usb-pctv452e卡列表文档虽然只有一张三行表格,却是驱动与硬件之间的"契约":PCTV HDTV USB(2304:021f)、TT Connect S2-3600(0b48:3007)与 S2-3650-CI(0b48:300a)三组 USB ID 分别对应源码中的设备枚举、前端挂载分支(ISL6423 vs LNBP22+CI)与属性块配置。在 pctv452e.c 中,这三款设备共用 STB0899/STB6100 前端、0xaa/0x55 同步字节的命令协议与 I2C 桥接层,而 S2-3650-CI 独享完整的 EN 50221 CI 栈。当你手头有上述任一设备时,启用CONFIG_DVB_USB_PCTV452E并借助lsusb核对 USB ID,即可确认驱动是否已接管硬件。
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考