请选择 进入手机版 | 继续访问电脑版

Linux设备驱动开发---USB主机(控制器)与设备驱动(一)

[复制链接]
密战 发表于 2021-1-1 10:30:55 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
USB主机控制器与设备驱动---主机侧



一、Linux USB驱动条理

1、USB驱动(主机侧)

  1. NOTE:在Linux 系统中,USB驱动可以从两个角度去观察,一个角度是主机侧,一个角度是设备侧。
复制代码
  1. 从主机侧角度看,USB驱动从底到上依次是:USB主机控制器硬件层 --> USB主机控制器驱动层 --> USB焦点层 --> USB设备驱动层
复制代码

  1. USB主机控制器驱动层:控制插入的USB设备;USB焦点层:负责USB驱动管理和协议处理。                        ---界说一些数据结构、宏和功能函数,分别向上层(USB设备驱动层)和下层(USB主机控制器驱动层)        提供编程接口;                        ---通过全局变量维护整个系统的USB信息;                        ---完成设备热拔插控制、总线数据传输控制等;USB设备驱动层:控制USB设备和主机的通信;
复制代码
2、USB的逻辑组合(4个条理)


  1. 设备(device):包罗一个/多个设置。
复制代码
  1.                 设备形貌符: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));
复制代码
  1. 设置(config):差别的设置使设备表现出差别的功能组合。                        ---每个设置可以有多个接口,可由多个接口组成。
复制代码
  1.                 设置形貌符:struct usb_config_descriptor {                                                        __u8  bLength;                                                        __u8  bDescriptorType;                                                                        __le16 wTotalLength;                                                        __u8  bNumInterfaces;                                                        __u8  bConfigurationValue;                                                        __u8  iConfiguration;                                                        __u8  bmAttributes;                                                        __u8  bMaxPower;                                                } __attribute__ ((packed));
复制代码
  1. 接口(interface):代表一个根本功能,是USB 设备驱动步伐控制的对象。                                  ---设置中的所有接口可以同时有效,并可被差别的驱动步伐连接。                                  ---接口可以有备用接口,以提供差别质量的服务参数。                                  ---接口是端点的搜集。
复制代码
  1.                 接口形貌符:struct usb_interface_descriptor {                                                                __u8  bLength;                                                                __u8  bDescriptorType;                                                                                __u8  bInterfaceNumber;                                                                __u8  bAlternateSetting;                                                                __u8  bNumEndpoints;                                                                __u8  bInterfaceClass;                                                                __u8  bInterfaceSubClass;                                                                __u8  bInterfaceProtocol;                                                                __u8  iInterface;                                                        } __attribute__ ((packed));
复制代码
  1. 端点(endpoint):USB通信的根本形式(主机只能通过端点与设备举行通信,以使用设备的功能)。                                  ---USB系统中每一个端点都有惟一的所在,由设备所在和端点号给出的。                                  ---每个端点的属性包罗传输方式、总线访问频率、带宽、端点号和数据包的最大容量等。                                  ---每个USB 端点只能在一个方向承载数据,或主机到设备(输出端点),或设备到主机(输入端点)。                                  ---端点0(控制端点,用于设备初始化参数),只要设备连接到USB而且上电端点0就可以被访问。
复制代码
  1.                 端点形貌符: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下令检察设备详细信息:

二、USB主机(控制器)驱动

1、主机控制器规格

  1. OHCI:Open Host Controller Interface.UHCI:Universal Host Controller Interface. EHCI:Enhance(增强型),主要用于USB2.0,兼容OHCI和UHCI;xHCI:eXtensible(可扩展的),主要用于USB3.0,兼容EHCI、UHCI及OHCI;
复制代码
2、主机控制器的相关结构

  1. usb_hcd结构体:形貌USB主机控制器驱动。
复制代码
  1.                 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))));                        };
复制代码
  1. hc_driver结构体:用于操纵主机控制器。
复制代码
  1.                 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);                                ...                                ...                        };
复制代码
  1. 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);
复制代码
  1. 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);
复制代码
3、实例:xHCI主机控制器驱动

  1. 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;                        }
复制代码
三、USB设备驱动(详解)

USB主机(控制器)与设备驱动(三)
四、实例

  1. 4.1 USB串口驱动:drivers/usb/serial/usb-serial.c
复制代码
  1. 4.2 USB键盘驱动:drivers/hid/usbhid/usbkbd.c
复制代码
来源:https://blog.csdn.net/tpmamba/article/details/111768813
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )