Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: USBJoystick/USBJoystick.cpp
- Revision:
- 54:fd77a6b2f76c
- Parent:
- 53:9b2611964afc
- Child:
- 61:3c7e6e9ec355
--- a/USBJoystick/USBJoystick.cpp Fri Apr 22 17:58:35 2016 +0000 +++ b/USBJoystick/USBJoystick.cpp Sat Apr 30 17:43:38 2016 +0000 @@ -55,7 +55,7 @@ #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) (put((idx)+2, val), put(idx, (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); @@ -496,7 +496,7 @@ }; -const uint8_t *USBJoystick::reportDescN(int idx) +const uint8_t *USBJoystick::reportDesc(int idx, uint16_t &len) { switch (idx) { @@ -506,12 +506,12 @@ // feature is enabled. if (enableJoystick) { - reportLength = sizeof(reportDescriptorJS); + len = sizeof(reportDescriptorJS); return reportDescriptorJS; } else { - reportLength = sizeof(reportDescriptorLW); + len = sizeof(reportDescriptorLW); return reportDescriptorLW; } @@ -519,18 +519,18 @@ // Interface 1 is the keyboard, only if it's enabled if (useKB) { - reportLength = sizeof(reportDescriptorKB); + len = sizeof(reportDescriptorKB); return reportDescriptorKB; } else { - reportLength = 0; + len = 0; return 0; } default: // Unknown interface ID - reportLength = 0; + len = 0; return 0; } } @@ -544,13 +544,51 @@ return stringImanufacturerDescriptor; } -const uint8_t *USBJoystick::stringIserialDesc() { - static const uint8_t stringIserialDescriptor[] = { - 0x16, /*bLength*/ - STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ - '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/ - }; - return stringIserialDescriptor; +const uint8_t *USBJoystick::stringIserialDesc() +{ + // set up a buffer with the length prefix and descriptor type + static uint8_t buf[2 + (3+16+1)*2]; + uint8_t *dst = buf; + *dst++ = sizeof(buf); + *dst++ = STRING_DESCRIPTOR; + + // Create an ASCII version of our unique serial number string: + // + // PSCxxxxxxxxxxxxxxxxi + // + // where: + // + // xxx... = decimal representation of low 64 bits of CPU ID (16 hex digits) + // i = interface type: first character is J if joystick is enabled, + // L = LedWiz/control interface only, no input + // J = Joystick + LedWiz + // K = Keyboard + LedWiz + // C = Joystick + Keyboard + LedWiz ("C" for combo) + // + // The suffix for the interface type resolves a problem on some Windows systems + // when switching between interface types. Windows can cache device information + // that includes the interface descriptors, and it won't recognize a change in + // 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. + char xbuf[3+16+1+1]; + uint32_t x = SIM->UIDML; + static char ifcCode[] = "LJKC"; + sprintf(xbuf, "PSC%08lX%08lX%c", + SIM->UIDML, + SIM->UIDL, + ifcCode[(enableJoystick ? 0x01 : 0x00) | (useKB ? 0x02 : 0x00)]); + + // copy the ascii bytes into the descriptor buffer, converting to unicode + // 16-bit little-endian characters + for (char *src = xbuf ; *src != '\0' && dst < buf + sizeof(buf) ; ) + { + *dst++ = *src++; + *dst++ = '\0'; + } + + // return the buffer + return buf; } const uint8_t *USBJoystick::stringIproductDesc() { @@ -568,8 +606,8 @@ const uint8_t *USBJoystick::configurationDesc() { - int rptlen0 = reportDescLengthN(0); - int rptlen1 = reportDescLengthN(1); + int rptlen0 = reportDescLength(0); + int rptlen1 = reportDescLength(1); if (useKB) { const int cfglenKB = @@ -587,7 +625,7 @@ DEFAULT_CONFIGURATION, // bConfigurationValue 0x00, // iConfiguration C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPowerHello World from Mbed + C_POWER(0), // bMaxPower // ***** INTERFACE 0 - JOYSTICK/LEDWIZ ****** INTERFACE_DESCRIPTOR_LENGTH, // bLength @@ -661,7 +699,7 @@ E_INTERRUPT, // bmAttributes LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) + 1 // bInterval (milliseconds) }; // Keyboard + joystick interfaces @@ -685,7 +723,7 @@ DEFAULT_CONFIGURATION, // bConfigurationValue 0x00, // iConfiguration C_RESERVED | C_SELF_POWERED, // bmAttributes - C_POWER(0), // bMaxPowerHello World from Mbed + C_POWER(0), // bMaxPower INTERFACE_DESCRIPTOR_LENGTH, // bLength INTERFACE_DESCRIPTOR, // bDescriptorType @@ -721,7 +759,7 @@ E_INTERRUPT, // bmAttributes LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) - 1, // bInterval (milliseconds) + 1 // bInterval (milliseconds) }; return configurationDescriptorNoKB;