这个文章是从网上看到的,主要介绍了usb设备驱动的注册,并如何进行匹配的
即usb插入,如果依据上报的设备描述符找到相应的设备驱动
一.usb设备驱动注册
- static inline int usb_register(struct usb_driver *driver)
- {
- return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
- }
usb_register_driver
- int usb_register_driver(struct usb_driver *new_driver, struct module *owner,const char *mod_name)
- {
- int retval = 0;
- if (usb_disabled())
- return -ENODEV;
- new_driver->drvwrap.for_devices = 0; //usb接口设备
- new_driver->drvwrap.driver.name = (char *) new_driver->name; //设置设备名
- new_driver->drvwrap.driver.bus = &usb_bus_type; //设置总线类型
- new_driver->drvwrap.driver.probe = usb_probe_interface; //设置probe方法
- new_driver->drvwrap.driver.remove = usb_unbind_interface; //设置remove方法
- new_driver->drvwrap.driver.owner = owner; //设置模块所有者
- new_driver->drvwrap.driver.mod_name = mod_name;
- spin_lock_init(&new_driver->dynids.lock);
- INIT_LIST_HEAD(&new_driver->dynids.list);
- retval = driver_register(&new_driver->drvwrap.driver); //注册设备驱动
- if (retval)
- goto out;
- usbfs_update_special();
- retval = usb_create_newid_file(new_driver);
- if (retval)
- goto out_newid;
- retval = usb_create_removeid_file(new_driver);
- if (retval)
- goto out_removeid;
- pr_info("%s: registered new interface driver %s\n",usbcore_name, new_driver->name);
- out:
- return retval;
- out_removeid:
- usb_remove_newid_file(new_driver);
- out_newid:
- driver_unregister(&new_driver->drvwrap.driver);
- printk(KERN_ERR "%s: error %d registering interface driver %s\n",usbcore_name, retval, new_driver->name);
- goto out;
- }
注册设备驱动后会调用总线的match方法
- static int usb_device_match(struct device *dev, struct device_driver *drv)
- {
- if (is_usb_device(dev)) { //usb设备
- if (!is_usb_device_driver(drv))
- return 0;
- return 1;
- } else if (is_usb_interface(dev)) { //usb接口
- struct usb_interface *intf;
- struct usb_driver *usb_drv;
- const struct usb_device_id *id;
- if (is_usb_device_driver(drv))
- return 0;
- intf = to_usb_interface(dev); //获取usb接口结构体
- usb_drv = to_usb_driver(drv); //获取usb_driver
- id = usb_match_id(intf, usb_drv->id_table); //id匹配
- if (id)
- return 1;
- id = usb_match_dynamic_id(intf, usb_drv);
- if (id)
- return 1;
- }
- return 0;
- }
usb_match_id
- const struct usb_device_id *usb_match_id(struct usb_interface *interface,const struct usb_device_id *id)
- {
- if (id == NULL)
- return NULL;
- for (; id->idVendor || id->idProduct || id->bDeviceClass ||id->bInterfaceClass || id->driver_info; id++) {
- if (usb_match_one_id(interface, id))
- return id;
- }
- return NULL;
- }
usb_match_one_id
- int usb_match_one_id(struct usb_interface *interface,const struct usb_device_id *id)
- {
- struct usb_host_interface *intf;
- struct usb_device *dev;
- if (id == NULL)
- return 0;
- intf = interface->cur_altsetting;
- dev = interface_to_usbdev(interface);
- if (!usb_match_device(dev, id))
- return 0;
- 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)))
- return 0;
- 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;
- return 1;
- }
usb_match_device
- 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;
- 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;
- }
匹配成功则调用usb_probe_interface
- static int usb_probe_interface(struct device *dev)
- {
- struct usb_driver *driver = to_usb_driver(dev->driver);
- struct usb_interface *intf = to_usb_interface(dev);
- struct usb_device *udev = interface_to_usbdev(intf);
- const struct usb_device_id *id;
- int error = -ENODEV;
- dev_dbg(dev, "%s\n", __func__);
- intf->needs_binding = 0;
- if (usb_device_is_owned(udev))
- return error;
- if (udev->authorized == 0) {
- dev_err(&intf->dev, "Device is not authorized for usage\n");
- return error;
- }
- id = usb_match_id(intf, driver->id_table);
- if (!id)
- id = usb_match_dynamic_id(intf, driver);
- if (!id)
- return error;
- dev_dbg(dev, "%s - got id\n", __func__);
- error = usb_autoresume_device(udev);
- if (error)
- return error;
- intf->condition = USB_INTERFACE_BINDING;
- pm_runtime_set_active(dev);
- pm_suspend_ignore_children(dev, false);
- if (driver->supports_autosuspend)
- pm_runtime_enable(dev);
- if (intf->needs_altsetting0) {
- error = usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
- if (error < 0)
- goto err;
- intf->needs_altsetting0 = 0;
- }
- error = driver->probe(intf, id);
- if (error)
- goto err;
- intf->condition = USB_INTERFACE_BOUND;
- usb_autosuspend_device(udev);
- return error;
- err:
- intf->needs_remote_wakeup = 0;
- intf->condition = USB_INTERFACE_UNBOUND;
- usb_cancel_queued_reset(intf);
- if (driver->supports_autosuspend)
- pm_runtime_disable(dev);
- pm_runtime_set_suspended(dev);
- usb_autosuspend_device(udev);
- return error;
- }
usb_set_interface
- int usb_set_interface(struct usb_device *dev, int interface, int alternate)
- {
- struct usb_interface *iface;
- struct usb_host_interface *alt;
- struct usb_hcd *hcd = bus_to_hcd(dev->bus);
- int ret;
- int manual = 0;
- unsigned int epaddr;
- unsigned int pipe;
- if (dev->state == USB_STATE_SUSPENDED)
- return -EHOSTUNREACH;
- iface = usb_ifnum_to_if(dev, interface);
- if (!iface) {
- dev_dbg(&dev->dev, "selecting invalid interface %d\n",interface);
- return -EINVAL;
- }
- alt = usb_altnum_to_altsetting(iface, alternate);
- if (!alt) {
- dev_warn(&dev->dev, "selecting invalid altsetting %d\n",alternate);
- return -EINVAL;
- }
- mutex_lock(&hcd->bandwidth_mutex);
- ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
- if (ret < 0) {
- dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",alternate);
- mutex_unlock(&hcd->bandwidth_mutex);
- return ret;
- }
- if (dev->quirks & USB_QUIRK_NO_SET_INTF)
- ret = -EPIPE;
- else
- ret = usb_control_msg(dev, usb_sndctrlpipe(dev,0),USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,alternate, interface, NULL, 0, 5000);
- if (ret == -EPIPE && iface->num_altsetting == 1) {
- dev_dbg(&dev->dev,"manual set_interface for iface %d, alt %d\n",interface, alternate);
- manual = 1;
- } else if (ret < 0) {
- usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
- mutex_unlock(&hcd->bandwidth_mutex);
- return ret;
- }
- mutex_unlock(&hcd->bandwidth_mutex);
- if (iface->cur_altsetting != alt) {
- remove_intf_ep_devs(iface);
- usb_remove_sysfs_intf_files(iface);
- }
- usb_disable_interface(dev, iface, true);
- iface->cur_altsetting = alt;
- if (manual) {
- int i;
- for (i = 0; i < alt->desc.bNumEndpoints; i++) {
- epaddr = alt->endpoint[i].desc.bEndpointAddress;
- pipe = __create_pipe(dev,USB_ENDPOINT_NUMBER_MASK & epaddr) |(usb_endpoint_out(epaddr) ?USB_DIR_OUT : USB_DIR_IN);
- usb_clear_halt(dev, pipe);
- }
- }
- usb_enable_interface(dev, iface, true);
- if (device_is_registered(&iface->dev)) {
- usb_create_sysfs_intf_files(iface);
- create_intf_ep_devs(iface);
- }
- return 0;
- }
二.usb设备注册
- int usb_register_dev(struct usb_interface *intf,struct usb_class_driver *class_driver)
- {
- int retval;
- int minor_base = class_driver->minor_base;
- int minor;
- char name[20];
- char *temp;
- #ifdef CONFIG_USB_DYNAMIC_MINORS
- minor_base = 0;
- #endif
- if (class_driver->fops == NULL)
- return -EINVAL;
- if (intf->minor >= 0)
- return -EADDRINUSE;
- retval = init_usb_class();
- if (retval)
- return retval;
- dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
- down_write(&minor_rwsem);
- for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
- if (usb_minors[minor]) //若数组不为空
- continue;
- usb_minors[minor] = class_driver->fops; //将操作函数集放入全局usb_minors数组中
- intf->minor = minor; //设置接口的次设备号
- break;
- }
- up_write(&minor_rwsem);
- if (intf->minor < 0)
- return -EXFULL;
- snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
- temp = strrchr(name, '/');
- if (temp && (temp[1] != '\0'))
- ++temp;
- else
- temp = name;
- //创建设备
- intf->usb_dev = device_create(usb_class->class, &intf->dev,MKDEV(USB_MAJOR, minor), class_driver,"%s", temp);
- if (IS_ERR(intf->usb_dev)) {
- down_write(&minor_rwsem);
- usb_minors[minor] = NULL;
- intf->minor = -1;
- up_write(&minor_rwsem);
- retval = PTR_ERR(intf->usb_dev);
- }
- return retval;
- }