正文

[转载]USB HID设备驱动程序设计 2006-10-06 11:46:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/embed/19059.html

分享到:

 来源:微计算机信息

摘要:USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。它的出现大大简化了PC机和外围设备的连接过程,使PC机接口的扩展变得更加容易。USB作为近年来计算机和嵌入式领域中的热点,推动了计算机外设的飞速发展。本文介绍了适用于PC的嵌入式操作系统的USB HID设备驱动的设计,并给出了具体的实现方法。
关键词: USB HID设备 PC 嵌入式 驱动程序

从USB 1.1到USB2.0再到目前的USB OTG(On-The-Go),USB在不断自我完善,并走向成熟。USB具有高速度、低成本、低功耗、即插即用和使用维护方便等优点,不仅成为了PC主板上的标准接口,而且成为了所有PC外部设备如键盘、鼠标、显示器、打印机、数码相机等与PC相连的标准协议之一,迅速占领了计算机中、低速外部设备的市场。

USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。USB的拓扑结构中居于核心地位的是Host(也称为主机)。任何一次USB的数据传输都必须由主机来发起和控制,所有的USB外设都只能和主机建立连接,任何两个外设之间或是两个主机之间无法直接通信。而目前,大量的扮演主机角色的是个人电脑PC。

随着USB应用领域的逐渐扩大,对于USB的期望也越来越高。我们希望USB能应用在各种计算机领域中,希望能通过PDA等移动设备直接和USB外设通信,使得USB能应用在没有PC的领域中。

而我们目前所使用的USB移动设备,大多数都是USB的外设,比如USB的移动硬盘、USB接口的数码相机等。所有这些设备都只能在PC上使用,只能通过PC来进行相互的文件和数据交换。

本驱动程序是为完善我们自行设计的嵌入式操作系统,使得它具备能识别USB HID设备的功能而开发的。所使用的编程语言为C语言,并下载到目标机上,通过测试验证可以识别USB HID设备,如USB键盘,USB鼠标等。本文探讨的即是PC上实现USB HID设备驱动的方法。

⒈ HID 设备       驱动简介

为简化USB设备的开发过程,USB提出了设备类的概念。HID设备类,即人机接口设备。典型的HID设备如键盘、鼠标。

所有设备类都必须支持标准USB描述符和标准USB设备请求。如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称为设备类定义描述符和设备类定义请求。另外,一个完整的设备类还将指明其接口和端点的使用方法,如如接口所包含端点的个数、端点的最大数据包长度等。

HID设备既可以是低速设备也可以是全速设备,其典型的数据传输类型为中断IN传输,即它适用于主机接收USB设备发来的小量到中等量的数据。HID具有以下的功能特点:1)适用于传输少量或中量的数据;2)传输的数据具有突发性;3)传输的最大速率有限制;4)无固定的传输率。

HID设备类除支持标准USB描述符外(设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符),还自行定义了3种类描述符,分别为HID描述符(主要用于识别HID设备所包含的其他类描述符)、报告描述符(提供HID设备和主机间交换数据的格式)和物理描述符。一个HID设备只能支持一个HID描述符;可以支持一个或多个报告描述符;物理描述符是可选的,大多数HID设备不需要使用它。

⒉  USB HID设备驱动原理

设备的USB 人机交互设备必须遵循以下的USB开始程序:

1)         插入设备

    USB设备第一次连接到总线时,虽然接上了电源,但是总线仍然没有任何功能,一定要到重置总线为止才可以开始运作。注意,一旦USB在D端使用了1.5kΩ的提升电阻,就会立即通知总线的集线器,有一个低速设备(1.5Mb/s)刚被连接上。而程序以设备地址0开始运行。

   设备插上时,电源打开重置的过程: 重置->执行初始设置并出发总线重置中断->位于中止模式下知道总线被重置为止->等待设备列举->执行程序循环

2)         总线重置

     接着主机将会辨认新的USB设备并重置它。在总线重置过程中,除了设定堆栈指针外,也出发所有被使用到的中断。(总线重置的中断服务程序ISR功能)

3)        设备列举。

   主机会负责检测与设定所有连接至根集线器的设备,辨别与设定一个USB设备的程序,称为设备列举。主机首先会送出SETUP封包以读取默认地址0的设备描述符。当收到描述符后,主机将会指定新的USB地址给设备。从设备所返回的信息中,主机就会知道设备所支持的数据端点的数量。完成设备列举。

4)        数据捕捉与转换

   这里以键盘为例,在固件中将以周期性的方式,把扫描的形式写入到扫描矩阵的列I/O端口伤(接口2),并且在行I/O接口伤读取结果值以决定哪个键被按下了。通过键盘扫描后所得到的数据码,可以使用中断传输以端点1来传送给主机。设备就将键盘的8B数据放置在IN令牌包随后跟随的资料封包的数据域位内,再返回给主机。

   当含有LED的按键(如NumLock ,Caps lock 与 Scroll lock)被按下或放开时,主机就会送出含有设定报告(Set_Report)要求的SETUP封包,通过控制传输传至设备的端口0上。

⒊ USB HID设备驱动程序设计的流程说明

