二,usb描述符-设备 配置 接口 端点

一,基础概念
在USB设备的逻辑组织中,包含设备、配置、接口和端点4个层次。
每个USB设备都提供了不同级别的配置信息,可以包含一个或多个配置,不同的配置使设备表现出不同的功能组合(在探测/连接期间需从其中选定一个),配置由多个接口组成。

在USB协议中,接口由多个端点组成,代表一个基本的功能,是USB设备驱动程序控制的对象,一个功能复杂的USB设备可以具有多个接口。每个配置中可以有多个接口,而设备接口是端点的汇集(collection)。例如USB扬声器可以包含一个音频接口以及对旋钮和按钮的接口。一个配置中的所有接口可以同时有效,并可被不同的驱动程序连接。每个接口可以有备用接口,以提供不同质量的服务参数。

USB设备是由一些配置、接口和端点组成,即一个USB设备可以含有一个或多个配置,在每个配置中可含有一个或多个接口,在每个接口中可含有若干个端点。其中,配置和接口是对USB设备功能的抽象,实际的数据传输由端点来完成。在使用USB设备前,必须指明其采用的配置和接口。这个步骤一般是在设备接入主机时设备进行枚举时完成的。

这些单元之间的关系如下:
设备配置接口端点
设备通常有一个或多个配置;
配置通常有一个或多个接口;
接口通常有一个或多个设置;
接口有零或多个端点。

二,USB描述符
USB设备使用各种描述符来说明其设备架构,包括设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符,他们通常被保存在USB设备的固件程序中
usb设备结构体描述(include/linux/usb.h) — usb设备的描述符信息(include/uapi/linux/usb/ch9.h)
struct usb_device — struct usb_device_descriptor
struct usb_host_config — struct usb_config_descriptor
struct usb_interface — struct usb_interface_descriptor
struct usb_host_endpoint — struct usb_endpoint_descriptor

1,设备描述符
设备代表一个USB设备,它由一个或多个配置组成。设备描述符用于说明设备的总体信息,并指明其所含的配置的个数。一个USB设备只能有一个设备描述符。

struct usb_device { //代表一个USB设备
	int		devnum;
	char		devpath[16];
	u32		route;
	enum usb_device_state	state;
	enum usb_device_speed	speed;//device speed: high/full/low (or error)
	unsigned int		rx_lanes;//number of rx lanes in use, USB 3.2 adds dual-lane support
	unsigned int		tx_lanes;//number of tx lanes in use, USB 3.2 adds dual-lane support
	enum usb_ssp_rate	ssp_rate;

	struct usb_tt	*tt;
	int		ttport;

	unsigned int toggle[2];//one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints

	struct usb_device *parent;
	struct usb_bus *bus;//bus we're part of
	struct usb_host_endpoint ep0;//endpoint 0 data (default control pipe)

	struct device dev;

	struct usb_device_descriptor descriptor;//USB device descriptor
	struct usb_host_bos *bos;
	struct usb_host_config *config;

	struct usb_host_config *actconfig;
	struct usb_host_endpoint *ep_in[16];//array of IN endpoints
	struct usb_host_endpoint *ep_out[16];//array of OUT endpoints

	char **rawdescriptors;

	unsigned short bus_mA;//Current available from the bus
	u8 portnum;
	u8 level;
	u8 devaddr;

	unsigned can_submit:1;
	unsigned persist_enabled:1;
	unsigned have_langid:1;
	unsigned authorized:1;
	unsigned authenticated:1;
	unsigned wusb:1;
	unsigned lpm_capable:1;//device supports LPM
	unsigned usb2_hw_lpm_capable:1;
	unsigned usb2_hw_lpm_besl_capable:1;
	unsigned usb2_hw_lpm_enabled:1;
	unsigned usb2_hw_lpm_allowed:1;
	unsigned usb3_lpm_u1_enabled:1;
	unsigned usb3_lpm_u2_enabled:1;
	int string_langid;

	/* static strings from the device */
	char *product;//iProduct string, if present (static)
	char *manufacturer;//iManufacturer string, if present (static)
	char *serial;//iSerialNumber string, if present (static)

	struct list_head filelist;

	int maxchild;

	u32 quirks;
	atomic_t urbnum;//number of URBs submitted for the whole device

	unsigned long active_duration;

#ifdef CONFIG_PM
	unsigned long connect_time;

	unsigned do_remote_wakeup:1;
	unsigned reset_resume:1;
	unsigned port_is_suspended:1;
#endif
	struct wusb_dev *wusb_dev;
	int slot_id;
	struct usb2_lpm_parameters l1_params;
	struct usb3_lpm_parameters u1_params;
	struct usb3_lpm_parameters u2_params;
	unsigned lpm_disable_count;

	u16 hub_delay;
	unsigned use_generic_driver:1;

	ANDROID_KABI_RESERVE(1);
	ANDROID_KABI_RESERVE(2);
	ANDROID_KABI_RESERVE(3);
	ANDROID_KABI_RESERVE(4);
};

/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor { //usb设备描述符
    __u8  bLength;//长度
    __u8  bDescriptorType;//描述符类型

    __le16 bcdUSB;//usb SPEC的版本
    __u8  bDeviceClass;//设别类型
    __u8  bDeviceSubClass;//设备子类型
    __u8  bDeviceProtocol;//协议
    __u8  bMaxPacketSize0;//最大传输大小
    __le16 idVendor;//厂商ID
    __le16 idProduct;//设备ID
    __le16 bcdDevice;//设备版本号
    __u8  iManufacturer;//描述厂商字符串的索引
    __u8  iProduct;//描述产品字符串的索引
    __u8  iSerialNumber;//序列号
    __u8  bNumConfigurations;//设备当前速度模式下支持的配置数量。有的设备可以在多个速度模式下操作,这里包括的只是当前速度模式下的配置数目,不是总的配置数目
} __attribute__ ((packed));

2,配置描述符
一个USB设备可以包含一个或多个配置,如USB设备的低功耗模式和高功耗模式可分别对应一个配置。在使用USB设备前,必须为其选择一个合适的配置。配置描述符用于说明USB设备中各个配置的特性,如配置所含接口的个数等。USB设备的每一个配置都必须有一个配置描述符。

struct usb_host_config {//表示一个设备的配置
	struct usb_config_descriptor	desc;//the device's configuration descriptor

	char *string;		/* iConfiguration string, if present */

	/* List of any Interface Association Descriptors in this
	 * configuration. */
	struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];

	/* the interfaces associated with this configuration,
	 * stored in no particular order */
	struct usb_interface *interface[USB_MAXINTERFACES];

	/* Interface information available even when this is not the
	 * active configuration */
	struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];

	unsigned char *extra;   /* Extra descriptors */
	int extralen;
};

struct usb_config_descriptor { //配置描述符
    __u8  bLength;//描述符长度
    __u8  bDescriptorType;//配置描述符的类型

    __le16 wTotalLength;//使用GET_DESCRIPTOR请求从设备里获得配置描述符信息时,返回的数据长度
    __u8  bNumInterfaces;//这个配置包含的接口数量
    __u8  bConfigurationValue;//对于拥有多个配置的设备来说,可以拿这个值为参数,使用SET_CONFIGURATION请求来改变正在被使用的 USB配置,
	                          bConfigurationValue就指明了将要激活哪个配置。咱们的设备虽然可以有多个配置,但同一时间却也只能有一个配置被激活。捎带着提一下,
	                          SET_CONFIGURATION请求也是标准的设备请求之一,专门用来设置设备的配置。
    __u8  iConfiguration;//描述配置信息的字符串描述符的索引值
    __u8  bmAttributes;//这个字段表征了配置的一些特点,比如bit 6为1表示self-powered,bit 5为1表示这个配置支持远程唤醒。
	                    另外,它的bit 7必须为1
    __u8  bMaxPower;//设备正常运转时,从总线那里分得的最大电流值,以2mA为单位。
	                 设备可以使用这个字段向hub表明自己需要的的电流,但如果设备需求过于旺盛,
	                 请求的超出了hub所能给予的,hub就会直接拒绝还记得struct usb_device结构里的bus_mA吗?它就表示hub所能够给予的。计算机的usb端口可以提供最多500mA的电流
} __attribute__ ((packed));

