USB的总体概述

1 篇文章 0 订阅

USB类型与速度

usb1.0 low-speed 1.5Mbps
usb1.1 full-speed 12Mbps
usb2.0 high-speed 480Mbps
usb3.0 super-speed 4.8Gbps

USB组成

综述

可以在/sys/bus/usb/device路径查看usb信息
lsusb也可以快速查询
设备》配置》接口》端点
手机是一个设备,将其配置为摄像,接口就是摄像的不同功能,端点就是调整焦距的通道
USB 描述符主要有四种:设备描述符、配置描述符、接口描述符和端点描述符,都放在USB 设备中的EEPROM
wc –l ./* 可以显示每一个文件的行数,方便查看代码量
在这里插入图片描述)
其中2-1:1.0表示2号总线,也就是2号 Root Hub,1就是这里我们说的usb_device的 devpath,1 表示配置为 1 号, 0 表示接口号为 0。

USBcore

内核中 USB 子系统的结构)

lsmod中可以查询到ehci_hcd 或 uhci_hcd就是usb主机控制器,OHCI/UHCI,这都是在 USB spec 1.0 时, 2.0 时代推出了 EHCI,高速设备应运而生
在usbcore目录下,config USB_DEVICEFS开启关于 usbfs 文件系统的。 usbfs 文件系统挂载在/proc/bus/usb 上。
在/driver/usb/core/usb.c中初始化usb,如下:

static int __init usb_init(void)
{
	int retval;
	if (usb_disabled()) {
		pr_info("%s: USB support disabled\n", usbcore_name);
		return 0;
	}
	usb_init_pool_max();
	usb_debugfs_init();
	usb_acpi_register();
	retval = bus_register(&usb_bus_type);
	retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
	retval = usb_major_init();
	retval = usb_register(&usbfs_driver);
	retval = usb_devio_init();
	retval = usb_hub_init();
	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
}

USB设备

Linux 设备模型中的 device 落实在 USB 子系统,成了两个结构:一个是 struct usb_device,一个是 struct usb_interface

USB的设备号

//USB的设备号
#define USB_MAJOR			180
#define USB_DEVICE_MAJOR		189
struct usb_device {
	int		devnum;
	char		devpath[16];
	u32		route;
	enum usb_device_state	state;
	enum usb_device_speed	speed;
	unsigned int		rx_lanes;
	unsigned int		tx_lanes;
	enum usb_ssp_rate	ssp_rate;

	struct usb_tt	*tt;
	int		ttport;

	unsigned int toggle[2];

	struct usb_device *parent;
	struct usb_bus *bus;
	struct usb_host_endpoint ep0;

	struct device dev;

	struct usb_device_descriptor descriptor;
	struct usb_host_bos *bos;
	struct usb_host_config *config;

	struct usb_host_config *actconfig;
	struct usb_host_endpoint *ep_in[16];
	struct usb_host_endpoint *ep_out[16];

	char **rawdescriptors;

	unsigned short bus_mA;
	u8 portnum;
	u8 level;
	u8 devaddr;

	unsigned can_submit:1;
	unsigned persist_enabled:1;
	unsigned reset_in_progress:1;
	unsigned have_langid:1;
	unsigned authorized:1;
	unsigned authenticated:1;
	unsigned wusb:1;
	unsigned lpm_capable:1;
	unsigned lpm_devinit_allow:1;
	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;
	char *manufacturer;
	char *serial;

	struct list_head filelist;

	int maxchild;

	u32 quirks;
	atomic_t urbnum;

	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;
};

USB设备描述符

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

	__le16 bcdUSB;
	__u8  bDeviceClass;
	__u8  bDeviceSubClass;
	__u8  bDeviceProtocol;
	__u8  bMaxPacketSize0;
	__le16 idVendor;
	__le16 idProduct;
	__le16 bcdDevice;
	__u8  iManufacturer;
	__u8  iProduct;
	__u8  iSerialNumber;
	__u8  bNumConfigurations;
} __attribute__ ((packed));

USB的接口

struct usb_interface {
	/* 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;
	struct work_struct reset_ws;	/* for resets in atomic context */
};

USB配置

USB设备的配置

struct usb_host_config {
	struct usb_config_descriptor	desc;

	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;
};

USB配置描述符

struct usb_config_descriptor {
	__u8  bLength;
	__u8  bDescriptorType;

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

USB接口

设备可以有多个接口,每个接口代表一个功能,每个接口对应着一个驱动。
接口的设置如下

/* host-side wrapper for one interface setting's parsed descriptors */
struct usb_host_interface {
	struct usb_interface_descriptor	desc;

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

	/* array of desc.bNumEndpoints endpoints associated with this
	 * interface setting.  these will be in no particular order.
	 */
	struct usb_host_endpoint *endpoint;

