zoukankan      html  css  js  c++  java
  • USB总线驱动程序

    USB主机控制器:UHCI OHCI EHCI

    UHCI:intel 低速(1.5Mbps)(USB1.1)/全速(12Mbps)(USB2.0,USB2.0又分为全速和高速)
    OHCI:microsoft:低速/全速
    EHCI:高速(480Mbps)

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

    2. 查找并安装对应的设备驱动程序
    3. 提供USB读写函数

    在程序中是如何调用的,简单的看一下:

    在drivers/usb/core/hub.c文件中:
    每一个USB控制器都自带有一个hub

    hub_irq
      kick_khubd
        hub_thread
          hub_events
            hub_port_connect_change
              choose_devnum //给新设备选择新的编号(地址)
              hub_port_init
                hub_set_address//把编号(地址)告诉USB设备,以后就使用这个地址了。
                usb_get_device_descriptor(udev, 8);//获取设备描述符
                retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

              usb_new_device(udev)

                    //把device放入bus的dev链表,从bus的driver链表中取出driver,如果能够匹配,调用driver的probe
                device_add(&udev->dev);

    注意:这个中断是主机控制器里面注册的中断,不是usb设备的中断。当接上一个USB设备之后,硬件上的手脚就使得D+或D-由低电平变为高电平,硬件上就感知了有USB设备接入,里面就会产生某个中断。从而就有了上面的调用过程。

    hub_port_connect_change
      choose_devnum //给新设备选择新的编号(地址)
      /* Try to allocate the next devnum beginning at bus->devnum_next. */
      //查找下一个0位,显然某个地址用了,里面的相应的地址就会设置为1,表示这个地址正在使用。从1找到128,如果找不到,就会从头找。假设你上次插入USB设备号,它devnum=5,那么它就会从5开始找,找到128后,如果没找到,它会从1开始再找。就是找一圈后,如果没找到,再回来。从这个地方也可以看出,一个USB主机控制器最多可以接128个USB设备。
      devnum = find_next_zero_bit(bus->devmap.devicemap, 128,bus->devnum_next);

    2、分析几个重要的数据结构

    设备描述符:

    /* USB_DT_DEVICE: Device descriptor */
    struct usb_device_descriptor {
    __u8 bLength;
    __u8 bDescriptorType;

    __le16 bcdUSB; //USB版本号
    __u8 bDeviceClass;
    __u8 bDeviceSubClass;
    __u8 bDeviceProtocol;
    __u8 bMaxPacketSize0; //最大包大小,0表示端点0.每个设备都有端点0,因为是通过端点0识别出USB设备的
    __le16 idVendor; //厂家ID
    __le16 idProduct; //产品ID
    __le16 bcdDevice;
    __u8 iManufacturer;
    __u8 iProduct;
    __u8 iSerialNumber;
    __u8 bNumConfigurations;
    } __attribute__ ((packed));

    配置描述符:
    struct usb_config_descriptor {
    __u8 bLength;
    __u8 bDescriptorType;

    __le16 wTotalLength;
    __u8 bNumInterfaces;
    __u8 bConfigurationValue;
    __u8 iConfiguration;
    __u8 bmAttributes;
    __u8 bMaxPower;
    } __attribute__ ((packed));

    接口描述符:
    /* USB_DT_INTERFACE: Interface descriptor */
    struct usb_interface_descriptor {
    __u8 bLength;
    __u8 bDescriptorType;

    __u8 bInterfaceNumber;
    __u8 bAlternateSetting;
    __u8 bNumEndpoints;
    __u8 bInterfaceClass;
    __u8 bInterfaceSubClass;
    __u8 bInterfaceProtocol;
    __u8 iInterface;
    } __attribute__ ((packed));

    端点描述符
    /* USB_DT_ENDPOINT: Endpoint descriptor */
    struct usb_endpoint_descriptor {
    __u8 bLength;
    __u8 bDescriptorType;

    __u8 bEndpointAddress;
    __u8 bmAttributes;
    __le16 wMaxPacketSize; //从端点中一次写入或读出多少数据
    __u8 bInterval;用查询的方式实现实时性的,此变量就表示查询的时间间隔。

    /* NOTE: these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8 bRefresh;
    __u8 bSynchAddress;
    } __attribute__ ((packed));

    它们的关系:

    每一个USB设备,都有一个设备描述符,可以发出某些命令,得到USB设备描述符。一个硬件里面有一个设备描述符,
    一个设备描述符里面还有配置描述符,一个设备描述符里面可能有多个配置描述符。

     本节只是进行了简单的分析,并没有进行深入分析。需看《linux内核源码代码情景分析》

  • 相关阅读:
    docker1
    Ubuntu中安装deb包程序
    Linux性能评测工具之一:gprof篇介绍
    Lua在Linux下的安装
    gprof的使用介绍
    Linux性能评测工具之一:gprof篇
    google-perftools 分析JAVA 堆外内存
    NetHogs下载和监控
    Google perf tools for nginx
    ECLIPSE中添加TPTP插件
  • 原文地址:https://www.cnblogs.com/-glb/p/11568992.html
Copyright © 2011-2022 走看看