当前位置:文档之家› USB HID 设备驱动程序设计

USB HID 设备驱动程序设计

USB HID 设备驱动程序设计引自:/hudaweikevin/archive/2009/11/02/4756394.aspx摘要: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,失败返回ERROR3。

STATUS usbdDynamicAttachRegister(USB_KBD_ATTACH_CALLBACK callback, /* new callback to be registered */ T_VOID* arg /* user-defined arg to callback */)功能:每次插上或者移除键盘时,都会由回调函数调用,该函数实现USB设备动态插拔。

返回值:操作成功返回OK,失败返回ERROR4.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结构返回值:成功返回指向该结构的指针,失败返回NULL6.T_MODULE T_BOOL configureSioChan(pUSB_KBD_SIO_CHAN pSioChan)功能:配置键盘信息返回值:成功返回TRUE,失败返回FALSE7.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外设上的标准接口。

相关主题