一、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))