赞
踩
NOTE:在Linux 系统中,USB驱动可以从两个角度去观察,一个角度是主机侧,一个角度是设备侧。
从主机侧角度看,USB驱动从底到上依次是:
USB主机控制器硬件层 --> USB主机控制器驱动层 --> USB核心层 --> USB设备驱动层
USB主机控制器驱动层:控制插入的USB设备;
USB核心层:负责USB驱动管理和协议处理。
---定义一些数据结构、宏和功能函数,分别向上层(USB设备驱动层)和下层(USB主机控制器驱动层) 提供编程接口;
---通过全局变量维护整个系统的USB信息;
---完成设备热拔插控制、总线数据传输控制等;
USB设备驱动层:控制USB设备和主机的通信;
设备(device):包含一个/多个配置。
设备描述符: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));
配置(config):不同的配置使设备表现出不同的功能组合。
---每个配置可以有多个接口,可由多个接口组成。
配置描述符:struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
} __attribute__ ((packed));
接口(interface):代表一个基本功能,是USB 设备驱动程序控制的对象。
---配置中的所有接口可以同时有效,并可被不同的驱动程序连接。
---接口可以有备用接口,以提供不同质量的服务参数。
---接口是端点的汇集。
接口描述符:struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
端点(endpoint):USB通信的基本形式(主机只能通过端点与设备进行通信,以使用设备的功能)。
---USB系统中每一个端点都有惟一的地址,由设备地址和端点号给出的。
---每个端点的属性包含传输方式、总线访问频率、带宽、端点号和数据包的最大容量等。
---每个USB 端点只能在一个方向承载数据,或主机到设备(输出端点),或设备到主机(输入端点)。
---端点0(控制端点,用于设备初始化参数),只要设备连接到USB并且上电端点0就可以被访问。
端点描述符: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));
实例:在linux机器上插入U盘/读卡器,利用lsusb -v命令查看设备详细信息:
OHCI:Open Host Controller Interface.
UHCI:Universal Host Controller Interface.
EHCI:Enhance(增强型),主要用于USB2.0,兼容OHCI和UHCI;
xHCI:eXtensible(可扩展的),主要用于USB3.0,兼容EHCI、UHCI及OHCI;
usb_hcd结构体:描述USB主机控制器驱动。
struct usb_hcd { /* housekeeping */ struct usb_bus self; /* hcd is-a bus */ struct kref kref; /* reference counter */ const char *product_desc; /* product/vendor string */ int speed; /* Speed for this roothub. char irq_descr[24]; /* driver + bus # */ struct timer_list rh_timer; /* drives root-hub polling */ struct urb *status_urb; /* the current status urb */ /* * hardware info/state */ const struct hc_driver *driver; /* hw-specific hooks(特定硬件的钩子函数) */ /* * OTG and some Host controllers need software interaction with phys; * other external phys should be software-transparent */ struct usb_phy *usb_phy; struct phy *phy; ... ... int state; # define __ACTIVE 0x01 # define __SUSPEND 0x04 # define __TRANSIENT 0x80 ... /* The HC driver's private data is stored at the end of * this structure. */ unsigned long hcd_priv[0] __attribute__ ((aligned(sizeof(s64)))); };
hc_driver结构体:用于操作主机控制器。
struct hc_driver { const char *description; /* "ehci-hcd" etc */ const char *product_desc; /* product/vendor string */ size_t hcd_priv_size; /* size of private data */ /* irq handler */ irqreturn_t (*irq) (struct usb_hcd *hcd); int flags; #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ ... /* called to init HCD and root hub */ int (*reset) (struct usb_hcd *hcd); int (*start) (struct usb_hcd *hcd); /* NOTE: these suspend/resume calls relate to the HC as * a whole, not just the root hub; they're for PCI bus glue. */ /* called after suspending the hub, before entering D3 etc */ int (*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup); /* called after entering D0 (etc), before resuming the hub */ int (*pci_resume)(struct usb_hcd *hcd, bool hibernated); /* cleanly make HCD stop writing memory and doing I/O */ void (*stop) (struct usb_hcd *hcd); /* shutdown HCD */ void (*shutdown) (struct usb_hcd *hcd); /* return current frame number */ int (*get_frame_number) (struct usb_hcd *hcd); /* manage i/o requests, device state */ int (*urb_enqueue)(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); int (*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb, int status); ... ... };
hcd的创建、添加和移除:
struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name);
int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags);
void usb_remove_hcd(struct usb_hcd *hcd);
xhci主机控制器 1)xhci_hcd结构体:drivers/usb/host/xhci.h struct xhci_hcd { struct usb_hcd *main_hcd; struct usb_hcd *shared_hcd; /* glue to PCI and HCD framework */ struct xhci_cap_regs __iomem *cap_regs; struct xhci_op_regs __iomem *op_regs; struct xhci_run_regs __iomem *run_regs; struct xhci_doorbell_array __iomem *dba; /* Our HCD's current interrupter register set */ struct xhci_intr_reg __iomem *ir_set; /* Cached register copies of read-only HC data */ __u32 hcs_params1; ... spinlock_t lock; /* packed release number */ u8 sbrn; u16 hci_version; ... ... ... }; 2)usb_hcd和xhci_hcd的相互转换: struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd); struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci); 3)xHCI主机控制器的初始化: int xhci_init(struct usb_hcd *hcd); 4)xHCI主机控制器的开启、停止、复位: int xhci_start(struct xhci_hcd *xhci); void xhci_stop(struct usb_hcd *hcd); int xhci_reset(struct xhci_hcd *xhci);
xHCI主机控制器驱动 drivers/usb/host/xhci.c static const struct hc_driver xhci_hc_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", .hcd_priv_size = sizeof(struct xhci_hcd), /* * generic hardware linkage */ .irq = xhci_irq, .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, /* * basic lifecycle operations */ .reset = NULL, /* set in xhci_init_driver() */ .start = xhci_run, .stop = xhci_stop, .shutdown = xhci_shutdown, /* * managing i/o requests and associated device resources */ .urb_enqueue = xhci_urb_enqueue, .urb_dequeue = xhci_urb_dequeue, .alloc_dev = xhci_alloc_dev, .free_dev = xhci_free_dev, ... ... /* * scheduling support */ .get_frame_number = xhci_get_frame, /* * root hub support */ .hub_control = xhci_hub_control, .hub_status_data = xhci_hub_status_data, .bus_suspend = xhci_bus_suspend, .bus_resume = xhci_bus_resume, /* * call back when device connected and addressed */ .update_device = xhci_update_device, .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, .find_raw_port_number = xhci_find_raw_port_number, .submit_single_step_set_feature = xhci_submit_single_step_set_feature, }; int xhci_run(struct usb_hcd *hcd) { u32 temp; u64 temp_64; int ret; struct xhci_hcd *xhci = hcd_to_xhci(hcd); /* Start the xHCI host controller running only after the USB 2.0 roothub * is setup. */ hcd->uses_new_polling = 1; if (!usb_hcd_is_primary_hcd(hcd)) return xhci_run_finished(xhci); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_run"); ret = xhci_try_enable_msi(hcd); ... ... temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp_64 &= ~ERST_PTR_MASK; ... temp = readl(&xhci->ir_set->irq_control); temp &= ~ER_IRQ_INTERVAL_MASK; /* * the increment interval is 8 times as much as that defined * in xHCI spec on MTK's controller */ temp |= (u32) ((xhci->quirks & XHCI_MTK_HOST) ? 20 : 160); writel(temp, &xhci->ir_set->irq_control); /* Set the HCD state before we enable the irqs */ temp = readl(&xhci->op_regs->command); temp |= (CMD_EIE); ... writel(temp, &xhci->op_regs->command); temp = readl(&xhci->ir_set->irq_pending); ... writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); xhci_print_ir_set(xhci, 0); if (xhci->quirks & XHCI_NEC_HOST) { struct xhci_command *command; command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); ... xhci_queue_vendor_command(xhci, command, 0, 0, 0, TRB_TYPE(TRB_NEC_GET_FW)); } ... return 0; }
4.1 USB串口驱动:drivers/usb/serial/usb-serial.c
4.2 USB键盘驱动:drivers/hid/usbhid/usbkbd.c
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。