1、使用 USB 鼠标历程。
2、修改几个USB节点
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* USB Standard Device Descriptor */
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
0x12, /*bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
0x01, /*bcdUSB */
0x10,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
0x40, /*bMaxPacketSize40*/
0xf3, /*idVendor (0x0483)*/
0x04,
0x04, /*idProduct = 0x5750*/
0x01,
0x00, /*bcdDevice rel. 2.00*/
0x02,
1, /*Index of string descriptor describing
manufacturer */
2, /*Index of string descriptor describing
product*/
3, /*Index of string descriptor describing the
device serial number */
0x01 /*bNumConfigurations*/
}
; /* Joystick_DeviceDescriptor */
/* USB Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
0x09, /* bLength: Configuation Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
JOYSTICK_SIZ_CONFIG_DESC,
/* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing
the configuration*/
0xC0, /* bmAttributes: Bus powered */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
/************** Descriptor of Custom HID interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0, /* iInterface: Index of string descriptor */
/******************** Descriptor of Custom HID HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x00, /* bcdHID: HID Class Spec release number */
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
JOYSTICK_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */
0x00,
/******************** Descriptor of Custom HID endpoints ******************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x81, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x08, /* wMaxPacketSize: 16 Bytes max */
0x00,
0x20, /* bInterval: Polling Interval (32 ms) */
/* 34 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
/* Endpoint descriptor type */
0x01, /* bEndpointAddress: */
/* Endpoint Address (OUT) */
0x03, /* bmAttributes: Interrupt endpoint */
0x08, /* wMaxPacketSize: 16 Bytes max */
0x00,
0x20, /* bInterval: Polling Interval (20 ms) */
/* 41 */
}
; /* MOUSE_ConfigDescriptor */
const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x02, // USAGE_MAXIMUM (Caps Lock)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x06, // REPORT_SIZE (6)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0xc0 // END_COLLECTION
}
; /* Joystick_ReportDescriptor */
3、void Joystick_Reset(void)
/* Initialize Endpoint In 1 */
SetEPType(ENDP1, EP_INTERRUPT); //初始化为中断端点类型
SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送数据的地址
SetEPTxCount(ENDP1, 8); //设置发送的长度
// SetEPRxStatus(ENDP1, EP_RX_DIS);
SetEPTxStatus(ENDP1, EP_TX_NAK); //设置端点处于忙状态
/* Initialize Endpoint Out 1 */
SetEPRxAddr(ENDP1, ENDP1_RXADDR); //设置接收数据的地址
SetEPRxCount(ENDP1, 1); //设置接收长度
SetEPRxStatus(ENDP1, EP_RX_VALID); //设置端点有效,可以接收数据
4、设置USB键盘控制LED
#define EP1_OUT_Callback EP1_OUT_Callback
void EP1_OUT_Callback(void)
{
u8 DataLen; //保存接收数据的长度
u8 DataBuffer[64]; //保存接收数据的缓冲区
DataLen = GetEPRxCount(ENDP1); //获取收到的长度
PMAToUserBufferCopy(DataBuffer, ENDP1_RXADDR, DataLen); //复制数据
SetEPRxValid(ENDP1); //设置端点有效,以接收下一次数据
}
5、USB 键盘发送数据到 PC
void Joystick_Send(u8 *Key)
{
while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
/*copy mouse position info in ENDP1 Tx Packet Memory Area*/
UserToPMABufferCopy(Key, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
memset(Key,0x00,8);
while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
/*copy mouse position info in ENDP1 Tx Packet Memory Area*/
UserToPMABufferCopy(Key, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
}
/*
发送一串字符模拟键盘输入这段字符
Keys 字符缓冲区
KeyLen 长度
SendEnterFlag 发送结束后是否发送 ENTER 键
*/
void Joystick_Send_KeyString(u8 *Keys,u16 KeyLen,u16 SendEnterFlag)
{
u8 Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
u8 loop,i;
u16 nSendCouter;
u16 nTableOffset;
nSendCouter = 0 ;
// i=2;
for(loop=0;loop<KeyLen;loop++)
{
//memset(Buffer,0x00,sizeof(Buffer));
//KEY down 消息
//memcpy(Buffer+2,Keys+loop*6,6);
nTableOffset = Keys[loop] - 0x20 ;
if(nSendCouter)
{
if((Buffer[0] != Key_Table[nTableOffset][0]) || nSendCouter >= 6)
{
//如果有数据需要按 SHFIT 和不需要按SHFIT的去别
//则先把之前缓冲区里面的数据发送出去
//或者缓冲区满就发送出去
Joystick_Send(Buffer);
Buffer[0] = Key_Table[nTableOffset][0] ;
Buffer[2] = Key_Table[nTableOffset][1] ;
nSendCouter = 1 ;
}
else
{
for(i=0;i<nSendCouter;i++)
{
//判断缓冲区里面有没有重复的数据
//如果有重复的就先把缓冲区里面的
//数据发送出去
if(Buffer[2+i] == Key_Table[nTableOffset][1])
{
Joystick_Send(Buffer);
nSendCouter = 0 ;
break;
}
}
Buffer[0] = Key_Table[nTableOffset][0] ;
Buffer[2+nSendCouter] = Key_Table[nTableOffset][1] ;
nSendCouter ++ ;
}
}
else
{
Buffer[0] = Key_Table[nTableOffset][0] ;
Buffer[2] = Key_Table[nTableOffset][1] ;
nSendCouter ++ ;
}
}
if(nSendCouter)
{
Joystick_Send(Buffer);
}
if(SendEnterFlag)
{
Buffer[0] = 0 ;
Buffer[2] = 0x28 ;
Joystick_Send(Buffer);
}
}
void Joystick_Send_Keyup(void)
{
u8 Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
/*copy mouse position info in ENDP1 Tx Packet Memory Area*/
UserToPMABufferCopy(Buffer, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
}