三、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设备注册

你可能感兴趣的:(三、usb主控器注册)