如何解决自定义usb驱动被hid驱动抢占的问题

文章详细阐述了USB设备如何触发与驱动的匹配过程,特别是涉及到USB设备初始化、hub初始化以及hid设备的匹配规则。同时,解释了如何屏蔽usbhid驱动的方法,包括模块参数和内核黑名单。文章还讨论了自定义驱动如何在系统中卸载和手动触发hid驱动的probe过程。

一、usb如何触发一次设备匹配

(1)usb_init 初始化

subsys_initcall(usb_init);
static int __init usb_init(void) 
{
    ...
    retval = usb_debugfs_init();
    ...
    retval = bus_register(&usb_bus_type); 
    ...
    // 注册了BUS_NOTIFY_ADD_DEVICE和BUS_NOTIFY_DEL_DEVICE的处理
    retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); 
    ...
    retval = usb_major_init();
    ...
    // 注册usbfs驱动
    retval = usb_register(&usbfs_driver)
    ...
    // 主要创建/dev/bus/usb节点
    retval = usb_devio_init();
    ...
    // 详见下面的描述
    retval = usb_hub_init();  
    ...
    retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
    ...
}
struct bus_type usb_bus_type = {
    .name = "usb", 
    .match = usb_device_match, // usb设备和驱动匹配的函数
    .uevent = usb_uevent,
}

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    if (is_usb_device(dev)) {
        if (!is_usb_device_driver(drv))
            return 0;
        return 1;
    } else if (is_usb_interface(dev)) {
        intf = to_usb_interface(dev);
        usb_drv = to_usb_driver(drv);
        
        id = usb_match_id(intf, usb_drv->id_table)
        if (id) 
            return 1;
        
        id = usb_match_dynamic_id(intf, usb_drv);
         if (id) 
            return 1;
    }
    
    return 0;
}


const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
{
    ...
    for (; id->idVendor || id->idProduct || id->bDeviceClass || 
        id->bInterfaceClass || id->driver_info; id++) { 
        if (usb_match_one_id(interface, id)) 
            return id;
}

int usb_match_one_id(struct usb_interface *interface, const struct usb_device_id *id)
{
    ...
    intf = interface->cur_altsetting;
    dev = interface_to_usbdev(interface);
    if (!usb_match_device(dev, id))
        return 0;
    return usb_match_one_id_intf(dev, intf, id);
}


/* returns 0 if no match, 1 if match */
int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
{
	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
	    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
		return 0;

	/* No need to test id->bcdDevice_lo != 0, since 0 is never
	   greater than any unsigned number. */
	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
	    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
	    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
	    (id->bDeviceClass != dev->descriptor.bDeviceClass))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
	    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
		return 0;

	return 1;
}


/* returns 0 if no match, 1 if match */
int usb_match_one_id_intf(struct usb_device *dev,
			  struct usb_host_interface *intf,
			  const struct usb_device_id *id)
{
	/* The interface class, subclass, protocol and number should never be
	 * checked for a match if the device class is Vendor Specific,
	 * unless the match record specifies the Vendor ID. */
	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
				USB_DEVICE_ID_MATCH_INT_PROTOCOL |
				USB_DEVICE_ID_MATCH_INT_NUMBER)))
		return 0;

    // usbhid驱动会匹配成功
	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
	    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
		return 0;

	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
	    (id->bInterfaceNumber != intf->desc.bInterfaceNumber))
		return 0;

	return 1;
}

struct usb_device_driver usb_generic_driver = {
    .name = "usb",
    .probe = generic_probe,
}

static int generic_probe(struct usb_device *udev)
{
    ...
    usb_notify_add_device(udev);
    ...
}
int usb_hub_init(void)                                                          
{
    if (usb_register(&hub_driver) < 0) { 
    ...
    hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0); 
    ...
    
}

static struct usb_driver hub_driver = { 
    .name = "hub",
    .probe = hub_probe, 
    ...
    .id_table = hub_id_table,
    ...
}

static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    ...
    desc = intf->cur_altsetting; 
    ...
    INIT_WORK(&hub->events, hub_event); 
    ...
    if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) 
    ...
}

static void hub_event(struct work_struct *work)
{
    ...
    for (i = 1; i <= hdev->maxchild; i++) { 
        struct usb_port *port_dev = hub->ports[i - 1];
        if (test_bit(i, hub->event_bits) 
            || test_bit(i, hub->change_bits)
            || test_bit(i, hub->wakeup_bits))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值