Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150461
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-06-08 10:29:49

1. 启动过程分析
a. 入口
    a.1 在usb模块的启动函数中usb_init调用了usb_hub_init
    a.2 usb_hub_init向usb_core注册了hub_driver
    a.3 并启动线程hub_thread
b. hub_thread
    b.1 线程hub_thread 会卡在等侍消息上,
    b.2 当有u盘插入时,触发中断hub_irq并通过kick_khubd(hub)将消息插入到队列中,
    b.3 这时hub_thread就会被激活,进入处理函数hub_events中
c. hub_events
    a. usb_husb向device发送get_status命令,此时portchange是STAT_C_CONNECTION
        设标志位connect_change=1,进入hub_port_connect_change处理
    b.  hub_port_connect_change的处理  
        b.1 hub_port_debounce-->判断usb口是否真正有设备接入
         类似于去抖: 每隔100ms查询usb口的状态,执行三次如果都是CONNECTION,说明hub上有usb设备接入了
        b.2 choose_address --> 为usb设备选一个地址
        b.3 hub_port_init  --> hub_port_reset后获取dev_descriptor
        b.4 判断descriptor中类型,若不为hub,则说明是usb_device,就usb_new_device
    c. usb_new_device的处理
        c.1 usb_detect_quirks, 判断是不是黑名单的usb设备
        c.2 usb_configure_device
            c.2.1 usb_get_configuration,先获取一次descriptor(主要是为了获取整个descriptor的长度),知道长度之后获取完整的descriptor
                    然后调用usb_parse_configuration,解析配置描述符和接口描述符
            c.2.2 usb_cache_string获取product manufactor与serial并储存在缓存中
        c.3 device_add历级一系列的调用最终会调到probe函数usb_probe_interface

2.总结
2.1 当有一个u盘插入到hub时,其调用关系如下:   
    hub_thread() -> hub_events() -> hub_port_connect_change() ->usb_new_device() -> device_add()
2.2 device_add的过程
       device_add() -> bus_probe_device() -> device_attach() -> __device_attach() -> driver_probe_device() -> really_probe()--> usb_probe_interface


为什么device_add之后会调用storage_probe呢? 这个地方还没有看懂,只是通过打印信息发现是在really_probe中,
调用了usb_probe_interface
    --> struct usb_driver *driver = to_usb_driver(dev->driver);
    --> error = driver->probe(intf, id);
这个driver->probe就是storage_probe,应该是在really_probe中把driver赋值的,但具体是根据什么赋值的还没有搞明白。




usb_match_id分析:
1.预先写好usb设备列表:
  1. ./drivers/usb/storage/usual-tables.c
  2. struct usb_device_id usb_storage_usb_ids[] = {
  3. # include "unusual_devs.h"
  4.     { } /* Terminating entry */
  5. };


  1. 分为两种:
  2. /work/tq/kernel/drivers/usb/storage/unusual_devs.h
  3. a. 特殊的设备用PID与VID匹配
  4. /* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
  5. UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
  6.         "TGE",
  7.         "Digital MP3 Audio Player",
  8.         US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
  9. b.普通的设备,直接跳过PID与VID匹配,只看其class类型
  10. USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
2. usb_match_id过程
    a. for循环遍历usb设备列表中的每一项,调用usb_match_one_id进行匹配
        a.1 usb_match_one_id先调用usb_match_device匹配特殊的设备
        a.2 若为普通设备,则不关心PID与VID,只检查class sub_class protocol,若匹配说明是普通设备

    





阅读(2158) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~