USB总线与设备间的交互都是通过USBD即USB总线驱动程序完成。USBD起着中间桥梁作用,解释USB设备类驱动程序发来的命令并将其划分为一系列的USB事务,然后发送给USB主控制器驱动程序。

具体流程是插入一个USB设备后,主机检测到有设备接入,USBD就从链表中查找匹配HID设备类。为每一个接入的HID设备驱动建立一个对应的USB_HID_SIO_CHAN结构来对该HID设备驱动进行管理。这里的USB_HID_SIO_CHAN结构是USBD为每一个HID设备所分配的一个关键的内部数据结构。此后由USB主控制器驱动程序来负责硬件底层的驱动。

    而HID设备移除时,会调用函数usbHIDDeviceAttachCallback() ,这时先判断是否有与该HID设备绑定的结构,有则清除该结构。

   成功注册一个没有被初始化的USB HID设备的程序流程如下:

⒋ USB HID设备驱动程序的实现

因为键盘和鼠标同为HID设备,具体驱动程序实现极为相似,这里仅以键盘的驱动程序实现为例,给出最主要的函数说明:

1. STATUS  usbKeyboardDevInit()

功能:键盘初始化函数,依次初始化与USBD的连接,和其他所需的内部资源。

返回值:操作成功返回OK,失败返回ERROR

注意:在调用usbKeyboardDevInit ( )前,必须保证USBD层已经初始化-至少调用了usbdInitialize().还要保证至少一个USB HCD(USB Host Controller Driver)连接到了USBD层。

2.STATUS  usbdClientRegister

    (

    T_BYTE* pClientName,                    /* Client name */

    pUSBD_CLIENT_HANDLE pClientHandle      /* Client hdl returned by USBD */

    )

功能:向USBD注册一个新客户(键盘,鼠标等)

返回值:操作成功返回OK,失败返回ERROR

3。STATUS usbdDynamicAttachRegister

 (

    USB_KBD_ATTACH_CALLBACK callback,    /* new callback to be registered */

    T_VOID* arg                  /* user-defined arg to callback */

    )

功能:每次插上或者移除键盘时,都会由回调函数调用,

该函数实现USB设备动态插拔。

返回值:操作成功返回OK,失败返回ERROR

4. T_MODULE T_VOID usbKeyboardAttachCallback

(

    USBD_NODE_ID nodeId,

    T_UHWORD attachAction,

    T_UHWORD configuration,

    T_UHWORD interface,

    T_UHWORD deviceClass,

    T_UHWORD deviceSubClass,

    T_UHWORD deviceProtocol

    )

功能:每次插上或者移除键盘时由USBD调用

注意:有可能同一个设备会多次插拔,对这种情况USBD会忽略除第一次外的callback

返回值:无

5. T_ MODULE pUSB_KBD_SIO_CHAN createSioChan

    (

    USBD_NODE_ID nodeId,

    T_UHWORD configuration,

    T_UHWORD interface

    )

功能:给USBD分配的nodeId创建一个新的USB_KBD_SIO_CHAN结构

返回值:成功返回指向该结构的指针,失败返回NULL

6. T_MODULE T_BOOL configureSioChan

    (

    pUSB_KBD_SIO_CHAN pSioChan

)

功能:配置键盘信息

返回值:成功返回TRUE,失败返回FALSE

7. T_MODULE T_VOID usbKeyboardIrpCallback

    (

    T_VOID* p        /* completed IRP */

)

功能: IRP完成或取消时调用

返回值:无

8. T_MODULE T_VOID interpKbdReport

    (

    pUSB_KBD_SIO_CHAN pSioChan

    )

功能:解释USB键盘的BOOT REPORT,得到键盘扫描码。

返回值:无

⒌ USB HID设备的数据获取方式

必须注意的是这里鼠标和键盘的处理方式完全不一样。

键盘是以轮询方式获得数据。使用如下的函数:

T_MODULE T_WORD usbKeyboardPollInput

   (

    SIO_CHAN *pChan,

        T_BYTE *thisChar          /*按键值*/

    )

返回值:收到字符返回OK;

设备错误返回EIO;

如果输入缓冲为空返回EAGAIN;

设备只能在中断模式下工作返回ENOSYS.

所获取的按键值都将存放在给键盘分配的对应的USB_KBD_SIO_CHAN结构里的inQueue [KBD_Q_DEPTH]。

   而鼠标驱动程序的设计则是在IRP成功返回的时候,直接由函数usbMouseIrpCallback()通过调用函数interpMseReport()取得USB_MSE_SIO_CHAN结构结构里的pReport项。该pReport项即包含的是鼠标按键的状态。

 

随着USB2.0的发布,USB越来越流行,它已经成为绝大多数PC外设上的标准接口。我们看到,USB的应用开发也在不断发展,不断完善。因此,研究USB技术将具有极大的应用背景和市场前景。

 

参考文献:

[1.]    王成儒,李英伟.USB2.0原理与工程开发.第一版.北京:国防工业出版社,2004

[2.]    Universal Serial Bus Specification 1.1 .http://www.usb.org/

[3.]    http://www.usb.org/

[4.]    http://www.usbing.net

阅读(8309) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册