HID 是Single Interface Device 信号接口设备。
USB HID类是比较大的一个类,HID类设备属于人机交互操作的设备。用于控制计算机操作的一些方面,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球、电话拨号设备、VCR遥控等等设备。另外,使用HID设备的一个好处就是,操作系统自带了HID类的驱动程序,而用户无需去开发很麻烦的驱动程序,只要直接使用API调用即可完成通信。所以很多简单的USB设备,喜欢枚举成HID设备,这样就可以不用安装驱动而直接使用。
本程是一个通用的HID例子,在开发板上按键盘可以在计算机那边显示。
在ui.c中是用户定义的操作:
#include <asf.h>
#include "ui.h"
/** HID report buffer */
static uint8_t ui_hid_report[UDI_HID_REPORT_OUT_SIZE];
void ui_init(void)
{
/* Initialize LEDs */
LED_Off(LED0);
LED_Off(LED1);
}
void ui_powerdown(void)
{
LED_Off(LED0);
LED_Off(LED1);
}
void ui_wakeup_enable(void)
{
}
void ui_wakeup_disable(void)
{
}
void ui_wakeup(void)
{
LED_On(LED0);
}
void ui_process(uint16_t framenumber)
{
bool b_btn_state;
static bool btn0_last_state = false;
static bool btn1_last_state = false;
static uint8_t cpt_sof = 0;
if ((framenumber % 1000) == 0) {
LED_On(LED1);
}
if ((framenumber % 1000) == 500) {
LED_Off(LED1);
}
/* Scan process running each 40ms */
cpt_sof++;
if (cpt_sof < 40) {
return;
}
cpt_sof = 0;
/* Scan push buttons 1 and 2 */
b_btn_state = !ioport_get_pin_level(GPIO_PUSH_BUTTON_1);
if (b_btn_state != btn0_last_state) {
ui_hid_report[0]=b_btn_state;
udi_hid_generic_send_report_in(ui_hid_report);
btn0_last_state = b_btn_state;
}
b_btn_state = !ioport_get_pin_level(GPIO_PUSH_BUTTON_2);
if (b_btn_state != btn1_last_state) {
ui_hid_report[0]=b_btn_state;
udi_hid_generic_send_report_in(ui_hid_report);
btn1_last_state = b_btn_state;
}
}
void ui_led_change(uint8_t *report)
{
if (report[0]=='1') {
/* A led must be on */
switch(report[1]) {
case '1':
LED_On(LED2);
break;
}
} else {
/* A led must be off */
switch(report[1]) {
case '1':
LED_Off(LED2);
break;
}
}
}
/**
* \defgroup UI User Interface
*
* Human interface on SAM4E-EK:
* - Led 0 (D2) is on when USB is wakeup
* - Led 1 (D3) blinks when USB host has checked and enabled HID generic interface
* - Led 2 (D4) is linked on HID events LED1
* - Event buttons are linked to push button 1 (BP2) and push button 2 (BP3)
*
*/
在config_usb.h中定义参数:
#ifndef _CONF_USB_H_
#define _CONF_USB_H_
#include "compiler.h"
/**
* USB Device Configuration
* @{
*/
//! Device definition (mandatory)
#define USB_DEVICE_VENDOR_ID USB_VID_ATMEL
#define USB_DEVICE_PRODUCT_ID USB_PID_ATMEL_ASF_HIDGENERIC
#define USB_DEVICE_MAJOR_VERSION 1
#define USB_DEVICE_MINOR_VERSION 0
#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA)
#define USB_DEVICE_ATTR \
(USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
// (USB_CONFIG_ATTR_SELF_POWERED)
// (USB_CONFIG_ATTR_BUS_POWERED)
//! USB Device string definitions (Optional)
#define USB_DEVICE_MANUFACTURE_NAME "ATMEL ASF"
#define USB_DEVICE_PRODUCT_NAME "HID Generic"
// #define USB_DEVICE_SERIAL_NAME "12...EF"
/**
* Device speeds support
* @{
*/
//! To define a Low speed device
//#define USB_DEVICE_LOW_SPEED
//! To authorize the High speed
#if (UC3A3||UC3A4)
//#define USB_DEVICE_HS_SUPPORT
#elif (SAM3XA||SAM3U)
//#define USB_DEVICE_HS_SUPPORT
#endif
//@}
/**
* USB Device Callbacks definitions (Optional)
* @{
*/
#define UDC_VBUS_EVENT(b_vbus_high)
#define UDC_SOF_EVENT() main_sof_action()
#define UDC_SUSPEND_EVENT() main_suspend_action()
#define UDC_RESUME_EVENT() main_resume_action()
//! Mandatory when USB_DEVICE_ATTR authorizes remote wakeup feature
#define UDC_REMOTEWAKEUP_ENABLE() main_remotewakeup_enable()
#define UDC_REMOTEWAKEUP_DISABLE() main_remotewakeup_disable()
//! When a extra string descriptor must be supported
//! other than manufacturer, product and serial string
// #define UDC_GET_EXTRA_STRING()
//@}
//@}
/**
* USB Interface Configuration
* @{
*/
/**
* Configuration of HID Generic interface
* @{
*/
//! Interface callback definition
#define UDI_HID_GENERIC_ENABLE_EXT() main_generic_enable()
#define UDI_HID_GENERIC_DISABLE_EXT() main_generic_disable()
#define UDI_HID_GENERIC_REPORT_OUT(ptr) ui_led_change(ptr)
#define UDI_HID_GENERIC_SET_FEATURE(report) main_hid_set_feature(report)
//! Sizes of I/O reports
#define UDI_HID_REPORT_IN_SIZE 8
#define UDI_HID_REPORT_OUT_SIZE 8
#define UDI_HID_REPORT_FEATURE_SIZE 4
//! Sizes of I/O endpoints
#define UDI_HID_GENERIC_EP_SIZE 8
描述符在udi_hid_generic.h说明:
#ifndef _UDI_HID_GENERIC_H_
#define _UDI_HID_GENERIC_H_
#include "conf_usb.h"
#include "usb_protocol.h"
#include "usb_protocol_hid.h"
#include "udc_desc.h"
#include "udi.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup udi_hid_generic_group_udc
* @{
*/
//! Global structure which contains standard UDI API for UDC
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_generic;
//@}
/**
* \ingroup udi_hid_generic_group
* \defgroup udi_hid_generic_group_desc USB interface descriptors
*
* The following structures provide predefined USB interface descriptors.
* It must be used to define the final USB descriptors.
*/
//@{
//! Interface descriptor structure for HID generic
typedef struct {
usb_iface_desc_t iface;
usb_hid_descriptor_t hid;
usb_ep_desc_t ep_in;
usb_ep_desc_t ep_out;
} udi_hid_generic_desc_t;
//! Report descriptor for HID generic
typedef struct {
uint8_t array[53];
} udi_hid_generic_report_desc_t;
//! By default no string associated to this interface
#ifndef UDI_HID_GENERIC_STRING_ID
#define UDI_HID_GENERIC_STRING_ID 0
#endif
//! Content of HID generic interface descriptor for all speed
#define UDI_HID_GENERIC_DESC {\
.iface.bLength = sizeof(usb_iface_desc_t),\
.iface.bDescriptorType = USB_DT_INTERFACE,\
.iface.bInterfaceNumber = UDI_HID_GENERIC_IFACE_NUMBER,\
.iface.bAlternateSetting = 0,\
.iface.bNumEndpoints = 2,\
.iface.bInterfaceClass = HID_CLASS,\
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
.iface.bInterfaceProtocol = HID_PROTOCOL_GENERIC,\
.iface.iInterface = UDI_HID_GENERIC_STRING_ID,\
.hid.bLength = sizeof(usb_hid_descriptor_t),\
.hid.bDescriptorType = USB_DT_HID,\
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
.hid.wDescriptorLength = LE16(sizeof(udi_hid_generic_report_desc_t)),\
.ep_in.bLength = sizeof(usb_ep_desc_t),\
.ep_in.bDescriptorType = USB_DT_ENDPOINT,\
.ep_in.bEndpointAddress = UDI_HID_GENERIC_EP_IN,\
.ep_in.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep_in.wMaxPacketSize = LE16(UDI_HID_GENERIC_EP_SIZE),\
.ep_in.bInterval = 4,\
.ep_out.bLength = sizeof(usb_ep_desc_t),\
.ep_out.bDescriptorType = USB_DT_ENDPOINT,\
.ep_out.bEndpointAddress = UDI_HID_GENERIC_EP_OUT,\
.ep_out.bmAttributes = USB_EP_TYPE_INTERRUPT,\
.ep_out.wMaxPacketSize = LE16(UDI_HID_GENERIC_EP_SIZE),\
.ep_out.bInterval = 4,\
}
//@}
/**
* \ingroup udi_hid_group
* \defgroup udi_hid_generic_group USB Device Interface (UDI) for Human Interface Device (HID) Generic Class
*
* Common APIs used by high level application to use this USB class.
*
* See \ref udi_hid_generic_quickstart.
* @{
*/
/**
* \brief Routine used to send a report to USB Host
*
* \param data Pointer on the report to send (size = UDI_HID_REPORT_IN_SIZE)
*
* \return \c 1 if function was successfully done, otherwise \c 0.
*/
bool udi_hid_generic_send_report_in(uint8_t *data);
//@}
#ifdef __cplusplus
}
而定议端点数及缓冲大小在udi_hid_generic_conf.h:
#ifndef _UDI_HID_GENERIC_CONF_H_
#define _UDI_HID_GENERIC_CONF_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup udi_hid_generic_group_single_desc
* @{
*/
//! Control endpoint size
#ifdef USB_DEVICE_HS_SUPPORT
# define USB_DEVICE_EP_CTRL_SIZE 64
#else
# define USB_DEVICE_EP_CTRL_SIZE 8
#endif
//! Endpoint number used by HID generic interface
#define UDI_HID_GENERIC_EP_OUT (2 | USB_EP_DIR_OUT)
#define UDI_HID_GENERIC_EP_IN (1 | USB_EP_DIR_IN)
//! Interface number
#define UDI_HID_GENERIC_IFACE_NUMBER 0
/**
* \name UDD Configuration
*/
//@{
//! 2 endpoints used by HID generic standard interface
#undef USB_DEVICE_MAX_EP // undefine this definition in header file
#define USB_DEVICE_MAX_EP 2
//@}
//@}
#ifdef __cplusplus
}
#endif
#include "udi_hid_generic.h"
#endif // _UDI_HID_GENERIC_CONF_H_
而其它的统统交给HID USB 模块处理。
该程序的运行结果如下:
当我插上USB线是,多了一个设备:
打开Atmel提供的上位机软件,我按键时有反应:
|