TM4C USB-HID了解学习(一)

HID设备类驱动程序USB人机接口类设备类是一个非常通用的体系结构,用于支持各种各样的输入/输出设备,而不管它们是否真正处理“人机接口”。尽管该规范通常是在键盘、鼠标和操纵杆的上下文中考虑的,但它实际上可以涵盖提供用户控制或数据收集功能的任何设备。HID设备和主机之间的通信是通过HID报告描述符中设备定义的“报告”结构的集合进行的,主机可以查询这些结构。报告是为设备输入到主机的通信以及主机的输出和功能选择而定义的。除了基本架构提供的灵活性外,HID设备还受益于对类的优秀操作系统支持,这意味着不需要编写驱动程序,对于键盘和操纵杆等标准设备,设备可以连接到主机系统并与之一起操作,而无需任何新的主机软件必须被写下来。即使对于非标准或特定于供应商的HID设备,操作系统支持也使编写主机端软件比使用特定于供应商的类开发设备简单得多。尽管有这些优点,但使用HID有一个缺点。接口的可传输数据量有限,因此不适合期望使用高百分比USB总线带宽的设备使用。对于设备支持的每个报表,设备的最大数据限制为每秒64KB。如有必要,可以使用多个报告,但需要高带宽设备最好使用支持大容量而不是中断端点的类(例如CDC或通用大容量设备类)来实现。

TM4C USB-HID了解学习(一)除了端点0之外,此设备类还使用一个或两个端点(可选)。端点中的一个中断将HID输入报告从设备传送到主机。从主机到设备的输出和功能报告通常通过端点0进行,但是期望高主机到设备数据速率的设备可以选择提供独立的中断输出端点来进行这些操作。端点0承载标准USB请求,还隐藏特定的描述符请求。本文后面描述的HID鼠标和键盘设备API都是在HID设备类驱动程序API之上实现的。

 

 

HID设备类事件HID设备类驱动程序将以下事件发送到应用程序回调函数:

接收频道事件

USB_EVENT_CONNECTED
USB_EVENT_DISCONNECTED
USB_EVENT_RX_AVAILABLE
USB_EVENT_ERROR
USB_EVENT_SUSPEND
USB_EVENT_RESUME
USBD_HID_EVENT_IDLE_TIMEOUT
USBD_HID_EVENT_GET_REPORT_BUFFER
USBD_HID_EVENT_GET_REPORT
USBD_HID_EVENT_SET_PROTOCOL
USBD_HID_EVENT_GET_PROTOCOL
USBD_HID_EVENT_SET_REPORT
USBD_HID_EVENT_REPORT_SENT

注意:如果MCU的PB1/USB0VBUS引脚连接到固定的+5伏,而不是直接连接到USB连接器上的VBUS引脚,或者如果USB控制器配置为强制设备模式,则不会向应用程序报告USB事件断开连接事件。

发送通道事件

USB_EVENT_TX_COMPLETE

使用HID设备类驱动程序要使用HID设备类驱动程序向应用程序添加USB HID接口,请执行以下步骤。

将以下头文件添加到要支持USB的源文件中:

#include“src/USB.h”

#include“usblib/usblib.h”

#include“usblib/usbhid.h”

#include“usblib/device/usbdevice.h”

#include“usblib/device/usbdhid.h”

定义用于描述新设备到主机系统的各种功能的字符串表。以下是从usb dev_鼠标示例应用程序获取的字符串表。编辑实际的字符串以适合您的应用程序,并注意确保同时更新每个描述符的长度字段(第一个字节),以正确反映字符串和描述符头的长度。所包含的字符串数量因设备而异,但必须至少为5个。HID报告描述符可能引用字符串id,如果设备的描述符包含这些id,则需要其他字符串。此外,如果字符串描述符0中报告了多种语言,则必须确保每种语言都有可用的字符串,并且所有语言1字符串在所有语言2字符串之前的一个块中按顺序出现,依此类推。

