带着上次留下的疑问,我们继续来学习操作系统如何通过USBDISK读写USB设备的。我们先看USB/CLASS/STORAGE/DISK/SCSI2/usbdisk6.def文件。在这个文件中可以看到,该DLL一共导出了14个函数,其中两个是上次内容当中被设备驱动程序调用的UsbDiskAttach和UsbDiskDetach,余下的是一组以DSK开头的流驱动接口,易见,USBDISK是以流驱动的形式向操作系统提供服务的。 为了清晰起见,以下大量的程序我们并不学习,而只关心设备读写,因此我们来看DISK.C这个程序文件。找到DSK_Read和DSK_Write两个函数,令我们大失所望,因为这两个函数都是形如 UNREFERENCED_PARAMETER(pDevice); UNREFERENCED_PARAMETER(pBuffer); UNREFERENCED_PARAMETER(BufferLength); DEBUGMSG(ZONE_ERR,(TEXT("DSK_Read/n"))); SetLastError(ERROR_INVALID_FUNCTION); return 0; 这样的实现,也就是说用户无法通过常规的ReadFile和WriteFile函数使用这个设备,那怎么办?是否意味着这个DISK无法读写呢?当然不是,我们应该马上想到DSK_IOControl()这个函数,当遇到某些设备无法用常规的文件操作函数操作时,我们有DeviceIoControl()用户函数可以使用,而这个函数就会调用到驱动程序中的DSK_IOControl函数。 在这个函数中,我们找到了对IOCTL_DISK_READ等命令的处理程序,其中最关键的一句就是ScsiRWSG(pDevice, pSgReq, pDevice->Lun, bRead),即调用了一个ScsiRWSG的函数。 在Scsi2.c这个程序中,我们找到了这个函数,其中SG指的是一种读写缓冲区的数据结构,实际上就是带有缓冲区及长度的一个结构体,是CE下磁盘设备通用的读写数据结构,可以在diskio.h中找到它的定义。在这个函数中我们发现它再次调用了ScsiReadWrite()这个函数进行读写操作,找到这个函数,里面有我们最重要的一行调用,即调用了UsbsDataTransfer()函数,还记得这个函数在哪见过吗?没错,就是在USB设备的驱动程序当中。 通过这一过程我们发现,那些Scsi的函数都只是在准备一些缓冲区、数据结构等,并没有对硬件进行操作,真正要操作硬件设备的还是由驱动程序来完成的,可见,设备驱动程序是有着很强层次结构的,下层是专门针对物理设备的,上层是针对操作系统的抽象设备的,下层是U盘等物理实体,上层是文件夹,二者通过一定的通信或调用机制完成了设备在操作系统下的正常工作。 回到usbmsc.c程序中来,找到UsbsDataTransfer函数,这个函数很简单,根据传输协议调用CBIT_DataTransfer()或BOT_DataTransfer() 即可。 |
USB设备驱动程序导读(8)
最新推荐文章于 2024-04-26 15:30:39 发布