	char *string;		/* iInterface string, if present */
};

接口描述符如下

/* 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));

bInterfaceClass与bInterfaceSubClass是对usb设备的分类,比如Mass Storage 的 Class 就是 0x08, Hub的 Class 就是 0x09。

USB端点

端点0

端点0可以是in端点也可以是out端点,用来实现默认的控制管道来控制设备

传输方式

控制传输:用来传送控制信息,端点0
中断传输:USB键盘鼠标
批量传输:U盘
等时传输:视频
PIPE_ISOCHRONOUS 就是标志等时通道, PIPE_INTERRUPT 就是中断通道, PIPE_CONTROL 就是控制通道, PIPE_BULK 就是批量通道

端点是 USB 数据传输的终点。看一看它在内核中的定义。

struct usb_host_endpoint {
	struct usb_endpoint_descriptor		desc;
	struct usb_ss_ep_comp_descriptor	ss_ep_comp;
	struct usb_ssp_isoc_ep_comp_descriptor	ssp_isoc_ep_comp;
	struct list_head		urb_list;
	void				*hcpriv;
	struct ep_device		*ep_dev;	/* For sysfs info */

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

端点描述符

/* 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驱动

USB接口驱动
向接口驱动中添加新的厂商和产品 id ,在/sys/bus/usb/drivers 的new_id 写入id即可,如echo 0557 2008 > /sys/bus/usb/drivers/foo_driver/new_id

struct usb_driver {
	const char *name;

	int (*probe) (struct usb_interface *intf,
		      const struct usb_device_id *id);

	void (*disconnect) (struct usb_interface *intf);

	int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
			void *buf);

	int (*suspend) (struct usb_interface *intf, pm_message_t message);
	int (*resume) (struct usb_interface *intf);
	int (*reset_resume)(struct usb_interface *intf);

	int (*pre_reset)(struct usb_interface *intf);
	int (*post_reset)(struct usb_interface *intf);

	const struct usb_device_id *id_table;
	const struct attribute_group **dev_groups;

	struct usb_dynids dynids;
	struct usbdrv_wrap drvwrap;
	unsigned int no_dynamic_id:1;
	unsigned int supports_autosuspend:1;
	unsigned int disable_hub_initiated_lpm:1;
	unsigned int soft_unbind:1;
};

USB设备驱动

struct usb_device_driver {
	const char *name;

	bool (*match) (struct usb_device *udev);
	int (*probe) (struct usb_device *udev);
	void (*disconnect) (struct usb_device *udev);

	int (*suspend) (struct usb_device *udev, pm_message_t message);
	int (*resume) (struct usb_device *udev, pm_message_t message);
	const struct attribute_group **dev_groups;
	struct usbdrv_wrap drvwrap;
	const struct usb_device_id *id_table;
	unsigned int supports_autosuspend:1;
	unsigned int generic_subclass:1;
};

USB设备流程

  1. usb_alloc_dev当有hub检测到新的usb插入时,分配usb_device,调用设备模型提供的接口将设备添加到 USB总线的设备列表里,然后 USB 总线会遍历驱动列表里的每个驱动,调用自己的 match 函数看它们和你的设备或接口是否匹配,就走到 match 函数了。
  2. 初始化usb_device结构体,包括设备状态,支持速度,设备等级等,设备从powered状态进入Default 状态,再进入Address 状态,需要函数 usb_control_ msg,给设备发送 SET_ADDRESS 请求
  3. usb_control_ msg调用函数usb_internal_control_ msg,以一个 struct urb 结构体为中心,以 usb_alloc_urb、usb_fill_control_urb、 usb_start_wait_urb 三个函数为基本点。usb_alloc_urb创建一个 urb;usb_fill_control_urb 函数,进行初始化控制 urb;usb_start_wait_urb 函数,将 urb 提交给 USB Core,以便分配给特定的主机控制器驱动进行处理,然后默默地等待处理结果,或者超时;
    kref, urb 的引用计数,控制kref就可以控制urb存亡
struct urb {
	/* private: usb core and host controller only fields in the urb */
	struct kref kref;		/* reference count of the URB */
	int unlinked;			/* unlink error code */
	void *hcpriv;			/* private data for host controller */
	atomic_t use_count;		/* concurrent submissions counter */
	atomic_t reject;		/* submissions will fail */

