RootHub感应设备的插拔
来源:互联网 发布:哪下载软件安全 编辑:程序博客网 时间:2024/04/30 05:26
其实,RootHub的中断传输 是使用定时器来实现的。下面仔细欣赏。
首先你要明白的是: xHC控制器有两个RootHub,
一个是RootHub2.0的。 (遇到的开发板中它引出8个port.这些port对应寄存器为PORTSC0~7),
一个是RootHub3.0的。(引出7个port,PORTSC8~13),
那么就对应了两条bus总线了,但是这两条总线对应这同一个控制器xhc
port 状态变化 这块 很复杂,在后面会慢慢道来。往下看吧。
int usb_submit_urb(struct urb *urb, gfp_t mem_flags){ .... //先跳过,后面详细分析。 return usb_hcd_submit_urb(urb, mem_flags);}int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags){ if (is_root_hub(urb->dev)) //RootHub { status = rh_urb_enqueue(hcd, urb); } else { //非RootHub的先跳过。 }}static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb){ if (usb_endpoint_xfer_int(&urb->ep->desc)) //中断传输 { return rh_queue_status (hcd, urb); } if (usb_endpoint_xfer_control(&urb->ep->desc))//控制传输 { return rh_call_control (hcd, urb); } return -EINVAL;}static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb){ int retval; unsigned long flags; unsigned len = 1 + (urb->dev->maxchild / 8); spin_lock_irqsave (&hcd_root_hub_lock, flags); /** 如果roothub已经在处理中断传输或者是非法的urb */ if (hcd->status_urb || urb->transfer_buffer_length < len) { dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); retval = -EINVAL; goto done; } /** 将urb添加到endpoint的urb队列上。 */ retval = usb_hcd_link_urb_to_ep(hcd, urb); if (retval) { goto done; } hcd->status_urb = urb; urb->hcpriv = hcd; /** 支持新的轮询方式。 问: 那么他是再什么时候被赋值的呢? int xhci_run(struct usb_hcd *hcd) { u32 temp; u64 temp_64; int ret; struct xhci_hcd *xhci = hcd_to_xhci(hcd); hcd->uses_new_polling = 1; //支持新的轮询方式。 if (!usb_hcd_is_primary_hcd(hcd)) //RootHub 3.0 { return xhci_run_finished(xhci); } ... } 看,他是在xhci_run()中被赋值的。那么,xhci_run()函数又是在什么时候被调用的? 往下看。 xhci_register_pci() { return pci_register_driver(&xhci_pci_driver); } static struct pci_driver xhci_pci_driver = { .name = (char *) hcd_name, .id_table = pci_ids, .probe = xhci_pci_probe, .remove = xhci_pci_remove, }; /* 看他的porbe()函数。 注册了两个roothub。 一个是3.0的 一个是2.0的 但是 2.0的必须现注册.(为什么是2.0的要先注册?) */ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { ... /** 注册2.0的roothub . 必须先注册 2.0的 roothub. */ retval = usb_hcd_pci_probe(dev, id); /** 这个函数中会初始化定时器,并设定定时器到期执行的函数。 看,在xhci_register_pci()函数完成的时候 定时器轮询roothub就已经准备好了 init_timer(&hcd->rh_timer); hcd->rh_timer.function = rh_timer_func; hcd->rh_timer.data = (unsigned long) hcd; 这个rh_timer_func()在下面详细分析。 */ xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev,pci_name(dev), hcd); .... retval = usb_add_hcd(xhci->shared_hcd, dev->irq,IRQF_SHARED); } int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags) { ... ... /* 调用reset( )函数 */ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { dev_err(hcd->self.controller, "can't setup: %d\n", retval); goto err_hcd_driver_setup; } /* 设置可轮询 */ hcd->rh_pollable = 1; /* 注册了irq,也就使能了中断。 */ if (usb_hcd_is_primary_hcd(hcd) && irqnum) { retval = usb_hcd_request_irqs(hcd, irqnum, irqflags); if (retval) { goto err_request_irq; } } /* 调用start函数。 这里的start函数就是xhci_run()函数。 */ retval = hcd->driver->start(hcd); /* 注册RootHub */ if ((retval = register_root_hub(hcd)) != 0) { goto err_register_root_hub; } /* 创建属性文件 */ retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); 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) //如果不支持新的轮询方式。 { mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); }else if (HCD_POLL_PENDING(hcd)) { mod_timer(&hcd->rh_timer, jiffies); } retval = 0; done: spin_unlock_irqrestore (&hcd_root_hub_lock, flags); return retval;}
从头开始说把。
这个probe函数只要做了一下事情:
一 调用usb_hcd_pci_probe()注册roothub2.0,
USB core must know to register the USB 2.0 roothub first
上面是内核中的注释, 说注册3.0的RootHub之前,必须要先注册2.0的RootHub。
二 :调用usb_create_shared_hcd()创建和初始化一个HCD structure。
在这个函数中 它初始化了一个定时器,这个定时器的到期执行函数 会 轮询RootHub。
下面是一幅图:
下面好好的说说这个函数!
0 0
- RootHub感应设备的插拔
- 感应设备的插拔
- USB设备的插拔事件监测
- MFC实现设备的插拔检测
- MFC实现设备的插拔检测
- linux设备插拔
- 动态检测设备拔插
- 监控USB设备插拔
- 监控USB设备插拔
- 获取USB设备插拔消息的备忘
- 获取USB设备插拔消息的备忘
- WinCE下监视设备插拔的参考代码
- 再论检测usb口的设备插拔
- 获取USB设备插拔消息的备忘
- WinCE下监视设备插拔的参考代码
- WinCE下监视设备插拔的参考代码
- 一个可靠的USB设备插拔检测
- vc检测usb设备的拔插状态
- JS逗号运算符的用法详解
- 主成分分析(PCA)
- MySQL创建存储过程
- Android实现跑马灯效果总结
- MySql查询方式优化-重新构建查询
- RootHub感应设备的插拔
- 嵌入式dvfs动态调频调压技术
- 关于结对编程
- java---转换流1(InputStreamReader和OutputStreamWriter)
- 欢迎使用CSDN-markdown编辑器
- hdoj 5672 String (尺取法)
- Android 自定义字母搜索表
- 进制转换(随意转)
- 页 页表 页表项