Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
USBJoystick.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * Modified Mouse code for Joystick - WH 2012 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without 00006 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00007 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00008 * Software is furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 #include "stdint.h" 00021 #include "USBJoystick.h" 00022 00023 #include "config.h" // Pinscape configuration 00024 00025 00026 00027 // Maximum report sizes 00028 const int MAX_REPORT_JS_TX = USBJoystick::reportLen; 00029 const int MAX_REPORT_JS_RX = 8; 00030 const int MAX_REPORT_KB_TX = 8; 00031 const int MAX_REPORT_KB_RX = 4; 00032 00033 bool USBJoystick::update(int16_t x, int16_t y, int16_t z, uint32_t buttons, uint16_t status) 00034 { 00035 _x = x; 00036 _y = y; 00037 _z = z; 00038 _buttonsLo = (uint16_t)(buttons & 0xffff); 00039 _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff); 00040 _status = status; 00041 00042 // send the report 00043 return update(); 00044 } 00045 00046 bool USBJoystick::update() 00047 { 00048 HID_REPORT report; 00049 00050 // Fill the report according to the Joystick Descriptor 00051 #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff) 00052 #define putbe(idx, val) (report.data[(idx)+1] = (val) & 0xff, report.data[idx] = ((val) >> 8) & 0xff) 00053 #define putl(idx, val) (put(idx, val), put((idx)+2, (val) >> 16)) 00054 #define putlbe(idx, val) (putbe((idx)+2, val), putbe(idx, (val) >> 16)) 00055 #define put64(idx, val) (putl(idx, val), putl((idx)+4, (val) >> 32)) 00056 put(0, _status); 00057 put(2, 0); // second word of status - zero in high bit identifies as normal joystick report 00058 put(4, _buttonsLo); 00059 put(6, _buttonsHi); 00060 put(8, _x); 00061 put(10, _y); 00062 put(12, _z); 00063 00064 // important: keep reportLen in sync with the actual byte length of 00065 // the reports we build here 00066 report.length = reportLen; 00067 00068 // send the report 00069 return sendTO(&report, 100); 00070 } 00071 00072 bool USBJoystick::kbUpdate(uint8_t data[8]) 00073 { 00074 // set up the report 00075 HID_REPORT report; 00076 report.data[0] = REPORT_ID_KB; // report ID = keyboard 00077 memcpy(&report.data[1], data, 8); // copy the kb report data 00078 report.length = 9; // length = ID prefix + kb report length 00079 00080 // send it to endpoint 4 (the keyboard interface endpoint) 00081 return writeTO(EP4IN, report.data, report.length, MAX_PACKET_SIZE_EPINT, 100); 00082 } 00083 00084 bool USBJoystick::mediaUpdate(uint8_t data) 00085 { 00086 // set up the report 00087 HID_REPORT report; 00088 report.data[0] = REPORT_ID_MEDIA; // report ID = media 00089 report.data[1] = data; // key pressed bits 00090 report.length = 2; 00091 00092 // send it 00093 return writeTO(EP4IN, report.data, report.length, MAX_PACKET_SIZE_EPINT, 100); 00094 } 00095 00096 bool USBJoystick::sendPlungerStatus( 00097 int npix, int plungerPos, int flags, uint32_t avgScanTime, uint32_t processingTime) 00098 { 00099 HID_REPORT report; 00100 00101 // Set the special status bits to indicate it's an extended 00102 // exposure report. 00103 put(0, 0x87FF); 00104 00105 // start at the second byte 00106 int ofs = 2; 00107 00108 // write the report subtype (0) to byte 2 00109 report.data[ofs++] = 0; 00110 00111 // write the number of pixels to bytes 3-4 00112 put(ofs, uint16_t(npix)); 00113 ofs += 2; 00114 00115 // write the detected plunger position to bytes 5-6 00116 put(ofs, uint16_t(plungerPos)); 00117 ofs += 2; 00118 00119 // Add the calibration mode flag if applicable 00120 extern bool plungerCalMode; 00121 if (plungerCalMode) flags |= 0x04; 00122 00123 // write the flags to byte 7 00124 report.data[ofs++] = flags; 00125 00126 // write the average scan time in 10us intervals to bytes 8-10 00127 uint32_t t = uint32_t(avgScanTime / 10); 00128 report.data[ofs++] = t & 0xff; 00129 report.data[ofs++] = (t >> 8) & 0xff; 00130 report.data[ofs++] = (t >> 16) & 0xff; 00131 00132 // write the processing time to bytes 11-13 00133 t = uint32_t(processingTime / 10); 00134 report.data[ofs++] = t & 0xff; 00135 report.data[ofs++] = (t >> 8) & 0xff; 00136 report.data[ofs++] = (t >> 16) & 0xff; 00137 00138 // send the report 00139 report.length = reportLen; 00140 return sendTO(&report, 100); 00141 } 00142 00143 bool USBJoystick::sendPlungerStatus2( 00144 int nativeScale, 00145 int jitterLo, int jitterHi, int rawPos, 00146 int axcTime) 00147 { 00148 HID_REPORT report; 00149 memset(report.data, 0, sizeof(report.data)); 00150 00151 // Set the special status bits to indicate it's an extended 00152 // exposure report. 00153 put(0, 0x87FF); 00154 00155 // start at the second byte 00156 int ofs = 2; 00157 00158 // write the report subtype (1) to byte 2 00159 report.data[ofs++] = 1; 00160 00161 // write the native scale to bytes 3:4 00162 put(ofs, uint16_t(nativeScale)); 00163 ofs += 2; 00164 00165 // limit the jitter filter bounds to the native scale 00166 if (jitterLo < 0) 00167 jitterLo = 0; 00168 else if (jitterLo > nativeScale) 00169 jitterLo = nativeScale; 00170 if (jitterHi < 0) 00171 jitterHi = 0; 00172 else if (jitterHi > nativeScale) 00173 jitterHi = nativeScale; 00174 00175 // write the jitter filter window bounds to 5:6 and 7:8 00176 put(ofs, uint16_t(jitterLo)); 00177 ofs += 2; 00178 put(ofs, uint16_t(jitterHi)); 00179 ofs += 2; 00180 00181 // add the raw position 00182 put(ofs, uint16_t(rawPos)); 00183 ofs += 2; 00184 00185 // add the auto-exposure time 00186 put(ofs, uint16_t(axcTime)); 00187 ofs += 2; 00188 00189 // send the report 00190 report.length = reportLen; 00191 return sendTO(&report, 100); 00192 } 00193 00194 bool USBJoystick::sendPlungerStatusBarcode( 00195 int nbits, int codetype, int startOfs, int pixPerBit, int raw, int mask) 00196 { 00197 HID_REPORT report; 00198 memset(report.data, 0, sizeof(report.data)); 00199 00200 // Set the special status bits to indicate it's an extended 00201 // status report for barcode sensors 00202 put(0, 0x87FF); 00203 00204 // start at the second byte 00205 int ofs = 2; 00206 00207 // write the report subtype (2) to byte 2 00208 report.data[ofs++] = 2; 00209 00210 // write the bit count and code type 00211 report.data[ofs++] = nbits; 00212 report.data[ofs++] = codetype; 00213 00214 // write the bar code starting pixel offset 00215 put(ofs, uint16_t(startOfs)); 00216 ofs += 2; 00217 00218 // write the pixel width per bit 00219 report.data[ofs++] = pixPerBit; 00220 00221 // write the raw bar code and success bit mask 00222 put(ofs, uint16_t(raw)); 00223 ofs += 2; 00224 put(ofs, uint16_t(mask)); 00225 ofs += 2; 00226 00227 // send the report 00228 report.length = reportLen; 00229 return sendTO(&report, 100); 00230 } 00231 00232 bool USBJoystick::sendPlungerStatusQuadrature(int chA, int chB) 00233 { 00234 HID_REPORT report; 00235 memset(report.data, 0, sizeof(report.data)); 00236 00237 // set the status bits to indicate that it's an extended 00238 // status report for quadrature sensors 00239 put(0, 0x87FF); 00240 int ofs = 2; 00241 00242 // write the report subtype (3) 00243 report.data[ofs++] = 3; 00244 00245 // write the channel "A" and channel "B" values 00246 report.data[ofs++] = static_cast<uint8_t>(chA); 00247 report.data[ofs++] = static_cast<uint8_t>(chB); 00248 00249 // send the report 00250 report.length = reportLen; 00251 return sendTO(&report, 100); 00252 } 00253 00254 bool USBJoystick::sendPlungerStatusVCNL4010(int filteredProxCount, int rawProxCount) 00255 { 00256 HID_REPORT report; 00257 memset(report.data, 0, sizeof(report.data)); 00258 00259 // set the status bits to indicate that it's an extended 00260 // status report for quadrature sensors 00261 put(0, 0x87FF); 00262 int ofs = 2; 00263 00264 // write the report subtype (4) 00265 report.data[ofs++] = 4; 00266 00267 // write the filtered and raw proximity count from the sensor 00268 put(ofs, static_cast<uint16_t>(filteredProxCount)); 00269 put(ofs + 2, static_cast<uint16_t>(rawProxCount)); 00270 00271 // send the report 00272 report.length = reportLen; 00273 return sendTO(&report, 100); 00274 } 00275 00276 00277 bool USBJoystick::sendPlungerPix(int &idx, int npix, const uint8_t *pix) 00278 { 00279 HID_REPORT report; 00280 00281 // Set the special status bits to indicate it's an exposure report. 00282 // The high 5 bits of the status word are set to 10000, and the 00283 // low 11 bits are the current pixel index. 00284 uint16_t s = idx | 0x8000; 00285 put(0, s); 00286 00287 // start at the second byte 00288 int ofs = 2; 00289 00290 // now fill out the remaining bytes with exposure values 00291 report.length = reportLen; 00292 for ( ; ofs < report.length ; ++ofs) 00293 report.data[ofs] = (idx < npix ? pix[idx++] : 0); 00294 00295 // send the report 00296 return sendTO(&report, 100); 00297 } 00298 00299 bool USBJoystick::reportID(int index) 00300 { 00301 HID_REPORT report; 00302 00303 // initially fill the report with zeros 00304 memset(report.data, 0, sizeof(report.data)); 00305 00306 // Set the special status bits to indicate that it's an ID report 00307 uint16_t s = 0x9000; 00308 put(0, s); 00309 00310 // add the requested ID index 00311 report.data[2] = (uint8_t)index; 00312 00313 // figure out which ID we're reporting 00314 switch (index) 00315 { 00316 case 1: 00317 // KL25Z CPU ID 00318 putbe(3, SIM->UIDMH); 00319 putlbe(5, SIM->UIDML); 00320 putlbe(9, SIM->UIDL); 00321 break; 00322 00323 case 2: 00324 // OpenSDA ID. Copy the low-order 80 bits of the OpenSDA ID. 00325 // (The stored value is 128 bits = 16 bytes; we only want the last 00326 // 80 bits = 10 bytes. So skip ahead 16 and back up 10 to get 00327 // the starting point.) 00328 extern const char *getOpenSDAID(); 00329 memcpy(&report.data[3], getOpenSDAID() + 16 - 10, 10); 00330 break; 00331 } 00332 00333 // send the report 00334 report.length = reportLen; 00335 return sendTO(&report, 100); 00336 } 00337 00338 bool USBJoystick::reportBuildInfo(const char *date) 00339 { 00340 HID_REPORT report; 00341 00342 // initially fill the report with zeros 00343 memset(report.data, 0, sizeof(report.data)); 00344 00345 // Set the special status bits to indicate that it's a build 00346 // info report 00347 uint16_t s = 0xA000; 00348 put(0, s); 00349 00350 // Parse the date. This is given in the standard __DATE__ " " __TIME 00351 // macro format, "Mon dd yyyy hh:mm:ss" (e.g., "Feb 16 2016 12:15:06"). 00352 static const char mon[][4] = { 00353 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 00354 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 00355 }; 00356 long dd = (atol(date + 7) * 10000L) // YYYY0000 00357 + (atol(date + 4)); // 000000DD 00358 for (int i = 0 ; i < 12 ; ++i) 00359 { 00360 if (memcmp(mon[i], date, 3) == 0) 00361 { 00362 dd += (i+1)*100; // 0000MM00 00363 break; 00364 } 00365 } 00366 00367 // parse the time into a long formatted as decimal HHMMSS (e.g., 00368 // "12:15:06" turns into 121506 decimal) 00369 long tt = (atol(date+12)*10000) 00370 + (atol(date+15)*100) 00371 + (atol(date+18)); 00372 00373 // store the build date and time 00374 putl(2, dd); 00375 putl(6, tt); 00376 00377 // send the report 00378 report.length = reportLen; 00379 return sendTO(&report, 100); 00380 } 00381 00382 bool USBJoystick::reportConfigVar(const uint8_t *data) 00383 { 00384 HID_REPORT report; 00385 00386 // initially fill the report with zeros 00387 memset(report.data, 0, sizeof(report.data)); 00388 00389 // Set the special status bits to indicate that it's a config 00390 // variable report 00391 uint16_t s = 0x9800; 00392 put(0, s); 00393 00394 // Copy the variable data (7 bytes, starting with the variable ID) 00395 memcpy(report.data + 2, data, 7); 00396 00397 // send the report 00398 report.length = reportLen; 00399 return sendTO(&report, 100); 00400 } 00401 00402 bool USBJoystick::reportConfig( 00403 int numOutputs, int unitNo, 00404 int plungerZero, int plungerMax, int plungerRlsTime, 00405 bool configured, bool sbxpbx, bool newAccelFeatures, 00406 bool flashStatusFeature, bool reportTimingFeatures, 00407 bool chimeLogicFeature, size_t freeHeapBytes) 00408 { 00409 HID_REPORT report; 00410 00411 // initially fill the report with zeros 00412 memset(report.data, 0, sizeof(report.data)); 00413 00414 // Set the special status bits to indicate that it's a config report. 00415 uint16_t s = 0x8800; 00416 put(0, s); 00417 00418 // write the number of configured outputs 00419 put(2, numOutputs); 00420 00421 // write the unit number 00422 put(4, unitNo); 00423 00424 // write the plunger zero and max values 00425 put(6, plungerZero); 00426 put(8, plungerMax); 00427 report.data[10] = uint8_t(plungerRlsTime); 00428 00429 // write the status bits: 00430 // 0x01 -> configuration loaded 00431 // 0x02 -> SBX/PBX protocol extensions supported 00432 // 0x04 -> new accelerometer features supported 00433 // 0x08 -> flash status feature supported 00434 // 0x10 -> joystick report timing features supported 00435 // 0x20 -> chime logic feature supported 00436 report.data[11] = 00437 (configured ? 0x01 : 0x00) 00438 | (sbxpbx ? 0x02 : 0x00) 00439 | (newAccelFeatures ? 0x04 : 0x00) 00440 | (flashStatusFeature ? 0x08 : 0x00) 00441 | (reportTimingFeatures ? 0x10 : 0x00) 00442 | (chimeLogicFeature ? 0x20 : 0x00); 00443 00444 // write the free heap space 00445 put(12, freeHeapBytes); 00446 00447 // send the report 00448 report.length = reportLen; 00449 return sendTO(&report, 100); 00450 } 00451 00452 // report physical button status 00453 bool USBJoystick::reportButtonStatus(int numButtons, const uint8_t *state) 00454 { 00455 // initially fill the report with zeros 00456 HID_REPORT report; 00457 memset(report.data, 0, sizeof(report.data)); 00458 00459 // set the special status bits to indicate that it's a buton report 00460 uint16_t s = 0xA100; 00461 put(0, s); 00462 00463 // write the number of buttons 00464 report.data[2] = uint8_t(numButtons); 00465 00466 // Write the buttons - these are packed into ceil(numButtons/8) bytes. 00467 size_t btnBytes = (numButtons+7)/8; 00468 if (btnBytes + 3 > reportLen) btnBytes = reportLen - 3; 00469 memcpy(&report.data[3], state, btnBytes); 00470 00471 // send the report 00472 report.length = reportLen; 00473 return sendTO(&report, 100); 00474 } 00475 00476 // report raw IR timing codes (for learning mode) 00477 bool USBJoystick::reportRawIR(int n, const uint16_t *data) 00478 { 00479 // initially fill the report with zeros 00480 HID_REPORT report; 00481 memset(report.data, 0, sizeof(report.data)); 00482 00483 // set the special status bits to indicate that it's an IR report 00484 uint16_t s = 0xA200; 00485 put(0, s); 00486 00487 // limit the number of items reported to the available space 00488 if (n > maxRawIR) 00489 n = maxRawIR; 00490 00491 // write the number of codes 00492 report.data[2] = uint8_t(n); 00493 00494 // write the codes 00495 for (int i = 0, ofs = 3 ; i < n ; ++i, ofs += 2) 00496 put(ofs, data[i]); 00497 00498 // send the report 00499 report.length = reportLen; 00500 return sendTO(&report, 100); 00501 } 00502 00503 // report a decoded IR command 00504 bool USBJoystick::reportIRCode(uint8_t pro, uint8_t flags, uint64_t code) 00505 { 00506 // initially fill the report with zeros 00507 HID_REPORT report; 00508 memset(report.data, 0, sizeof(report.data)); 00509 00510 // set the special status bits to indicate that it's an IR report 00511 uint16_t s = 0xA200; 00512 put(0, s); 00513 00514 // set the raw count to 0xFF to flag that it's a decoded command 00515 report.data[2] = 0xFF; 00516 00517 // write the data 00518 report.data[3] = pro; 00519 report.data[4] = flags; 00520 put64(5, code); 00521 00522 // send the report 00523 report.length = reportLen; 00524 return sendTO(&report, 100); 00525 } 00526 00527 bool USBJoystick::move(int16_t x, int16_t y) 00528 { 00529 _x = x; 00530 _y = y; 00531 return update(); 00532 } 00533 00534 bool USBJoystick::setZ(int16_t z) 00535 { 00536 _z = z; 00537 return update(); 00538 } 00539 00540 bool USBJoystick::buttons(uint32_t buttons) 00541 { 00542 _buttonsLo = (uint16_t)(buttons & 0xffff); 00543 _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff); 00544 return update(); 00545 } 00546 00547 bool USBJoystick::updateStatus(uint32_t status) 00548 { 00549 HID_REPORT report; 00550 00551 // Fill the report according to the Joystick Descriptor 00552 memset(report.data, 0, reportLen); 00553 put(0, status); 00554 report.length = reportLen; 00555 00556 // send the report 00557 return sendTO(&report, 100); 00558 } 00559 00560 void USBJoystick::_init() { 00561 00562 _x = 0; 00563 _y = 0; 00564 _z = 0; 00565 _buttonsLo = 0x0000; 00566 _buttonsHi = 0x0000; 00567 _status = 0; 00568 } 00569 00570 00571 // -------------------------------------------------------------------------- 00572 // 00573 // USB HID Report Descriptor - Joystick 00574 // 00575 static const uint8_t reportDescriptorJS[] = 00576 { 00577 USAGE_PAGE(1), 0x01, // Generic desktop 00578 USAGE(1), 0x04, // Joystick 00579 COLLECTION(1), 0x01, // Application 00580 00581 // input report (device to host) 00582 USAGE_PAGE(1), 0x06, // generic device controls - for config status 00583 USAGE(1), 0x00, // undefined device control 00584 LOGICAL_MINIMUM(1), 0x00, // 8-bit values 00585 LOGICAL_MAXIMUM(1), 0xFF, 00586 REPORT_SIZE(1), 0x08, // 8 bits per report 00587 REPORT_COUNT(1), 0x04, // 4 reports (4 bytes) 00588 INPUT(1), 0x02, // Data, Variable, Absolute 00589 00590 USAGE_PAGE(1), 0x09, // Buttons 00591 USAGE_MINIMUM(1), 0x01, // { buttons } 00592 USAGE_MAXIMUM(1), 0x20, // { 1-32 } 00593 LOGICAL_MINIMUM(1), 0x00, // 1-bit buttons - 0... 00594 LOGICAL_MAXIMUM(1), 0x01, // ...to 1 00595 REPORT_SIZE(1), 0x01, // 1 bit per report 00596 REPORT_COUNT(1), 0x20, // 32 reports 00597 UNIT_EXPONENT(1), 0x00, // Unit_Exponent (0) 00598 UNIT(1), 0x00, // Unit (None) 00599 INPUT(1), 0x02, // Data, Variable, Absolute 00600 00601 USAGE_PAGE(1), 0x01, // Generic desktop 00602 USAGE(1), 0x30, // X axis 00603 USAGE(1), 0x31, // Y axis 00604 USAGE(1), 0x32, // Z axis 00605 LOGICAL_MINIMUM(2), 0x00,0xF0, // each value ranges -4096 00606 LOGICAL_MAXIMUM(2), 0x00,0x10, // ...to +4096 00607 REPORT_SIZE(1), 0x10, // 16 bits per report 00608 REPORT_COUNT(1), 0x03, // 3 reports (X, Y, Z) 00609 INPUT(1), 0x02, // Data, Variable, Absolute 00610 00611 // output report (host to device) 00612 REPORT_SIZE(1), 0x08, // 8 bits per report 00613 REPORT_COUNT(1), 0x08, // output report count - 8-byte LedWiz format 00614 0x09, 0x01, // usage 00615 0x91, 0x01, // Output (array) 00616 00617 END_COLLECTION(0) 00618 }; 00619 00620 // Joystick report descriptor with "R" axis reports. This version 00621 // uses Rx and Ry for the accelerometer readings and Rz for the 00622 // plunger, instead of the standard X/Y/Z axes. This can be used 00623 // to avoid conflicts with other devices reporting on the normal 00624 // X/Y/Z axes. 00625 static const uint8_t reportDescriptorJS_RXRYRZ[] = 00626 { 00627 USAGE_PAGE(1), 0x01, // Generic desktop 00628 USAGE(1), 0x04, // Joystick 00629 COLLECTION(1), 0x01, // Application 00630 00631 // input report (device to host) 00632 USAGE_PAGE(1), 0x06, // generic device controls - for config status 00633 USAGE(1), 0x00, // undefined device control 00634 LOGICAL_MINIMUM(1), 0x00, // 8-bit values 00635 LOGICAL_MAXIMUM(1), 0xFF, 00636 REPORT_SIZE(1), 0x08, // 8 bits per report 00637 REPORT_COUNT(1), 0x04, // 4 reports (4 bytes) 00638 INPUT(1), 0x02, // Data, Variable, Absolute 00639 00640 USAGE_PAGE(1), 0x09, // Buttons 00641 USAGE_MINIMUM(1), 0x01, // { buttons } 00642 USAGE_MAXIMUM(1), 0x20, // { 1-32 } 00643 LOGICAL_MINIMUM(1), 0x00, // 1-bit buttons - 0... 00644 LOGICAL_MAXIMUM(1), 0x01, // ...to 1 00645 REPORT_SIZE(1), 0x01, // 1 bit per report 00646 REPORT_COUNT(1), 0x20, // 32 reports 00647 UNIT_EXPONENT(1), 0x00, // Unit_Exponent (0) 00648 UNIT(1), 0x00, // Unit (None) 00649 INPUT(1), 0x02, // Data, Variable, Absolute 00650 00651 USAGE_PAGE(1), 0x01, // Generic desktop 00652 USAGE(1), 0x33, // Rx axis ("X rotation") 00653 USAGE(1), 0x34, // Ry axis 00654 USAGE(1), 0x35, // Rz axis 00655 LOGICAL_MINIMUM(2), 0x00,0xF0, // each value ranges -4096 00656 LOGICAL_MAXIMUM(2), 0x00,0x10, // ...to +4096 00657 REPORT_SIZE(1), 0x10, // 16 bits per report 00658 REPORT_COUNT(1), 0x03, // 3 reports (X, Y, Z) 00659 INPUT(1), 0x02, // Data, Variable, Absolute 00660 00661 // output report (host to device) 00662 REPORT_SIZE(1), 0x08, // 8 bits per report 00663 REPORT_COUNT(1), 0x08, // output report count - 8-byte LedWiz format 00664 0x09, 0x01, // usage 00665 0x91, 0x01, // Output (array) 00666 00667 END_COLLECTION(0) 00668 }; 00669 00670 00671 // 00672 // USB HID Report Descriptor - Keyboard/Media Control 00673 // 00674 static const uint8_t reportDescriptorKB[] = 00675 { 00676 USAGE_PAGE(1), 0x01, // Generic Desktop 00677 USAGE(1), 0x06, // Keyboard 00678 COLLECTION(1), 0x01, // Application 00679 REPORT_ID(1), REPORT_ID_KB, 00680 00681 USAGE_PAGE(1), 0x07, // Key Codes 00682 USAGE_MINIMUM(1), 0xE0, 00683 USAGE_MAXIMUM(1), 0xE7, 00684 LOGICAL_MINIMUM(1), 0x00, 00685 LOGICAL_MAXIMUM(1), 0x01, 00686 REPORT_SIZE(1), 0x01, 00687 REPORT_COUNT(1), 0x08, 00688 INPUT(1), 0x02, // Data, Variable, Absolute 00689 REPORT_COUNT(1), 0x01, 00690 REPORT_SIZE(1), 0x08, 00691 INPUT(1), 0x01, // Constant 00692 00693 REPORT_COUNT(1), 0x05, 00694 REPORT_SIZE(1), 0x01, 00695 USAGE_PAGE(1), 0x08, // LEDs 00696 USAGE_MINIMUM(1), 0x01, 00697 USAGE_MAXIMUM(1), 0x05, 00698 OUTPUT(1), 0x02, // Data, Variable, Absolute 00699 REPORT_COUNT(1), 0x01, 00700 REPORT_SIZE(1), 0x03, 00701 OUTPUT(1), 0x01, // Constant 00702 00703 REPORT_COUNT(1), 0x06, 00704 REPORT_SIZE(1), 0x08, 00705 LOGICAL_MINIMUM(1), 0x00, 00706 LOGICAL_MAXIMUM(1), 0xA4, 00707 USAGE_PAGE(1), 0x07, // Key Codes 00708 USAGE_MINIMUM(1), 0x00, 00709 USAGE_MAXIMUM(1), 0xA4, 00710 INPUT(1), 0x00, // Data, Array 00711 END_COLLECTION(0), 00712 00713 // Media Control 00714 USAGE_PAGE(1), 0x0C, 00715 USAGE(1), 0x01, 00716 COLLECTION(1), 0x01, 00717 REPORT_ID(1), REPORT_ID_MEDIA, 00718 USAGE_PAGE(1), 0x0C, 00719 LOGICAL_MINIMUM(1), 0x00, 00720 LOGICAL_MAXIMUM(1), 0x01, 00721 REPORT_SIZE(1), 0x01, 00722 REPORT_COUNT(1), 0x07, 00723 USAGE(1), 0xE2, // Mute -> 0x01 00724 USAGE(1), 0xE9, // Volume Up -> 0x02 00725 USAGE(1), 0xEA, // Volume Down -> 0x04 00726 USAGE(1), 0xB5, // Next Track -> 0x08 00727 USAGE(1), 0xB6, // Previous Track -> 0x10 00728 USAGE(1), 0xB7, // Stop -> 0x20 00729 USAGE(1), 0xCD, // Play / Pause -> 0x40 00730 INPUT(1), 0x02, // Input (Data, Variable, Absolute) -> 0x80 00731 REPORT_COUNT(1), 0x01, 00732 INPUT(1), 0x01, 00733 END_COLLECTION(0), 00734 }; 00735 00736 // 00737 // USB HID Report Descriptor - LedWiz only, with no joystick or keyboard 00738 // input reporting 00739 // 00740 static const uint8_t reportDescriptorLW[] = 00741 { 00742 USAGE_PAGE(1), 0x01, // Generic desktop 00743 USAGE(1), 0x00, // Undefined 00744 00745 COLLECTION(1), 0x01, // Application 00746 00747 // input report (device to host) 00748 USAGE_PAGE(1), 0x06, // generic device controls - for config status 00749 USAGE(1), 0x00, // undefined device control 00750 LOGICAL_MINIMUM(1), 0x00, // 8-bit values 00751 LOGICAL_MAXIMUM(1), 0xFF, 00752 REPORT_SIZE(1), 0x08, // 8 bits per report 00753 REPORT_COUNT(1), USBJoystick::reportLen, // standard report length (same as if we were in joystick mode) 00754 INPUT(1), 0x02, // Data, Variable, Absolute 00755 00756 // output report (host to device) 00757 REPORT_SIZE(1), 0x08, // 8 bits per report 00758 REPORT_COUNT(1), 0x08, // output report count (LEDWiz messages) 00759 0x09, 0x01, // usage 00760 0x91, 0x01, // Output (array) 00761 00762 END_COLLECTION(0) 00763 }; 00764 00765 00766 const uint8_t *USBJoystick::reportDesc(int idx, uint16_t &len) 00767 { 00768 switch (idx) 00769 { 00770 case 0: 00771 // If the joystick is enabled, this is the joystick. 00772 // Otherwise, it's the plain LedWiz control interface. 00773 if (enableJoystick) 00774 { 00775 switch (axisFormat) 00776 { 00777 case AXIS_FORMAT_XYZ: 00778 default: 00779 len = sizeof(reportDescriptorJS); 00780 return reportDescriptorJS; 00781 00782 case AXIS_FORMAT_RXRYRZ: 00783 len = sizeof(reportDescriptorJS_RXRYRZ); 00784 return reportDescriptorJS_RXRYRZ; 00785 } 00786 } 00787 else 00788 { 00789 len = sizeof(reportDescriptorLW); 00790 return reportDescriptorLW; 00791 } 00792 00793 case 1: 00794 // This is the keyboard, if enabled. 00795 if (useKB) 00796 { 00797 len = sizeof(reportDescriptorKB); 00798 return reportDescriptorKB; 00799 } 00800 else 00801 { 00802 len = 0; 00803 return 0; 00804 } 00805 00806 default: 00807 // Unknown interface ID 00808 len = 0; 00809 return 0; 00810 } 00811 } 00812 00813 const uint8_t *USBJoystick::stringImanufacturerDesc() { 00814 static const uint8_t stringImanufacturerDescriptor[] = { 00815 0x0E, /* bLength */ 00816 STRING_DESCRIPTOR, /* bDescriptorType 0x03 (String Descriptor) */ 00817 'm',0,'j',0,'r',0,'n',0,'e',0,'t',0 /* bString iManufacturer - mjrnet */ 00818 }; 00819 return stringImanufacturerDescriptor; 00820 } 00821 00822 const uint8_t *USBJoystick::stringIserialDesc() 00823 { 00824 // set up a buffer with space for the length prefix byte, descriptor type 00825 // byte, and serial number (as a wide-character string) 00826 const int numChars = 3 + 16 + 1 + 1 + 3; 00827 static uint8_t buf[2 + numChars*2]; 00828 uint8_t *dst = buf; 00829 00830 // store a placeholder for the length, followed by the descriptor type byte 00831 *dst++ = 0; 00832 *dst++ = STRING_DESCRIPTOR; 00833 00834 // Create an ASCII version of our unique serial number string: 00835 // 00836 // PSCxxxxxxxxxxxxxxxxi[a]vvv 00837 // 00838 // where: 00839 // 00840 // xxx... = decimal representation of low 64 bits of CPU ID (16 hex digits) 00841 // i = interface type: first character is J if joystick is enabled, 00842 // L = LedWiz/control interface only, no input 00843 // J = Joystick + LedWiz 00844 // K = Keyboard + LedWiz 00845 // C = Joystick + Keyboard + LedWiz ("C" for combo) 00846 // a = joystick axis types: 00847 // <empty> = X,Y,Z, or no joystick interface at all 00848 // A = Rx,Ry,Rz 00849 // vvv = version suffix 00850 // 00851 // The suffix for the interface type resolves a problem on some Windows systems 00852 // when switching between interface types. Windows can cache device information 00853 // that includes the interface descriptors, and it won't recognize a change in 00854 // the interfaces once the information is cached, causing connection failures. 00855 // The cache key includes the device serial number, though, so this can be 00856 // resolved by changing the serial number when the interface setup changes. 00857 char xbuf[numChars + 1]; 00858 uint32_t x = SIM->UIDML; 00859 static char ifcCode[] = "LJKC"; 00860 static const char *axisCode[] = { "", "A" }; 00861 sprintf(xbuf, "PSC%08lX%08lX%c%s008", 00862 SIM->UIDML, 00863 SIM->UIDL, 00864 ifcCode[(enableJoystick ? 0x01 : 0x00) | (useKB ? 0x02 : 0x00)], 00865 axisCode[(enableJoystick ? axisFormat : 0)]); 00866 00867 // copy the ascii bytes into the descriptor buffer, converting to unicode 00868 // 16-bit little-endian characters 00869 for (char *src = xbuf ; *src != '\0' && dst < buf + sizeof(buf) ; ) 00870 { 00871 *dst++ = *src++; 00872 *dst++ = '\0'; 00873 } 00874 00875 // store the final length (in bytes) in the length prefix byte 00876 buf[0] = dst - buf; 00877 00878 // return the buffer 00879 return buf; 00880 } 00881 00882 const uint8_t *USBJoystick::stringIproductDesc() { 00883 static const uint8_t stringIproductDescriptor[] = { 00884 0x28, /*bLength*/ 00885 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ 00886 'P',0,'i',0,'n',0,'s',0,'c',0,'a',0,'p',0,'e',0, 00887 ' ',0,'C',0,'o',0,'n',0,'t',0,'r',0,'o',0,'l',0, 00888 'l',0,'e',0,'r',0 /*String iProduct */ 00889 }; 00890 return stringIproductDescriptor; 00891 } 00892 00893 #define DEFAULT_CONFIGURATION (1) 00894 00895 const uint8_t *USBJoystick::configurationDesc() 00896 { 00897 int rptlen0 = reportDescLength(0); 00898 int rptlen1 = reportDescLength(1); 00899 if (useKB) 00900 { 00901 const int cfglenKB = 00902 ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) 00903 + (2 * INTERFACE_DESCRIPTOR_LENGTH) 00904 + (2 * HID_DESCRIPTOR_LENGTH) 00905 + (4 * ENDPOINT_DESCRIPTOR_LENGTH)); 00906 static uint8_t configurationDescriptorWithKB[] = 00907 { 00908 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength 00909 CONFIGURATION_DESCRIPTOR, // bDescriptorType 00910 LSB(cfglenKB), // wTotalLength (LSB) 00911 MSB(cfglenKB), // wTotalLength (MSB) 00912 0x02, // bNumInterfaces - TWO INTERFACES (JOYSTICK + KEYBOARD) 00913 DEFAULT_CONFIGURATION, // bConfigurationValue 00914 0x00, // iConfiguration 00915 C_RESERVED | C_SELF_POWERED, // bmAttributes 00916 C_POWER(0), // bMaxPower 00917 00918 // ***** INTERFACE 0 - JOYSTICK/LEDWIZ ****** 00919 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00920 INTERFACE_DESCRIPTOR, // bDescriptorType 00921 0x00, // bInterfaceNumber 00922 0x00, // bAlternateSetting 00923 0x02, // bNumEndpoints 00924 HID_CLASS, // bInterfaceClass 00925 HID_SUBCLASS_NONE, // bInterfaceSubClass 00926 HID_PROTOCOL_NONE, // bInterfaceProtocol 00927 0x00, // iInterface 00928 00929 HID_DESCRIPTOR_LENGTH, // bLength 00930 HID_DESCRIPTOR, // bDescriptorType 00931 LSB(HID_VERSION_1_11), // bcdHID (LSB) 00932 MSB(HID_VERSION_1_11), // bcdHID (MSB) 00933 0x00, // bCountryCode 00934 0x01, // bNumDescriptors 00935 REPORT_DESCRIPTOR, // bDescriptorType 00936 LSB(rptlen0), // wDescriptorLength (LSB) 00937 MSB(rptlen0), // wDescriptorLength (MSB) 00938 00939 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00940 ENDPOINT_DESCRIPTOR, // bDescriptorType 00941 PHY_TO_DESC(EPINT_IN), // bEndpointAddress - EPINT == EP1 00942 E_INTERRUPT, // bmAttributes 00943 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00944 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00945 1, // bInterval (milliseconds) 00946 00947 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00948 ENDPOINT_DESCRIPTOR, // bDescriptorType 00949 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - EPINT == EP1 00950 E_INTERRUPT, // bmAttributes 00951 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00952 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00953 1, // bInterval (milliseconds) 00954 00955 // ****** INTERFACE 1 - KEYBOARD ****** 00956 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00957 INTERFACE_DESCRIPTOR, // bDescriptorType 00958 0x01, // bInterfaceNumber 00959 0x00, // bAlternateSetting 00960 0x02, // bNumEndpoints 00961 HID_CLASS, // bInterfaceClass 00962 HID_SUBCLASS_BOOT, // bInterfaceSubClass 00963 HID_PROTOCOL_KB, // bInterfaceProtocol 00964 0x00, // iInterface 00965 00966 HID_DESCRIPTOR_LENGTH, // bLength 00967 HID_DESCRIPTOR, // bDescriptorType 00968 LSB(HID_VERSION_1_11), // bcdHID (LSB) 00969 MSB(HID_VERSION_1_11), // bcdHID (MSB) 00970 0x00, // bCountryCode 00971 0x01, // bNumDescriptors 00972 REPORT_DESCRIPTOR, // bDescriptorType 00973 LSB(rptlen1), // wDescriptorLength (LSB) 00974 MSB(rptlen1), // wDescriptorLength (MSB) 00975 00976 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00977 ENDPOINT_DESCRIPTOR, // bDescriptorType 00978 PHY_TO_DESC(EP4IN), // bEndpointAddress 00979 E_INTERRUPT, // bmAttributes 00980 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00981 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00982 1, // bInterval (milliseconds) 00983 00984 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00985 ENDPOINT_DESCRIPTOR, // bDescriptorType 00986 PHY_TO_DESC(EP4OUT), // bEndpointAddress 00987 E_INTERRUPT, // bmAttributes 00988 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00989 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00990 1, // bInterval (milliseconds) 00991 00992 }; 00993 00994 // Keyboard + joystick interfaces 00995 return configurationDescriptorWithKB; 00996 } 00997 else 00998 { 00999 // No keyboard - joystick interface only 01000 const int cfglenNoKB = 01001 ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) 01002 + (1 * INTERFACE_DESCRIPTOR_LENGTH) 01003 + (1 * HID_DESCRIPTOR_LENGTH) 01004 + (2 * ENDPOINT_DESCRIPTOR_LENGTH)); 01005 static uint8_t configurationDescriptorNoKB[] = 01006 { 01007 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength 01008 CONFIGURATION_DESCRIPTOR, // bDescriptorType 01009 LSB(cfglenNoKB), // wTotalLength (LSB) 01010 MSB(cfglenNoKB), // wTotalLength (MSB) 01011 0x01, // bNumInterfaces 01012 DEFAULT_CONFIGURATION, // bConfigurationValue 01013 0x00, // iConfiguration 01014 C_RESERVED | C_SELF_POWERED, // bmAttributes 01015 C_POWER(0), // bMaxPower 01016 01017 INTERFACE_DESCRIPTOR_LENGTH, // bLength 01018 INTERFACE_DESCRIPTOR, // bDescriptorType 01019 0x00, // bInterfaceNumber 01020 0x00, // bAlternateSetting 01021 0x02, // bNumEndpoints 01022 HID_CLASS, // bInterfaceClass 01023 HID_SUBCLASS_NONE, // bInterfaceSubClass 01024 HID_PROTOCOL_NONE, // bInterfaceProtocol (keyboard) 01025 0x00, // iInterface 01026 01027 HID_DESCRIPTOR_LENGTH, // bLength 01028 HID_DESCRIPTOR, // bDescriptorType 01029 LSB(HID_VERSION_1_11), // bcdHID (LSB) 01030 MSB(HID_VERSION_1_11), // bcdHID (MSB) 01031 0x00, // bCountryCode 01032 0x01, // bNumDescriptors 01033 REPORT_DESCRIPTOR, // bDescriptorType 01034 (uint8_t)(LSB(rptlen0)), // wDescriptorLength (LSB) 01035 (uint8_t)(MSB(rptlen0)), // wDescriptorLength (MSB) 01036 01037 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 01038 ENDPOINT_DESCRIPTOR, // bDescriptorType 01039 PHY_TO_DESC(EPINT_IN), // bEndpointAddress 01040 E_INTERRUPT, // bmAttributes 01041 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 01042 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 01043 1, // bInterval (milliseconds) 01044 01045 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 01046 ENDPOINT_DESCRIPTOR, // bDescriptorType 01047 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress 01048 E_INTERRUPT, // bmAttributes 01049 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 01050 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 01051 1 // bInterval (milliseconds) 01052 }; 01053 01054 return configurationDescriptorNoKB; 01055 } 01056 } 01057 01058 // Set the configuration. We need to set up the endpoints for 01059 // our active interfaces. 01060 bool USBJoystick::USBCallback_setConfiguration(uint8_t configuration) 01061 { 01062 // we only have one valid configuration 01063 if (configuration != DEFAULT_CONFIGURATION) 01064 return false; 01065 01066 // Configure endpoint 1 - we use this in all cases, for either 01067 // the combined joystick/ledwiz interface or just the ledwiz interface 01068 addEndpoint(EPINT_IN, MAX_REPORT_JS_TX + 1); 01069 addEndpoint(EPINT_OUT, MAX_REPORT_JS_RX + 1); 01070 readStart(EPINT_OUT, MAX_REPORT_JS_TX + 1); 01071 01072 // if the keyboard is enabled, configure endpoint 4 for the kb interface 01073 if (useKB) 01074 { 01075 addEndpoint(EP4IN, MAX_REPORT_KB_TX + 1); 01076 addEndpoint(EP4OUT, MAX_REPORT_KB_RX + 1); 01077 readStart(EP4OUT, MAX_REPORT_KB_TX + 1); 01078 } 01079 01080 // success 01081 return true; 01082 } 01083 01084 // Handle incoming messages on the joystick/LedWiz interface = endpoint 1. 01085 // This interface receives LedWiz protocol commands and commands using our 01086 // custom LedWiz protocol extensions. 01087 // 01088 // We simply queue the messages in our circular buffer for processing in 01089 // the main loop. The circular buffer object is designed for safe access 01090 // from the interrupt handler using the rule that only the interrupt 01091 // handler can change the write pointer, and only the regular code can 01092 // change the read pointer. 01093 bool USBJoystick::EP1_OUT_callback() 01094 { 01095 // Read this message 01096 union { 01097 LedWizMsg msg; 01098 uint8_t buf[MAX_HID_REPORT_SIZE]; 01099 } buf; 01100 uint32_t bytesRead = 0; 01101 USBDevice::readEP(EP1OUT, buf.buf, &bytesRead, MAX_HID_REPORT_SIZE); 01102 01103 // if it's the right length, queue it to our circular buffer 01104 if (bytesRead == 8) 01105 lwbuf.write(buf.msg); 01106 01107 // start the next read 01108 return readStart(EP1OUT, MAX_HID_REPORT_SIZE); 01109 } 01110 01111 // Handle incoming messages on the keyboard interface = endpoint 4. 01112 // The host uses this to send updates for the keyboard indicator LEDs 01113 // (caps lock, num lock, etc). We don't do anything with these, but 01114 // we have to read them to keep the pipe open. 01115 bool USBJoystick::EP4_OUT_callback() 01116 { 01117 // read this message 01118 uint32_t bytesRead = 0; 01119 uint8_t led[MAX_HID_REPORT_SIZE]; 01120 USBDevice::readEP(EP4OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); 01121 01122 // start the next read 01123 return readStart(EP4OUT, MAX_HID_REPORT_SIZE); 01124 } 01125
Generated on Thu Jul 14 2022 12:20:36 by 1.7.2