usb主控器注册
来源:互联网 发布:企业收支软件 编辑:程序博客网 时间:2024/04/29 03:21
第一步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主控器注册
- 三、usb主控器注册
- 嵌入式Linux下高速USB主控制器的设计与实现
- 嵌入式Linux下高速USB主控制器的设计与实现
- 主控制器接口
- 主控制器接口
- otg 主控制器移植
- CI主控制器CI_Controller
- 四、usb设备注册
- 四、usb设备注册
- ohci中文 第六章主控制器
- linux spi 主控制器驱动
- 6410 otg 主控制器驱动移植
- SPI驱动之主控制器驱动程序
- mini2440 spi主控制器支持
- 主控制器问题汇总20150827更新
- SPI驱动之主控制器驱动程序
- usb子系统相关结构体
- MySQL的mysqldump工具的基本用法
- 邓超返沪黑脸苦等接机人 扎辫子头潮味十足(图)
- xp系统下硬盘安装ubuntu11.04
- 英语学习13/1/14翻译
- usb主控器注册
- iOS中打印日志显示系统详细时间,类名,行号及打印值
- git 代理的使用方法
- 2PM佑荣被抓拍僵硬表情 对李贞贤90度鞠躬问候
- apache的性能调配 MaxClients 与MaxRequestsPerChild
- 开启关闭数据的莫名错误 Oracle ORA-24324 ORA-01041 ORA-01089
- ActionbarSherlock的Style讲解
- 处理死锁 阻塞问题预备知识之SELECT,UPDATE,DELETE操作需要申请的锁(一 SELECT操作)
- Acm 结果原因