转自:http://blog.csdn.net/jacobywu/article/details/8819001
[cpp] view plaincopy
/**
* usb_alloc_dev - usb device constructor (usbcore-internal)
* @parent: 设备连接的那个hub
* @bus: 设备连接的那条总线
* @ port1 就是设备连接在hub 上的那个端口
* 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;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) //判断内存申请成功了没
return NULL;
//一个主机控制器对应着一条usb总线
//函数bus_to_hcd是为了获得总线对应的主机控制器
//驱动,也就是struct usb_hcd结构对象,函数usb_get_hcd只是将得到的这个usb_hcd
//结构对象的引用计数加1
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;
}
//device_initialize 是设备模型里的函数,这里就是将struct usb_device 结构里
//嵌入的那个struct device 结构体初始化掉
device_initialize(&dev->dev);
dev->dev.bus = &usb_bus_type;//将设备所在的总线类型设置为usb_bus_type
dev->dev.type = &usb_device_type;//将设备的设备类型初始化为usb_device_type
dev->dev.groups = usb_device_groups;
dev->dev.dma_mask = bus->controller->dma_mask;//dma_mask 被设置为host controller 的dma_mask
set_dev_node(&dev->dev, dev_to_node(bus->controller));
dev->state = USB_STATE_ATTACHED;//将usb 设备的状态设置为Attached,表示设备已经连接到usb 接口上了,是hub检测到设备时的初始状态
atomic_set(&dev->urbnum, 0);
INIT_LIST_HEAD(&dev->ep0.urb_list);//,struct usb_device里直接就有这么一个成员ep0,这行就将ep0 的urb_list 给初始化掉
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;//初始化了端点0 的描述符长度
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;//初始化了端点0 的描述符类型
/* ep0 maxpacket comes later, from device descriptor */
//使struct usb_device 结构里的ep_in 和ep_out 指针数组的第一个成员指向ep0,ep_in[0]和ep_out[0]本来表示的就是端点0。
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.
*/
/*
unlikely(x)就是告诉编译器条件x 发生的
可能性不大,那么这个条件块儿里语句的目标码可能就会被放在一个比较远的为止,以保证
经常执行的目标码更紧凑。likely 则相反。
*/
if (unlikely(!parent)) {
dev->devpath[0] = ‘0‘;//首先判断你的设备是不是直接连到root hub 上的,如果是,将dev->devpath[0]赋值为‘0’,以示特
dev->route = 0;
dev->dev.parent = bus->controller;
dev_set_name(&dev->dev, "usb%d", bus->busnum);
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);//初始化一个队列,usbfs 用的
#ifdef CONFIG_PM
pm_runtime_set_autosuspend_delay(&dev->dev,
usb_autosuspend_delay * 1000);
dev->connect_time = jiffies;
dev->active_duration = -jiffies;
#endif
if (root_hub) /* Root hub always ok [and always wired] */
dev->authorized = 1;
else {
dev->authorized = usb_hcd->authorized_default;
dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
}
return dev;
}
起码能够知道端点0一次能够处理的最大数据长度啊,协议里说,对于高速设备,这个值为为64 字节,对于低
速设备为8 字节,而对于全速设备可能为8,16,32,64 其中的一个.
[cpp] view plaincopy
struct usb_ctrlrequest {
__u8 bRequestType;//它的bit7 就表示了控制传输中DATA transaction 阶段的方向,
//当然,如果有DATA 阶段的话。bit5~6 表示request 的类型,是标准的
__u8 bRequest;//表示具体是哪个request
__le16 wValue;//这个字段是request 的参数,request 不同,wValue 就不同。
__le16 wIndex;//也是request 的参数,bRequestType 指明request 针对的是设备上的某个接口或端点的时候,wIndex 就用来指明是哪个接口或端点。
__le16 wLength;//控制传输中DATA transaction 阶段的长度, 方向已经在
//bRequestType 那儿指明了。如果这个值为0,就表示没有DATA transaction 阶段,bRequestType 的方向位也就无效了。
} __attribute__ ((packed));
控制传输最少要有两个阶段的transaction,SETUP 和STATUS,SETUP 和STATUS 中间的那个DATA阶段是可有可无的.
SETUP transaction 一般来说也有三个阶段,就是主机向设备发送Setup Token 包、然后发送Data0 包,如果一切顺利,设备回应ACK
Handshake 包表示OK.
经过 SETUP、DATA、STATUS 这三个transaction 阶段,一个完整的控制传输完成了.
[cpp] view plaincopy
static int usb_internal_control_msg(struct usb_device *usb_dev,
unsigned int pipe,
struct usb_ctrlrequest *cmd,
void *data, int len, int timeout)
{
struct urb *urb;
int retv;
int length;
urb = usb_alloc_urb(0, GFP_NOIO); //:usb_alloc_urb函数,创建一个urb,struct urb结构体只能使用它来创建
if (!urb)
return -ENOMEM;
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
len, usb_api_blocking_completion, NULL); //,初始化一个控制urb,urb被创建之后,使用之前必须要正确的初始化。
retv = usb_start_wait_urb(urb, timeout, &length);//将urb提交给咱们的usb core,以便分配给特定的主机控制器驱动进行处理
if (retv < 0)
return retv;
else
return length;
}
此函数可以概括为一个中心,三个基本点,以一个struct urb结构体为中心,
以usb_alloc_urb、usb_fill_control_urb、usb_start_wait_urb三个函数为基本点