usb杂谈之获取设备信息——举例鼠标urb

梳理USB port口检测设备

首先梳理一下usb设备的检测过程:
当usb设备接到port时,控制器会监测到该port电平状态发生改变,继而产生中断
port状态中断函数:handle_port_status
中断函数做了两件事:
第一件处理当前中断
第二件继续轮询该port状态

第一件事:使用tasklet中断下半部处理,然后使用工作队列创建出设备
    else if (high_prio_bh)                            // 同步传输或中断传输
        tasklet_hi_schedule(&bh->bh);
    else
        tasklet_schedule(&bh->bh);            // 控制传输或批量传输
tasklet执行usb_giveback_urb_bh,继而会执行urb的complete_fn。对于hub,complete_fn为hub_irq
hub_irq会执行唤醒工作队列hub_wq queue_work(hub_wq, &hub->events)
执行hub_event,然后故事就开始了。

第二件事:唤起定时器函数hcd->rh_timer - rh_timer_func - usb_hcd_poll_rh_status


插入鼠标获取usbmon

第一部分port相关包

ffffffa0e8a9af00 2329250566 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <    USB_RT_PORT    | IN
ffffffa0e8a9af00 2329250601 C Ci:3:001:0 0 4 = 01010100
ffffffa0e8a9af00 2329250614 S Co:3:001:0 s 23 01 0010 0001 0000 0
ffffffa0e8a9af00 2329250643 C Co:3:001:0 0 0
ffffffa0e8a9af00 2329250685 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329250709 C Ci:3:001:0 0 4 = 01010000
ffffffa0e8a9af00 2329284024 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329284053 C Ci:3:001:0 0 4 = 01010000
ffffffa0e8a9af00 2329320017 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329320044 C Ci:3:001:0 0 4 = 01010000
ffffffa0e8a9af00 2329356036 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329356079 C Ci:3:001:0 0 4 = 01010000
ffffffa0e8a9af00 2329392022 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329392054 C Ci:3:001:0 0 4 = 01010000
ffffffa0e8a9af00 2329392417 S Co:3:001:0 s 23 03 0004 0001 0000 0
ffffffa0e8a9af00 2329392446 C Co:3:001:0 0 0
ffffffa0e8a9b000 2329460039 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9b000 2329460080 C Ci:3:001:0 0 4 = 03031000
ffffffa0e8a9b000 2329460108 S Co:3:001:0 s 23 01 0014 0001 0000 0
ffffffa0e8a9b000 2329460134 C Co:3:001:0 0 0
ffffffa0e8a9af00 2329520737 S Ci:3:000:0 s 80 06 0100 0000 0040 64 <
ffffffa0e8a9af00 2329524946 C Ci:3:000:0 0 18 = 12011001 00000008 3a091025 00010102 0001  // 鼠标设备描述符
ffffffa0e8a9af00 2329524971 S Co:3:001:0 s 23 03 0004 0001 0000 0
ffffffa0e8a9af00 2329525005 C Co:3:001:0 0 0
ffffffa0e8a9af00 2329592022 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
ffffffa0e8a9af00 2329592071 C Ci:3:001:0 0 4 = 03031000
ffffffa0e8a9af00 2329592081 S Co:3:001:0 s 23 01 0014 0001 0000 0
ffffffa0e8a9af00 2329592101 C Co:3:001:0 0 0
X3 为port操作
struct usb_ctrlrequest {
    __u8 bRequestType;   方向 in:80 / out:0
#define USB_DIR_OUT            0        /* to device */
#define USB_DIR_IN            0x80        /* to host */
#define USB_RT_PORT    (USB_TYPE_CLASS | USB_RECIP_OTHER)
#define USB_TYPE_CLASS            (0x01 << 5)
#define USB_RECIP_OTHER            0x03

    __u8 bRequest;                描述符操作
#define USB_REQ_GET_STATUS        0x00
#define USB_REQ_CLEAR_FEATURE        0x01
#define USB_REQ_SET_FEATURE        0x03

    __le16 wValue;                描述符类型
#define HUB_PORT_STATUS        0
#define HUB_PORT_PD_STATUS    1
#define HUB_EXT_PORT_STATUS    2

    __le16 wIndex;                // port号
    __le16 wLength;
} __attribute__ ((packed));
上述包来自hub_port_init中的hub_port_reset。

usb_control_msg 中会做如下填充
    struct usb_ctrlrequest *dr;
    dr->bRequestType = requesttype;
    dr->bRequest = request;
    dr->wValue = cpu_to_le16(value);
    dr->wIndex = cpu_to_le16(index);
    dr->wLength = cpu_to_le16(size);
其中value的组成:(type << 8) + index,index为port index号

第二部分鼠标相关包

