一.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; }
<---usb主控器注册
--->从usb的插入开始