	/* public: documented fields in the urb that can be used by drivers */
	struct list_head urb_list;	/* list head for use by the urb's
					 * current owner */
	struct list_head anchor_list;	/* the URB may be anchored */
	struct usb_anchor *anchor;
	struct usb_device *dev;		/* (in) pointer to associated device */
	struct usb_host_endpoint *ep;	/* (internal) pointer to endpoint */
	unsigned int pipe;		/* (in) pipe information */
	unsigned int stream_id;		/* (in) stream ID */
	int status;			/* (return) non-ISO status */
	unsigned int transfer_flags;	/* (in) URB_SHORT_NOT_OK | ...*/
	void *transfer_buffer;		/* (in) associated data buffer */
	dma_addr_t transfer_dma;	/* (in) dma addr for transfer_buffer */
	struct scatterlist *sg;		/* (in) scatter gather buffer list */
	int num_mapped_sgs;		/* (internal) mapped sg entries */
	int num_sgs;			/* (in) number of entries in the sg list */
	u32 transfer_buffer_length;	/* (in) data buffer length */
	u32 actual_length;		/* (return) actual transfer length */
	unsigned char *setup_packet;	/* (in) setup packet (control only) */
	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
	int start_frame;		/* (modify) start frame (ISO) */
	int number_of_packets;		/* (in) number of ISO packets */
	int interval;			/* (modify) transfer interval
					 * (INT/ISO) */
	int error_count;		/* (return) number of ISO errors */
	void *context;			/* (in) context for completion */
	usb_complete_t complete;	/* (in) completion routine */
	struct usb_iso_packet_descriptor iso_frame_desc[];
					/* (in) ISO ONLY */
};
  1. urb_list,每个端点都会有的那个 urb 队列; dev,它表示 urb 要去的那个 USB 设备; pipe,urb 到达端点之前,需要经过一个通往端点的管道,就是这个 pipe,端点有四种,又有OUT和IN,就有八种管道;status, urb 的当前状态;transfer_flags,一些标记;
  2. usb_submit_urb 函数在urb.c中,对 urb 做些前期处理之后扔给 HCD;对于控制/批量/中断传输,实际上很多时候你可以不用创建 urb,不用对它初始化,不用调用 usb_submit_urb 来提交, USB Core 将这个过程分别封装在了 usb_control_ msg、usb_bulk_ msg 和 usb_interrupt_ msg 这三个函数中,不同的是它们的实现是同步的,会去等待传输完全结束。
  3. HCD最重要的就是drivers/usb/core/hcd.h 中定义的 struct usb_hcd;CONFIG_USB_MON,一个所谓的 USB Monitor,也就是 USB 监视器就会编进内核。这个 Monitor 是用来监视 USB 总线上的底层通信流的,相关的文件都在 drivers/usb/mon 下面。
  4. struct usb_hcd中的kref, USB 主机控制器的引用计数;
  5. 设备进入Configured状态,使用函数usb_get_device_descriptor()先获取设备描述符,接下来就要获得各个配置的配置描述符,函数usb_get_configuration
  6. 数据不管是配置描述符、接口描述符还是端点描述符都挤在一起,所以得想办法将它们给分开,于是用到了 usb_parse_configuration()函数,调用到了usb_parse_configuration、 usb_parse_interface 和 usb_parse_endpoint三个函数。

USB驱动流程

USB状态流程:power>default>address>configured

  1. usb_register_device_driver开始,将usb_generic_driver 注册给系统,usb_generic_driver 和 USB 设备匹配成功后,调用usb_probe_
    device()函数,调用generic_probe()对你的设备进行进一步的审查,从而让设备进入Configured 状态;
  2. Core 配置设备使用的是 message.c 里的 usb_set_configuration 函数
  3. usb_disable_device 函数处于Configured 状 态 了, 退 回 到 Address状态。

USB字符串描述符

字符串描述符的地位仅次于设备/配置/接口/端点四大描述符,那么四大设备必须支持它。而字符串描述符对设备来说则是可选的。
usb_cache_string获得字符串描述符,调用usb_string()

USB-HUB

hub作用

存在只是为了支持更多设备连接到 USB 总线上来

在这里插入图片描述
usb_hub_init()函数初始化hub
第一个函数, usb_alloc_dev(),一个 struct usb_device 结构体指针,申请内存,这个结构体指针可不是为 Hub 准备的,它正是为了 Hub 这个端口所接的设备而申请的,别忘了我们此时此刻的上下文,之所以进入这个循环,是因为我们的 Hub 检测到某个端口有设备连接,所以, Hub驱动就义不容辞地要为该设备做点什么。
第二个函数, usb_set_device_state(),这个函数用来设置设备的状态,在 struct usb_device结构体中,有一个成员 enum usb_device_state state,这一刻会把这个设备的状态设置为USB_STATE_POWERED,即上电状态。
第三个函数, choose_address(),为设备选择一个地址。后面会用实例来查看效果。
第四个函数, hub_port_init(),端口初始化,主要就是前面所讲的获取设备的描述符。
第五个函数, usb_get_status(),这个函数是专门为 Hub 准备的,不是为当前的这个 Hub,而是说当前 Hub 的这个端口上连接的如果又是 Hub,那么和连接普通设备就不一样。
第六个函数, check_highspeed(),不同速度的设备,当然待遇不一样。
第七个函数, usb_new_device()。寻找驱动程序,调用驱动程序的 probe,跟踪这个函数就
能一直到设备驱动程序的 probe()函数的调用。
第八个函数, hub_power_remaining(),电源管理。
查看usb参数/sys/bus/usb/devices/1-1/power,autosuspend 如果设备闲置了 2s,那么它将被自动挂起;level 就是所反映的设备的电源级别,可以为 auto/on/suspend,auto 是最为常见的级别,而 on 就意味着不允许设备进行 autosuspend

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值