【Linux】USB驱动程序

       我们把USB设备插入电脑的时候,比如安卓手机,电脑会弹出“发现XXX设备”并自动或者弹出对话框选择安装驱动程序,这一系列的操作都是USB总线驱动程序实现的,总的来说,USB总线驱动程序负责识别USB设别并为之找到对应的驱动设备。而USB总线驱动程序之所以能够是被USB设备的种类取决于PC与USB设备之间的规范:当USB插入的时候,USB总线驱动程序会发出命令,等待USB设备返回相关信息,USB设备收到命令后会根据规范返回自己的信息。

       那么在USB总线驱动程序识别由USB设备插入之前硬件是如何感知由USB设备插入并且进而告知USB总线驱动程序的呢?

       这就是硬件上的设计了,USB接口由四条线:GND、D+、D-、VCC,在PC的USB接口里D+和D-接着下拉电阻,而在USB设备里D+和D-接着上拉电阻,当设备未接入的时候,PC的USB接口是低电平,当USB设备接入时候,PC的USB接口瞬间被拉高,这样就能够感知有设备被插入。

       每个单板上的USB主机控制器都接有hub用于连接USB,当接上USB设备的时候,硬件就会感知然后产生中断:hub_irq,hub_irq会用kick_khubd唤醒hub产生线程hub_thread,进而发生hub_events,系统上也就感知到USB设别的连接变化hub_port_connect_change,从而初始化hub_port_init(),打印出发现USB设备的语句。

       PC机为了能够区分和管理多个USB设备,USB总线驱动程序会在USB设备刚接入的时候以0的编号与设备进行通信,并为USB设别分配一个全新的编号,后续PC想访问某一USB设备时候,得用新分配的编号与之通信。这些动作都会在hub_port_connect_change这个函数中实现。分配完地址后调用hub_port_init(),在这个函数中使用hub_set_address设置分配好的地址,然后调用usb_get_device_descriptor中获取设备描述符。

       在所有设备都准备好之后,会调用usb_new_device创建一个设备,通过usb_get_configuration()获取所有设备的描述符并解析。

       然后把device放入总线的链表中,接下来的操作跟总线驱动程序一样:从总线的driver链表中去除driver,把usb_interface和usb_driver的id_table一一比较,如果匹配成功则调用driver的probe函数/

        我们来回顾一下USB总线驱动程序的作用:

1、识别设备 ——>分配地址,并告诉USB设备:hub_port_connect_change

                     ——>读取命令来获取设备描述符:usb_get_device_descriptor

2、查找并安装对应的驱动设别程序

3、为usb提供读写函数

       那么如何写一个USB设备驱动程序呢?

  1. 首先分配并设置一个usb_driver结构体并设置结构体中的.id_table、.probe、.disconnect,设置完成后在入口函数中注册。
  2. 在prob函数中:a、分配一个input_dev结构体;b、设置USB能够产生的事件;c、注册input_dev结构体;d、硬件相关的操作:数据传输三要素:源(设备的某个端点)、长度、目的;e、使用这三要素