3,接口描述符
一个配置可以包含一个或多个接口,例如对一个光驱来说,当用于文件传输时,使用其大容量存储接口;而当用于播放CD时,使用其音频接口。接口是端点的集合,可以包含一个或多个可替换设置,用户能够在USB处于配置状态时改变当前接口所含的个数和特性。接口描述符用于说明设备中各个接口的特性,如接口所属的设备类及其子类等。USB设备的每个接口都必须有一个接口描述符。

struct usb_interface {//usb设备驱动通信的接口
    /* array of alternate settings for this interface,
     * stored in no particular order */
    struct usb_host_interface *altsetting;

    struct usb_host_interface *cur_altsetting;  /* the currently
                     * active alternate setting */
    unsigned num_altsetting;    /* number of alternate settings */

    /* If there is an interface association descriptor then it will list
     * the associated interfaces */
    struct usb_interface_assoc_descriptor *intf_assoc;

    int minor;          /* minor number this interface is
                     * bound to */
    enum usb_interface_condition condition;     /* state of binding */
    unsigned sysfs_files_created:1; /* the sysfs attributes exist */
    unsigned ep_devs_created:1; /* endpoint "devices" exist */
    unsigned unregistering:1;   /* unregistration is in progress */
    unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
    unsigned needs_altsetting0:1;   /* switch to altsetting 0 is pending */
    unsigned needs_binding:1;   /* needs delayed unbind/rebind */
    unsigned resetting_device:1;    /* true: bandwidth alloc after reset */
    unsigned authorized:1;      /* used for interface authorization */

    struct device dev;      /* interface specific device info */
    struct device *usb_dev; /*if an interface is bound to the USB major, this will point
                            to the sysfs representation for that device*/
    struct work_struct reset_ws;    /* for resets in atomic context */

    ANDROID_KABI_RESERVE(1);
    ANDROID_KABI_RESERVE(2);
    ANDROID_KABI_RESERVE(3);
    ANDROID_KABI_RESERVE(4);
};

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

    __u8  bInterfaceNumber;//接口号。每个配置可以包含多个接口,这个值就是它们的索引值。
    __u8  bAlternateSetting;//接口使用的是哪个可选设置。协议里规定,接口默认使用的设置总为0号设置。
    __u8  bNumEndpoints;//接口拥有的端点数量。这里并不包括端点0,因为端点0是控制传输,是所有的设备都必须提供的,
	                    所以这里就没必要多此一举的包括它了。对于hub,因为它的传输是中断传输,所以此值为1(不包括端点0)
    __u8  bInterfaceClass;//接口类型
    __u8  bInterfaceSubClass;//接口子类型
    __u8  bInterfaceProtocol;//接口所遵循的协议
    __u8  iInterface;//描述该接口的字符串索引值
} __attribute__ ((packed));

4,端点描述符
端点是USB设备中的实际物理单元,USB数据传输就是在主机和USB设备各个端点之间进行的。端点一般由USB接口芯片提供,例如Freescale公司的MC68HC908JB8和MC9S12UF32。USB设备中的每一个端点都有唯一的端点号,每个端点所支持的数据传输方向一般而言也是确定的:或是输入(IN),或是输出(OUT)。也有些芯片提供的端点的数据方向是可以配置的,例如MC68HC908JB8包含有两个用于数据收发的端点:端点1和端点2。其中端点1只能用于数据发送,即支持输入(IN)操作;端点2既能用于数据发送,也可用于数据接收,即支持输入(IN)和输出(OUT)操作。而MC9S12UF32具有6个端点。

利用设备地址、端点号和传输方向就可以指定一个端点,并与它进行通信。端点的传输特性还决定了其与主机通信是所采用的传输类型,例如控制端点只能使用控制传输。根据端点的不同用途,可将端点分为两类:0号端点和非0号端点。
0号端点比较特殊,它有数据输入IN和数据输出OUT两个物理单元,且只能支持控制传输。所有的USB设备都必须含有一个0号端点,用作默认控制管道。USB系统软件就是使用该管道与USB逻辑设备进行配置通信的。0号端点在USB设备上的以后就可以使用,而非0号端点必须要在配置以后才可以使用。
根据具体应用的需要,USB设备还可以含有多个除0号端点以外的其他端点。对于低速设备,其附加的端点数最多为2个;对于全速/高速设备,其附加的端点数最多为15个。

struct usb_host_endpoint {//host-side endpoint descriptor and queue
    struct usb_endpoint_descriptor      desc;//descriptor for this endpoint, wMaxPacketSize in native byteorder
    struct usb_ss_ep_comp_descriptor    ss_ep_comp;//SuperSpeed companion descriptor for this endpoint
    struct usb_ssp_isoc_ep_comp_descriptor  ssp_isoc_ep_comp;//SuperSpeedPlus isoc companion descriptor for this endpoint
    struct list_head        urb_list;//urbs queued to this endpoint; maintained by usbcore
    void                *hcpriv;
    struct ep_device        *ep_dev;    /* For sysfs info */

    unsigned char *extra;   /* Extra descriptors */
    int extralen;
    int enabled;
    int streams;
};

/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {//USB 端点描述符(每个USB设备最多有16个端点)
    __u8  bLength;//描述符的字节长度
    __u8  bDescriptorType;//描述符类型,对于端点就是USB_DT_ENDPOIN

    __u8  bEndpointAddress;//bit0~3表示端点地址,bit8 表示方向,输入还是输出
    __u8  bmAttributes;//属性(bit0、bit1构成传输类型,00--控制,01--等时,10--批量,11--中断)
    __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;//对于同步传送的端点,此域必须为1
} __attribute__ ((packed));

5,字符串描述符
在USB设备中通常还含有字符串描述符,以说明一些专用信息,如制造商的名称、设备的序列号等。它的内容以UNICODE的形式给出,且可以被客户软件所读取。对USB设备来说,字符串描述符是可选的。

/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;

    __le16 wData[1];        /* UTF-16LE encoded */
} __attribute__ ((packed));

6,usb端点分类
USB 通讯的最基本形式是通过端点。一个USB端点只能向一个方向传输数据(从主机到设备(称为输出端点)或者从设备到主机(称为输入端点))。端点可被看作一个单向的管道。

USB 端点有 4 种不同类型, 分别具有不同的数据传送方式:

  1. 控制CONTROL
    控制端点被用来控制对USB设备的不同部分访问. 通常用作配置设备、获取设备信息、发送命令到设备或获取设备状态报告。这些端点通常较小。每个 USB 设备都有一个控制端点称为"端点 0", 被 USB 核心用来在插入时配置设备。USB协议保证总有足够的带宽留给控制端点传送数据到设备.

  2. 中断INTERRUPT
    每当 USB 主机向设备请求数据时,中断端点以固定的速率传送小量的数据。此为USB 键盘和鼠标的主要的数据传送方法。它还用以传送数据到USB设备来控制设备。通常不用来传送大量数据。USB协议保证总有足够的带宽留给中断端点传送数据到设备.

  3. 批量BULK
    批量端点用以传送大量数据。这些端点通常比中断端点大得多. 它们普遍用于不能有任何数据丢失的情况。USB 协议不保证传输在特定时间范围内完成。如果总线上没有足够的空间来发送整个BULK包,它被分为多个包进行传输。这些端点普遍用于打印机、USB Mass Storage和USB网络设备上。

  4. 等时ISOCHRONOUS
    等时端点也批量传送大量数据, 但是这个数据不被保证能送达。这些端点用在可以处理数据丢失的设备中,并且更多依赖于保持持续的数据流。如音频和视频设备等等。
    控制和批量端点用于异步数据传送,而中断和等时端点是周期性的。这意味着这些端点被设置来在固定的时间连续传送数据,USB 核心为它们保留了相应的带宽。

在这里插入图片描述
参考文档:
https://www.cnblogs.com/wen123456/p/14212640.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值