U盘插入到主机的usb接口上会发生什么?在linux内核中会发生很多事情。
首先,U盘插入后会触发主机上的usb控制器中断,并先后由主机控制器中断处理程序、usb核心(主机控制器的代码一般位于drivers/usb/host,而usb核心的代码位于/drivers/usb/core)来处理。进入到usb核心处理阶段会创建、注册这个新插入的设备--U盘。这个过程会根据U盘的vendor id和device id等等来把U盘和对应的驱动链接起来,然后U盘的驱动程序就会开始初始化这个U盘设备,这里的初始化是把它作为一个U“盘”来初始化,重点是“盘”,而usb core部分的初始化只是把它作为一个usb设备来初始化。
另一方面,U盘它既是一个usb设备(遵循usb协议),又是一个盘---即一个storage设备,遵循的是scsi协议。那这两种特点是如何结合共存的呢?
很简单,U盘挂在usb这个总线上,就要遵循usb协议,但是要使用U盘这个设备的功能就要遵守scsi协议(U盘具体的协议是bulk only)。读写U盘等等的操作都是通过scsi协议标准的命令来执行,一般这个过程分为:命令、数据和状态三个阶段。而这三个阶段传输的不论是命令、数据还是状态,说穿了它也就是一些数据信息(也就是bit位,而已),U盘驱动把这些scsi传输最后还是要封装成usb能够识别的bulk传输来进行,这样即照顾了scsi协议,也体谅了usb的感受。
言归正传,usb core创建、注册的时候会把调用到U盘的驱动来初始化---主要是usb_storage_driver-->probe函数来实现,这个porbe的原型是storage_probe。在drivers/usb/strorage目录下的usb.c文件中有定义:
static struct usb_driver usb_storage_driver = {
.name = "usb-storage",
.probe = storage_probe,
.disconnect = usb_stor_disconnect,
.suspend = usb_stor_suspend,
.resume = usb_stor_resume,
.reset_resume = usb_stor_reset_resume,
.pre_reset = usb_stor_pre_reset,
.post_reset = usb_stor_post_reset,
.id_table = usb_storage_usb_ids,
.soft_unbind = 1,
};
好,到这个地方,我们就需要引出我们的主角了:strorage_probe。
static int storage_probe(struct usb_interface *intf,const struct usb_device_id *id)
{
struct us_data *us;
int result;
/*
* If libusual is configured, let it decide whether a standard
* device should be handled by usb-storage or by ub.
* If the device isn't standard (is handled by a subdriver
* module) then don't accept it.
*/
if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||usb_usual_ignore_device(intf))
return -ENXIO;
/*
* Call the general probe procedures.
*
* The unusual_dev_list array is parallel to the usb_storage_usb_ids
* table, so we use the index of the id entry to find the
* corresponding unusual_devs entry.
*/
result = usb_stor_probe1(&us, intf, id, (id - usb_storage_usb_ids) + us_unusual_dev_list);
if (result)
return result;
/* No special transport or protocol settings in the main module */
result = usb_stor_probe2(us);
return result;
}
代码不多而且也很简洁明了,probe分为两个阶段,usb_stor_probe1和usb_stor_probe2,在接下来的时光中我们将会详细讲述这两个函数。
阅读(1622) | 评论(0) | 转发(0) |