内核模块中获取USB设备树及同Hub端口设备检测问题咨询
检测同一USB Hub指定端口设备组合的实现方案
核心思路
基于Linux内核USB子系统的Hub控制结构体,从目标设备的父Hub入手,遍历Hub的所有端口获取连接设备信息,验证指定的设备-端口组合是否符合条件,以此决定加载特殊驱动还是默认驱动。
具体实现步骤
1. 从设备获取Hub核心结构体
通过当前设备的usb_device->parent拿到Hub的设备指针,再转换为Hub的核心控制结构体struct usb_hub:
#include <linux/usb/hub.h> // 假设当前设备的usb_device指针为usb_dev struct usb_device *hub_dev = usb_dev->parent; if (!hub_dev || !usb_device_is_hub(hub_dev)) { // 当前设备未连接到Hub,直接走默认驱动逻辑 goto load_default_driver; } struct usb_hub *hub = usb_hub_to_struct_hub(hub_dev); if (!hub) { // Hub结构体转换失败,走默认逻辑 goto load_default_driver; }
2. 遍历Hub端口,定位目标设备
Hub的端口数量可通过hub_dev->maxchild获取,端口数组hub->ports下标从0开始,对应物理端口号1~maxchild:
// 示例:检查端口3是否连接了设备B(已知VID/PID) #define DEV_B_VID 0xXXXX #define DEV_B_PID 0xYYYY int target_port = 3; struct usb_port *target_port_node = hub->ports[target_port - 1]; if (!target_port_node) { // 目标端口不存在,走默认逻辑 goto load_default_driver; } struct usb_device *dev_b = target_port_node->child; if (!dev_b) { // 目标端口无设备连接,走默认逻辑 goto load_default_driver; } // 验证设备B的身份 if (dev_b->descriptor.idVendor != DEV_B_VID || dev_b->descriptor.idProduct != DEV_B_PID) { // 端口3连接的不是设备B,走默认逻辑 goto load_default_driver; }
3. 验证当前设备的端口匹配
获取当前设备连接的Hub端口号,确认是否符合预期:
// 示例:当前设备是设备A,预期连接端口1 int expected_port_a = 1; if (usb_dev->portnum != expected_port_a) { goto load_default_driver; } // 所有条件满足,加载特殊驱动 load_special_driver: // 此处编写特殊驱动的初始化逻辑 return 0; load_default_driver: // 此处编写默认驱动的初始化逻辑 return -ENODEV;
枚举阶段的注意事项
- 设备枚举顺序:若两款设备先后枚举,先枚举的设备需暂存自身的Hub和端口信息,等另一款设备枚举时再做组合验证,可通过静态全局变量或内核链表实现暂存。
- 内核版本兼容性:不同Linux内核版本的
struct usb_hub和struct usb_port结构体可能存在字段差异,需根据目标内核版本调整代码。 - 端口状态同步:枚举阶段依赖USB子系统的时序即可,无需额外同步操作,确保Hub端口状态已完成更新。
内容的提问来源于stack exchange,提问作者x915
相关产品推荐
相关产品推荐

