目标:使用CH567 在 USB1 上实现微软Microsoft 5-Button Mouse with IntelliEye(TM) 鼠标。
为了更好的进行调试,首先将UART 设置为 1M的速率,这样做的好处是:调试信息能够更快的发送出来同时避免因为调试影响 USB 的时序。在 MYdebug.h 中修改如下:
#define STDIO_BAUD_RATE 1000000 //波特率为1000000BPS
使用时,将一个 USB 转串口Dongle的 RX接在CH567的PA5引脚上(UART3),共地之后使用 1 000 000波特率即可看到信息。
描述符如下:
1.Device Descriptor
Device Descriptor Microsoft 5-Button Mouse with IntelliEye(TM)
| Offset | Field | Size | Value | Description |
| 0 | bLength | 1 | 12h | |
| 1 | bDescriptorType | 1 | 01h | Device |
| 2 | bcdUSB | 2 | 0110h | USB Spec 1.1 |
| 4 | bDeviceClass | 1 | 00h | Class info in Ifc Descriptors |
| 5 | bDeviceSubClass | 1 | 00h | |
| 6 | bDeviceProtocol | 1 | 00h | |
| 7 | bMaxPacketSize0 | 1 | 08h | 8 bytes |
| 8 | idVendor | 2 | 045Eh | |
| 10 | idProduct | 2 | 0039h | |
| 12 | bcdDevice | 2 | 0300h | 3.00 |
| 14 | iManufacturer | 1 | 01h | “Microsoft” |
| 15 | iProduct | 1 | 03h | “Microsoft 5-Button Mouse with IntelliEye(TM)” |
| 16 | iSerialNumber | 1 | 00h | |
| 17 | bNumConfigurations | 1 | 01h |
2.Configuration Descriptor
Configuration Descriptor 1 Bus Powered, 100 mA
| Offset | Field | Size | Value | Description |
| 0 | bLength | 1 | 09h | |
| 1 | bDescriptorType | 1 | 02h | Configuration |
| 2 | wTotalLength | 2 | 0022h | |
| 4 | bNumInterfaces | 1 | 01h | |
| 5 | bConfigurationValue | 1 | 01h | |
| 6 | iConfiguration | 1 | 00h | |
| 7 | bmAttributes | 1 | A0h | Bus Powered, Remote Wakeup |
| 4..0: Reserved | …00000 | |||
| 5: Remote Wakeup | ..1….. | Yes | ||
| 6: Self Powered | .0…… | No, Bus Powered | ||
| 7: Reserved (set to one) (bus-powered for 1.0) | 1……. | |||
| 8 | bMaxPower | 1 | 32h | 100 mA |
Interface Descriptor 0/0 HID, 1 Endpoint
| Offset | Field | Size | Value | Description |
| 0 | bLength | 1 | 09h | |
| 1 | bDescriptorType | 1 | 04h | Interface |
| 2 | bInterfaceNumber | 1 | 00h | |
| 3 | bAlternateSetting | 1 | 00h | |
| 4 | bNumEndpoints | 1 | 01h | |
| 5 | bInterfaceClass | 1 | 03h | HID |
| 6 | bInterfaceSubClass | 1 | 01h | Boot Interface |
| 7 | bInterfaceProtocol | 1 | 02h | Mouse |
| 8 | iInterface | 1 | 00h |
| Offset | Field | Size | Value | Description |
| 0 | bLength | 1 | 09h | |
| 1 | bDescriptorType | 1 | 21h | HID |
| 2 | bcdHID | 2 | 0110h | 1.10 |
| 4 | bCountryCode | 1 | 00h | |
| 5 | bNumDescriptors | 1 | 01h | |
| 6 | bDescriptorType | 1 | 22h | Report |
| 7 | wDescriptorLength | 2 | 0048h | 72 bytes |
Endpoint Descriptor 81 1 In, Interrupt, 10 ms
| Offset | Field | Size | Value | Description |
| 0 | bLength | 1 | 07h | |
| 1 | bDescriptorType | 1 | 05h | Endpoint |
| 2 | bEndpointAddress | 1 | 81h | 1 In |
| 3 | bmAttributes | 1 | 03h | Interrupt |
| 1..0: Transfer Type | ……11 | Interrupt | ||
| 7..2: Reserved | 000000.. | |||
| 4 | wMaxPacketSize | 2 | 0004h | 4 bytes |
| 6 | bInterval | 1 | 0Ah | 10 ms |
3.Language ID Descriptor
04 03 09 04
4.String Index 3
Microsoft 5-Button Mouse with IntelliEye(TM)
5. String Index 1
Microsoft
6.SET_CONFIGURATION
7.SET_IDLE 暂时未实现
8. GET_DESCRIPTOR REPORT_DESCRIPTOR 这里返回 HID Descriptor
Interface 0 HID Report Descriptor Mouse
| Item Tag (Value) | Raw Data |
| Usage Page (Generic Desktop) | 05 01 |
| Usage (Mouse) | 09 02 |
| Collection (Application) | A1 01 |
| Usage (Pointer) | 09 01 |
| Collection (Physical) | A1 00 |
| Usage Page (Button) | 05 09 |
| Usage Minimum (Button 1) | 19 01 |
| Usage Maximum (Button 5) | 29 05 |
| Logical Minimum (0) | 15 00 |
| Logical Maximum (1) | 25 01 |
| Report Size (1) | 75 01 |
| Report Count (5) | 95 05 |
| Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) | 81 02 |
| Report Size (3) | 75 03 |
| Report Count (1) | 95 01 |
| Input (Cnst,Ary,Abs) | 81 01 |
| Usage Page (Generic Desktop) | 05 01 |
| Usage (X) | 09 30 |
| Usage (Y) | 09 31 |
| Usage (Wheel) | 09 38 |
| Logical Minimum (-127) | 15 81 |
| Logical Maximum (127) | 25 7F |
| Report Size (8) | 75 08 |
| Report Count (3) | 95 03 |
| Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) | 81 06 |
| End Collection | C0 |
| Usage Page | 05 FF |
| Usage | 09 02 |
| Logical Minimum (0) | 15 00 |
| Logical Maximum (1) | 25 01 |
| Report Size (1) | 75 01 |
| Report Count (1) | 95 01 |
| Feature (Data,Var,Abs,NWrp,Lin,NPrf,NNul,NVol,Bit) | B1 22 |
| Report Size (7) | 75 07 |
| Report Count (1) | 95 01 |
| Feature (Cnst,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) | B1 01 |
| End Collection | C0 |
代码是从USB1_DevCH372 修改而来的,其中的一些关于Endpoint 2 3 4 的代码并未去除。主要的修改如下:
1. void USB1DeviceInit( void ) // 初始化USB设备 中,因为鼠标是低速设备,进行如下修改:
R8_USB1_CTRL = UCST_LS | bUC_INT_BUSY |bUC_DMA_EN; //设备模式,低速,
2. 用我们自己的描述符替换之前代码中的,在 case USB_GET_DESCRIPTOR: 中。因为我们是 HID设备,所以需要多一个 HID描述符,增加了处理的代码:
// GET_DESCRIPTOR REPORT_DESCRIPTOR
case USB_DESCR_TYP_REPORT:
printf("REPORT_DESCRIPTOR Start\n");
pDescr = (PUINT8)( &HidDescr[0] );
len = sizeof( HidDescr );
printf("REPORT_DESCRIPTOR End\n");
break;
上述完成之后,插入设备,Windows 就会认为有一个USB 鼠标插入系统。为了让鼠标有动作,还需要在Main 中添加如下代码。简单的说有如下2点:
- 我们使用 UsbConfig 作为鼠标配置完成的标志,只有 Windows 读取完各种必要的信息之后,进行的数据传输才是有效的;
- 鼠标的动作就是放在 Ep1Buffer的 512 字节中,然后给R8_UEP1_TX_CTRL1寄存器赋值即可进行发送;
int main()
{
Interrupt_init( 1<<INT_ID_USB1 ); /* 系统总中断开启 */
SysClkInit(); /* 初始化系统时钟 */
mInitSTDIO_UR3(); /* 调试信息初始化 printf调用 */
USB1DeviceInit(); /* USB1Device Init */
printf("USB1 Device Init!\n");
while(1) {
if (UsbConfig!=0) {
printf("Move mouse\n");
Ep1Buffer[0+512]=0;
Ep1Buffer[1+512]=0x20;
Ep1Buffer[2+512]=0;
Ep1Buffer[3+512]=0;
R16_UEP1_T_LEN1=4;
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
mDelaymS(100);
Ep1Buffer[0+512]=0;
Ep1Buffer[1+512]=0;
Ep1Buffer[2+512]=0x20;
Ep1Buffer[3+512]=0;
R16_UEP1_T_LEN1=4;
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
mDelaymS(100);
Ep1Buffer[0+512]=0;
Ep1Buffer[1+512]=0xE0;
Ep1Buffer[2+512]=0;
Ep1Buffer[3+512]=0;
R16_UEP1_T_LEN1=4;
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
mDelaymS(100);
Ep1Buffer[0+512]=0;
Ep1Buffer[1+512]=0;
Ep1Buffer[2+512]=0xE0;
Ep1Buffer[3+512]=0;
R16_UEP1_T_LEN1=4;
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
mDelaymS(100);
}
mDelaymS(5000);
};
return 0;
}
整体上并不复杂,但是因为缺少示例,个人感觉整体代码比较乱,如果未来对于功能进行扩展可能会遇到麻烦。
完整代码下载