📄 lpc_hid.c
字号:
#include "lpc_hid.h"
typedef union {
unsigned int Data[2];
unsigned short SetupRecuest;
struct {
unsigned char RequestType;
unsigned char Request;
unsigned short Value;
unsigned short Index;
unsigned short Length;
} DataFields;
} USB_SETUP_PACKET_DEF;
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
unsigned char currentConfiguration;
unsigned char currentAddress;
const short mouseDescriptor[] = { // 鼠标描述符
0x0105, // Usage Page (Generic Desktop)
0x0209, // Usage (Mouse)
0x01A1, // Collection (Application)
0x0109, // Usage (Pointer)
0x00A1, // Collection (Physical)
0x0905, // Usage Page (Buttons)
0x0119, // Usage Minimum?(01)
0x0329, // Usage Maximum (03)
0x0015, // Logical Minimum (0)
0x0125, // Logical Maximum (1)
0x0395, // Report Count (3)
0x0175, // Report Size (1)
0x0281, // 3 Button bits
0x0195, // Report Count (1)
0x0575, // Report Size (6)
0x0181, // 6 bit padding
0x0105, // Generic desktop
0x3009, // Usage(X)
0x3109, // Usage(Y)
0x8115, // Logical Minimum (-127)
0x7F25, // Logical Maximum (127)
0x0875, // Report Size (8)
0x0295, // Report Count (2)
0x0681, // 2 position bytes
0xC0C0 // End collection x2
};
const char devDescriptor[] = { // 设备描述符
/* Device descriptor */
0x12, // bLength
0x01, // bDescriptorType
0x10, // bcdUSBL
0x01, //
0x00, // bDeviceClass:
0x00, // bDeviceSubclass:
0x00, // bDeviceProtocol:
MAX_CTRL_EP_PK_SIZE, // bMaxPacketSize0
0xFF, // idVendorL
0xFF, //
0x01, // idProductL
0x00, //
0x00, // bcdDeviceL
0x00, //
0x01, // iManufacturer
0x02, // iProduct
0x00, // SerialNumber
0x01 // bNumConfigs
};
const char cfgDescriptor[] = { // 配置描述符
0x09, // CbLength
0x02, // CbDescriptorType
0x22, // CwTotalLength 2 EP + Control
0x00,
0x01, // CbNumInterfaces
0x01, // CbConfigurationValue
0x00, // CiConfiguration
0xA0, // CbmAttributes Bus powered + Remote Wakeup
0x32, // CMaxPower: 100mA
/* 鼠标接口描述符 */
0x09, // bLength
0x04, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndpoints
0x03, // bInterfaceClass: HID code
0x01, // bInterfaceSubclass
0x02, // bInterfaceProtocol: Mouse
0x00, // iInterface
/* HID 述符 */
0x09, // bLength
0x21, // bDescriptor type: HID Descriptor Type
0x00, // bcdHID
0x01,
0x00, // bCountry Code
0x01, // bNumDescriptors
0x22, // bDescriptorType
sizeof(mouseDescriptor), // wItemLength
0x00,
/* 端点1述符 */
0x07, // bLength
0x05, // bDescriptorType
((EP_REP&1)<<7) + (EP_REP>>1),// bEndpointAddress and direction, Endpoint Logic address!!
0x03, // bmAttributes INT
0x04, // wMaxPacketSize: 3 bytes (button, x, y)
0x00,
0x0A, // bInterval
};
const char LanguagesStr[] = { //语言字符串
/* 字符串述符0 */
0x04, // bLength
0x03, // bDescriptorType
0x09,0x04 // Language English
};
const char ManufacturerStr[] = { // 厂家字符串
/* 字符串述符1 */
60, // bLength
0x03, // bDescriptorType
'P',0,'h',0,'i',0,'l',0,'i',0,
'p',0,' ',0,'S',0,'e',0,'m',0,
'i',0,'c',0,'o',0,'n',0,'d',0,
'u',0,'c',0,'t',0,'o',0,'r',0,
's',0,' ',0,'L',0,'P',0,'C',0,
'2',0,'1',0,'4',0,'8',0,
};
const char ProductStr[] = // 产品字符串
{
/* 字符串述符2 */
98, // bLength
0x03, // bDescriptorType
'I',0,'A',0,'R',0,' ',0,'E',0,
'm',0,'b',0,'e',0,'d',0,'d',0,
'e',0,'d',0,' ',0,'W',0,'o',0,
'r',0,'k',0,'b',0,'e',0,'n',0,
'c',0,'h',0,' ',0,'A',0,'R',0,
'M',0,' ',0,'-',0,' ',0,'H',0,
'I',0,'D',0,' ',0,'D',0,'e',0,
'v',0,'i',0,'c',0,'e',0,' ',0,
'e',0,'x',0,'a',0,'m',0,'p',0,
'l',0,'e',0,'!',0
};
const char * const StrPoin [] = {
LanguagesStr,ManufacturerStr,ProductStr
};
/*************************************************************************
* 说明: HID_Intr函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_Init (void) {
currentConfiguration = 0;
currentAddress = 0;
// 实现 I/O 控制端点
USB_RealizeEndPoint(CTRL_ENP_OUT,MAX_CTRL_EP_PK_SIZE,USB_LowPrior,1);
USB_RealizeEndPoint(CTRL_ENP_IN ,MAX_CTRL_EP_PK_SIZE,USB_LowPrior,0);
// 设置默认地址
USB_SetAdd(currentAddress);
// 设置设备状态,激活软连接
USB_Cmd(CMD_USB_SET_DEV_STAT,1);
}
/*************************************************************************
* 说明:HID_GetConfiguration函数
* 参数:无
* 返回值:unsigned char
*************************************************************************/
unsigned char HID_GetConfiguration (void) {
return(currentConfiguration);
}
/*************************************************************************
* 说明:HID_CallBack函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_CallBack (void) {
if (DEVINTS & USB_ErrorInterrupt) {
// 出错中断
USB_Cmd(CMD_USB_RD_ERROR_STAT,0);
DEVINTCLR = USB_ErrorInterrupt;
}
if (DEVINTS & USB_DevStatusInterrupt) {
// 设备状态中断
int USB_DevIntrStaus = USB_Cmd(CMD_USB_GET_DEV_STAT,0);
// 总线复位
if (USB_DevIntrStaus & USB_BusReset) {
HID_Init();
}
DEVINTCLR = USB_DevStatusInterrupt;
}
if (DEVINTS & USB_FastInterrupt) {
DEVINTCLR = USB_FastInterrupt;
}
if (DEVINTS & USB_SlowInterrupt) {
// 慢中断
if (ENDPINTS & (1<<CTRL_ENP_OUT)) {
// 选择并清除中断
HID_ImplSetupPacket();
ENDPINTCLR = 1<<CTRL_ENP_OUT;
}
DEVINTCLR = USB_SlowInterrupt;
}
}
/*************************************************************************
* 说明:HID_CtrlStall函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_CtrlStall (void) {
USB_Cmd(CMD_USB_SET_EP_STAT + CTRL_ENP_OUT,0x80);
}
/*************************************************************************
* 说明:HID_SendDataByCtrlEP函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_SendZeroLengthByCtrlEP (void) {
USBCTRL_bit.LOG_ENDPOINT = 0;
USBCTRL_bit.WR_EN = 1;
TPKTLEN = 0;
do {
TDATA = 0;
}
while (USBCTRL_bit.WR_EN);
// 有效缓冲区
USB_ValidateBuffer(CTRL_ENP_IN);
// 等待端点0输入中断
while ((ENDPINTS & (1<<CTRL_ENP_IN)) == 0) {
if ((USB_Cmd(CMD_USB_SET_EP_STAT + CTRL_ENP_IN,0) & 1) == 0) {
if((ENDPINTS & (1<<CTRL_ENP_IN)) == 0) {
break;
}
}
}
// 清除端点中断(在USB时钟范围之内)
USB_Cmd(CMD_USB_SEL_CLR_INT_EP + CTRL_ENP_IN,0);
// 清除中断
ENDPINTCLR = (1<<CTRL_ENP_IN);
}
/*************************************************************************
* 说明:HID_SendDataByCtrlEP函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_SendDataByCtrlEP (unsigned char * Data, unsigned int DataSize) {
unsigned int * pData = (unsigned int *)Data;
unsigned int i;
int ZerroLength = 0;
do {
if (DataSize == MAX_CTRL_EP_PK_SIZE) {
++ZerroLength;
}
i = MIN(DataSize,MAX_CTRL_EP_PK_SIZE);
DataSize -= i;
// 选择端点
USBCTRL_bit.LOG_ENDPOINT = 0;
USBCTRL_bit.WR_EN = 1;
TPKTLEN = i;
do {
TDATA = *pData++;
}
while (USBCTRL_bit.WR_EN);
// 有效缓冲区
USB_ValidateBuffer(CTRL_ENP_IN);
// 等待数据传输或被设置包覆盖
while ((ENDPINTS & (1<<CTRL_ENP_IN)) == 0) {
if ((USB_Cmd(CMD_USB_SET_EP_STAT + CTRL_ENP_IN,0) & 1) == 0) {
if((ENDPINTS & (1<<CTRL_ENP_IN)) == 0) {
USB_Cmd(CMD_USB_SEL_CLR_INT_EP + CTRL_ENP_IN,0);
return;
}
}
}
USB_Cmd(CMD_USB_SEL_CLR_INT_EP + CTRL_ENP_IN,0);
ENDPINTCLR = (1<<CTRL_ENP_IN);
}
while (DataSize);
if (ZerroLength) {
HID_SendZeroLengthByCtrlEP();
}
}
/*************************************************************************
* 说明:HID_ImplSetupPacket函数
* 参数:无
* 返回值:无
*************************************************************************/
void HID_ImplSetupPacket (void) {
USB_SETUP_PACKET_DEF Setup;
unsigned short Status,Length;
int i = 0;
do {
// 读控制端点(0 - 输出)
USBCTRL_bit.LOG_ENDPOINT = 0;
USBCTRL_bit.RD_EN = 1;
// 等待数据包就绪标志
while (RCVEPKTLEN_bit.PKT_RDY == 0);
// 从 USB FIFO 读取数据,获得数据包大小
Length = RCVEPKTLEN_bit.PKT_LNGTH;
while (RCVEPKTLEN_bit.DV) {
Setup.Data[i++] = RCVEDATA;
}
// 清除缓冲区满标志
i = USB_ClearBuffer(CTRL_ENP_OUT);
USB_Cmd(CMD_USB_SEL_CLR_INT_EP+CTRL_ENP_OUT,0);
}
while(i);
if (Length == 0) return;
switch (Setup.SetupRecuest) {
case USB_GET_DESCRIPTOR:
if (Setup.DataFields.Value == 0x100) { // 返回设备描述符
HID_SendDataByCtrlEP((unsigned char *)devDescriptor,MIN(sizeof(devDescriptor), Setup.DataFields.Length));
}
else if (Setup.DataFields.Value == 0x200) { // 返回配置描述符
HID_SendDataByCtrlEP((unsigned char *)cfgDescriptor,MIN(sizeof(cfgDescriptor), Setup.DataFields.Length));
}
else if ((Setup.DataFields.Value & 0xFF00) == 0x300) { // 返回字符串
if ((Setup.DataFields.Value & 0xF) < 3) {
const char * Data = StrPoin[Setup.DataFields.Value & 0xF];
HID_SendDataByCtrlEP((unsigned char *)Data,MIN(*Data, Setup.DataFields.Length));
}
else {
HID_CtrlStall();
}
}
else {
HID_CtrlStall();
}
break;
case USB_SET_ADD:
HID_SendZeroLengthByCtrlEP();
currentAddress = Setup.DataFields.Value;
USB_SetAdd(currentAddress);
break;
case USB_SET_CONFIGURATION:
if (Setup.DataFields.Value == 1) {
currentConfiguration = Setup.DataFields.Value;
USB_RealizeEndPoint(EP_REP,4,USB_LowPrior,0);
USB_Cmd(CMD_USB_CFG_DEV,1);
HID_SendZeroLengthByCtrlEP();
}
else {
// 仅允许端点0
USB_Cmd(CMD_USB_CFG_DEV,0);
HID_SendZeroLengthByCtrlEP();
}
break;
case USB_GET_CONFIGURATION:
HID_SendDataByCtrlEP(¤tConfiguration,sizeof(currentConfiguration));
break;
case USB_GET_STATUS_DEV:
case USB_GET_STATUS_INTERFACE:
Status = 0;
HID_SendDataByCtrlEP((unsigned char *)&Status,sizeof(Status));
break;
case USB_GET_STATUS_ENDPOINT:
Status = 0;
if (currentConfiguration && (Setup.DataFields.Index <= 1)) {
HID_SendDataByCtrlEP((unsigned char *)&Status,sizeof(Status));
}
else if (currentAddress && (Setup.DataFields.Index == 0)) {
HID_SendDataByCtrlEP((unsigned char *)&Status,sizeof(Status));
}
else {
HID_CtrlStall();
}
break;
case USB_SET_FEATURE_ENDPOINT:
if (Setup.DataFields.Index <= 1) {
HID_SendZeroLengthByCtrlEP();
}
else {
HID_CtrlStall();
}
break;
case USB_CLEAR_FEATURE_ENDPOINT:
if ((Setup.DataFields.Value == 0) && (Setup.DataFields.Index == 1)) {
HID_SendZeroLengthByCtrlEP();
}
else {
HID_CtrlStall();
}
break;
case USB_SET_FEATURE_INTERFACE:
case USB_CLEAR_FEATURE_INTERFACE:
case USB_HID_SET_IDLE:
HID_SendZeroLengthByCtrlEP();
break;
case USB_GET_HID_DESCRIPTOR:
HID_SendDataByCtrlEP((unsigned char*) mouseDescriptor,MIN(sizeof(mouseDescriptor), Setup.DataFields.Length));
break;
case USB_SET_FEATURE_DEV:
case USB_CLEAR_FEATURE_DEV:
case USB_SET_DESCRIPTOR:
case USB_GET_INTERFACE:
case USB_SET_INTERFACE:
default:
HID_CtrlStall();
break;
}
}
/*************************************************************************
* 说明:HID_SendReport
* 参数:char button, char x, char y
* 返回值:无
*************************************************************************/
void HID_SendReport(char button, char x, char y) {
unsigned int Data = button + (x<<8) + (y<<16);
USBCTRL_bit.LOG_ENDPOINT = EP_REP >> 1;
USBCTRL_bit.WR_EN = 1;
TPKTLEN = 3;
TDATA = Data;
if (USBCTRL_bit.WR_EN) {
#ifndef NDEBUG
printf("Error Send Data");
#endif
return;
}
// 有效缓冲区
USB_ValidateBuffer(EP_REP);
// 等待传输完成
while ((ENDPINTS & (1<<EP_REP)) == 0) {
// 获得端点状态
if ((USB_Cmd(CMD_USB_SET_EP_STAT + EP_REP,0) & 1) == 0) {
if((ENDPINTS & (1<<EP_REP)) == 0) {
break;
}
}
}
USB_Cmd(CMD_USB_SEL_CLR_INT_EP + EP_REP,0);
ENDPINTCLR = (1<<EP_REP);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -