一、usb子系统相关结构体
1. usb总线
struct usb_bus {
struct device *controller;
int busnum; //总线号
const char *bus_name; //总线名
u8 uses_dma;
u8 uses_pio_for_control;
u8 otg_port;
unsigned is_b_host:1;
unsigned b_hnp_enable:1;
unsigned sg_tablesize;
int devnum_next; //下一个地址
struct usb_devmap devmap; //usb设备地址表
struct usb_device *root_hub; //根hub
struct usb_bus *hs_companion;
struct list_head bus_list; //总线链表
int bandwidth_allocated;
int bandwidth_int_reqs;
int bandwidth_isoc_reqs;
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry;
#endif
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
struct mon_bus *mon_bus;
int monitored;
#endif
};
2. usb hub
struct usb_hub {
struct device *intfdev;
struct usb_device *hdev; //usb设备
struct kref kref;
struct urb *urb;
char (*buffer)[8];
union {
struct usb_hub_status hub;
struct usb_port_status port;
}*status;
struct mutex status_mutex;
int error; //出错标志
int nerrors;
struct list_head event_list; //事件链表
unsigned long event_bits[1];
unsigned long change_bits[1];
unsigned long busy_bits[1];
unsigned long removed_bits[1];
#if USB_MAXCHILDREN > 31
#error event_bits[] is too short!
#endif
struct usb_hub_descriptor *descriptor; //hub描述符
struct usb_tt tt;
unsigned mA_per_port; //每个端口电流量
unsigned limited_power:1;
unsigned quiescing:1;
unsigned disconnected:1;
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
struct delayed_work leds;
struct delayed_work init_work;
void **port_owners;
};
3. usb主控器驱动
struct hc_driver {
const char *description; //主控器类型
const char *product_desc; //厂商字串
size_t hcd_priv_size; //私有数据大小
irqreturn_t (*irq) (struct usb_hcd *hcd);
int flags; //版本标志
int (*reset) (struct usb_hcd *hcd); //重置
int (*start) (struct usb_hcd *hcd); //启动
int (*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup);
int (*pci_resume)(struct usb_hcd *hcd, bool hibernated);
void (*stop) (struct usb_hcd *hcd); //停止
void (*shutdown) (struct usb_hcd *hcd); //关闭
int (*get_frame_number) (struct usb_hcd *hcd);
int (*urb_enqueue)(struct usb_hcd *hcd,struct urb *urb, gfp_t mem_flags);
int (*urb_dequeue)(struct usb_hcd *hcd,struct urb *urb, int status);
void (*endpoint_disable)(struct usb_hcd *hcd,struct usb_host_endpoint *ep);
void (*endpoint_reset)(struct usb_hcd *hcd,struct usb_host_endpoint *ep);
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,u16 typeReq, u16 wValue, u16 wIndex,char *buf, u16 wLength);
int (*bus_suspend)(struct usb_hcd *); //总线挂起
int (*bus_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
void (*relinquish_port)(struct usb_hcd *, int);
int (*port_handed_over)(struct usb_hcd *, int);
void (*clear_tt_buffer_complete)(struct usb_hcd *,struct usb_host_endpoint *);
void (*recover_hcd)(struct work_struct *data);
int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
void (*free_dev)(struct usb_hcd *, struct usb_device *);
int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev,struct usb_host_endpoint **eps,
unsigned int num_eps,unsigned int num_streams, gfp_t mem_flags);
int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev,struct usb_host_endpoint **eps,
unsigned int num_eps,gfp_t mem_flags);
int (*add_endpoint)(struct usb_hcd *, struct usb_device *,struct usb_host_endpoint *);
int (*drop_endpoint)(struct usb_hcd *, struct usb_device *,struct usb_host_endpoint *);
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
int (*address_device)(struct usb_hcd *, struct usb_device *udev);
int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,struct usb_tt *tt, gfp_t mem_flags);
int (*reset_device)(struct usb_hcd *, struct usb_device *);
int (*update_device)(struct usb_hcd *, struct usb_device *);
};
4. usb主控器设备
struct usb_hcd {
struct usb_bus self;
struct kref kref;
const char *product_desc; //厂商字串
char irq_descr[24];
struct timer_list rh_timer; //轮询定时器
struct urb *status_urb; //urb状态
#ifdef CONFIG_USB_SUSPEND
struct work_struct wakeup_work;
#endif
struct work_struct ehci_omap_work;
const struct hc_driver *driver;
unsigned long flags;
unsigned rh_registered:1;
unsigned rh_pollable:1;
unsigned uses_new_polling:1;
unsigned wireless:1;
unsigned authorized_default:1;
unsigned has_tt:1;
int irq; //中断号
void __iomem *regs; //设备内存
u64 rsrc_start; //设备内存资源起始地址
u64 rsrc_len; //设备内存资源长度
unsigned power_budget;
struct mutex bandwidth_mutex;
struct dma_pool *pool[HCD_BUFFER_POOLS];
int state;
unsigned long hcd_priv[0] __attribute__ ((aligned(sizeof(unsigned long))));
};
5. usb设备驱动
struct usb_driver {
const char *name; //usb驱动名
int (*probe) (struct usb_interface *intf,const struct usb_device_id *id); //插入
void (*disconnect) (struct usb_interface *intf); //拔出
int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,void *buf); //控制
int (*suspend) (struct usb_interface *intf, pm_message_t message); //挂起
int (*resume) (struct usb_interface *intf); //唤醒
int (*reset_resume)(struct usb_interface *intf); //复位唤醒
int (*pre_reset)(struct usb_interface *intf); //预复位
int (*post_reset)(struct usb_interface *intf);
const struct usb_device_id *id_table; //支持设备id表
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap; //设备驱动的一个封装
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int soft_unbind:1;
};
6. usb设备
struct usb_device {
int devnum; //usb设备地址
char devpath[16]; //usb树中的路径
u32 route;
enum usb_device_state state; //usb设备状态
enum usb_device_speed speed; //usb速度
struct usb_tt *tt;
int ttport;
unsigned int toggle[2];
struct usb_device *parent; //父设备hub
struct usb_bus *bus; //总线
struct usb_host_endpoint ep0; //端点0
struct device dev; //设备文件
struct usb_device_descriptor descriptor; //设备描述符
struct usb_host_config *config;
struct usb_host_config *actconfig;
struct usb_host_endpoint *ep_in[16]; //输入端点
struct usb_host_endpoint *ep_out[16]; //输出端点
char **rawdescriptors;
unsigned short bus_mA; //总线电流限值
u8 portnum; //端口数
u8 level; //所处hub层数
unsigned can_submit:1;
unsigned persist_enabled:1;
unsigned have_langid:1;
unsigned authorized:1;
unsigned authenticated:1;
unsigned wusb:1;
int string_langid;
char *product; //产品id
char *manufacturer; //厂商id
char *serial;
struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev;
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; //usbfs入口
#endif
int maxchild; //最大子设备个数
struct usb_device *children[USB_MAXCHILDREN]; //子设备数组
u32 quirks;
atomic_t urbnum;
unsigned long active_duration;
#ifdef CONFIG_PM
unsigned long last_busy;
int autosuspend_delay;
unsigned long connect_time;
unsigned do_remote_wakeup:1;
unsigned reset_resume:1;
#endif
struct wusb_dev *wusb_dev;
int slot_id;
};
7. usb接口
struct usb_interface {
struct usb_host_interface *altsetting;
struct usb_host_interface *cur_altsetting;
unsigned num_altsetting;
struct usb_interface_assoc_descriptor *intf_assoc;
int minor;
enum usb_interface_condition condition;
unsigned sysfs_files_created:1;
unsigned ep_devs_created:1;
unsigned unregistering:1;
unsigned needs_remote_wakeup:1;
unsigned needs_altsetting0:1;
unsigned needs_binding:1;
unsigned reset_running:1;
unsigned resetting_device:1;
struct device dev;
struct device *usb_dev;
atomic_t pm_usage_cnt;
struct work_struct reset_ws;
};
8. usb请求块urb
struct urb {
struct kref kref; //参考计数
void *hcpriv;
atomic_t use_count;
atomic_t reject;
int unlinked;
struct list_head urb_list; //urb链表头
struct list_head anchor_list;
struct list_head giveback_list;
struct usb_anchor *anchor;
struct usb_device *dev; //usb设备
struct usb_host_endpoint *ep;
unsigned int pipe; //pipe
unsigned int stream_id;
int status;
unsigned int transfer_flags;
void *transfer_buffer; //传输缓冲区
dma_addr_t transfer_dma;
struct scatterlist *sg;
int num_sgs;
u32 transfer_buffer_length; //缓冲区长度
u32 actual_length;
unsigned char *setup_packet; //setup包
dma_addr_t setup_dma;
int start_frame;
int number_of_packets; //包数
int interval;
int error_count;
void *context;
usb_complete_t complete; //回调函数
struct usb_iso_packet_descriptor iso_frame_desc[0];
};
9. usb设备id
struct usb_device_id {
__u16 match_flags; //匹配标志
__u16 idVendor; //厂商id
__u16 idProduct; //产品id
__u16 bcdDevice_lo; //usb版本信息低位
__u16 bcdDevice_hi; //usb版本信息高位
__u8 bDeviceClass; //设备类
__u8 bDeviceSubClass; //子设备类
__u8 bDeviceProtocol; //设备协议
__u8 bInterfaceClass; //接口类
__u8 bInterfaceSubClass; //接口之类
__u8 bInterfaceProtocol; //接口协议
kernel_ulong_t driver_info; //驱动信息
};
1.usb设备描述符
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
} __attribute__ ((packed));
2.usb配置描述符
struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
} __attribute__ ((packed));
3.usb端点描述符
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
4.usb接口描述符
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
二、usb子系统初始化
在/drivers/usb/core/Usb.c中,subsys_initcall(usb_init)声明了usb子系统入口函数usb_init
static int __init usb_init(void)
{
int retval;
if (nousb) {
pr_info("%s: USB support disabled\n", usbcore_name);
return 0;
}
retval = usb_debugfs_init(); //1.usb debugfs初始化
if (retval)
goto out;
retval = bus_register(&usb_bus_type); //2.usb总线注册
if (retval)
goto bus_register_failed;
retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); //3.usb总线通知链注册
if (retval)
goto bus_notifier_failed;
retval = usb_major_init(); //4.注册usb主控器字符设备
if (retval)
goto major_init_failed;
retval = usb_register(&usbfs_driver); //5.注册usbfs驱动
if (retval)
goto driver_register_failed;
retval = usb_devio_init(); //6.usb设备字符设备初始化
if (retval)
goto usb_devio_init_failed;
retval = usbfs_init(); //7.usbfs初始化
if (retval)
goto fs_init_failed;
retval = usb_hub_init(); //8.usb hub初始化
if (retval)
goto hub_init_failed;
retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); //9.usb注册同样设备驱动
if (!retval)
goto out;
usb_hub_cleanup();
hub_init_failed:
usbfs_cleanup();
fs_init_failed:
usb_devio_cleanup();
usb_devio_init_failed:
usb_deregister(&usbfs_driver);
driver_register_failed:
usb_major_cleanup();
major_init_failed:
bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
bus_notifier_failed:
bus_unregister(&usb_bus_type);
bus_register_failed:
usb_debugfs_cleanup();
out:
return retval;
}
1.usb_debugfs_init --usb debugfs初始化
static int usb_debugfs_init(void)
{
usb_debug_root = debugfs_create_dir("usb", NULL); //创建"$(debugfs)/usb"
if (!usb_debug_root)
return -ENOENT;
usb_debug_devices = debugfs_create_file("devices", 0444,usb_debug_root, NULL,&usbfs_devices_fops);
//创建"$(debugfs)/usb/device",捆绑usbfs_devices_fops结构体
if (!usb_debug_devices) { //若创建失败
debugfs_remove(usb_debug_root); //则必须把“$(debugfs)/usb”也删除掉
usb_debug_root = NULL;
return -ENOENT;
}
return 0;
}
要使用debugfs下面的usb功能,需要先挂着debugfs(mount -t debugfs none $(debugfs) ),具体初始化了啥调试接口,看下usbfs_devices_fops操作函数集
2.usb总线的注册
struct bus_type usb_bus_type = {
.name = "usb", //总线名
.match = usb_device_match, //匹配方法
.uevent = usb_uevent, //事件处理
#ifdef CONFIG_USB_SUSPEND
.pm = &usb_bus_pm_ops, //电源管理
#endif
};
这里总线的match方法是usb设备与usb驱动匹配的函数.
3.注册usb总线通知链
int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
{
return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
}
当总线添加删除设备的时候会调用usb_bus_nb指定的notifier_cal方法,既usb_bus_notify
static int usb_bus_notify(struct notifier_block *nb, unsigned long action,void *data)
{
struct device *dev = data;
switch (action) {
case BUS_NOTIFY_ADD_DEVICE: //添加设备
if (dev->type == &usb_device_type) //usb设备
(void) usb_create_sysfs_dev_files(to_usb_device(dev));
else if (dev->type == &usb_if_device_type) //usb接口
(void) usb_create_sysfs_intf_files(to_usb_interface(dev));
break;
case BUS_NOTIFY_DEL_DEVICE: //删除设备
if (dev->type == &usb_device_type) //usb设备
usb_remove_sysfs_dev_files(to_usb_device(dev));
else if (dev->type == &usb_if_device_type) //usb接口
usb_remove_sysfs_intf_files(to_usb_interface(dev));
break;
}
return 0;
}
4.初始化usb主控器字符设备,USB_MAJOR=180
int usb_major_init(void)
{
int error;
error = register_chrdev(USB_MAJOR, "usb", &usb_fops); //注册usb控制器字符设备,捆绑usb_fops
if (error)
printk(KERN_ERR "Unable to get major %d for usb devices\n",USB_MAJOR);
return error;
}
捆绑usb_fops
static const struct file_operations usb_fops = {
.owner = THIS_MODULE,
.open = usb_open,
.llseek = noop_llseek,
};
5.注册usbfs_driver
struct usb_driver usbfs_driver = {
.name = "usbfs",
.probe = driver_probe,
.disconnect = driver_disconnect,
.suspend = driver_suspend,
.resume = driver_resume,
};
6.usb_devio_init USB_DEVICE_DEV=189
int __init usb_devio_init(void)
{
int retval;
retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,"usb_device"); //分配设备号
if (retval) {
printk(KERN_ERR "Unable to register minors for usb_device\n");
goto out;
}
cdev_init(&usb_device_cdev, &usbdev_file_operations); //字符设备初始化
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); //添加字符设备
if (retval) {
printk(KERN_ERR "Unable to get usb_device major %d\n",USB_DEVICE_MAJOR);
goto error_cdev;
}
#ifdef CONFIG_USB_DEVICE_CLASS
usb_classdev_class = class_create(THIS_MODULE, "usb_device"); //创建"/sys/class/usb_device"
if (IS_ERR(usb_classdev_class)) {
printk(KERN_ERR "Unable to register usb_device class\n");
retval = PTR_ERR(usb_classdev_class);
cdev_del(&usb_device_cdev);
usb_classdev_class = NULL;
goto out;
}
usb_classdev_class->dev_kobj = NULL;
#endif
usb_register_notify(&usbdev_nb); //注册设备通知链
out:
return retval;
error_cdev:
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
goto out;
}
usb注册的通知链
void usb_register_notify(struct notifier_block *nb)
{
blocking_notifier_chain_register(&usb_notifier_list, nb);
}
usb通知链表头为usb_notifier_list
在/drivers/usb/core/Notify.c文件中,有四个函数()对usb_notifier_list中发送通知,这四个函数如下:
usb_notify_add_device //有设备添加
usb_notify_remove_device //有设备移除
usb_notify_add_bus //总线添加
usb_notify_remove_bus //总线移除
当这些事件发生后会调用usbdev_nb指定的notifier_cal方法,既usbdev_notify
static int usbdev_notify(struct notifier_block *self,unsigned long action, void *dev)
{
switch (action) {
case USB_DEVICE_ADD: //设备添加
if (usb_classdev_add(dev))
return NOTIFY_BAD;
break;
case USB_DEVICE_REMOVE: //设备删除
usb_classdev_remove(dev);
usbdev_remove(dev);
break;
}
return NOTIFY_OK;
}
7.usbfs初始化
int __init usbfs_init(void)
{
int retval;
retval = register_filesystem(&usb_fs_type); //注册文件系统
if (retval)
return retval;
usb_register_notify(&usbfs_nb); //注册通知链
usbdir = proc_mkdir("bus/usb", NULL); //创建"/proc/bus/usb"
return 0;
}
通知链回调函数
static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
{
switch (action) {
case USB_DEVICE_ADD: //设备添加
usbfs_add_device(dev);
break;
case USB_DEVICE_REMOVE: //设备移除
usbfs_remove_device(dev);
break;
case USB_BUS_ADD: //总线添加
usbfs_add_bus(dev);
break;
case USB_BUS_REMOVE: //总线移除
usbfs_remove_bus(dev);
}
usbfs_update_special();
usbfs_conn_disc_event();
return NOTIFY_OK;
}
8.usb hub初始化
int usb_hub_init(void)
{
if (usb_register(&hub_driver) < 0) { //注册usb hub设备驱动
printk(KERN_ERR "%s: can't register hub driver\n",usbcore_name);
return -1;
}
khubd_task = kthread_run(hub_thread, NULL, "khubd"); //创建守护进程
if (!IS_ERR(khubd_task))
return 0;
usb_deregister(&hub_driver);
printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);
return -1;
}
hub也是usb设备,所以需要注册器设备驱动,创建hub_thread守护进程
捆绑的hub usb设备驱动
static struct usb_driver hub_driver = {
.name = "hub",
.probe = hub_probe, //hub连接上
.disconnect = hub_disconnect, //hub断开
.suspend = hub_suspend, //hub挂起
.resume = hub_resume, //hub唤醒
.reset_resume = hub_reset_resume, //hub复位唤醒
.pre_reset = hub_pre_reset,
.post_reset = hub_post_reset,
.unlocked_ioctl = hub_ioctl,
.id_table = hub_id_table, //hub设备驱动 id表
.supports_autosuspend = 1,
};
hub_thread守护进程
static int hub_thread(void *__unused)
{
set_freezable(); //设置可冻结
do {
hub_events(); //hub事件处理函数
wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop()); //进入睡眠
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
pr_debug("%s: khubd exiting\n", usbcore_name);
return 0;
}
这里while循环是在hub_event_list不为空时候循环执行
当hub_events执行完,会执行wait_event_freezable进入睡眠,其他函数调用wake_up(&khubd_wait)唤醒队列
hub_events函数
static void hub_events(void)
{
struct list_head *tmp;
struct usb_device *hdev;
struct usb_interface *intf;
struct usb_hub *hub;
struct device *hub_dev;
u16 hubstatus;
u16 hubchange;
u16 portstatus;
u16 portchange;
int i, ret;
int connect_change;
while (1) {
spin_lock_irq(&hub_event_lock);
//第一次执行假设usb主控器还没注册
if (list_empty(&hub_event_list)) { //usb事件链表为空
spin_unlock_irq(&hub_event_lock);
break; //跳出循环
}
tmp = hub_event_list.next;
list_del_init(tmp);
hub = list_entry(tmp, struct usb_hub, event_list);
kref_get(&hub->kref);
spin_unlock_irq(&hub_event_lock);
hdev = hub->hdev;
hub_dev = hub->intfdev;
intf = to_usb_interface(hub_dev);
usb_lock_device(hdev);
if (unlikely(hub->disconnected))
goto loop_disconnected;
if (hdev->state == USB_STATE_NOTATTACHED) {
hub->error = -ENODEV;
hub_quiesce(hub, HUB_DISCONNECT);
goto loop;
}
ret = usb_autopm_get_interface(intf);
if (ret) {
dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
goto loop;
}
if (hub->quiescing)
goto loop_autopm;
if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n",hub->error);
ret = usb_reset_device(hdev);
if (ret) {
dev_dbg (hub_dev,"error resetting hub: %d\n", ret);
goto loop_autopm;
}
hub->nerrors = 0;
hub->error = 0;
}
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
if (test_bit(i, hub->busy_bits))
continue;
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&!connect_change)
continue;
ret = hub_port_status(hub, i,&portstatus, &portchange);
if (ret < 0)
continue;
if (portchange & USB_PORT_STAT_C_CONNECTION) {
clear_port_feature(hdev, i,USB_PORT_FEAT_C_CONNECTION);
connect_change = 1;
}
if (portchange & USB_PORT_STAT_C_ENABLE) {
if (!connect_change)
dev_dbg (hub_dev,"port %d enable change,status %08x\n",i, portstatus);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_ENABLE);
if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change&& hdev->children[i-1]) {
dev_err (hub_dev,"port %i disabled by hub (EMI?),re-enabling...\n",i);
connect_change = 1;
}
}
if (portchange & USB_PORT_STAT_C_SUSPEND) {
struct usb_device *udev;
clear_port_feature(hdev, i,USB_PORT_FEAT_C_SUSPEND);
udev = hdev->children[i-1];
if (udev) {
msleep(10);
usb_lock_device(udev);
ret = usb_remote_wakeup(hdev->children[i-1]);
usb_unlock_device(udev);
if (ret < 0)
connect_change = 1;
} else {
ret = -ENODEV;
hub_port_disable(hub, i, 1);
}
dev_dbg (hub_dev,"resume on port %d, status %d\n",i, ret);
}
if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
dev_err (hub_dev,"over-current change on port %d\n",i);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_OVER_CURRENT);
hub_power_on(hub, true);
}
if (portchange & USB_PORT_STAT_C_RESET) {
dev_dbg (hub_dev,"reset change on port %d\n",i);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_RESET);
}
if (connect_change)
hub_port_connect_change(hub, i,portstatus, portchange);
}
if (test_and_clear_bit(0, hub->event_bits) == 0)
;
else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
dev_err (hub_dev, "get_hub_status failed\n");
else {
if (hubchange & HUB_CHANGE_LOCAL_POWER) {
dev_dbg (hub_dev, "power change\n");
clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
if (hubstatus & HUB_STATUS_LOCAL_POWER)
hub->limited_power = 1;
else
hub->limited_power = 0;
}
if (hubchange & HUB_CHANGE_OVERCURRENT) {
dev_dbg (hub_dev, "overcurrent change\n");
msleep(500);
clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
hub_power_on(hub, true);
}
}
loop_autopm:
usb_autopm_put_interface_no_suspend(intf);
loop:
usb_autopm_put_interface(intf);
loop_disconnected:
usb_unlock_device(hdev);
kref_put(&hub->kref, hub_release);
}
}
9.usb注册通用设备驱动
int usb_register_device_driver(struct usb_device_driver *new_udriver,struct module *owner)
{
int retval = 0;
if (usb_disabled())
return -ENODEV;
new_udriver->drvwrap.for_devices = 1; //usb设备
new_udriver->drvwrap.driver.name = (char *) new_udriver->name; //设备名
new_udriver->drvwrap.driver.bus = &usb_bus_type; //总线类型
new_udriver->drvwrap.driver.probe = usb_probe_device; //probe方法
new_udriver->drvwrap.driver.remove = usb_unbind_device; //remove方法
new_udriver->drvwrap.driver.owner = owner; //模块所有者
retval = driver_register(&new_udriver->drvwrap.driver); //注册设备驱动
if (!retval) {
pr_info("%s: registered new device driver %s\n",usbcore_name, new_udriver->name);
usbfs_update_special();
} else {
printk(KERN_ERR "%s: error %d registering device driver %s\n",usbcore_name, retval, new_udriver->name);
}
return retval;
}
usb_device_driver结构体是usb_driver的简化版本,这里注册的是usb设备(非接口)驱动
usb总线的match方法对usb设备和usb接口做了区分处理,针对usb设备,直接match的,(分析match时候再细化)
然后调用usb设备驱动的probe方法
static int usb_probe_device(struct device *dev)
{
struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
struct usb_device *udev = to_usb_device(dev);
int error = 0;
dev_dbg(dev, "%s\n", __func__);
if (!udriver->supports_autosuspend) //条件成立
error = usb_autoresume_device(udev);
if (!error)
error = udriver->probe(udev); //调用usb_device_driver的probe方法
return error;
}
接着调用usb_generic_driver的probe方法
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
#ifdef CONFIG_PM
.suspend = generic_suspend,
.resume = generic_resume,
#endif
.supports_autosuspend = 1,
};
所以generic_probe函数会接着被调用
static int generic_probe(struct usb_device *udev)
{
int err, c;
if (usb_device_is_owned(udev))
;
else if (udev->authorized == 0) //明显不执行
dev_err(&udev->dev, "Device is not authorized for usage\n");
else { //
c = usb_choose_configuration(udev); //选择一个配置
if (c >= 0) {
err = usb_set_configuration(udev, c); //设置一个配置
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",c, err);
}
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev); //发送设备添加通知
return 0;
}
<---usb子系统相关结构体
--->usb主控器注册
三、usb主控器注册
第一步usb主控器设备的分配
usb_create_hcd
struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,struct device *dev, const char *bus_name)
{
struct usb_hcd *hcd;
hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); //分配usb_hcd和私有数据内存
if (!hcd) {
dev_dbg (dev, "hcd alloc failed\n");
return NULL;
}
dev_set_drvdata(dev, hcd); //dev->p->driver_data=hcd
kref_init(&hcd->kref); //参考计数+1
usb_bus_init(&hcd->self); //初始化usb总线
hcd->self.controller = dev; //设置总线控制器设备
hcd->self.bus_name = bus_name; //设置总线名
hcd->self.uses_dma = (dev->dma_mask != NULL); //设置DMA标志
init_timer(&hcd->rh_timer); //初始化定时器
hcd->rh_timer.function = rh_timer_func; //定时器回调函数
hcd->rh_timer.data = (unsigned long) hcd; //回调函数参数
#ifdef CONFIG_USB_SUSPEND
INIT_WORK(&hcd->wakeup_work, hcd_resume_work); //唤醒执行hcd_resume_work函数
#endif
mutex_init(&hcd->bandwidth_mutex);
hcd->driver = driver; //设置主控器驱动
hcd->product_desc = (driver->product_desc) ? driver->product_desc :"USB Host Controller"; //设置厂商字串
if (hcd->driver->recover_hcd) //若主控器驱动存在recover_hcd方法
INIT_WORK(&hcd->ehci_omap_work, hcd->driver->recover_hcd); //则调用其方法
return hcd;
}
这里定时器的回调函数
static void rh_timer_func (unsigned long _hcd)
{
usb_hcd_poll_rh_status((struct usb_hcd *) _hcd); //调用hcd轮询检测状态的函数
}
第二步usb主控器设备添加
usb_add_hcd
int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)
{
int retval;
struct usb_device *rhdev; //usb设备(root hub)
dev_info(hcd->self.controller, "%s\n", hcd->product_desc); //设置usb主控器设备设备文件名称
hcd->authorized_default = hcd->wireless? 0 : 1; //检测无线受权信息
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); //置位usb主控器标志 (全功耗)
if ((retval = hcd_buffer_create(hcd)) != 0) { //分配usb主控器设备DMA缓冲池
dev_dbg(hcd->self.controller, "pool alloc failed\n");
return retval;
}
if ((retval = usb_register_bus(&hcd->self)) < 0) //usb注册总线
goto err_register_bus;
if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { //分配usb设备(根hub)
dev_err(hcd->self.controller, "unable to allocate root hub\n");
retval = -ENOMEM;
goto err_allocate_root_hub;
}
hcd->self.root_hub = rhdev;
switch (hcd->driver->flags & HCD_MASK) { //设置usb设备速度类型
case HCD_USB11:
rhdev->speed = USB_SPEED_FULL; //全速
break;
case HCD_USB2:
rhdev->speed = USB_SPEED_HIGH; //高速
break;
case HCD_USB3:
rhdev->speed = USB_SPEED_SUPER; //超速
break;
default:
goto err_set_rh_speed;
}
device_init_wakeup(&rhdev->dev, 1);
if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { //若usb主控器驱动存在重置方法则调用
dev_err(hcd->self.controller, "can't setup\n");
goto err_hcd_driver_setup;
}
hcd->rh_pollable = 1;//设置为可轮循
if (device_can_wakeup(hcd->self.controller)&& device_can_wakeup(&hcd->self.root_hub->dev)) //检测唤醒功能
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
if (hcd->driver->irq) { //可中断
if (irqflags & IRQF_SHARED) //不能支持共享中断
irqflags &= ~IRQF_DISABLED;
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",hcd->driver->description, hcd->self.busnum);
if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,hcd->irq_descr, hcd)) != 0) { //申请中断
dev_err(hcd->self.controller,"request interrupt %d failed\n", irqnum);
goto err_request_irq;
}
hcd->irq = irqnum; //设置中断号
dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,(hcd->driver->flags & HCD_MEMORY) ?
"io mem" : "io base",(unsigned long long)hcd->rsrc_start);
} else { //不可中断
hcd->irq = -1;
if (hcd->rsrc_start) //存在内存资源起始地址
dev_info(hcd->self.controller, "%s 0x%08llx\n",(hcd->driver->flags & HCD_MEMORY) ?
"io mem" : "io base",(unsigned long long)hcd->rsrc_start);
}
if ((retval = hcd->driver->start(hcd)) < 0) { //调用主机驱动的start方法
dev_err(hcd->self.controller, "startup error %d\n", retval);
goto err_hcd_driver_start;
}
rhdev->bus_mA = min(500u, hcd->power_budget); //设置总线电流限值
if ((retval = register_root_hub(hcd)) != 0) //注册根hub
goto err_register_root_hub;
retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); //创建root hub属性文件
if (retval < 0) {
printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",retval);
goto error_create_attr_group;
}
if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) //若使用新的轮询方式且flags为HCD_FLAG_POLL_RH
usb_hcd_poll_rh_status(hcd); //则轮询监控root hub状态
return retval;
error_create_attr_group:
if (HC_IS_RUNNING(hcd->state))
hcd->state = HC_STATE_QUIESCING;
spin_lock_irq(&hcd_root_hub_lock);
hcd->rh_registered = 0;
spin_unlock_irq(&hcd_root_hub_lock);
#ifdef CONFIG_USB_SUSPEND
cancel_work_sync(&hcd->wakeup_work);
#endif
mutex_lock(&usb_bus_list_lock);
usb_disconnect(&rhdev);
mutex_unlock(&usb_bus_list_lock);
err_register_root_hub:
hcd->rh_pollable = 0;
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
del_timer_sync(&hcd->rh_timer);
hcd->driver->stop(hcd);
hcd->state = HC_STATE_HALT;
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
del_timer_sync(&hcd->rh_timer);
err_hcd_driver_start:
if (hcd->irq >= 0)
free_irq(irqnum, hcd);
err_request_irq:
err_hcd_driver_setup:
err_set_rh_speed:
usb_put_dev(hcd->self.root_hub);
err_allocate_root_hub:
usb_deregister_bus(&hcd->self);
err_register_bus:
hcd_buffer_destroy(hcd);
return retval;
}
root hub中断例程
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
{
struct usb_hcd *hcd = __hcd;
unsigned long flags;
irqreturn_t rc;
local_irq_save(flags);
if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
rc = IRQ_NONE;
} else if (hcd->driver->irq(hcd) == IRQ_NONE) { //调用主控器驱动的中断处理例程
rc = IRQ_NONE;
} else {
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); //设置usb主控器标志HCD_FLAG_SAW_IRQ
if (unlikely(hcd->state == HC_STATE_HALT)) //root hub处于停止状态
usb_hc_died(hcd);
rc = IRQ_HANDLED;
}
local_irq_restore(flags);
return rc;
}
注册根hub register_root_hub
static int register_root_hub(struct usb_hcd *hcd)
{
struct device *parent_dev = hcd->self.controller;
struct usb_device *usb_dev = hcd->self.root_hub;
const int devnum = 1;
int retval;
usb_dev->devnum = devnum; //地址
usb_dev->bus->devnum_next = devnum + 1;
memset (&usb_dev->bus->devmap.devicemap, 0,sizeof usb_dev->bus->devmap.devicemap); //初始化总线usb设备号表
set_bit (devnum, usb_dev->bus->devmap.devicemap); //设置usb设备地址表第1位
usb_set_device_state(usb_dev, USB_STATE_ADDRESS); //设置设备为寻址态
mutex_lock(&usb_bus_list_lock);
usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); //获取设备描述符
if (retval != sizeof usb_dev->descriptor) {
mutex_unlock(&usb_bus_list_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",dev_name(&usb_dev->dev), retval);
return (retval < 0) ? retval : -EMSGSIZE;
}
retval = usb_new_device (usb_dev); //添加新的usb设备(root hub)-->枚举
if (retval) {
dev_err (parent_dev, "can't register root hub for %s, %d\n",dev_name(&usb_dev->dev), retval);
}
mutex_unlock(&usb_bus_list_lock);
if (retval == 0) {
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 1; //设置hub已注册标志
spin_unlock_irq (&hcd_root_hub_lock);
if (hcd->state == HC_STATE_HALT) //若root hub处于停止状态
usb_hc_died (hcd);
}
return retval;
}
调用usb_new_device添加新设备
int usb_new_device(struct usb_device *udev)
{
int err;
if (udev->parent) {
device_init_wakeup(&udev->dev, 0);
}
pm_runtime_set_active(&udev->dev);
pm_runtime_enable(&udev->dev);
err = usb_enumerate_device(udev); //读取usb设备描述符
if (err < 0)
goto fail;
dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",udev->devnum, udev->bus->busnum,(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,(((udev->bus->busnum-1) * 128) + (udev->devnum-1))); //分配设备号
announce_device(udev); //打印设备miOAHUDU
device_enable_async_suspend(&udev->dev);
err = device_add(&udev->dev); //设备添加
if (err) {
dev_err(&udev->dev, "can't device_add, error %d\n", err);
goto fail;
}
(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); //创建端点设备
return err;
fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
pm_runtime_disable(&udev->dev);
pm_runtime_set_suspended(&udev->dev);
return err;
}
有些主控器支持uses_new_polling方法则会调用usb_hcd_poll_rh_status函数
void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
{
struct urb *urb;
int length;
unsigned long flags;
char buffer[6];
if (unlikely(!hcd->rh_pollable)) //若不支持轮询
return;
if (!hcd->uses_new_polling && !hcd->status_urb) //若没有urb要处理
return;
length = hcd->driver->hub_status_data(hcd, buffer); //调用usb主控器驱动的hub_status_data方法
if (length > 0) {
spin_lock_irqsave(&hcd_root_hub_lock, flags);
urb = hcd->status_urb; //获取待处理的urb
if (urb) {
clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); //清除标志位
hcd->status_urb = NULL; //清除待处理urb
urb->actual_length = length; //指定处理的urb长度
memcpy(urb->transfer_buffer, buffer, length);
usb_hcd_unlink_urb_from_ep(hcd, urb);//urb与设备端点解绑
spin_unlock(&hcd_root_hub_lock);
usb_hcd_giveback_urb(hcd, urb, 0); //处理urb,并返回给usb设备
spin_lock(&hcd_root_hub_lock);
} else {
length = 0;
set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
}
spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
}
if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :(length == 0 && hcd->status_urb != NULL))
mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); //修改定时值,激活定时器
}
usb_hcd_giveback_urb //处理urb
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
{
urb->hcpriv = NULL;
if (unlikely(urb->unlinked))
status = urb->unlinked;
else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
urb->actual_length < urb->transfer_buffer_length &&!status))
status = -EREMOTEIO;
unmap_urb_for_dma(hcd, urb);
usbmon_urb_complete(&hcd->self, urb, status);
usb_unanchor_urb(urb);
urb->status = status;
urb->complete (urb); //urb 回调函数
atomic_dec (&urb->use_count);
if (unlikely(atomic_read(&urb->reject)))
wake_up (&usb_kill_urb_queue);
usb_put_urb (urb);
}
<--- 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;
}
五、从usb的插入开始
当usb设备插入接口,电压变化会通知到usb主控器,
触发主控器中断,如果主控器不支持中断,那么会使用rh_timer方法,轮询接口
其结果都是调用usb_hcd_poll_rh_status
void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
{
struct urb *urb;
int length;
unsigned long flags;
char buffer[6]; /* Any root hubs with > 31 ports? */
if (unlikely(!hcd->rh_pollable))
return;
if (!hcd->uses_new_polling && !hcd->status_urb)
return;
length = hcd->driver->hub_status_data(hcd, buffer); //获取urb数据长度
if (length > 0) {
/* try to complete the status urb */
spin_lock_irqsave(&hcd_root_hub_lock, flags);
urb = hcd->status_urb; //获取要处理的urb
if (urb) {
clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); //清除urb主控器poll标志
hcd->status_urb = NULL; //清空待处理urb
urb->actual_length = length; //获取urb数据长度
memcpy(urb->transfer_buffer, buffer, length); //复制urb缓冲区
usb_hcd_unlink_urb_from_ep(hcd, urb); //从主控器的端点上解绑urb
spin_unlock(&hcd_root_hub_lock);
usb_hcd_giveback_urb(hcd, urb, 0); //处理urb并回传urb给设备
spin_lock(&hcd_root_hub_lock);
} else {
length = 0;
set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags);
}
spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
}
if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
(length == 0 && hcd->status_urb != NULL))
mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
}
usb_hcd_giveback_urb函数
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
{
urb->hcpriv = NULL;
if (unlikely(urb->unlinked))
status = urb->unlinked;
else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
urb->actual_length < urb->transfer_buffer_length &&
!status))
status = -EREMOTEIO;
unmap_urb_for_dma(hcd, urb);
usbmon_urb_complete(&hcd->self, urb, status);
usb_unanchor_urb(urb);
/* pass ownership to the completion handler */
urb->status = status;
urb->complete (urb); //执行urb回调函数,就是hub_irq
atomic_dec (&urb->use_count);
if (unlikely(atomic_read(&urb->reject)))
wake_up (&usb_kill_urb_queue);
usb_put_urb (urb);
}
hub_irq函数
static void hub_irq(struct urb *urb)
{
struct usb_hub *hub = urb->context;
int status = urb->status;
unsigned i;
unsigned long bits;
switch (status) {
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
return;
default: //错误
dev_dbg (hub->intfdev, "transfer --> %d\n", status);
if ((++hub->nerrors < 10) || hub->error)
goto resubmit;
hub->error = status;
case 0: //端口状态有变化
bits = 0;
for (i = 0; i < urb->actual_length; ++i)
bits |= ((unsigned long) ((*hub->buffer)[i]))<< (i*8);
hub->event_bits[0] = bits; //填充hub->event_bit数组
break;
}
hub->nerrors = 0;
kick_khubd(hub); //调用kick_khubd函数
resubmit:
if (hub->quiescing)
return;
if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0&& status != -ENODEV && status != -EPERM)
dev_err (hub->intfdev, "resubmit --> %d\n", status);
}
kick_khubd函数
static void kick_khubd(struct usb_hub *hub)
{
unsigned long flags;
spin_lock_irqsave(&hub_event_lock, flags);
if (!hub->disconnected && list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
usb_autopm_get_interface_no_resume(to_usb_interface(hub->intfdev));
wake_up(&khubd_wait); //唤醒khubd_wait相关的等待队列
}
spin_unlock_irqrestore(&hub_event_lock, flags);
}
这里会触发hub_events函数,原因如下
do {
hub_events();
wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||kthread_should_stop());
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
hub_events函数
static void hub_events(void)
{
struct list_head *tmp;
struct usb_device *hdev;
struct usb_interface *intf;
struct usb_hub *hub;
struct device *hub_dev;
u16 hubstatus;
u16 hubchange;
u16 portstatus;
u16 portchange;
int i, ret;
int connect_change;
//hcd usb主控器的状态由usb主控器的中断例程根据具体硬件状态去设置
while (1) {
spin_lock_irq(&hub_event_lock);
//这次执行假设usb主控器已经注册
if (list_empty(&hub_event_list)) { //usb事件链表不为为空
spin_unlock_irq(&hub_event_lock);
break;
}
tmp = hub_event_list.next; //拿出hub_event链表项
list_del_init(tmp); //从hub_event_list删除其
hub = list_entry(tmp, struct usb_hub, event_list); //根据链表项获取usb_hub
kref_get(&hub->kref); //引用计数
spin_unlock_irq(&hub_event_lock);
hdev = hub->hdev; //获取hub usb设备
hub_dev = hub->intfdev; //获取hub 设备文件
intf = to_usb_interface(hub_dev); //获取hub usb接口
usb_lock_device(hdev);
if (unlikely(hub->disconnected))
goto loop_disconnected;
if (hdev->state == USB_STATE_NOTATTACHED) { //判断是否为USB_STATE_NOTATTACHED状态
hub->error = -ENODEV;
hub_quiesce(hub, HUB_DISCONNECT);
goto loop;
}
ret = usb_autopm_get_interface(intf);
if (ret) {
dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
goto loop;
}
if (hub->quiescing)
goto loop_autopm;
if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n",hub->error);
ret = usb_reset_device(hdev);
if (ret) {
dev_dbg (hub_dev,"error resetting hub: %d\n", ret);
goto loop_autopm;
}
hub->nerrors = 0;
hub->error = 0;
}
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
if (test_bit(i, hub->busy_bits))
continue;
connect_change = test_bit(i, hub->change_bits); //判断是否hub口状态变化
if (!test_and_clear_bit(i, hub->event_bits) &&!connect_change)
continue;
ret = hub_port_status(hub, i,&portstatus, &portchange);
if (ret < 0)
continue;
if (portchange & USB_PORT_STAT_C_CONNECTION) { //hub口连接上设备
clear_port_feature(hdev, i,USB_PORT_FEAT_C_CONNECTION);
connect_change = 1;
}
if (portchange & USB_PORT_STAT_C_ENABLE) { //hub口的设备使能
if (!connect_change)
dev_dbg (hub_dev,"port %d enable change,status %08x\n",i, portstatus);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_ENABLE);
if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change&& hdev->children[i-1]) {
dev_err (hub_dev,"port %i disabled by hub (EMI?),re-enabling...\n",i);
connect_change = 1;
}
}
if (portchange & USB_PORT_STAT_C_SUSPEND) { //hub口的设备挂起
struct usb_device *udev;
clear_port_feature(hdev, i,USB_PORT_FEAT_C_SUSPEND);
udev = hdev->children[i-1];
if (udev) {
msleep(10);
usb_lock_device(udev);
ret = usb_remote_wakeup(hdev->children[i-1]);
usb_unlock_device(udev);
if (ret < 0)
connect_change = 1;
} else {
ret = -ENODEV;
hub_port_disable(hub, i, 1);
}
dev_dbg (hub_dev,"resume on port %d, status %d\n",i, ret);
}
if (portchange & USB_PORT_STAT_C_OVERCURRENT) { //hub口设备过流
dev_err (hub_dev,"over-current change on port %d\n",i);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_OVER_CURRENT);
hub_power_on(hub, true);
}
if (portchange & USB_PORT_STAT_C_RESET) { //hub口设备重置
dev_dbg (hub_dev,"reset change on port %d\n",i);
clear_port_feature(hdev, i,USB_PORT_FEAT_C_RESET);
}
if (connect_change) //hub口有变化(设备插入肯定有变化)
hub_port_connect_change(hub, i,portstatus, portchange); //hub口变化处理
}
if (test_and_clear_bit(0, hub->event_bits) == 0)
;
else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
dev_err (hub_dev, "get_hub_status failed\n");
else {
if (hubchange & HUB_CHANGE_LOCAL_POWER) {
dev_dbg (hub_dev, "power change\n");
clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
if (hubstatus & HUB_STATUS_LOCAL_POWER)
hub->limited_power = 1;
else
hub->limited_power = 0;
}
if (hubchange & HUB_CHANGE_OVERCURRENT) {
dev_dbg (hub_dev, "overcurrent change\n");
msleep(500);
clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
hub_power_on(hub, true);
}
}
loop_autopm:
usb_autopm_put_interface_no_suspend(intf);
loop:
usb_autopm_put_interface(intf);
loop_disconnected:
usb_unlock_device(hdev);
kref_put(&hub->kref, hub_release);
}
}
hub口状态变化处理函数
static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)
{
struct usb_device *hdev = hub->hdev;
struct device *hub_dev = hub->intfdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
unsigned wHubCharacteristics =le16_to_cpu(hub->descriptor->wHubCharacteristics);
struct usb_device *udev;
int status, i;
dev_dbg (hub_dev,"port %d, status %04x, change %04x, %s\n",port1, portstatus, portchange, portspeed (portstatus));
if (hub->has_indicators) {
set_port_led(hub, port1, HUB_LED_AUTO);
hub->indicator[port1-1] = INDICATOR_AUTO;
}
#ifdef CONFIG_USB_OTG
if (hdev->bus->is_b_host)
portchange &= ~(USB_PORT_STAT_C_CONNECTION |USB_PORT_STAT_C_ENABLE);
#endif
udev = hdev->children[port1-1]; //获取usb_device
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&udev->state != USB_STATE_NOTATTACHED) {
usb_lock_device(udev);
if (portstatus & USB_PORT_STAT_ENABLE) {
status = 0;
#ifdef CONFIG_USB_SUSPEND
} else if (udev->state == USB_STATE_SUSPENDED &&udev->persist_enabled) {
status = usb_remote_wakeup(udev);
#endif
} else {
status = -ENODEV;
}
usb_unlock_device(udev);
if (status == 0) {
clear_bit(port1, hub->change_bits);
return;
}
}
if (udev)
usb_disconnect(&hdev->children[port1-1]);
clear_bit(port1, hub->change_bits); //清除标志位
if (!(portstatus & USB_PORT_STAT_CONNECTION) ||(portchange & USB_PORT_STAT_C_CONNECTION))
clear_bit(port1, hub->removed_bits);
if (portchange & (USB_PORT_STAT_C_CONNECTION |USB_PORT_STAT_C_ENABLE)) {
status = hub_port_debounce(hub, port1);
if (status < 0) {
if (printk_ratelimit())
dev_err(hub_dev, "connect-debounce failed,port %d disabled\n", port1);
portstatus &= ~USB_PORT_STAT_CONNECTION;
} else {
portstatus = status;
}
}
if (!(portstatus & USB_PORT_STAT_CONNECTION) ||test_bit(port1, hub->removed_bits)) {
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2&& !(portstatus & USB_PORT_STAT_POWER))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
goto done;
return;
}
for (i = 0; i < SET_CONFIG_TRIES; i++) { //配置usb设备
udev = usb_alloc_dev(hdev, hdev->bus, port1); //分配usb_device
if (!udev) {
dev_err (hub_dev,"couldn't allocate port %d usb_device\n",port1);
goto done;
}
usb_set_device_state(udev, USB_STATE_POWERED); //设置usb设备为得电态
udev->bus_mA = hub->mA_per_port; //指定其电流限额
udev->level = hdev->level + 1; //层数为所属的hub的层数+1
udev->wusb = hub_is_wusb(hub);
if (!(hcd->driver->flags & HCD_USB3)) //usb设备速度
udev->speed = USB_SPEED_UNKNOWN;
else if ((hdev->parent == NULL) &&(portstatus & USB_PORT_STAT_SUPER_SPEED))
udev->speed = USB_SPEED_SUPER;
else
udev->speed = USB_SPEED_UNKNOWN;
choose_address(udev); //选择一个usb设备地址
if (udev->devnum <= 0) {
status = -ENOTCONN; /* Don't retry */
goto loop;
}
status = hub_port_init(hub, udev, port1, i); //初始化hub端口,枚举
if (status < 0)
goto loop;
usb_detect_quirks(udev);
if (udev->quirks & USB_QUIRK_DELAY_INIT)
msleep(1000);
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB&& udev->bus_mA <= 100) { //若插进来的也是hub
u16 devstat;
status = usb_get_status(udev, USB_RECIP_DEVICE, 0,&devstat);
if (status < 2) {
dev_dbg(&udev->dev, "get status %d ?\n", status);
goto loop_disable;
}
le16_to_cpus(&devstat);
if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
dev_err(&udev->dev,"can't connect bus-powered hub to this port\n");
if (hub->has_indicators) {
hub->indicator[port1-1] =INDICATOR_AMBER_BLINK;
schedule_delayed_work (&hub->leds, 0);
}
status = -ENOTCONN;
goto loop_disable;
}
}
if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200&& udev->speed == USB_SPEED_FULL&& highspeed_hubs != 0)
check_highspeed (hub, udev, port1);
status = 0;
spin_lock_irq(&device_state_lock);
if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN;
else
hdev->children[port1-1] = udev; //设置hub usb设备的子设备
spin_unlock_irq(&device_state_lock);
if (!status) {
status = usb_new_device(udev); //usb添加新设备
if (status) {
spin_lock_irq(&device_state_lock);
hdev->children[port1-1] = NULL;
spin_unlock_irq(&device_state_lock);
}
}
if (status)
goto loop_disable;
status = hub_power_remaining(hub);
if (status)
dev_dbg(hub_dev, "%dmA power budget left\n", status);
return;
loop_disable:
hub_port_disable(hub, port1, 1);
loop:
usb_ep0_reinit(udev);
release_address(udev);
hub_free_dev(udev);
usb_put_dev(udev);
if ((status == -ENOTCONN) || (status == -ENOTSUPP))
break;
}
if (hub->hdev->parent ||!hcd->driver->port_handed_over ||!(hcd->driver->port_handed_over)(hcd, port1))
dev_err(hub_dev, "unable to enumerate USB device on port %d\n",port1);
done:
hub_port_disable(hub, port1, 1);
if (hcd->driver->relinquish_port && !hub->hdev->parent)
hcd->driver->relinquish_port(hcd, port1);
}
hub端口初始化
static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,int retry_counter)
{
static DEFINE_MUTEX(usb_address0_mutex);
struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
int i, j, retval;
unsigned delay = HUB_SHORT_RESET_TIME;
enum usb_device_speed oldspeed = udev->speed;
char *speed, *type;
int devnum = udev->devnum;
if (!hdev->parent) {
delay = HUB_ROOT_RESET_TIME;
if (port1 == hdev->bus->otg_port)
hdev->bus->b_hnp_enable = 0;
}
if (oldspeed == USB_SPEED_LOW)
delay = HUB_LONG_RESET_TIME;
mutex_lock(&usb_address0_mutex);
if (!udev->config && oldspeed == USB_SPEED_SUPER) {
usb_set_device_state(udev, USB_STATE_DEFAULT);
} else {
retval = hub_port_reset(hub, port1, udev, delay);
if (retval < 0)
goto fail;
}
retval = -ENODEV;
if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) {
dev_dbg(&udev->dev, "device reset changed speed!\n");
goto fail;
}
oldspeed = udev->speed;
switch (udev->speed) {
case USB_SPEED_SUPER:
case USB_SPEED_WIRELESS:
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
break;
case USB_SPEED_HIGH:
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
break;
case USB_SPEED_FULL:
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
break;
case USB_SPEED_LOW:
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
break;
default:
goto fail;
}
type = "";
switch (udev->speed) {
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
case USB_SPEED_SUPER: speed = "super"; break;
case USB_SPEED_WIRELESS: speed = "variable"; type = "Wireless "; break;
default: speed = "?"; break;
}
if (udev->speed != USB_SPEED_SUPER)
dev_info(&udev->dev,"%s %s speed %sUSB device using %s and address %d\n",
(udev->config) ? "reset" : "new", speed, type,udev->bus->controller->driver->name, devnum);
if (hdev->tt) {
udev->tt = hdev->tt;
udev->ttport = hdev->ttport;
} else if (udev->speed != USB_SPEED_HIGH&& hdev->speed == USB_SPEED_HIGH) {
udev->tt = &hub->tt;
udev->ttport = port1;
}
for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
struct usb_device_descriptor *buf;
int r = 0;
#define GET_DESCRIPTOR_BUFSIZE 64
buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
if (!buf) {
retval = -ENOMEM;
continue;
}
for (j = 0; j < 3; ++j) {
buf->bMaxPacketSize0 = 0;
r = usb_control_msg(udev, usb_rcvaddr0pipe(),USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,buf, GET_DESCRIPTOR_BUFSIZE,initial_descriptor_timeout);
//获取描述符
switch (buf->bMaxPacketSize0) {
case 8: case 16: case 32: case 64: case 255:
if (buf->bDescriptorType == USB_DT_DEVICE) {
r = 0;
break;
}
default:
if (r == 0)
r = -EPROTO;
break;
}
if (r == 0)
break;
}
udev->descriptor.bMaxPacketSize0 = buf->bMaxPacketSize0;
kfree(buf);
retval = hub_port_reset(hub, port1, udev, delay);
if (retval < 0)
goto fail;
if (oldspeed != udev->speed) {
dev_dbg(&udev->dev,"device reset changed speed!\n");
retval = -ENODEV;
goto fail;
}
if (r) {
dev_err(&udev->dev,"device descriptor read/64, error %d\n",r);
retval = -EMSGSIZE;
continue;
}
#undef GET_DESCRIPTOR_BUFSIZE
}
if (udev->wusb == 0) {
for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
retval = hub_set_address(udev, devnum); //hub设置usb地址并告诉usb设备
if (retval >= 0)
break;
msleep(200);
}
if (retval < 0) {
dev_err(&udev->dev,"device not accepting address %d, error %d\n",devnum, retval);
goto fail;
}
if (udev->speed == USB_SPEED_SUPER) {
devnum = udev->devnum;
dev_info(&udev->dev,"%s SuperSpeed USB device using %s and address %d\n",
(udev->config) ? "reset" : "new",udev->bus->controller->driver->name, devnum);
}
msleep(10);
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
break;
}
retval = usb_get_device_descriptor(udev, 8); //获取设备描述符先读8字节
if (retval < 8) {
dev_err(&udev->dev,"device descriptor read/8, error %d\n",retval);
if (retval >= 0)
retval = -EMSGSIZE;
} else {
retval = 0;
break;
}
}
if (retval)
goto fail;
if (udev->descriptor.bMaxPacketSize0 == 0xff ||
udev->speed == USB_SPEED_SUPER)
i = 512;
else
i = udev->descriptor.bMaxPacketSize0;
if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
if (udev->speed == USB_SPEED_LOW ||!(i == 8 || i == 16 || i == 32 || i == 64)) {
dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
retval = -EMSGSIZE;
goto fail;
}
if (udev->speed == USB_SPEED_FULL)
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
else
dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
usb_ep0_reinit(udev);
}
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); //再次获取设备描述符
if (retval < (signed)sizeof(udev->descriptor)) {
dev_err(&udev->dev, "device descriptor read/all, error %d\n",
retval);
if (retval >= 0)
retval = -ENOMSG;
goto fail;
}
retval = 0;
if (hcd->driver->update_device)
hcd->driver->update_device(hcd, udev);
fail:
if (retval) {
hub_port_disable(hub, port1, 0);
update_address(udev, devnum); /* for disconnect processing */
}
mutex_unlock(&usb_address0_mutex);
return retval;
}
usb_new_device
int usb_new_device(struct usb_device *udev)
{
int err;
if (udev->parent) {
device_init_wakeup(&udev->dev, 0);
}
pm_runtime_set_active(&udev->dev);
pm_runtime_enable(&udev->dev);
err = usb_enumerate_device(udev); //读取usb设备的描述符信息
if (err < 0)
goto fail;
dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",udev->devnum, udev->bus->busnum,
(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,(((udev->bus->busnum-1) * 128) + (udev->devnum-1))); //分配设备号
announce_device(udev); //打印usb设备厂商啊啥的信息
device_enable_async_suspend(&udev->dev);
err = device_add(&udev->dev); //添加设备(至此usb枚举完了)-->usb设备与驱动的匹配
if (err) {
dev_err(&udev->dev, "can't device_add, error %d\n", err);
goto fail;
}
(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
return err;
fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
pm_runtime_disable(&udev->dev);
pm_runtime_set_suspended(&udev->dev);
return err;
}
usb_enumerate_device
static int usb_enumerate_device(struct usb_device *udev)
{
int err;
if (udev->config == NULL) {
err = usb_get_configuration(udev); //usb获取配置描述符
if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n",err);
goto fail;
}
}
if (udev->wusb == 1 && udev->authorized == 0) {
udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
}
else {
udev->product = usb_cache_string(udev, udev->descriptor.iProduct); //设置产品id
udev->manufacturer = usb_cache_string(udev,udev->descriptor.iManufacturer); //设置厂商id
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); //设置产品序列号
}
err = usb_enumerate_device_otg(udev);
fail:
return err;
}
device_add函数会出发总线的通知链发送通知,最终会调用总线的match方法
usb设备和驱动一旦match,则会调用驱动的drvwrap.driver.probe方法
若是设备则调用usb_probe_device
若是接口则调用usb_probe_interface
这里我们调用的是usb接口的,也就是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); //静态id匹配
if (!id)
id = usb_match_dynamic_id(intf, driver); //动态id匹配
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); //最终调用usb驱动的probe方法
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设备驱动的probe方法中会调用usb_alloc_urb分配urb
用
usb_fill_int_urb
usb_fill_bulk_urb
usb_fill_control_urb
填充urb
然后用usb_submit_urb提交urb
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
int xfertype, max;
struct usb_device *dev;
struct usb_host_endpoint *ep;
int is_out;
if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL;
dev = urb->dev;
if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
return -ENODEV;
ep = usb_pipe_endpoint(dev, urb->pipe); //获取端点
if (!ep)
return -ENOENT;
urb->ep = ep; //设置端点
urb->status = -EINPROGRESS;
urb->actual_length = 0;
xfertype = usb_endpoint_type(&ep->desc);
if (xfertype == USB_ENDPOINT_XFER_CONTROL) { //控制传输
struct usb_ctrlrequest *setup =(struct usb_ctrlrequest *) urb->setup_packet; //设置setup包
if (!setup)
return -ENOEXEC;
is_out = !(setup->bRequestType & USB_DIR_IN) ||!setup->wLength;
} else {
is_out = usb_endpoint_dir_out(&ep->desc);
}
urb->transfer_flags &= ~(URB_DIR_MASK | URB_DMA_MAP_SINGLE |URB_DMA_MAP_PAGE | URB_DMA_MAP_SG | URB_MAP_LOCAL |
URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |URB_DMA_SG_COMBINED);
urb->transfer_flags |= (is_out ? URB_DIR_OUT : URB_DIR_IN); //输入还是输出端点
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&dev->state < USB_STATE_CONFIGURED)
return -ENODEV;
max = le16_to_cpu(ep->desc.wMaxPacketSize);
if (max <= 0) {
dev_dbg(&dev->dev,"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
usb_endpoint_num(&ep->desc), is_out ? "out" : "in",__func__, max);
return -EMSGSIZE;
}
if (xfertype == USB_ENDPOINT_XFER_ISOC) { //同步传输
int n, len;
if (dev->speed == USB_SPEED_HIGH) {
int mult = 1 + ((max >> 11) & 0x03);
max &= 0x07ff;
max *= mult;
}
if (urb->number_of_packets <= 0)
return -EINVAL;
for (n = 0; n < urb->number_of_packets; n++) {
len = urb->iso_frame_desc[n].length;
if (len < 0 || len > max)
return -EMSGSIZE;
urb->iso_frame_desc[n].status = -EXDEV;
urb->iso_frame_desc[n].actual_length = 0;
}
}
if (urb->transfer_buffer_length > INT_MAX)
return -EMSGSIZE;
switch (xfertype) { //传输类型
case USB_ENDPOINT_XFER_ISOC: //同步传输
case USB_ENDPOINT_XFER_INT: //中断传输
switch (dev->speed) {
case USB_SPEED_WIRELESS: //无线?
if (urb->interval < 6)
return -EINVAL;
break;
default:
if (urb->interval <= 0)
return -EINVAL;
break;
}
switch (dev->speed) {
case USB_SPEED_SUPER: //超速设备
if (urb->interval > (1 << 15))
return -EINVAL;
max = 1 << 15;
break;
case USB_SPEED_WIRELESS: //无线?
if (urb->interval > 16)
return -EINVAL;
break;
case USB_SPEED_HIGH: //高速设备
if (urb->interval > (1024 * 8))
urb->interval = 1024 * 8;
max = 1024 * 8;
break;
case USB_SPEED_FULL: //全速
case USB_SPEED_LOW: //低速
if (xfertype == USB_ENDPOINT_XFER_INT) {
if (urb->interval > 255)
return -EINVAL;
max = 128;
} else {
if (urb->interval > 1024)
urb->interval = 1024;
max = 1024;
}
break;
default:
return -EINVAL;
}
if (dev->speed != USB_SPEED_WIRELESS) {
urb->interval = min(max, 1 << ilog2(urb->interval));
}
}
return usb_hcd_submit_urb(urb, mem_flags);
}
调用主控器usb_hcd_submit_urb
int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
{
int status;
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
usb_get_urb(urb);
atomic_inc(&urb->use_count);
atomic_inc(&urb->dev->urbnum);
usbmon_urb_submit(&hcd->self, urb);
if (is_root_hub(urb->dev)) { //这次不是根hub
status = rh_urb_enqueue(hcd, urb);
} else {
status = map_urb_for_dma(hcd, urb, mem_flags);
if (likely(status == 0)) {
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); //调用主控器的urb_enqueue方法
if (unlikely(status))
unmap_urb_for_dma(hcd, urb);
}
}
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list);
atomic_dec(&urb->use_count);
atomic_dec(&urb->dev->urbnum);
if (atomic_read(&urb->reject))
wake_up(&usb_kill_urb_queue);
usb_put_urb(urb);
}
return status;
}
<---usb设备注册