USB驱动程序框架搭建



USB驱动程序框架搭建  

2012-05-27 06:00:13|  分类: 跟着韦东山老师学 |  标签: |举报 |字号 订阅

转自:

http://liu1227787871.blog.163.com/blog/static/205363197201242731042757/

1.首先我们先从理论上浅谈一下USB驱动的框架

app:   
-------------------------------------------
          USB设备驱动程序      // 知道数据含义
内核 --------------------------------------
          USB总线驱动程序      // 1. 识别, 2. 找到匹配的设备驱动, 3. 提供USB读写函数 (它不知道数据含义)
-------------------------------------------
           USB主机控制器
           UHCI OHCI EHCI
硬件        -----------
              USB设备

UHCI: intel,     低速(1.5Mbps)/全速(12Mbps)
OHCI: microsoft  低速/全速
EHCI:            高速(480Mbps)

也就是说最底层是usb设备,往上是USB总线控制器、USB总线驱动程序、USB驱动程序,最后是应用程序。其中USB总线控制器包括三种:UHCI OHCI EHCI

2. USB总线驱动程序的作用
1. 识别USB设备
  1.1 分配地址
  1.2 并告诉USB设备(set address)
  1.3 发出命令获取描述符
描述符的信息可以在include\linux\usb\Ch9.h看到

2. 查找并安装对应的设备驱动程序

3. 提供USB读写函数

3、我们开始正式构建linux usb框架了,小心了!!!

首先我们需要从开发板获得一些信息:
把USB设备接到开发板上,看输出信息:
usb 1-1: new full speed USB device using s3c2410-ohci and address 2
usb 1-1: configuration #1 chosen from 1 choice
scsi0 : SCSI emulation for USB Mass Storage devices
scsi 0:0:0:0: Direct-Access     HTC      Android Phone    0100 PQ: 0 ANSI: 2
sd 0:0:0:0: [sda] Attached SCSI removable disk
拔掉
usb 1-1: USB disconnect, address 2

再接上:
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: configuration #1 chosen from 1 choice
scsi1 : SCSI emulation for USB Mass Storage devices
scsi 1:0:0:0: Direct-Access     HTC      Android Phone    0100 PQ: 0 ANSI: 2
sd 1:0:0:0: [sda] Attached SCSI removable disk

接着我们就可以根据这些信息进行分析了:
首先我们在内核的dirvers目录下搜索:“ USB device using  
grep "USB device using" * -nR
结果搜到了下面这条信息: usb/core/hub.c:2186:              "%s %s speed %sUSB device using %s and address %d\n",

那么我们就从usb/core/hub.c这个文件开始分析:
 "%s %s speed %sUSB device using %s and address %d\n"这句话在hub_port_init 函数中被调用
hub_port_init 在函数hub_port_connect_change中被调用
hub_port_connect_change在函数hub_events中被调用
hub_events在函数hub_thread中被调用
hub_thread函数里有这么一句:
wait_event_interruptible(khubd_wait,!list_empty(&hub_event_list) || kthread_should_stop());
说明进程会在 khubd_wait这个等待队列里休眠,那么谁把它唤醒呢?我们搜索一下
在kick_khubd函数里有这么一句:wake_up(&khubd_wait);把进程唤醒了
kick_khubd被函数hub_irq调用,根据注释信息我们知道当连接发生变化或则出现措施就会发生中断,从而进入这个函数。

那么我们大致可以总结出了框架:
hub_irq   //发生接口状态变化或出现错误时调用
          kick_khubd
                    wake_up //唤醒进程
                              hub_thread //进程在这个函数里休眠了,被wake up唤醒后会继续执行
                                        hub_port_connect_change   //我们重点来分析它
                                                     udev = usb_alloc_dev(hdev, hdev->bus, port1);
                                                               dev->dev.bus = &usb_bus_type; //指定设备总线是usb类型的
                                                   choose_address(udev); //在0到128之间找到一个设备地址,至于为什么是128我们之前已经讲过了  
                                                   hub_port_init
                                                               hub_set_address //将上面找到的地址告诉usb设备
                                                               usb_get_device_descriptor(udev, 8); //获取设备描述符
                                                               usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); //再次获取设备描述符,我们在                                                                                                                                                                      //usb协议分析里面有谈到过的
                                                    usb_new_device //把所有的描述符都读出来并解析
                                                              usb_get_configuration(udev); //获取配置信息
                                                              usb_cache_string(udev, udev->descriptor.iProduct); //读取产品信息
                                                              usb_cache_string(udev,udev->descriptor.iManufacturer); //读取制造商信息
                                                              usb_cache_string(udev, udev->descriptor.iSerialNumber); //读取序列号信息
                                                              __usb_get_extra_descriptor //获得一些额外的信息
                                                              device_add(&udev->dev); // 把device放入usb_bus_type的dev链表, 
                                                      // 从usb_bus_type的driver链表里取出usb_driver,
                                                      // 把usb_interface和usb_driver的id_table比较
                                                      // 如果能匹配,调用usb_driver的probe
我们来总结一下上面的框架:首先接上usb设备时会发 生中断,然后唤醒进程。接着先设置usb设备的地址,然后获取设备描述符和配置描述符等各种描述符,这是为了寻找驱动程序。接着将usb设备加入到链表里,和驱动比较,如果匹配就调用probe函数。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值