// TITLE: USB HID Mouse device class driver
#include "usbdhidmouse.h"
#include <usb.h>
extern "C" {
#include <debug.h> // ASSERT
}
namespace usb{
// report descriptor
static const uint8_t ReportDesc[] = {
0x05,1, // UsagePage(GENERIC_DESKTOP)
0x09,2, // Usage(MOUSE),
0xA1,1, // Collection(APPLICATION)
0x09,1, // Usage(POINTER)
0xA1,0, // Collection(Physical)
// buttons
0x05,9, // UsagePage(BUTTONS)
0x19,1, // UsageMinimum(1)
0x29,3, // UsageMaximum(3)
0x15,0, // LogicalMinimum(0)
0x25,1, // LogicalMaximum(1)
0x75,1, // ReportSize(1)
0x95,3, // ReportCount(3)
0x81,2, // Input(VAR,ABS)
0x75,5, // ReportSize(5)
0x95,1, // ReportCount(1)
0x81,3, // Input(CONST|ARY|ABS)
// X and Y axis
0x05,1, // UsagePage(GENERIC_DESKTOP)
0x09,0x30, // Usage(X),
0x09,0x31, // Usage(Y),
0x15,(uint8_t)-127, // LogicalMinimum(-127)
0x25,127, // LogicalMaximum(127)
0x75,8, // ReportSize(8)
0x95,2, // ReportCount(2)
0x81,6, // Input(DATA|VAR|REL)
0xC0, // EndCollection
0xC0, // EndCollection
};
// Device Descriptor
static const uint8_t DeviceDesc[] = {
18, // Size of this structure.
1, // Type of this structure = DTYPE_DEVICE
USB2(0x110), // USB version 1.1
0, // USB Device Class
0, // USB Device Sub-class
0, // USB Device protocol
64, // Maximum packet size for default pipe.
USB2(0x1CBE), // Vendor ID = Texas Instruments
USB2(0), // Product ID = TI Mouse
USB2(0x100), // Device Version BCD.
1, // Manufacturer string identifier.
2, // Product string identifier.
0, // Product serial number.
1, // Number of configurations.
};
// configuration descriptor.
static const uint8_t ConfigDesc[] = {
9, // bLength
2, // USB_DTYPE_CONFIGURATION
USB2(9+9+9+7), // The total size of this full structure.
1, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xC0, // Bus Powered, Self Powered, remote wake up.
50, // The maximum power in 2mA increments.
// Interface Descriptor.
9, // Size of the interface descriptor.
4, //USB_DTYPE_INTERFACE, // Type of this descriptor.
0, // The index for this interface.
0, // The alternate setting for this interface.
1, // The number of endpoints used by this interface.
3, // USB_CLASS_HID, // interface class
0, // interface sub-class.
0, // interface protocol for the sub-class specified above.
0, // The string index for this interface.
// HID descriptor
9, // bLength
0x21, // bDescriptorType = DTYPE_HID
USB2(0x111), // bcdHID (version 1.11 compliant)
0, // bCountryCode (not localized)
1, // bNumDescriptors
0x22, // Report descriptor = DTYPE_REPORT
USB2(sizeof ReportDesc), // Size of report descriptor
// Interrupt IN endpoint descriptor
7, // The size of the endpoint descriptor.
5, //USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint.
0x81, // EP1IN
0x03, // Endpoint is an interrupt endpoint.
USB2(64), // The maximum packet size.
16, // The polling interval for this endpoint.
};
bool tHIDMouseDevice::cbRequestHandler(const tRequest&rq) {
switch (rq.wRequest()) {
case 0x01A1: if ( // GET_REPORT, class-specific, target=interface
rq.wIndexL == 0 // Interface 0
&& rq.wValueH == 0x01 // report_type = INPUT
&& rq.wValueL == 0) { // report_id
USBDevEndpointDataAck(USB_BASE, USB_EP_0, true);
SendDataEP0(inrep,3,rq);
return true;
}break;
case 0x06A1: return cbGetDescriptor(rq);
}
return tDevice::cbRequestHandler(rq); // chain down
}
static void buildStringDesc(uint8_t d[256],const char*s) {
uint8_t*p=d+1;
*p++=3;
wchar_t c;
while ((c=*s++)) {
if (c&0x80) {
if (c&0x20) { // 3-Byte-UTF-8
c<<=6;
c|=*s++&0x3F;
}else c&=0x3F; // 2-Byte-UTF-8
c<<=6;
c|=*s++&0x3F;
}
*p++=c&0xFF;
*p++=c>>8&0xFF;
}
ASSERT(p-d<256);
*d=p-d;
}
bool tHIDMouseDevice::cbGetDescriptor(const tRequest&rq) {
switch (rq.wValueH) {
case 1: { // device descriptor
SendDataEP0(DeviceDesc, sizeof DeviceDesc, rq);
}return true;
case 2: { // configuration descriptor
SendDataEP0(ConfigDesc, sizeof ConfigDesc, rq);
}return true;
case 3: {
uint8_t sd[256];
switch (rq.wValueL) { // string descriptor
// Bug+Workaround: C++2000 unterstützt weder L"\x0409" noch L"\u0409" richtig, nimmt nur Low-Byte
// Bug+Workaround: C++2000 unterstützt kein L"Ä", speichert UTF-8, daher UTF-8-Strings
case 0: buildStringDesc(sd,"\xD0\x87"); break; // 0x0407 deutsch
case 1: buildStringDesc(sd,"Texas Instruments"); break;
case 2: buildStringDesc(sd,"Mausbeispiel: ÄÖÜäöüß"); break;
default: return false;
}
SendDataEP0(sd,sd[0],rq);
}return true;
case 0x21: {
SendDataEP0(ConfigDesc+9+9, 9, rq);
}return true;
case 0x22: {
SendDataEP0(ReportDesc, sizeof ReportDesc, rq);
}return true;
}
return tDevice::cbGetDescriptor(rq);
}
bool tHIDMouseDevice::StateChange(uint8_t Buttons, int8_t DeltaX, int8_t DeltaY) {
inrep[0]=Buttons;
inrep[1]=(uint8_t)DeltaX;
inrep[2]=(uint8_t)DeltaY;
return SendReport(inrep,3);
}
bool tHIDMouseDevice::SendReport(uint8_t *data, unsigned len) {
int32_t i32Retcode = USBEndpointDataPut(USB_BASE,USB_EP_1,data,len);
if (!i32Retcode) {
i32Retcode = USBEndpointDataSend(USB_BASE,USB_EP_1,USB_TRANS_IN);
}
return i32Retcode==0;
}
}
Detected encoding: UTF-8 | 0
|