010devnum为鼠标 :鼠标读取配置部分
ffffffa0e8a9ae00 2329672054 S Ci:3:010:0 s 80 06 0100 0000 0012 18 <
ffffffa0e8a9ae00 2329676947 C Ci:3:010:0 0 18 = 12011001 00000008 3a091025 00010102 0001
ffffffa0e8a9ae00 2329676984 S Ci:3:010:0 s 80 06 0200 0000 0009 9 <
ffffffa0e8a9ae00 2329680943 C Ci:3:010:0 0 9 = 09022200 010100a0 32
ffffffa0e8a9ae00 2329680966 S Ci:3:010:0 s 80 06 0200 0000 0022 34 <
ffffffa0e8a9ae00 2329687944 C Ci:3:010:0 0 34 = 09022200 010100a0 32090400 00010301 02000921 11010001 22340007 05810304
ffffffa0e8a9bc00 2329687999 S Ci:3:010:0 s 80 06 0300 0000 00ff 255 <
ffffffa0e8a9bc00 2329690944 C Ci:3:010:0 0 4 = 04030904
ffffffa0e8a9bc00 2329690978 S Ci:3:010:0 s 80 06 0302 0409 00ff 255 <
ffffffa0e8a9bc00 2329697943 C Ci:3:010:0 0 36 = 24035500 53004200 20004f00 70007400 69006300 61006c00 20004d00 6f007500
ffffffa0e8a9bc00 2329697979 S Ci:3:010:0 s 80 06 0301 0409 00ff 255 <
ffffffa0e8a9bc00 2329701944 C Ci:3:010:0 0 14 = 0e035000 69007800 41007200 7400
鼠标设置部分
ffffffa0e8a9bc00 2329705350 S Co:3:010:0 s 00 09 0001 0000 0000 0
ffffffa0e8a9bc00 2329706934 C Co:3:010:0 0 0
ffffffa0e8a9af00 2329707250 S Co:3:010:0 s 21 0a 0000 0000 0000 0
ffffffa0e8a9af00 2329708983 C Co:3:010:0 -32 0
ffffffa0e8a9af00 2329709023 S Ci:3:010:0 s 81 06 2200 0000 0034 52 <
ffffffa0e8a9af00 2329718945 C Ci:3:010:0 0 52 = 05010902 a1010901 a1000509 19012903 15002501 75019503 81027505 95018101
ffffffa0e8a9bf00 2329719592 S Ii:3:010:1 -115:8 4 <
知识点010为devnum,动态分配的,但是hub dev的devnum是固定的,hub为1
xhc有两个hub一个2.0,一个3.0,devnum都为1。不信?lsusb -tv
至于devnum为0,没研究过lsusb代码,个人猜测为xhc dev

struct usb_ctrlrequest {
    __u8 bRequestType;   方向 in:80 / out:0
#define USB_DIR_OUT            0        /* to device */
#define USB_DIR_IN            0x80        /* to host */

    __u8 bRequest;                描述符操作
#define USB_REQ_SET_ADDRESS        0x05
#define USB_REQ_GET_DESCRIPTOR        0x06
#define USB_REQ_SET_DESCRIPTOR        0x07
#define USB_REQ_GET_CONFIGURATION    0x08
#define USB_REQ_SET_CONFIGURATION    0x09
#define USB_REQ_GET_INTERFACE        0x0A
#define USB_REQ_SET_INTERFACE        0x0B

    __le16 wValue;                描述符类型
#define USB_DT_DEVICE            0x01
#define USB_DT_CONFIG            0x02
#define USB_DT_STRING            0x03
#define USB_DT_INTERFACE        0x04
#define USB_DT_ENDPOINT            0x05

    __le16 wIndex;               ep号
    __le16 wLength;
} __attribute__ ((packed));

usb_control_msg 中会做如下填充
    struct usb_ctrlrequest *dr;
    dr->bRequestType = requesttype;
    dr->bRequest = request;
    dr->wValue = cpu_to_le16(value);
    dr->wIndex = cpu_to_le16(index);
    dr->wLength = cpu_to_le16(size);
其中value的组成:(type << 8) + index,index为ep index号


第一个包 18byte 是读取usb_device_descriptor
80 06 0100 0000 0012
第二个包 9byte 是读取usb_config_descriptor
80 06 0200 0000 0009
第三个包 32byte    是读取所有的配置信息
80 06 0200 0000 0022                
第四 五 六个包 255byte,读取string,ep0,ep1_in,ep2_in,三个ep
80 06 0300 0000 00ff
80 06 0302 0409 00ff
80 06 0301 0409 00ff
第七个包 是设置ep1_out配置
00 09 0001 0000 0000
第八个包
21 0a 0000 0000 0000
第九个包
81 06 2200 0000 0034
上述包都为setup包

hub_port_init 中实现了DEVICE包的发送,发送位置为
usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

usb_enumerate_device实现CONFIG和STRING包发送。
usb_get_configuratio(udev)
usb_cache_string(udev, udev->descriptor.iProduct);
usb_cache_string(udev, udev->descriptor.iManufacturer);
usb_cache_string(udev, udev->descriptor.iSerialNumber);

来来来对比一下:
lsusb -s 003:005 -v

Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x093a Pixart Imaging, Inc.
  idProduct          0x2510 Optical Mouse
  bcdDevice            1.00
  iManufacturer           1 PixArt
  iProduct                2 USB Optical Mouse
  iSerial                 0
  bNumConfigurations      1
对比一下返回
12011001 00000008 3a091025 00010102 0001

  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0022
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
对比一下返回
09022200 010100a0
协议包中数据以大端形式返回

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值