linux下USB驱动及其相关研究(二) --USB驱动模块工作原理

来源:互联网 发布:sql将某字段内容累加 编辑:程序博客网 时间:2024/05/17 22:55

  

      今天继续。上回说到如何自动mount/umount ,该如何实现呢?我曾经发过一帖子:希望能够得到帮助,不过意外的是自己最后通过google搜索,使用的关键字逐渐接近问题的本质,最后终于解决了问题。下面这个就是初期,我在csdn上提的一个问题:
  最近一直在看usb驱动的代码,希望能在驱动中做一个标记,用来告诉应用程序,这个时候可以umount拉,不会有device?busy的console提示了。有两个问题,不得解,希望得到各位帮助:
1.  usb_stor_control_thread()函数的for循环中,如果程序停在if(down_interruptible(&us->sema))这句,说明usb没有数据通讯,这个时候可以通知umount拉。这样想对吗?需要在scsi的模块代码中找标记吗?主要是这个问题。
2.  如果做了标记,要传到用户层,netlink,socket,klog,还是/proc/文件,用什么方法比较简便些呢?

  接下来我还是先不说USB接口监控程序如何编写,因为突然发现,在说这个之前,必须要介绍内核中usb模块工作原理,介绍编写内核模块遵循框架结构,还要介绍内核模块如何和用户层程序通讯。就按照这样的一个顺序来说明吧。

  下面将要介绍的是USB驱动工作原理,事实上,监控USB接口的工作在linux内核中早已经实现,当U盘插入接口的时候,hub就会发现有设备,如果你把内核当中的debug选项打开,就会发现一系列的操作。

       Usb.c(usbcore)模块的init函数是usb_init(), 在usb_init()中,一种叫usb_bus_type的bus驱动还被注册到system中,然后usb_generic_driver的usb device驱动还根据驱动中的相关bus信息注册到bus上面。
  而在usb_hub_init()函数中,hub.c定义的device驱动程序hub_driver将被注册到bus上,它是通过usb_regiseter()函数注册的,将会注册到device驱动hub_driver本身自带的bus上面。
  在看驱动代码的时候,发现有很多register,都搞不明白是怎么一回事,这里把它们澄清一下。register_chrdev()/register_blkdev() 与usb_register() 不同,虽然也是叫注册,它是将设备的major号,minor号向系统注册。如果major为0,会自动分配一个回给设备,这样就可以将设备当做一个文件来操作。
  usb_register_dev()也是注册,不过和usb_register()有少许不同,当你想让驱动使用usb major号的时候,就必须使用usb_register_dev()来。usb_register()也可以理解是向usb core注册驱动。
  上面的实际上是题外话。回到hub_port_init()中,当在hub上检测到u盘后,那么相应的驱动也会被调用,此时usb-storage里面设备驱动的函数就开始工作了。storage_probe() -> usb_stor_acquire_resources () -> usb_stor_control_thread(). 最后一个函数有一个永循环。
  下面在比较抽象介绍一下USB数据传输的步骤:
1.主机软件(如:samba,ftp读写取某个usb的挂载点)将数据保存在数据缓冲区中,然后向usb 所在的bus驱动程序发送数据传输请求。
2.Bus驱动程序对IRP(i/o请求包)响应,将其中的数据转化成usb协议中规定的事物处理格式。
3.Usb主控会将每一个事务处理转化为一系列的数据帧为单位的事物处理队列,这样的处理是为了满足usb传输协议的要求,并保证传输不超过usb的带宽。
(帧:在USB中,一帧就是1MS,它是一个独立的单元,包含了一系列总线动作,USB将1帧分为好几份,每一份中是一个USB的传输动作。)
4.Usb主控读事物处理队列,将其中的事物处理以信息包的形式发送到usb总线上。
5.功能设备从总线上接受信息,u盘芯片引擎解析信息包,并将数据保存在指定的端点缓冲区中。
(端点:位于USB设备或主机上的一个数据缓冲区,用来存放和发送USB的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性)
        写累了,下回再解释一下怎么写内核驱动模块吧!

原创粉丝点击