//*****************************************************************************
//
// The languages supported by this device.
//
//*****************************************************************************
const uint8_t g_pui8LangDescriptor[] =
{
4,
USB_DTYPE_STRING,
USBShort(USB_LANG_EN_US)
};
//*****************************************************************************
//
// The manufacturer string.
//
//*****************************************************************************
const uint8_t g_pui8ManufacturerString[] =
{
(17 + 1)*2,
USB_DTYPE_STRING,
’T’, 0, ’e’, 0, ’x’, 0, ’a’, 0, ’s’, 0, ’ ’, 0, ’I’, 0, ’n’, 0, ’s’, 0,
’t’, 0, ’r’, 0, ’u’, 0, ’m’, 0, ’e’, 0, ’n’, 0, ’t’, 0, ’s’, 0,
};
//*****************************************************************************
//
// The product string.
//
//*****************************************************************************
const uint8_t g_pui8ProductString[] =
{
(13 + 1)*2,
USB_DTYPE_STRING,
’M’, 0, ’o’, 0, ’u’, 0, ’s’, 0, ’e’, 0, ’ ’, 0, ’E’, 0, ’x’, 0, ’a’, 0,
’m’, 0, ’p’, 0, ’l’, 0, ’e’, 0
};
//*****************************************************************************
//
// The serial number string.
//
//*****************************************************************************
const uint8_t g_pui8SerialNumberString[] =
{
(8 + 1)*2,
USB_DTYPE_STRING,
’1’, 0, ’2’, 0, ’3’, 0, ’4’, 0, ’5’, 0, ’6’, 0, ’7’, 0, ’8’, 0
};
//*****************************************************************************
//
// The interface description string.
//
//*****************************************************************************
const uint8_t g_pui8HIDInterfaceString[] =
{
(19 + 1)*2,
USB_DTYPE_STRING,
’H’, 0, ’I’, 0, ’D’, 0, ’ ’, 0, ’M’, 0, ’o’, 0, ’u’, 0, ’s’, 0,
’e’, 0, ’ ’, 0, ’I’, 0, ’n’, 0, ’t’, 0, ’e’, 0, ’r’, 0, ’f’, 0,
’a’, 0, ’c’, 0, ’e’, 0
};
//*****************************************************************************
//
// The configuration description string.
//
//*****************************************************************************
const uint8_t g_pui8ConfigString[] =
{
(23 + 1)*2,
USB_DTYPE_STRING,
’H’, 0, ’I’, 0, ’D’, 0, ’ ’, 0, ’M’, 0, ’o’, 0, ’u’, 0, ’s’, 0,
’e’, 0, ’ ’, 0, ’C’, 0, ’o’, 0, ’n’, 0, ’f’, 0, ’i’, 0, ’g’, 0,
’u’, 0, ’r’, 0, ’a’, 0, ’t’, 0, ’i’, 0, ’o’, 0, ’n’, 0
};
//*****************************************************************************
//
// The descriptor string table.
//
//*****************************************************************************
const uint8_t*const g_pStringDescriptors[] =
{
g_pLangDescriptor,
g_pManufacturerString,
g_pProductString,
g_pSerialNumberString,
g_pHIDInterfaceString,
g_pConfigString
};
#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /  \
sizeof(uint8_t*))

在RAM中定义一个tHIDReportIdle结构数组,为设备支持的每个输入报告定义一个条目。初始化每个条目中的ucDuration4mS和ucReportID字段,以设置每个输入报告的默认空闲报告时间。请注意,ucDuration4mS以4mS为增量定义空闲时间,该时间用于USB HID Set_idle和Get_idle请求。这些结构中定义的时间用于确定给定的输入报告在没有任何设备状态更改的情况下重新发送给主机的频率。例如,支持IDs 1和IDs 2的两个输入报告的设备可以如下初始化阵列:

tHIDReportIdle g_psReportIdle[2] =
{
{ 125, 1, 0, 0 }, // Report 1 polled every 500mS (4*125).
{  0, 2, 0, 0}  // Report 2 is not polled (0mS timeout)
};

定义tUSBDHIDDevice结构并根据应用程序的需要初始化所有字段。

将接收事件处理程序函数Y ourusbreceiveventcallback添加到应用程序中,注意处理需要特定响应的所有消息。对于HID设备类,应用程序必须处理以下接收回调事件:

USB_EVENT_RX_AVAILABLE
• USBD_HID_EVENT_IDLE_TIMEOUT
• USBD_HID_EVENT_GET_REPORT_BUFFER
• USBD_HID_EVENT_GET_REPORT
• USBD_HID_EVENT_SET_PROTOCOL (for BIOS protocol devices)
• USBD_HID_EVENT_GET_PROTOCOL (for BIOS protocol devices)
• USBD_HID_EVENT_SET_REPORT

尽管不必处理其他事件,但通常需要连接USB事件和断开USB事件,因为这些事件指示主机何时连接或断开连接,并允许应用程序根据需要刷新任何缓冲区或重置状态。当主机断开连接时发送数据的尝试将被忽略并导致错误。

向应用程序中添加传输事件处理程序函数Y ourUSBT ransmitEventCallback,并使用usbu event_TX_COMPLETE指示何时可以计划传输新报告。

在传输报表时,将忽略通过USBDHIDReportWrite()发送另一个报表的尝试,并导致错误。从主初始化函数调用HID设备类驱动程序初始化函数来配置USB控制器并将设备放置在总线上。

pvDevice = USBDHIDMouseInit(0, &g_sHIDMouseDevice);

假设返回的pvDevice不为空,则设备现在可以与USB主机通信。一旦主机连接,您的控制事件处理程序将被发送到USB事件连接,并且第一个输入报告可以使用USBDHIDReportWrite()发送到主机,并且一旦通过传输事件处理程序接收到USB事件发送完成,就会发送以下数据包。