Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
Diff: USBJoystick/USBJoystick.cpp
- Revision:
- 62:f071ccde32a0
- Parent:
- 61:3c7e6e9ec355
- Child:
- 63:5cd1a5f3a41b
--- a/USBJoystick/USBJoystick.cpp Thu Jun 02 18:58:52 2016 +0000 +++ b/USBJoystick/USBJoystick.cpp Thu Jun 02 22:52:25 2016 +0000 @@ -31,8 +31,6 @@ // Maximum report sizes const int MAX_REPORT_JS_TX = reportLen; const int MAX_REPORT_JS_RX = 8; -const int MAX_REPORT_KB_TX = 8; -const int MAX_REPORT_KB_RX = 4; bool USBJoystick::update(int16_t x, int16_t y, int16_t z, uint32_t buttons, uint16_t status) { @@ -49,24 +47,26 @@ bool USBJoystick::update() { + // start the report with the report ID HID_REPORT report; - + report.data[0] = REPORT_ID_JS; + // Fill the report according to the Joystick Descriptor #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff) #define putbe(idx, val) (report.data[(idx)+1] = (val) & 0xff, report.data[idx] = ((val) >> 8) & 0xff) #define putl(idx, val) (put(idx, val), put((idx)+2, (val) >> 16)) #define putlbe(idx, val) (putbe((idx)+2, val), putbe(idx, (val) >> 16)) - put(0, _status); - put(2, 0); // second word of status - zero in high bit identifies as normal joystick report - put(4, _buttonsLo); - put(6, _buttonsHi); - put(8, _x); - put(10, _y); - put(12, _z); + put(1, _status); + put(3, 0); // second word of status - zero in high bit identifies as normal joystick report + put(5, _buttonsLo); + put(7, _buttonsHi); + put(9, _x); + put(11, _y); + put(13, _z); // important: keep reportLen in sync with the actual byte length of // the reports we build here - report.length = reportLen; + report.length = reportLen + 1; // send the report return sendTO(&report, 100); @@ -99,14 +99,16 @@ bool USBJoystick::sendPlungerStatus( int npix, int edgePos, int dir, uint32_t avgScanTime, uint32_t processingTime) { + // set up the report ID HID_REPORT report; + report.data[0] = REPORT_ID_STAT; // Set the special status bits to indicate it's an extended // exposure report. - put(0, 0x87FF); + put(1, 0x87FF); // start at the second byte - int ofs = 2; + int ofs = 3; // write the report subtype (0) to byte 2 report.data[ofs++] = 0; @@ -143,25 +145,26 @@ report.data[ofs++] = (t >> 16) & 0xff; // send the report - report.length = reportLen; + report.length = reportLen + 1; return sendTO(&report, 100); } bool USBJoystick::sendPlungerPix(int &idx, int npix, const uint8_t *pix) { HID_REPORT report; + report.data[0] = REPORT_ID_STAT; // Set the special status bits to indicate it's an exposure report. // The high 5 bits of the status word are set to 10000, and the // low 11 bits are the current pixel index. uint16_t s = idx | 0x8000; - put(0, s); + put(1, s); // start at the second byte - int ofs = 2; + int ofs = 3; // now fill out the remaining bytes with exposure values - report.length = reportLen; + report.length = reportLen + 1; for ( ; ofs < report.length ; ++ofs) report.data[ofs] = (idx < npix ? pix[idx++] : 0); @@ -176,21 +179,24 @@ // initially fill the report with zeros memset(report.data, 0, sizeof(report.data)); + // set the report ID + report.data[0] = REPORT_ID_STAT; + // Set the special status bits to indicate that it's an ID report uint16_t s = 0x9000; - put(0, s); + put(1, s); // add the requested ID index - report.data[2] = (uint8_t)index; + report.data[3] = (uint8_t)index; // figure out which ID we're reporting switch (index) { case 1: // KL25Z CPU ID - putbe(3, SIM->UIDMH); - putlbe(5, SIM->UIDML); - putlbe(9, SIM->UIDL); + putbe(4, SIM->UIDMH); + putlbe(6, SIM->UIDML); + putlbe(10, SIM->UIDL); break; case 2: @@ -199,12 +205,12 @@ // 80 bits = 10 bytes. So skip ahead 16 and back up 10 to get // the starting point.) extern const char *getOpenSDAID(); - memcpy(&report.data[3], getOpenSDAID() + 16 - 10, 10); + memcpy(&report.data[4], getOpenSDAID() + 16 - 10, 10); break; } // send the report - report.length = reportLen; + report.length = reportLen + 1; return sendTO(&report, 100); } @@ -215,10 +221,13 @@ // initially fill the report with zeros memset(report.data, 0, sizeof(report.data)); + // set the report ID + report.data[0] = REPORT_ID_STAT; + // Set the special status bits to indicate that it's a build // info report uint16_t s = 0xA000; - put(0, s); + put(1, s); // Parse the date. This is given in the standard __DATE__ " " __TIME // macro format, "Mon dd yyyy hh:mm:ss" (e.g., "Feb 16 2016 12:15:06"). @@ -244,11 +253,11 @@ + (atol(date+18)); // store the build date and time - putl(2, dd); - putl(6, tt); + putl(3, dd); + putl(7, tt); // send the report - report.length = reportLen; + report.length = reportLen + 1; return sendTO(&report, 100); } @@ -259,16 +268,19 @@ // initially fill the report with zeros memset(report.data, 0, sizeof(report.data)); + // set the report ID + report.data[0] = REPORT_ID_STAT; + // Set the special status bits to indicate that it's a config // variable report uint16_t s = 0x9800; - put(0, s); + put(1, s); // Copy the variable data (7 bytes, starting with the variable ID) - memcpy(report.data + 2, data, 7); + memcpy(report.data + 3, data, 7); // send the report - report.length = reportLen; + report.length = reportLen + 1; return sendTO(&report, 100); } @@ -282,27 +294,30 @@ // initially fill the report with zeros memset(report.data, 0, sizeof(report.data)); + // set the report ID + report.data[0] = REPORT_ID_STAT; + // Set the special status bits to indicate that it's a config report. uint16_t s = 0x8800; - put(0, s); + put(1, s); // write the number of configured outputs - put(2, numOutputs); + put(3, numOutputs); // write the unit number - put(4, unitNo); + put(5, unitNo); // write the plunger zero and max values - put(6, plungerZero); - put(8, plungerMax); - report.data[10] = uint8_t(plungerRlsTime); + put(7, plungerZero); + put(9, plungerMax); + report.data[11] = uint8_t(plungerRlsTime); // write the status bits: // 0x01 -> configuration loaded - report.data[11] = (configured ? 0x01 : 0x00); + report.data[12] = (configured ? 0x01 : 0x00); // send the report - report.length = reportLen; + report.length = reportLen + 1; return sendTO(&report, 100); } @@ -330,11 +345,15 @@ { HID_REPORT report; - // Fill the report according to the Joystick Descriptor -#define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff) - memset(report.data, 0, reportLen); - put(0, status); - report.length = reportLen; + // clear the report + memset(report.data, 0, sizeof(report.data)); + + // set the report ID + report.data[0] = REPORT_ID_STAT; + + // Indicate that it's a status report + put(1, status); + report.length = reportLen + 1; // send the report return sendTO(&report, 100); @@ -353,185 +372,205 @@ // -------------------------------------------------------------------------- // -// USB HID Report Descriptor - Joystick +// USB HID Report Descriptors // -static const uint8_t reportDescriptorJS[] = -{ - USAGE_PAGE(1), 0x01, // Generic desktop - USAGE(1), 0x04, // Joystick - COLLECTION(1), 0x01, // Application - - // input report (device to host) - USAGE_PAGE(1), 0x06, // generic device controls - for config status - USAGE(1), 0x00, // undefined device control - LOGICAL_MINIMUM(1), 0x00, // 8-bit values - LOGICAL_MAXIMUM(1), 0xFF, - REPORT_SIZE(1), 0x08, // 8 bits per report - REPORT_COUNT(1), 0x04, // 4 reports (4 bytes) - INPUT(1), 0x02, // Data, Variable, Absolute +#define HID_REPORT_JS \ + USAGE_PAGE(1), 0x01, /* Generic desktop */ \ + USAGE(1), 0x04, /* Joystick */ \ + COLLECTION(1), 0x01, /* Application */ \ + /* input report (device to host) */ \ + REPORT_ID(1), REPORT_ID_JS, \ + USAGE_PAGE(1), 0x06, /* generic device controls - for config status */ \ + USAGE(1), 0x00, /* undefined device control */ \ + LOGICAL_MINIMUM(1), 0x00, /* 8-bit values */ \ + LOGICAL_MAXIMUM(1), 0xFF, \ + REPORT_SIZE(1), 0x08, /* 8 bits per report */ \ + REPORT_COUNT(1), 0x04, /* 4 reports (4 bytes) */ \ + INPUT(1), 0x02, /* Data, Variable, Absolute */ \ + \ + USAGE_PAGE(1), 0x09, /* Buttons */ \ + USAGE_MINIMUM(1), 0x01, /* { buttons } */ \ + USAGE_MAXIMUM(1), 0x20, /* { 1-32 } */ \ + LOGICAL_MINIMUM(1), 0x00, /* 1-bit buttons - 0... */ \ + LOGICAL_MAXIMUM(1), 0x01, /* ...to 1 */ \ + REPORT_SIZE(1), 0x01, /* 1 bit per report */ \ + REPORT_COUNT(1), 0x20, /* 32 reports */ \ + UNIT_EXPONENT(1), 0x00, /* Unit_Exponent (0) */ \ + UNIT(1), 0x00, /* Unit (None) */ \ + INPUT(1), 0x02, /* Data, Variable, Absolute */ \ + \ + USAGE_PAGE(1), 0x01, /* Generic desktop */ \ + USAGE(1), 0x30, /* X axis */ \ + USAGE(1), 0x31, /* Y axis */ \ + USAGE(1), 0x32, /* Z axis */ \ + LOGICAL_MINIMUM(2), 0x00,0xF0, /* each value ranges -4096 */ \ + LOGICAL_MAXIMUM(2), 0x00,0x10, /* ...to +4096 */ \ + REPORT_SIZE(1), 0x10, /* 16 bits per report */ \ + REPORT_COUNT(1), 0x03, /* 3 reports (X, Y, Z) */ \ + INPUT(1), 0x02, /* Data, Variable, Absolute */ \ + \ + /* output report (host to device) */ \ + REPORT_ID(1), REPORT_ID_JS, \ + REPORT_SIZE(1), 0x08, /* 8 bits per report */ \ + REPORT_COUNT(1), 0x08, /* output report count - 8-byte LedWiz format */ \ + 0x09, 0x01, /* usage */ \ + 0x91, 0x01, /* Output (array) */ \ + \ + END_COLLECTION(0) + + +#define HID_REPORT_STAT \ + USAGE_PAGE(1), 0x01, /* Generic desktop */ \ + USAGE(1), 0x00, /* Undefined */ \ + COLLECTION(1), 0x01, /* Application */ \ + REPORT_ID(1), REPORT_ID_STAT, \ + USAGE_PAGE(1), 0x06, /* generic device controls */ \ + USAGE(1), 0x00, /* undefined device control */ \ + LOGICAL_MINIMUM(1), 0x00, /* 8-bit value range */ \ + LOGICAL_MAXIMUM(1), 0xFF, \ + REPORT_SIZE(1), 0x08, /* 8 bits per report */ \ + REPORT_COUNT(1), reportLen, /* 'reportLen' reports==bytes */ \ + INPUT(1), 0x02, /* Data, Variable, Absolute */ \ + END_COLLECTION(0) - USAGE_PAGE(1), 0x09, // Buttons - USAGE_MINIMUM(1), 0x01, // { buttons } - USAGE_MAXIMUM(1), 0x20, // { 1-32 } - LOGICAL_MINIMUM(1), 0x00, // 1-bit buttons - 0... - LOGICAL_MAXIMUM(1), 0x01, // ...to 1 - REPORT_SIZE(1), 0x01, // 1 bit per report - REPORT_COUNT(1), 0x20, // 32 reports - UNIT_EXPONENT(1), 0x00, // Unit_Exponent (0) - UNIT(1), 0x00, // Unit (None) - INPUT(1), 0x02, // Data, Variable, Absolute - - USAGE_PAGE(1), 0x01, // Generic desktop - USAGE(1), 0x30, // X axis - USAGE(1), 0x31, // Y axis - USAGE(1), 0x32, // Z axis - LOGICAL_MINIMUM(2), 0x00,0xF0, // each value ranges -4096 - LOGICAL_MAXIMUM(2), 0x00,0x10, // ...to +4096 - REPORT_SIZE(1), 0x10, // 16 bits per report - REPORT_COUNT(1), 0x03, // 3 reports (X, Y, Z) - INPUT(1), 0x02, // Data, Variable, Absolute - - // output report (host to device) - REPORT_SIZE(1), 0x08, // 8 bits per report - REPORT_COUNT(1), 0x08, // output report count - 8-byte LedWiz format - 0x09, 0x01, // usage - 0x91, 0x01, // Output (array) +#define HID_REPORT_KB \ + USAGE_PAGE(1), 0x01, /* Generic Desktop */ \ + USAGE(1), 0x06, /* Keyboard */ \ + \ + /* Keyboard keys */ \ + COLLECTION(1), 0x01, /* Application */ \ + REPORT_ID(1), REPORT_ID_KB, \ + \ + /* input report (device to host) - regular keys */ \ + REPORT_COUNT(1), 0x06, \ + REPORT_SIZE(1), 0x08, \ + LOGICAL_MINIMUM(1), 0x00, \ + LOGICAL_MAXIMUM(1), 0x65, \ + USAGE_PAGE(1), 0x07, /* Key Codes */ \ + USAGE_MINIMUM(1), 0x00, \ + USAGE_MAXIMUM(1), 0x65, \ + INPUT(1), 0x00, /* Data, Array */ \ + \ + /* input report (device to host) - modifier keys */ \ + USAGE_PAGE(1), 0x07, /* Key Codes */ \ + USAGE_MINIMUM(1), 0xE0, \ + USAGE_MAXIMUM(1), 0xE7, \ + LOGICAL_MINIMUM(1), 0x00, \ + LOGICAL_MAXIMUM(1), 0x01, \ + REPORT_SIZE(1), 0x01, \ + REPORT_COUNT(1), 0x08, \ + INPUT(1), 0x02, /* Data, Variable, Absolute */ \ + REPORT_COUNT(1), 0x01, \ + REPORT_SIZE(1), 0x08, \ + INPUT(1), 0x01, /* Constant */ \ + \ + /* output report (host to device) - LED status */ \ + REPORT_COUNT(1), 0x05, \ + REPORT_SIZE(1), 0x01, \ + USAGE_PAGE(1), 0x08, /* LEDs */ \ + USAGE_MINIMUM(1), 0x01, \ + USAGE_MAXIMUM(1), 0x05, \ + OUTPUT(1), 0x02, /* Data, Variable, Absolute */ \ + REPORT_COUNT(1), 0x01, \ + REPORT_SIZE(1), 0x03, \ + OUTPUT(1), 0x01, /* Constant */ \ + END_COLLECTION(0), \ + \ + /* Media Control Keys */ \ + USAGE_PAGE(1), 0x0C, \ + USAGE(1), 0x01, \ + COLLECTION(1), 0x01, \ + /* input report (device to host) */ \ + REPORT_ID(1), REPORT_ID_MEDIA, \ + USAGE_PAGE(1), 0x0C, \ + LOGICAL_MINIMUM(1), 0x00, \ + LOGICAL_MAXIMUM(1), 0x01, \ + REPORT_SIZE(1), 0x01, \ + REPORT_COUNT(1), 0x07, \ + USAGE(1), 0xE2, /* Mute -> 0x01 */ \ + USAGE(1), 0xE9, /* Volume Up -> 0x02 */ \ + USAGE(1), 0xEA, /* Volume Down -> 0x04 */ \ + USAGE(1), 0xB5, /* Next Track -> 0x08 */ \ + USAGE(1), 0xB6, /* Previous Track -> 0x10 */ \ + USAGE(1), 0xB7, /* Stop -> 0x20 */ \ + USAGE(1), 0xCD, /* Play / Pause -> 0x40 */ \ + INPUT(1), 0x02, /* Input (Data, Variable, Absolute) -> 0x80 */ \ + REPORT_COUNT(1), 0x01, \ + INPUT(1), 0x01, \ + END_COLLECTION(0) +#define HID_REPORT_LW \ + USAGE_PAGE(1), 0x01, /* Generic desktop */ \ + USAGE(1), 0x00, /* Undefined */ \ + COLLECTION(1), 0x01, /* Application */ \ + /* output report (host to device) */ \ + REPORT_ID(1), REPORT_ID_JS, \ + REPORT_SIZE(1), 0x08, /* 8 bits per report */ \ + REPORT_COUNT(1), 0x08, /* output report count (LEDWiz messages) */ \ + 0x09, 0x01, /* usage */ \ + 0x91, 0x01, /* Output (array) */ \ + END_COLLECTION(0) + + +// Joystick + Keyboard + LedWiz +static const uint8_t reportDescriptorJS[] = +{ + USAGE_PAGE(1), 0x01, /* Generic desktop */ \ + USAGE(1), 0x04, /* Joystick */ \ + COLLECTION(1), 0x01, /* Application */ \ + + HID_REPORT_JS, + HID_REPORT_STAT, + HID_REPORT_KB, + END_COLLECTION(0) }; -// -// USB HID Report Descriptor - Keyboard/Media Control -// +// Keyboard + LedWiz static const uint8_t reportDescriptorKB[] = { - USAGE_PAGE(1), 0x01, // Generic Desktop - USAGE(1), 0x06, // Keyboard - COLLECTION(1), 0x01, // Application - REPORT_ID(1), REPORT_ID_KB, - - USAGE_PAGE(1), 0x07, // Key Codes - USAGE_MINIMUM(1), 0xE0, - USAGE_MAXIMUM(1), 0xE7, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x08, - INPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x08, - INPUT(1), 0x01, // Constant - - REPORT_COUNT(1), 0x05, - REPORT_SIZE(1), 0x01, - USAGE_PAGE(1), 0x08, // LEDs - USAGE_MINIMUM(1), 0x01, - USAGE_MAXIMUM(1), 0x05, - OUTPUT(1), 0x02, // Data, Variable, Absolute - REPORT_COUNT(1), 0x01, - REPORT_SIZE(1), 0x03, - OUTPUT(1), 0x01, // Constant - - REPORT_COUNT(1), 0x06, - REPORT_SIZE(1), 0x08, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x65, - USAGE_PAGE(1), 0x07, // Key Codes - USAGE_MINIMUM(1), 0x00, - USAGE_MAXIMUM(1), 0x65, - INPUT(1), 0x00, // Data, Array - END_COLLECTION(0), - - // Media Control - USAGE_PAGE(1), 0x0C, - USAGE(1), 0x01, - COLLECTION(1), 0x01, - REPORT_ID(1), REPORT_ID_MEDIA, - USAGE_PAGE(1), 0x0C, - LOGICAL_MINIMUM(1), 0x00, - LOGICAL_MAXIMUM(1), 0x01, - REPORT_SIZE(1), 0x01, - REPORT_COUNT(1), 0x07, - USAGE(1), 0xE2, // Mute -> 0x01 - USAGE(1), 0xE9, // Volume Up -> 0x02 - USAGE(1), 0xEA, // Volume Down -> 0x04 - USAGE(1), 0xB5, // Next Track -> 0x08 - USAGE(1), 0xB6, // Previous Track -> 0x10 - USAGE(1), 0xB7, // Stop -> 0x20 - USAGE(1), 0xCD, // Play / Pause -> 0x40 - INPUT(1), 0x02, // Input (Data, Variable, Absolute) -> 0x80 - REPORT_COUNT(1), 0x01, - INPUT(1), 0x01, - END_COLLECTION(0), + HID_REPORT_LW, + HID_REPORT_STAT, + HID_REPORT_KB }; -// -// USB HID Report Descriptor - LedWiz only, with no joystick or keyboard -// input reporting -// -static const uint8_t reportDescriptorLW[] = -{ - USAGE_PAGE(1), 0x01, // Generic desktop - USAGE(1), 0x00, // Undefined - - COLLECTION(1), 0x01, // Application - - // input report (device to host) - USAGE_PAGE(1), 0x06, // generic device controls - for config status - USAGE(1), 0x00, // undefined device control - LOGICAL_MINIMUM(1), 0x00, // 8-bit values - LOGICAL_MAXIMUM(1), 0xFF, - REPORT_SIZE(1), 0x08, // 8 bits per report - REPORT_COUNT(1), reportLen, // standard report length (same as if we were in joystick mode) - INPUT(1), 0x02, // Data, Variable, Absolute - - // output report (host to device) - REPORT_SIZE(1), 0x08, // 8 bits per report - REPORT_COUNT(1), 0x08, // output report count (LEDWiz messages) - 0x09, 0x01, // usage - 0x91, 0x01, // Output (array) - - END_COLLECTION(0) +// LedWiz only +static const uint8_t reportDescriptorLW[] = +{ + HID_REPORT_LW, + HID_REPORT_STAT }; - const uint8_t *USBJoystick::reportDesc(int idx, uint16_t &len) { - switch (idx) + // we only have one interface (#0) + if (idx != 0) { - case 0: - // If the joystick is enabled, this is the joystick. - // Otherwise, it's the plain LedWiz control interface. - if (enableJoystick) - { - len = sizeof(reportDescriptorJS); - return reportDescriptorJS; - } - else - { - len = sizeof(reportDescriptorLW); - return reportDescriptorLW; - } - - case 1: - // This is the keyboard, if enabled. - if (useKB) - { - len = sizeof(reportDescriptorKB); - return reportDescriptorKB; - } - else - { - len = 0; - return 0; - } - - default: - // Unknown interface ID len = 0; return 0; } + + // figure which type of reports we generate according to which + // features are enabled + if (enableJoystick) + { + // joystick enabled - use the JS + KB + LW descriptor + len = sizeof(reportDescriptorJS); + return reportDescriptorJS; + } + else if (useKB) + { + // joystick disabled, keyboard enabled - use KB + LW + len = sizeof(reportDescriptorKB); + return reportDescriptorKB; + } + else + { + // joystick and keyboard disabled - LW only + len = sizeof(reportDescriptorLW); + return reportDescriptorLW; + } } const uint8_t *USBJoystick::stringImanufacturerDesc() { @@ -572,10 +611,18 @@ // the interfaces once the information is cached, causing connection failures. // The cache key includes the device serial number, though, so this can be // resolved by changing the serial number when the interface setup changes. + // + // The version suffix serves a similar purpose, to force a new Windows cache + // key whenever we make changes in the USB descriptors that require a refresh + // on the Windows side. The version here is completely unrelated to any other + // version numbers throughout the system; it's purely internal to this class + // and doesn't have to be synced to anything else. There aren't any particular + // rules about when it needs to be changed; we'll change it as needed when we + // observe the need for it due to caching problems on Windows. char xbuf[numChars + 1]; uint32_t x = SIM->UIDML; static char ifcCode[] = "LJKC"; - sprintf(xbuf, "PSC%08lX%08lX%c008", + sprintf(xbuf, "PSC%08lX%08lX%c009", SIM->UIDML, SIM->UIDL, ifcCode[(enableJoystick ? 0x01 : 0x00) | (useKB ? 0x02 : 0x00)]); @@ -607,165 +654,67 @@ const uint8_t *USBJoystick::configurationDesc() { - int rptlen0 = reportDescLength(0); - int rptlen1 = reportDescLength(1); - if (useKB) + int rptlen = reportDescLength(0); + const int cfglen = + ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) + + (1 * INTERFACE_DESCRIPTOR_LENGTH) + + (1 * HID_DESCRIPTOR_LENGTH) + + (2 * ENDPOINT_DESCRIPTOR_LENGTH)); + static uint8_t configurationDescriptor[] = { - const int cfglenKB = - ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) - + (2 * INTERFACE_DESCRIPTOR_LENGTH) - + (2 * HID_DESCRIPTOR_LENGTH) - + (4 * ENDPOINT_DESCRIPTOR_LENGTH)); - static uint8_t configurationDescriptorWithKB[] = - { - CONFIGURATION_DESCRIPTOR_LENGTH,// bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(cfglenKB), // wTotalLength (LSB) - MSB(cfglenKB), // wTotalLength (MSB) - 0x02, // bNumInterfaces - TWO INTERFACES (JOYSTICK + KEYBOARD) - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPower - - // ***** INTERFACE 0 - JOYSTICK/LEDWIZ ****** - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_NONE, // bInterfaceSubClass - HID_PROTOCOL_NONE, // bInterfaceProtocol - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - LSB(rptlen0), // wDescriptorLength (LSB) - MSB(rptlen0), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_IN), // bEndpointAddress - EPINT == EP1 - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - EPINT == EP1 - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - // ****** INTERFACE 1 - KEYBOARD ****** - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_BOOT, // bInterfaceSubClass - HID_PROTOCOL_KB, // bInterfaceProtocol - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - LSB(rptlen1), // wDescriptorLength (LSB) - MSB(rptlen1), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EP4IN), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EP4OUT), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) + // Configuration descriptor + CONFIGURATION_DESCRIPTOR_LENGTH,// bLength + CONFIGURATION_DESCRIPTOR, // bDescriptorType + LSB(cfglen), // wTotalLength (LSB) + MSB(cfglen), // wTotalLength (MSB) + 0x01, // bNumInterfaces + DEFAULT_CONFIGURATION, // bConfigurationValue + 0x00, // iConfiguration + C_RESERVED | C_SELF_POWERED, // bmAttributes + C_POWER(0), // bMaxPower + + // Interface descriptor + INTERFACE_DESCRIPTOR_LENGTH, // bLength + INTERFACE_DESCRIPTOR, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + HID_CLASS, // bInterfaceClass + HID_SUBCLASS_NONE, // bInterfaceSubClass + HID_PROTOCOL_NONE, // bInterfaceProtocol + 0x00, // iInterface + + // HID descriptor, with link to report descriptor + HID_DESCRIPTOR_LENGTH, // bLength + HID_DESCRIPTOR, // bDescriptorType + LSB(HID_VERSION_1_11), // bcdHID (LSB) + MSB(HID_VERSION_1_11), // bcdHID (MSB) + 0x00, // bCountryCode + 0x01, // bNumDescriptors + REPORT_DESCRIPTOR, // bDescriptorType + LSB(rptlen), // wDescriptorLength (LSB) + MSB(rptlen), // wDescriptorLength (MSB) + + // IN endpoint descriptor + ENDPOINT_DESCRIPTOR_LENGTH, // bLength + ENDPOINT_DESCRIPTOR, // bDescriptorType + PHY_TO_DESC(EPINT_IN), // bEndpointAddress - EPINT == EP1 + E_INTERRUPT, // bmAttributes + LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) + MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) + 1, // bInterval (milliseconds) + + // OUT endpoint descriptor + ENDPOINT_DESCRIPTOR_LENGTH, // bLength + ENDPOINT_DESCRIPTOR, // bDescriptorType + PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - EPINT == EP1 + E_INTERRUPT, // bmAttributes + LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) + MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) + 1 // bInterval (milliseconds) + }; - }; - - // Keyboard + joystick interfaces - return configurationDescriptorWithKB; - } - else - { - // No keyboard - joystick interface only - const int cfglenNoKB = - ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) - + (1 * INTERFACE_DESCRIPTOR_LENGTH) - + (1 * HID_DESCRIPTOR_LENGTH) - + (2 * ENDPOINT_DESCRIPTOR_LENGTH)); - static uint8_t configurationDescriptorNoKB[] = - { - CONFIGURATION_DESCRIPTOR_LENGTH,// bLength - CONFIGURATION_DESCRIPTOR, // bDescriptorType - LSB(cfglenNoKB), // wTotalLength (LSB) - MSB(cfglenNoKB), // wTotalLength (MSB) - 0x01, // bNumInterfaces - DEFAULT_CONFIGURATION, // bConfigurationValue - 0x00, // iConfiguration - C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPower - - INTERFACE_DESCRIPTOR_LENGTH, // bLength - INTERFACE_DESCRIPTOR, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - HID_CLASS, // bInterfaceClass - HID_SUBCLASS_NONE, // bInterfaceSubClass - HID_PROTOCOL_NONE, // bInterfaceProtocol (keyboard) - 0x00, // iInterface - - HID_DESCRIPTOR_LENGTH, // bLength - HID_DESCRIPTOR, // bDescriptorType - LSB(HID_VERSION_1_11), // bcdHID (LSB) - MSB(HID_VERSION_1_11), // bcdHID (MSB) - 0x00, // bCountryCode - 0x01, // bNumDescriptors - REPORT_DESCRIPTOR, // bDescriptorType - (uint8_t)(LSB(rptlen0)), // wDescriptorLength (LSB) - (uint8_t)(MSB(rptlen0)), // wDescriptorLength (MSB) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_IN), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) - - ENDPOINT_DESCRIPTOR_LENGTH, // bLength - ENDPOINT_DESCRIPTOR, // bDescriptorType - PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - E_INTERRUPT, // bmAttributes - LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1 // bInterval (milliseconds) - }; - - return configurationDescriptorNoKB; - } + return configurationDescriptor; } // Set the configuration. We need to set up the endpoints for @@ -776,19 +725,10 @@ if (configuration != DEFAULT_CONFIGURATION) return false; - // Configure endpoint 1 - we use this in all cases, for either - // the combined joystick/ledwiz interface or just the ledwiz interface + // Configure endpoint 1 addEndpoint(EPINT_IN, MAX_REPORT_JS_TX + 1); addEndpoint(EPINT_OUT, MAX_REPORT_JS_RX + 1); readStart(EPINT_OUT, MAX_REPORT_JS_TX + 1); - - // if the keyboard is enabled, configure endpoint 4 for the kb interface - if (useKB) - { - addEndpoint(EP4IN, MAX_REPORT_KB_TX + 1); - addEndpoint(EP4OUT, MAX_REPORT_KB_RX + 1); - readStart(EP4OUT, MAX_REPORT_KB_TX + 1); - } // success return true; @@ -806,33 +746,31 @@ bool USBJoystick::EP1_OUT_callback() { // Read this message - union { - LedWizMsg msg; - uint8_t buf[MAX_HID_REPORT_SIZE]; - } buf; + uint8_t buf[MAX_HID_REPORT_SIZE]; uint32_t bytesRead = 0; - USBDevice::readEP(EP1OUT, buf.buf, &bytesRead, MAX_HID_REPORT_SIZE); + USBDevice::readEP(EP1OUT, buf, &bytesRead, MAX_HID_REPORT_SIZE); - // if it's the right length, queue it to our circular buffer - if (bytesRead == 8) - lwbuf.write(buf.msg); + // check the report type + switch (buf[0]) + { + case REPORT_ID_JS: + // Joystick/ledwiz. These are LedWiz or private protocol command + // messages. Queue to the incoming LW command list. + if (bytesRead == 9) + lwbuf.write((LedWizMsg *)&buf[1]); + break; + + case REPORT_ID_KB: + // Keyboard. These are standard USB keyboard protocol messages, + // telling us the shift key LED status. We don't do anything with + // these; just accept and ignore them. + break; + + default: + // Other report types are unexpected; just ignore them. + break; + } // start the next read return readStart(EP1OUT, MAX_HID_REPORT_SIZE); } - -// Handle incoming messages on the keyboard interface = endpoint 4. -// The host uses this to send updates for the keyboard indicator LEDs -// (caps lock, num lock, etc). We don't do anything with these, but -// we have to read them to keep the pipe open. -bool USBJoystick::EP4_OUT_callback() -{ - // read this message - uint32_t bytesRead = 0; - uint8_t led[MAX_HID_REPORT_SIZE]; - USBDevice::readEP(EP4OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); - - // start the next read - return readStart(EP4OUT, MAX_HID_REPORT_SIZE); -} -