linux的usb hub<第一步>
以前不太了解hub,一直认为它只是一个可选设备,和网络集线器类似,有它不多,少它也可;
太低调了,以至于都不晓得它长在哪里,今天在网上百度了一下,发现它是window和linux系统上一个必备的设备;是EHCI/UHCI的私生子,一直躺在妈妈的怀里;
设备部分:<usb_device_type 篇>
hub是usb控制器的私生子,那么他就在hcd.c中生成:
usb_add_hcd()
{
...
rhdev = usb_alloc_dev(NULL, &hcd->self, 0);
hcd->self.root_hub = rhdev;
register_root_hub(hcd);//完成设备添加了;
...
}
下面中的介绍usb_alloc_dev和register_root_hub
函数一
-
/**
-
* usb_add_hcd - finish generic HCD structure initialization and register
-
* @hcd: the usb_hcd structure to initialize
-
* @irqnum: Interrupt line to allocate
-
* @irqflags: Interrupt type flags
-
*
-
* Finish the remaining parts of generic HCD initialization: allocate the
-
* buffers of consistent memory, register the bus, request the IRQ line,
-
* and call the driver's reset() and start() routines.
-
*/
-
int usb_add_hcd(struct usb_hcd *hcd,
-
unsigned int irqnum, unsigned long irqflags)
-
{
-
int retval;
-
struct usb_device *rhdev;
-
-
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
-
-
hcd->authorized_default = hcd->wireless? 0 : 1;
-
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-
/* HC is in reset state, but accessible. Now do the one-time init,
-
* bottom up so that hcds can customize the root hubs before khubd
-
* starts talking to them. (Note, bus id is assigned early too.)
-
*/
-
if ((retval = hcd_buffer_create(hcd)) != 0) {
-
dev_dbg(hcd->self.controller, "pool alloc failed\n");
-
return retval;
-
}
-
-
if ((retval = usb_register_bus(&hcd->self)) < 0)
-
goto err_register_bus;
-
-
if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
-
dev_err(hcd->self.controller, "unable to allocate root hub\n");
-
retval = -ENOMEM;
-
goto err_allocate_root_hub;
-
}
-
-
switch (hcd->driver->flags & HCD_MASK) {
-
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_allocate_root_hub;
-
}
-
hcd->self.root_hub = rhdev;//设备
-
-
/* wakeup flag init defaults to "everything works" for root hubs,
-
* but drivers can override it in reset() if needed, along with
-
* recording the overall controller's system wakeup capability.
-
*/
-
device_init_wakeup(&rhdev->dev, 1);
-
-
/* "reset" is misnamed; its role is now one-time init. the controller
-
* should already have been reset (and boot firmware kicked off etc).
-
*/
-
//控制器复位:ehci_pci_setup
-
if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
-
dev_err(hcd->self.controller, "can't setup\n");
-
goto err_hcd_driver_setup;
-
}
-
-
/* NOTE: root hub and controller capabilities may not be the same */
-
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");
-
//控制器中断处理接口
-
/* enable irqs just before we start the controller */
-
if (hcd->driver->irq) {
-
-
/* IRQF_DISABLED doesn't work as advertised when used together
-
* with IRQF_SHARED. As usb_hcd_irq() will always disable
-
* interrupts we can remove it here.
-
*/
-
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);
-
}
-
//控制器run:ehci_run
-
if ((retval = hcd->driver->start(hcd)) < 0) {
-
dev_err(hcd->self.controller, "startup error %d\n", retval);
-
goto err_hcd_driver_start;
-
}
-
-
/* starting here, usbcore will pay attention to this root hub */
-
rhdev->bus_mA = min(500u, hcd->power_budget);
-
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 && hcd->poll_rh)
-
usb_hcd_poll_rh_status(hcd);
-
return retval;
-
-
error_create_attr_group:
-
mutex_lock(&usb_bus_list_lock);
-
usb_disconnect(&hcd->self.root_hub);
-
mutex_unlock(&usb_bus_list_lock);
-
err_register_root_hub:
-
hcd->driver->stop(hcd);
-
err_hcd_driver_start:
-
if (hcd->irq >= 0)
-
free_irq(irqnum, hcd);
-
err_request_irq:
-
err_hcd_driver_setup:
-
hcd->self.root_hub = NULL;
-
usb_put_dev(rhdev);
-
err_allocate_root_hub:
-
usb_deregister_bus(&hcd->self);
-
err_register_bus:
-
hcd_buffer_destroy(hcd);
-
return retval;
-
}
函数二
-
/**
-
* usb_alloc_dev - usb device constructor (usbcore-internal)
-
* @parent: hub to which device is connected; null to allocate a root hub
-
* @bus: bus used to access the device
-
* @port1: one-based index of port; ignored for root hubs
-
* Context: !in_interrupt()
-
*
-
* Only hub drivers (including virtual root hub drivers for host
-
* controllers) should ever call this.
-
*
-
* This call may not be used in a non-sleeping context.
-
*/
-
struct usb_device *usb_alloc_dev(struct usb_device *parent,
-
struct usb_bus *bus, unsigned port1)
-
{
-
struct usb_device *dev;
-
struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
-
unsigned root_hub = 0;
-
//usb设备对象;
-
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-
if (!dev)
-
return NULL;
-
-
if (!usb_get_hcd(bus_to_hcd(bus))) {
-
kfree(dev);
-
return NULL;
-
}
-
/* Root hubs aren't true devices, so don't allocate HCD resources */
-
if (usb_hcd->driver->alloc_dev && parent &&
-
!usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
-
usb_put_hcd(bus_to_hcd(bus));
-
kfree(dev);
-
return NULL;
-
}
-
//usb_device_type
-
//usb设备的基本属性还是device;
-
device_initialize(&dev->dev);
-
dev->dev.bus = &usb_bus_type;//所属总线;
-
dev->dev.type = &usb_device_type;//usb设备类型,有别于usb_if_device_type;
-
dev->dev.groups = usb_device_groups;
-
dev->dev.dma_mask = bus->controller->dma_mask;
-
set_dev_node(&dev->dev, dev_to_node(bus->controller));
-
//USB设备的状态变化;表示已连接上(生来就是在一起的)
-
//后面这个状态会一直变化的;
-
dev->state = USB_STATE_ATTACHED;
-
atomic_set(&dev->urbnum, 0);
-
-
INIT_LIST_HEAD(&dev->ep0.urb_list);
-
//初始化端点信息
-
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
-
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
-
/* ep0 maxpacket comes later, from device descriptor */
-
//使能控制:ep->enabled = 1;
-
usb_enable_endpoint(dev, &dev->ep0, false);
-
dev->can_submit = 1;
-
-
/* Save readable and stable topology id, distinguishing devices
-
* by location for diagnostics, tools, driver model, etc. The
-
* string is a path along hub ports, from the root. Each device's
-
* dev->devpath will be stable until USB is re-cabled, and hubs
-
* are often labeled with these port numbers. The name isn't
-
* as stable: bus->busnum changes easily from modprobe order,
-
* cardbus or pci hotplugging, and so on.
-
*/
-
if (unlikely(!parent)) {//hub就是这条路;
-
dev->devpath[0] = '0';
-
dev->route = 0;
-
-
dev->dev.parent = bus->controller;
-
dev_set_name(&dev->dev, "usb%d", bus->busnum);//设备名称usbXX
-
root_hub = 1;
-
} else {
-
/* match any labeling on the hubs; it's one-based */
-
if (parent->devpath[0] == '0') {
-
snprintf(dev->devpath, sizeof dev->devpath,
-
"%d", port1);
-
/* Root ports are not counted in route string */
-
dev->route = 0;
-
} else {
-
snprintf(dev->devpath, sizeof dev->devpath,
-
"%s.%d", parent->devpath, port1);
-
/* Route string assumes hubs have less than 16 ports */
-
if (port1 < 15)
-
dev->route = parent->route +
-
(port1 << ((parent->level - 1)*4));
-
else
-
dev->route = parent->route +
-
(15 << ((parent->level - 1)*4));
-
}
-
-
dev->dev.parent = &parent->dev;
-
dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
-
-
/* hub driver sets up TT records */
-
}
-
-
dev->portnum = port1;
-
dev->bus = bus;
-
dev->parent = parent;
-
INIT_LIST_HEAD(&dev->filelist);
-
-
#ifdef CONFIG_PM
-
mutex_init(&dev->pm_mutex);
-
INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
-
INIT_WORK(&dev->autoresume, usb_autoresume_work);
-
dev->autosuspend_delay = usb_autosuspend_delay * HZ;
-
dev->connect_time = jiffies;
-
dev->active_duration = -jiffies;
-
#endif
-
if (root_hub) /* Root hub always ok [and always wired] */
-
dev->authorized = 1;//hub 默认;
-
else {
-
dev->authorized = usb_hcd->authorized_default;
-
dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
-
}
-
return dev;
-
}
函数三
-
/**
-
* register_root_hub - called by usb_add_hcd() to register a root hub
-
* @hcd: host controller for this root hub
-
*
-
* This function registers the root hub with the USB subsystem. It sets up
-
* the device properly in the device tree and then calls usb_new_device()
-
* to register the usb device. It also assigns the root hub's USB address
-
* (always 1).
-
*/
-
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);
-
set_bit (devnum, usb_dev->bus->devmap.devicemap);
-
//作为usb设备状态,第二种:USB_STATE_ADDRESS
-
usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
-
-
mutex_lock(&usb_bus_list_lock);
-
-
usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
-
//usb_get_descriptor--usb_control_msg--usb_start_wait_urb--usb_hcd_submit_urb--rh_urb_enqueue
-
//其实只知道一点就好了,roothub的描述符都是不需要控制器帮忙的,
-
//自带的;hub.c中有列出来;
-
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;
-
}
-
//这里面就是很熟悉的代码了
-
//device_add(dev);
-
retval = usb_new_device (usb_dev);
-
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;
-
spin_unlock_irq (&hcd_root_hub_lock);
-
-
/* Did the HC die before the root hub was registered? */
-
if (hcd->state == HC_STATE_HALT)
-
usb_hc_died (hcd); /* This time clean up */
-
}
-
-
return retval;
-
}
阅读(1516) | 评论(0) | 转发(0) |