Arnaud VALLEY / Mbed 2 deprecated Pinscape_Controller_V2_arnoz

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Thu Jun 02 22:52:25 2016 +0000
Revision:
62:f071ccde32a0
Parent:
61:3c7e6e9ec355
Child:
63:5cd1a5f3a41b
EXPERIMENTAL/ABANDONED: Combine all message types (JS+KB+LW) into a single HID interface, as a failed attempt to work around ledwiz.dll crash with multiple interfaces. This approach creates a new incompatibility due to the non-zero report ID.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 3:3514575d4f86 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
mjr 3:3514575d4f86 2 * Modified Mouse code for Joystick - WH 2012
mjr 3:3514575d4f86 3 *
mjr 3:3514575d4f86 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
mjr 3:3514575d4f86 5 * and associated documentation files (the "Software"), to deal in the Software without
mjr 3:3514575d4f86 6 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
mjr 3:3514575d4f86 7 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
mjr 3:3514575d4f86 8 * Software is furnished to do so, subject to the following conditions:
mjr 3:3514575d4f86 9 *
mjr 3:3514575d4f86 10 * The above copyright notice and this permission notice shall be included in all copies or
mjr 3:3514575d4f86 11 * substantial portions of the Software.
mjr 3:3514575d4f86 12 *
mjr 3:3514575d4f86 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
mjr 3:3514575d4f86 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
mjr 3:3514575d4f86 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
mjr 3:3514575d4f86 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mjr 3:3514575d4f86 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
mjr 3:3514575d4f86 18 */
mjr 3:3514575d4f86 19
mjr 3:3514575d4f86 20 #include "stdint.h"
mjr 3:3514575d4f86 21 #include "USBJoystick.h"
mjr 21:5048e16cc9ef 22
mjr 21:5048e16cc9ef 23 #include "config.h" // Pinscape configuration
mjr 21:5048e16cc9ef 24
mjr 35:e959ffba78fd 25
mjr 35:e959ffba78fd 26
mjr 21:5048e16cc9ef 27 // Length of our joystick reports. Important: This must be kept in sync
mjr 21:5048e16cc9ef 28 // with the actual joystick report format sent in update().
mjr 21:5048e16cc9ef 29 const int reportLen = 14;
mjr 21:5048e16cc9ef 30
mjr 48:058ace2aed1d 31 // Maximum report sizes
mjr 48:058ace2aed1d 32 const int MAX_REPORT_JS_TX = reportLen;
mjr 48:058ace2aed1d 33 const int MAX_REPORT_JS_RX = 8;
mjr 48:058ace2aed1d 34
mjr 11:bd9da7088e6e 35 bool USBJoystick::update(int16_t x, int16_t y, int16_t z, uint32_t buttons, uint16_t status)
mjr 3:3514575d4f86 36 {
mjr 3:3514575d4f86 37 _x = x;
mjr 3:3514575d4f86 38 _y = y;
mjr 3:3514575d4f86 39 _z = z;
mjr 11:bd9da7088e6e 40 _buttonsLo = (uint16_t)(buttons & 0xffff);
mjr 11:bd9da7088e6e 41 _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff);
mjr 10:976666ffa4ef 42 _status = status;
mjr 3:3514575d4f86 43
mjr 3:3514575d4f86 44 // send the report
mjr 3:3514575d4f86 45 return update();
mjr 3:3514575d4f86 46 }
mjr 35:e959ffba78fd 47
mjr 11:bd9da7088e6e 48 bool USBJoystick::update()
mjr 11:bd9da7088e6e 49 {
mjr 62:f071ccde32a0 50 // start the report with the report ID
mjr 3:3514575d4f86 51 HID_REPORT report;
mjr 62:f071ccde32a0 52 report.data[0] = REPORT_ID_JS;
mjr 62:f071ccde32a0 53
mjr 3:3514575d4f86 54 // Fill the report according to the Joystick Descriptor
mjr 6:cc35eb643e8f 55 #define put(idx, val) (report.data[idx] = (val) & 0xff, report.data[(idx)+1] = ((val) >> 8) & 0xff)
mjr 53:9b2611964afc 56 #define putbe(idx, val) (report.data[(idx)+1] = (val) & 0xff, report.data[idx] = ((val) >> 8) & 0xff)
mjr 40:cc0d9814522b 57 #define putl(idx, val) (put(idx, val), put((idx)+2, (val) >> 16))
mjr 54:fd77a6b2f76c 58 #define putlbe(idx, val) (putbe((idx)+2, val), putbe(idx, (val) >> 16))
mjr 62:f071ccde32a0 59 put(1, _status);
mjr 62:f071ccde32a0 60 put(3, 0); // second word of status - zero in high bit identifies as normal joystick report
mjr 62:f071ccde32a0 61 put(5, _buttonsLo);
mjr 62:f071ccde32a0 62 put(7, _buttonsHi);
mjr 62:f071ccde32a0 63 put(9, _x);
mjr 62:f071ccde32a0 64 put(11, _y);
mjr 62:f071ccde32a0 65 put(13, _z);
mjr 21:5048e16cc9ef 66
mjr 21:5048e16cc9ef 67 // important: keep reportLen in sync with the actual byte length of
mjr 21:5048e16cc9ef 68 // the reports we build here
mjr 62:f071ccde32a0 69 report.length = reportLen + 1;
mjr 3:3514575d4f86 70
mjr 5:a70c0bce770d 71 // send the report
mjr 10:976666ffa4ef 72 return sendTO(&report, 100);
mjr 10:976666ffa4ef 73 }
mjr 10:976666ffa4ef 74
mjr 35:e959ffba78fd 75 bool USBJoystick::kbUpdate(uint8_t data[8])
mjr 35:e959ffba78fd 76 {
mjr 35:e959ffba78fd 77 // set up the report
mjr 35:e959ffba78fd 78 HID_REPORT report;
mjr 35:e959ffba78fd 79 report.data[0] = REPORT_ID_KB; // report ID = keyboard
mjr 35:e959ffba78fd 80 memcpy(&report.data[1], data, 8); // copy the kb report data
mjr 35:e959ffba78fd 81 report.length = 9; // length = ID prefix + kb report length
mjr 35:e959ffba78fd 82
mjr 35:e959ffba78fd 83 // send it to endpoint 4 (the keyboard interface endpoint)
mjr 35:e959ffba78fd 84 return writeTO(EP4IN, report.data, report.length, MAX_PACKET_SIZE_EPINT, 100);
mjr 35:e959ffba78fd 85 }
mjr 35:e959ffba78fd 86
mjr 35:e959ffba78fd 87 bool USBJoystick::mediaUpdate(uint8_t data)
mjr 35:e959ffba78fd 88 {
mjr 35:e959ffba78fd 89 // set up the report
mjr 35:e959ffba78fd 90 HID_REPORT report;
mjr 35:e959ffba78fd 91 report.data[0] = REPORT_ID_MEDIA; // report ID = media
mjr 35:e959ffba78fd 92 report.data[1] = data; // key pressed bits
mjr 35:e959ffba78fd 93 report.length = 2;
mjr 35:e959ffba78fd 94
mjr 35:e959ffba78fd 95 // send it
mjr 35:e959ffba78fd 96 return writeTO(EP4IN, report.data, report.length, MAX_PACKET_SIZE_EPINT, 100);
mjr 35:e959ffba78fd 97 }
mjr 35:e959ffba78fd 98
mjr 52:8298b2a73eb2 99 bool USBJoystick::sendPlungerStatus(
mjr 52:8298b2a73eb2 100 int npix, int edgePos, int dir, uint32_t avgScanTime, uint32_t processingTime)
mjr 52:8298b2a73eb2 101 {
mjr 62:f071ccde32a0 102 // set up the report ID
mjr 52:8298b2a73eb2 103 HID_REPORT report;
mjr 62:f071ccde32a0 104 report.data[0] = REPORT_ID_STAT;
mjr 52:8298b2a73eb2 105
mjr 52:8298b2a73eb2 106 // Set the special status bits to indicate it's an extended
mjr 52:8298b2a73eb2 107 // exposure report.
mjr 62:f071ccde32a0 108 put(1, 0x87FF);
mjr 52:8298b2a73eb2 109
mjr 52:8298b2a73eb2 110 // start at the second byte
mjr 62:f071ccde32a0 111 int ofs = 3;
mjr 52:8298b2a73eb2 112
mjr 52:8298b2a73eb2 113 // write the report subtype (0) to byte 2
mjr 52:8298b2a73eb2 114 report.data[ofs++] = 0;
mjr 52:8298b2a73eb2 115
mjr 52:8298b2a73eb2 116 // write the number of pixels to bytes 3-4
mjr 52:8298b2a73eb2 117 put(ofs, uint16_t(npix));
mjr 52:8298b2a73eb2 118 ofs += 2;
mjr 52:8298b2a73eb2 119
mjr 52:8298b2a73eb2 120 // write the shadow edge position to bytes 5-6
mjr 52:8298b2a73eb2 121 put(ofs, uint16_t(edgePos));
mjr 52:8298b2a73eb2 122 ofs += 2;
mjr 52:8298b2a73eb2 123
mjr 52:8298b2a73eb2 124 // write the flags to byte 7
mjr 52:8298b2a73eb2 125 extern bool plungerCalMode;
mjr 52:8298b2a73eb2 126 uint8_t flags = 0;
mjr 52:8298b2a73eb2 127 if (dir == 1)
mjr 52:8298b2a73eb2 128 flags |= 0x01;
mjr 52:8298b2a73eb2 129 else if (dir == -1)
mjr 52:8298b2a73eb2 130 flags |= 0x02;
mjr 52:8298b2a73eb2 131 if (plungerCalMode)
mjr 52:8298b2a73eb2 132 flags |= 0x04;
mjr 52:8298b2a73eb2 133 report.data[ofs++] = flags;
mjr 52:8298b2a73eb2 134
mjr 52:8298b2a73eb2 135 // write the average scan time in 10us intervals to bytes 8-10
mjr 52:8298b2a73eb2 136 uint32_t t = uint32_t(avgScanTime / 10);
mjr 52:8298b2a73eb2 137 report.data[ofs++] = t & 0xff;
mjr 52:8298b2a73eb2 138 report.data[ofs++] = (t >> 8) & 0xff;
mjr 52:8298b2a73eb2 139 report.data[ofs++] = (t >> 16) & 0xff;
mjr 52:8298b2a73eb2 140
mjr 52:8298b2a73eb2 141 // write the processing time to bytes 11-13
mjr 52:8298b2a73eb2 142 t = uint32_t(processingTime / 10);
mjr 52:8298b2a73eb2 143 report.data[ofs++] = t & 0xff;
mjr 52:8298b2a73eb2 144 report.data[ofs++] = (t >> 8) & 0xff;
mjr 52:8298b2a73eb2 145 report.data[ofs++] = (t >> 16) & 0xff;
mjr 52:8298b2a73eb2 146
mjr 52:8298b2a73eb2 147 // send the report
mjr 62:f071ccde32a0 148 report.length = reportLen + 1;
mjr 52:8298b2a73eb2 149 return sendTO(&report, 100);
mjr 52:8298b2a73eb2 150 }
mjr 52:8298b2a73eb2 151
mjr 52:8298b2a73eb2 152 bool USBJoystick::sendPlungerPix(int &idx, int npix, const uint8_t *pix)
mjr 10:976666ffa4ef 153 {
mjr 10:976666ffa4ef 154 HID_REPORT report;
mjr 62:f071ccde32a0 155 report.data[0] = REPORT_ID_STAT;
mjr 10:976666ffa4ef 156
mjr 10:976666ffa4ef 157 // Set the special status bits to indicate it's an exposure report.
mjr 10:976666ffa4ef 158 // The high 5 bits of the status word are set to 10000, and the
mjr 10:976666ffa4ef 159 // low 11 bits are the current pixel index.
mjr 10:976666ffa4ef 160 uint16_t s = idx | 0x8000;
mjr 62:f071ccde32a0 161 put(1, s);
mjr 25:e22b88bd783a 162
mjr 25:e22b88bd783a 163 // start at the second byte
mjr 62:f071ccde32a0 164 int ofs = 3;
mjr 25:e22b88bd783a 165
mjr 47:df7a88cd249c 166 // now fill out the remaining bytes with exposure values
mjr 62:f071ccde32a0 167 report.length = reportLen + 1;
mjr 47:df7a88cd249c 168 for ( ; ofs < report.length ; ++ofs)
mjr 47:df7a88cd249c 169 report.data[ofs] = (idx < npix ? pix[idx++] : 0);
mjr 10:976666ffa4ef 170
mjr 10:976666ffa4ef 171 // send the report
mjr 35:e959ffba78fd 172 return sendTO(&report, 100);
mjr 3:3514575d4f86 173 }
mjr 9:fd65b0a94720 174
mjr 53:9b2611964afc 175 bool USBJoystick::reportID(int index)
mjr 40:cc0d9814522b 176 {
mjr 40:cc0d9814522b 177 HID_REPORT report;
mjr 40:cc0d9814522b 178
mjr 40:cc0d9814522b 179 // initially fill the report with zeros
mjr 40:cc0d9814522b 180 memset(report.data, 0, sizeof(report.data));
mjr 40:cc0d9814522b 181
mjr 62:f071ccde32a0 182 // set the report ID
mjr 62:f071ccde32a0 183 report.data[0] = REPORT_ID_STAT;
mjr 62:f071ccde32a0 184
mjr 40:cc0d9814522b 185 // Set the special status bits to indicate that it's an ID report
mjr 40:cc0d9814522b 186 uint16_t s = 0x9000;
mjr 62:f071ccde32a0 187 put(1, s);
mjr 40:cc0d9814522b 188
mjr 53:9b2611964afc 189 // add the requested ID index
mjr 62:f071ccde32a0 190 report.data[3] = (uint8_t)index;
mjr 53:9b2611964afc 191
mjr 53:9b2611964afc 192 // figure out which ID we're reporting
mjr 53:9b2611964afc 193 switch (index)
mjr 53:9b2611964afc 194 {
mjr 53:9b2611964afc 195 case 1:
mjr 53:9b2611964afc 196 // KL25Z CPU ID
mjr 62:f071ccde32a0 197 putbe(4, SIM->UIDMH);
mjr 62:f071ccde32a0 198 putlbe(6, SIM->UIDML);
mjr 62:f071ccde32a0 199 putlbe(10, SIM->UIDL);
mjr 53:9b2611964afc 200 break;
mjr 53:9b2611964afc 201
mjr 53:9b2611964afc 202 case 2:
mjr 53:9b2611964afc 203 // OpenSDA ID. Copy the low-order 80 bits of the OpenSDA ID.
mjr 53:9b2611964afc 204 // (The stored value is 128 bits = 16 bytes; we only want the last
mjr 53:9b2611964afc 205 // 80 bits = 10 bytes. So skip ahead 16 and back up 10 to get
mjr 53:9b2611964afc 206 // the starting point.)
mjr 53:9b2611964afc 207 extern const char *getOpenSDAID();
mjr 62:f071ccde32a0 208 memcpy(&report.data[4], getOpenSDAID() + 16 - 10, 10);
mjr 53:9b2611964afc 209 break;
mjr 53:9b2611964afc 210 }
mjr 53:9b2611964afc 211
mjr 53:9b2611964afc 212 // send the report
mjr 62:f071ccde32a0 213 report.length = reportLen + 1;
mjr 53:9b2611964afc 214 return sendTO(&report, 100);
mjr 53:9b2611964afc 215 }
mjr 53:9b2611964afc 216
mjr 53:9b2611964afc 217 bool USBJoystick::reportBuildInfo(const char *date)
mjr 53:9b2611964afc 218 {
mjr 53:9b2611964afc 219 HID_REPORT report;
mjr 53:9b2611964afc 220
mjr 53:9b2611964afc 221 // initially fill the report with zeros
mjr 53:9b2611964afc 222 memset(report.data, 0, sizeof(report.data));
mjr 53:9b2611964afc 223
mjr 62:f071ccde32a0 224 // set the report ID
mjr 62:f071ccde32a0 225 report.data[0] = REPORT_ID_STAT;
mjr 62:f071ccde32a0 226
mjr 53:9b2611964afc 227 // Set the special status bits to indicate that it's a build
mjr 53:9b2611964afc 228 // info report
mjr 53:9b2611964afc 229 uint16_t s = 0xA000;
mjr 62:f071ccde32a0 230 put(1, s);
mjr 53:9b2611964afc 231
mjr 53:9b2611964afc 232 // Parse the date. This is given in the standard __DATE__ " " __TIME
mjr 53:9b2611964afc 233 // macro format, "Mon dd yyyy hh:mm:ss" (e.g., "Feb 16 2016 12:15:06").
mjr 53:9b2611964afc 234 static const char mon[][4] = {
mjr 53:9b2611964afc 235 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
mjr 53:9b2611964afc 236 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
mjr 53:9b2611964afc 237 };
mjr 53:9b2611964afc 238 long dd = (atol(date + 7) * 10000L) // YYYY0000
mjr 53:9b2611964afc 239 + (atol(date + 4)); // 000000DD
mjr 53:9b2611964afc 240 for (int i = 0 ; i < 12 ; ++i)
mjr 53:9b2611964afc 241 {
mjr 53:9b2611964afc 242 if (memcmp(mon[i], date, 3) == 0)
mjr 53:9b2611964afc 243 {
mjr 53:9b2611964afc 244 dd += (i+1)*100; // 0000MM00
mjr 53:9b2611964afc 245 break;
mjr 53:9b2611964afc 246 }
mjr 53:9b2611964afc 247 }
mjr 53:9b2611964afc 248
mjr 53:9b2611964afc 249 // parse the time into a long formatted as decimal HHMMSS (e.g.,
mjr 53:9b2611964afc 250 // "12:15:06" turns into 121506 decimal)
mjr 53:9b2611964afc 251 long tt = (atol(date+12)*10000)
mjr 53:9b2611964afc 252 + (atol(date+15)*100)
mjr 53:9b2611964afc 253 + (atol(date+18));
mjr 53:9b2611964afc 254
mjr 53:9b2611964afc 255 // store the build date and time
mjr 62:f071ccde32a0 256 putl(3, dd);
mjr 62:f071ccde32a0 257 putl(7, tt);
mjr 40:cc0d9814522b 258
mjr 40:cc0d9814522b 259 // send the report
mjr 62:f071ccde32a0 260 report.length = reportLen + 1;
mjr 40:cc0d9814522b 261 return sendTO(&report, 100);
mjr 40:cc0d9814522b 262 }
mjr 40:cc0d9814522b 263
mjr 52:8298b2a73eb2 264 bool USBJoystick::reportConfigVar(const uint8_t *data)
mjr 52:8298b2a73eb2 265 {
mjr 52:8298b2a73eb2 266 HID_REPORT report;
mjr 52:8298b2a73eb2 267
mjr 52:8298b2a73eb2 268 // initially fill the report with zeros
mjr 52:8298b2a73eb2 269 memset(report.data, 0, sizeof(report.data));
mjr 52:8298b2a73eb2 270
mjr 62:f071ccde32a0 271 // set the report ID
mjr 62:f071ccde32a0 272 report.data[0] = REPORT_ID_STAT;
mjr 62:f071ccde32a0 273
mjr 52:8298b2a73eb2 274 // Set the special status bits to indicate that it's a config
mjr 52:8298b2a73eb2 275 // variable report
mjr 52:8298b2a73eb2 276 uint16_t s = 0x9800;
mjr 62:f071ccde32a0 277 put(1, s);
mjr 52:8298b2a73eb2 278
mjr 52:8298b2a73eb2 279 // Copy the variable data (7 bytes, starting with the variable ID)
mjr 62:f071ccde32a0 280 memcpy(report.data + 3, data, 7);
mjr 52:8298b2a73eb2 281
mjr 52:8298b2a73eb2 282 // send the report
mjr 62:f071ccde32a0 283 report.length = reportLen + 1;
mjr 52:8298b2a73eb2 284 return sendTO(&report, 100);
mjr 52:8298b2a73eb2 285 }
mjr 52:8298b2a73eb2 286
mjr 52:8298b2a73eb2 287 bool USBJoystick::reportConfig(
mjr 52:8298b2a73eb2 288 int numOutputs, int unitNo,
mjr 52:8298b2a73eb2 289 int plungerZero, int plungerMax, int plungerRlsTime,
mjr 52:8298b2a73eb2 290 bool configured)
mjr 33:d832bcab089e 291 {
mjr 33:d832bcab089e 292 HID_REPORT report;
mjr 33:d832bcab089e 293
mjr 33:d832bcab089e 294 // initially fill the report with zeros
mjr 33:d832bcab089e 295 memset(report.data, 0, sizeof(report.data));
mjr 33:d832bcab089e 296
mjr 62:f071ccde32a0 297 // set the report ID
mjr 62:f071ccde32a0 298 report.data[0] = REPORT_ID_STAT;
mjr 62:f071ccde32a0 299
mjr 33:d832bcab089e 300 // Set the special status bits to indicate that it's a config report.
mjr 33:d832bcab089e 301 uint16_t s = 0x8800;
mjr 62:f071ccde32a0 302 put(1, s);
mjr 33:d832bcab089e 303
mjr 33:d832bcab089e 304 // write the number of configured outputs
mjr 62:f071ccde32a0 305 put(3, numOutputs);
mjr 33:d832bcab089e 306
mjr 33:d832bcab089e 307 // write the unit number
mjr 62:f071ccde32a0 308 put(5, unitNo);
mjr 33:d832bcab089e 309
mjr 35:e959ffba78fd 310 // write the plunger zero and max values
mjr 62:f071ccde32a0 311 put(7, plungerZero);
mjr 62:f071ccde32a0 312 put(9, plungerMax);
mjr 62:f071ccde32a0 313 report.data[11] = uint8_t(plungerRlsTime);
mjr 35:e959ffba78fd 314
mjr 40:cc0d9814522b 315 // write the status bits:
mjr 40:cc0d9814522b 316 // 0x01 -> configuration loaded
mjr 62:f071ccde32a0 317 report.data[12] = (configured ? 0x01 : 0x00);
mjr 40:cc0d9814522b 318
mjr 33:d832bcab089e 319 // send the report
mjr 62:f071ccde32a0 320 report.length = reportLen + 1;
mjr 35:e959ffba78fd 321 return sendTO(&report, 100);
mjr 33:d832bcab089e 322 }
mjr 33:d832bcab089e 323
mjr 33:d832bcab089e 324 bool USBJoystick::move(int16_t x, int16_t y)
mjr 33:d832bcab089e 325 {
mjr 3:3514575d4f86 326 _x = x;
mjr 3:3514575d4f86 327 _y = y;
mjr 3:3514575d4f86 328 return update();
mjr 3:3514575d4f86 329 }
mjr 3:3514575d4f86 330
mjr 33:d832bcab089e 331 bool USBJoystick::setZ(int16_t z)
mjr 33:d832bcab089e 332 {
mjr 3:3514575d4f86 333 _z = z;
mjr 3:3514575d4f86 334 return update();
mjr 3:3514575d4f86 335 }
mjr 3:3514575d4f86 336
mjr 33:d832bcab089e 337 bool USBJoystick::buttons(uint32_t buttons)
mjr 33:d832bcab089e 338 {
mjr 11:bd9da7088e6e 339 _buttonsLo = (uint16_t)(buttons & 0xffff);
mjr 11:bd9da7088e6e 340 _buttonsHi = (uint16_t)((buttons >> 16) & 0xffff);
mjr 3:3514575d4f86 341 return update();
mjr 3:3514575d4f86 342 }
mjr 21:5048e16cc9ef 343
mjr 21:5048e16cc9ef 344 bool USBJoystick::updateStatus(uint32_t status)
mjr 21:5048e16cc9ef 345 {
mjr 21:5048e16cc9ef 346 HID_REPORT report;
mjr 21:5048e16cc9ef 347
mjr 62:f071ccde32a0 348 // clear the report
mjr 62:f071ccde32a0 349 memset(report.data, 0, sizeof(report.data));
mjr 62:f071ccde32a0 350
mjr 62:f071ccde32a0 351 // set the report ID
mjr 62:f071ccde32a0 352 report.data[0] = REPORT_ID_STAT;
mjr 62:f071ccde32a0 353
mjr 62:f071ccde32a0 354 // Indicate that it's a status report
mjr 62:f071ccde32a0 355 put(1, status);
mjr 62:f071ccde32a0 356 report.length = reportLen + 1;
mjr 21:5048e16cc9ef 357
mjr 21:5048e16cc9ef 358 // send the report
mjr 21:5048e16cc9ef 359 return sendTO(&report, 100);
mjr 21:5048e16cc9ef 360 }
mjr 21:5048e16cc9ef 361
mjr 3:3514575d4f86 362 void USBJoystick::_init() {
mjr 3:3514575d4f86 363
mjr 3:3514575d4f86 364 _x = 0;
mjr 3:3514575d4f86 365 _y = 0;
mjr 3:3514575d4f86 366 _z = 0;
mjr 11:bd9da7088e6e 367 _buttonsLo = 0x0000;
mjr 11:bd9da7088e6e 368 _buttonsHi = 0x0000;
mjr 9:fd65b0a94720 369 _status = 0;
mjr 3:3514575d4f86 370 }
mjr 3:3514575d4f86 371
mjr 3:3514575d4f86 372
mjr 35:e959ffba78fd 373 // --------------------------------------------------------------------------
mjr 35:e959ffba78fd 374 //
mjr 62:f071ccde32a0 375 // USB HID Report Descriptors
mjr 35:e959ffba78fd 376 //
mjr 35:e959ffba78fd 377
mjr 62:f071ccde32a0 378 #define HID_REPORT_JS \
mjr 62:f071ccde32a0 379 USAGE_PAGE(1), 0x01, /* Generic desktop */ \
mjr 62:f071ccde32a0 380 USAGE(1), 0x04, /* Joystick */ \
mjr 62:f071ccde32a0 381 COLLECTION(1), 0x01, /* Application */ \
mjr 62:f071ccde32a0 382 /* input report (device to host) */ \
mjr 62:f071ccde32a0 383 REPORT_ID(1), REPORT_ID_JS, \
mjr 62:f071ccde32a0 384 USAGE_PAGE(1), 0x06, /* generic device controls - for config status */ \
mjr 62:f071ccde32a0 385 USAGE(1), 0x00, /* undefined device control */ \
mjr 62:f071ccde32a0 386 LOGICAL_MINIMUM(1), 0x00, /* 8-bit values */ \
mjr 62:f071ccde32a0 387 LOGICAL_MAXIMUM(1), 0xFF, \
mjr 62:f071ccde32a0 388 REPORT_SIZE(1), 0x08, /* 8 bits per report */ \
mjr 62:f071ccde32a0 389 REPORT_COUNT(1), 0x04, /* 4 reports (4 bytes) */ \
mjr 62:f071ccde32a0 390 INPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 391 \
mjr 62:f071ccde32a0 392 USAGE_PAGE(1), 0x09, /* Buttons */ \
mjr 62:f071ccde32a0 393 USAGE_MINIMUM(1), 0x01, /* { buttons } */ \
mjr 62:f071ccde32a0 394 USAGE_MAXIMUM(1), 0x20, /* { 1-32 } */ \
mjr 62:f071ccde32a0 395 LOGICAL_MINIMUM(1), 0x00, /* 1-bit buttons - 0... */ \
mjr 62:f071ccde32a0 396 LOGICAL_MAXIMUM(1), 0x01, /* ...to 1 */ \
mjr 62:f071ccde32a0 397 REPORT_SIZE(1), 0x01, /* 1 bit per report */ \
mjr 62:f071ccde32a0 398 REPORT_COUNT(1), 0x20, /* 32 reports */ \
mjr 62:f071ccde32a0 399 UNIT_EXPONENT(1), 0x00, /* Unit_Exponent (0) */ \
mjr 62:f071ccde32a0 400 UNIT(1), 0x00, /* Unit (None) */ \
mjr 62:f071ccde32a0 401 INPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 402 \
mjr 62:f071ccde32a0 403 USAGE_PAGE(1), 0x01, /* Generic desktop */ \
mjr 62:f071ccde32a0 404 USAGE(1), 0x30, /* X axis */ \
mjr 62:f071ccde32a0 405 USAGE(1), 0x31, /* Y axis */ \
mjr 62:f071ccde32a0 406 USAGE(1), 0x32, /* Z axis */ \
mjr 62:f071ccde32a0 407 LOGICAL_MINIMUM(2), 0x00,0xF0, /* each value ranges -4096 */ \
mjr 62:f071ccde32a0 408 LOGICAL_MAXIMUM(2), 0x00,0x10, /* ...to +4096 */ \
mjr 62:f071ccde32a0 409 REPORT_SIZE(1), 0x10, /* 16 bits per report */ \
mjr 62:f071ccde32a0 410 REPORT_COUNT(1), 0x03, /* 3 reports (X, Y, Z) */ \
mjr 62:f071ccde32a0 411 INPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 412 \
mjr 62:f071ccde32a0 413 /* output report (host to device) */ \
mjr 62:f071ccde32a0 414 REPORT_ID(1), REPORT_ID_JS, \
mjr 62:f071ccde32a0 415 REPORT_SIZE(1), 0x08, /* 8 bits per report */ \
mjr 62:f071ccde32a0 416 REPORT_COUNT(1), 0x08, /* output report count - 8-byte LedWiz format */ \
mjr 62:f071ccde32a0 417 0x09, 0x01, /* usage */ \
mjr 62:f071ccde32a0 418 0x91, 0x01, /* Output (array) */ \
mjr 62:f071ccde32a0 419 \
mjr 62:f071ccde32a0 420 END_COLLECTION(0)
mjr 62:f071ccde32a0 421
mjr 62:f071ccde32a0 422
mjr 62:f071ccde32a0 423 #define HID_REPORT_STAT \
mjr 62:f071ccde32a0 424 USAGE_PAGE(1), 0x01, /* Generic desktop */ \
mjr 62:f071ccde32a0 425 USAGE(1), 0x00, /* Undefined */ \
mjr 62:f071ccde32a0 426 COLLECTION(1), 0x01, /* Application */ \
mjr 62:f071ccde32a0 427 REPORT_ID(1), REPORT_ID_STAT, \
mjr 62:f071ccde32a0 428 USAGE_PAGE(1), 0x06, /* generic device controls */ \
mjr 62:f071ccde32a0 429 USAGE(1), 0x00, /* undefined device control */ \
mjr 62:f071ccde32a0 430 LOGICAL_MINIMUM(1), 0x00, /* 8-bit value range */ \
mjr 62:f071ccde32a0 431 LOGICAL_MAXIMUM(1), 0xFF, \
mjr 62:f071ccde32a0 432 REPORT_SIZE(1), 0x08, /* 8 bits per report */ \
mjr 62:f071ccde32a0 433 REPORT_COUNT(1), reportLen, /* 'reportLen' reports==bytes */ \
mjr 62:f071ccde32a0 434 INPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 435 END_COLLECTION(0)
mjr 35:e959ffba78fd 436
mjr 62:f071ccde32a0 437 #define HID_REPORT_KB \
mjr 62:f071ccde32a0 438 USAGE_PAGE(1), 0x01, /* Generic Desktop */ \
mjr 62:f071ccde32a0 439 USAGE(1), 0x06, /* Keyboard */ \
mjr 62:f071ccde32a0 440 \
mjr 62:f071ccde32a0 441 /* Keyboard keys */ \
mjr 62:f071ccde32a0 442 COLLECTION(1), 0x01, /* Application */ \
mjr 62:f071ccde32a0 443 REPORT_ID(1), REPORT_ID_KB, \
mjr 62:f071ccde32a0 444 \
mjr 62:f071ccde32a0 445 /* input report (device to host) - regular keys */ \
mjr 62:f071ccde32a0 446 REPORT_COUNT(1), 0x06, \
mjr 62:f071ccde32a0 447 REPORT_SIZE(1), 0x08, \
mjr 62:f071ccde32a0 448 LOGICAL_MINIMUM(1), 0x00, \
mjr 62:f071ccde32a0 449 LOGICAL_MAXIMUM(1), 0x65, \
mjr 62:f071ccde32a0 450 USAGE_PAGE(1), 0x07, /* Key Codes */ \
mjr 62:f071ccde32a0 451 USAGE_MINIMUM(1), 0x00, \
mjr 62:f071ccde32a0 452 USAGE_MAXIMUM(1), 0x65, \
mjr 62:f071ccde32a0 453 INPUT(1), 0x00, /* Data, Array */ \
mjr 62:f071ccde32a0 454 \
mjr 62:f071ccde32a0 455 /* input report (device to host) - modifier keys */ \
mjr 62:f071ccde32a0 456 USAGE_PAGE(1), 0x07, /* Key Codes */ \
mjr 62:f071ccde32a0 457 USAGE_MINIMUM(1), 0xE0, \
mjr 62:f071ccde32a0 458 USAGE_MAXIMUM(1), 0xE7, \
mjr 62:f071ccde32a0 459 LOGICAL_MINIMUM(1), 0x00, \
mjr 62:f071ccde32a0 460 LOGICAL_MAXIMUM(1), 0x01, \
mjr 62:f071ccde32a0 461 REPORT_SIZE(1), 0x01, \
mjr 62:f071ccde32a0 462 REPORT_COUNT(1), 0x08, \
mjr 62:f071ccde32a0 463 INPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 464 REPORT_COUNT(1), 0x01, \
mjr 62:f071ccde32a0 465 REPORT_SIZE(1), 0x08, \
mjr 62:f071ccde32a0 466 INPUT(1), 0x01, /* Constant */ \
mjr 62:f071ccde32a0 467 \
mjr 62:f071ccde32a0 468 /* output report (host to device) - LED status */ \
mjr 62:f071ccde32a0 469 REPORT_COUNT(1), 0x05, \
mjr 62:f071ccde32a0 470 REPORT_SIZE(1), 0x01, \
mjr 62:f071ccde32a0 471 USAGE_PAGE(1), 0x08, /* LEDs */ \
mjr 62:f071ccde32a0 472 USAGE_MINIMUM(1), 0x01, \
mjr 62:f071ccde32a0 473 USAGE_MAXIMUM(1), 0x05, \
mjr 62:f071ccde32a0 474 OUTPUT(1), 0x02, /* Data, Variable, Absolute */ \
mjr 62:f071ccde32a0 475 REPORT_COUNT(1), 0x01, \
mjr 62:f071ccde32a0 476 REPORT_SIZE(1), 0x03, \
mjr 62:f071ccde32a0 477 OUTPUT(1), 0x01, /* Constant */ \
mjr 62:f071ccde32a0 478 END_COLLECTION(0), \
mjr 62:f071ccde32a0 479 \
mjr 62:f071ccde32a0 480 /* Media Control Keys */ \
mjr 62:f071ccde32a0 481 USAGE_PAGE(1), 0x0C, \
mjr 62:f071ccde32a0 482 USAGE(1), 0x01, \
mjr 62:f071ccde32a0 483 COLLECTION(1), 0x01, \
mjr 62:f071ccde32a0 484 /* input report (device to host) */ \
mjr 62:f071ccde32a0 485 REPORT_ID(1), REPORT_ID_MEDIA, \
mjr 62:f071ccde32a0 486 USAGE_PAGE(1), 0x0C, \
mjr 62:f071ccde32a0 487 LOGICAL_MINIMUM(1), 0x00, \
mjr 62:f071ccde32a0 488 LOGICAL_MAXIMUM(1), 0x01, \
mjr 62:f071ccde32a0 489 REPORT_SIZE(1), 0x01, \
mjr 62:f071ccde32a0 490 REPORT_COUNT(1), 0x07, \
mjr 62:f071ccde32a0 491 USAGE(1), 0xE2, /* Mute -> 0x01 */ \
mjr 62:f071ccde32a0 492 USAGE(1), 0xE9, /* Volume Up -> 0x02 */ \
mjr 62:f071ccde32a0 493 USAGE(1), 0xEA, /* Volume Down -> 0x04 */ \
mjr 62:f071ccde32a0 494 USAGE(1), 0xB5, /* Next Track -> 0x08 */ \
mjr 62:f071ccde32a0 495 USAGE(1), 0xB6, /* Previous Track -> 0x10 */ \
mjr 62:f071ccde32a0 496 USAGE(1), 0xB7, /* Stop -> 0x20 */ \
mjr 62:f071ccde32a0 497 USAGE(1), 0xCD, /* Play / Pause -> 0x40 */ \
mjr 62:f071ccde32a0 498 INPUT(1), 0x02, /* Input (Data, Variable, Absolute) -> 0x80 */ \
mjr 62:f071ccde32a0 499 REPORT_COUNT(1), 0x01, \
mjr 62:f071ccde32a0 500 INPUT(1), 0x01, \
mjr 62:f071ccde32a0 501 END_COLLECTION(0)
mjr 35:e959ffba78fd 502
mjr 62:f071ccde32a0 503 #define HID_REPORT_LW \
mjr 62:f071ccde32a0 504 USAGE_PAGE(1), 0x01, /* Generic desktop */ \
mjr 62:f071ccde32a0 505 USAGE(1), 0x00, /* Undefined */ \
mjr 62:f071ccde32a0 506 COLLECTION(1), 0x01, /* Application */ \
mjr 62:f071ccde32a0 507 /* output report (host to device) */ \
mjr 62:f071ccde32a0 508 REPORT_ID(1), REPORT_ID_JS, \
mjr 62:f071ccde32a0 509 REPORT_SIZE(1), 0x08, /* 8 bits per report */ \
mjr 62:f071ccde32a0 510 REPORT_COUNT(1), 0x08, /* output report count (LEDWiz messages) */ \
mjr 62:f071ccde32a0 511 0x09, 0x01, /* usage */ \
mjr 62:f071ccde32a0 512 0x91, 0x01, /* Output (array) */ \
mjr 62:f071ccde32a0 513 END_COLLECTION(0)
mjr 62:f071ccde32a0 514
mjr 62:f071ccde32a0 515
mjr 62:f071ccde32a0 516 // Joystick + Keyboard + LedWiz
mjr 62:f071ccde32a0 517 static const uint8_t reportDescriptorJS[] =
mjr 62:f071ccde32a0 518 {
mjr 62:f071ccde32a0 519 USAGE_PAGE(1), 0x01, /* Generic desktop */ \
mjr 62:f071ccde32a0 520 USAGE(1), 0x04, /* Joystick */ \
mjr 62:f071ccde32a0 521 COLLECTION(1), 0x01, /* Application */ \
mjr 62:f071ccde32a0 522
mjr 62:f071ccde32a0 523 HID_REPORT_JS,
mjr 62:f071ccde32a0 524 HID_REPORT_STAT,
mjr 62:f071ccde32a0 525 HID_REPORT_KB,
mjr 62:f071ccde32a0 526
mjr 35:e959ffba78fd 527 END_COLLECTION(0)
mjr 35:e959ffba78fd 528 };
mjr 35:e959ffba78fd 529
mjr 62:f071ccde32a0 530 // Keyboard + LedWiz
mjr 48:058ace2aed1d 531 static const uint8_t reportDescriptorKB[] =
mjr 35:e959ffba78fd 532 {
mjr 62:f071ccde32a0 533 HID_REPORT_LW,
mjr 62:f071ccde32a0 534 HID_REPORT_STAT,
mjr 62:f071ccde32a0 535 HID_REPORT_KB
mjr 35:e959ffba78fd 536 };
mjr 29:582472d0bc57 537
mjr 62:f071ccde32a0 538 // LedWiz only
mjr 62:f071ccde32a0 539 static const uint8_t reportDescriptorLW[] =
mjr 62:f071ccde32a0 540 {
mjr 62:f071ccde32a0 541 HID_REPORT_LW,
mjr 62:f071ccde32a0 542 HID_REPORT_STAT
mjr 35:e959ffba78fd 543 };
mjr 35:e959ffba78fd 544
mjr 54:fd77a6b2f76c 545 const uint8_t *USBJoystick::reportDesc(int idx, uint16_t &len)
mjr 35:e959ffba78fd 546 {
mjr 62:f071ccde32a0 547 // we only have one interface (#0)
mjr 62:f071ccde32a0 548 if (idx != 0)
mjr 35:e959ffba78fd 549 {
mjr 54:fd77a6b2f76c 550 len = 0;
mjr 48:058ace2aed1d 551 return 0;
mjr 35:e959ffba78fd 552 }
mjr 62:f071ccde32a0 553
mjr 62:f071ccde32a0 554 // figure which type of reports we generate according to which
mjr 62:f071ccde32a0 555 // features are enabled
mjr 62:f071ccde32a0 556 if (enableJoystick)
mjr 62:f071ccde32a0 557 {
mjr 62:f071ccde32a0 558 // joystick enabled - use the JS + KB + LW descriptor
mjr 62:f071ccde32a0 559 len = sizeof(reportDescriptorJS);
mjr 62:f071ccde32a0 560 return reportDescriptorJS;
mjr 62:f071ccde32a0 561 }
mjr 62:f071ccde32a0 562 else if (useKB)
mjr 62:f071ccde32a0 563 {
mjr 62:f071ccde32a0 564 // joystick disabled, keyboard enabled - use KB + LW
mjr 62:f071ccde32a0 565 len = sizeof(reportDescriptorKB);
mjr 62:f071ccde32a0 566 return reportDescriptorKB;
mjr 62:f071ccde32a0 567 }
mjr 62:f071ccde32a0 568 else
mjr 62:f071ccde32a0 569 {
mjr 62:f071ccde32a0 570 // joystick and keyboard disabled - LW only
mjr 62:f071ccde32a0 571 len = sizeof(reportDescriptorLW);
mjr 62:f071ccde32a0 572 return reportDescriptorLW;
mjr 62:f071ccde32a0 573 }
mjr 35:e959ffba78fd 574 }
mjr 3:3514575d4f86 575
mjr 48:058ace2aed1d 576 const uint8_t *USBJoystick::stringImanufacturerDesc() {
mjr 48:058ace2aed1d 577 static const uint8_t stringImanufacturerDescriptor[] = {
mjr 61:3c7e6e9ec355 578 0x0E, /* bLength */
mjr 61:3c7e6e9ec355 579 STRING_DESCRIPTOR, /* bDescriptorType 0x03 (String Descriptor) */
mjr 61:3c7e6e9ec355 580 'm',0,'j',0,'r',0,'n',0,'e',0,'t',0 /* bString iManufacturer - mjrnet */
mjr 3:3514575d4f86 581 };
mjr 3:3514575d4f86 582 return stringImanufacturerDescriptor;
mjr 3:3514575d4f86 583 }
mjr 3:3514575d4f86 584
mjr 54:fd77a6b2f76c 585 const uint8_t *USBJoystick::stringIserialDesc()
mjr 54:fd77a6b2f76c 586 {
mjr 54:fd77a6b2f76c 587 // set up a buffer with the length prefix and descriptor type
mjr 61:3c7e6e9ec355 588 const int numChars = 3 + 16 + 1 + 3;
mjr 61:3c7e6e9ec355 589 static uint8_t buf[2 + numChars*2];
mjr 54:fd77a6b2f76c 590 uint8_t *dst = buf;
mjr 54:fd77a6b2f76c 591 *dst++ = sizeof(buf);
mjr 54:fd77a6b2f76c 592 *dst++ = STRING_DESCRIPTOR;
mjr 54:fd77a6b2f76c 593
mjr 54:fd77a6b2f76c 594 // Create an ASCII version of our unique serial number string:
mjr 54:fd77a6b2f76c 595 //
mjr 61:3c7e6e9ec355 596 // PSCxxxxxxxxxxxxxxxxivvv
mjr 54:fd77a6b2f76c 597 //
mjr 54:fd77a6b2f76c 598 // where:
mjr 54:fd77a6b2f76c 599 //
mjr 54:fd77a6b2f76c 600 // xxx... = decimal representation of low 64 bits of CPU ID (16 hex digits)
mjr 54:fd77a6b2f76c 601 // i = interface type: first character is J if joystick is enabled,
mjr 54:fd77a6b2f76c 602 // L = LedWiz/control interface only, no input
mjr 54:fd77a6b2f76c 603 // J = Joystick + LedWiz
mjr 54:fd77a6b2f76c 604 // K = Keyboard + LedWiz
mjr 54:fd77a6b2f76c 605 // C = Joystick + Keyboard + LedWiz ("C" for combo)
mjr 61:3c7e6e9ec355 606 // vvv = version suffix
mjr 54:fd77a6b2f76c 607 //
mjr 54:fd77a6b2f76c 608 // The suffix for the interface type resolves a problem on some Windows systems
mjr 54:fd77a6b2f76c 609 // when switching between interface types. Windows can cache device information
mjr 54:fd77a6b2f76c 610 // that includes the interface descriptors, and it won't recognize a change in
mjr 54:fd77a6b2f76c 611 // the interfaces once the information is cached, causing connection failures.
mjr 54:fd77a6b2f76c 612 // The cache key includes the device serial number, though, so this can be
mjr 54:fd77a6b2f76c 613 // resolved by changing the serial number when the interface setup changes.
mjr 62:f071ccde32a0 614 //
mjr 62:f071ccde32a0 615 // The version suffix serves a similar purpose, to force a new Windows cache
mjr 62:f071ccde32a0 616 // key whenever we make changes in the USB descriptors that require a refresh
mjr 62:f071ccde32a0 617 // on the Windows side. The version here is completely unrelated to any other
mjr 62:f071ccde32a0 618 // version numbers throughout the system; it's purely internal to this class
mjr 62:f071ccde32a0 619 // and doesn't have to be synced to anything else. There aren't any particular
mjr 62:f071ccde32a0 620 // rules about when it needs to be changed; we'll change it as needed when we
mjr 62:f071ccde32a0 621 // observe the need for it due to caching problems on Windows.
mjr 61:3c7e6e9ec355 622 char xbuf[numChars + 1];
mjr 54:fd77a6b2f76c 623 uint32_t x = SIM->UIDML;
mjr 54:fd77a6b2f76c 624 static char ifcCode[] = "LJKC";
mjr 62:f071ccde32a0 625 sprintf(xbuf, "PSC%08lX%08lX%c009",
mjr 54:fd77a6b2f76c 626 SIM->UIDML,
mjr 54:fd77a6b2f76c 627 SIM->UIDL,
mjr 54:fd77a6b2f76c 628 ifcCode[(enableJoystick ? 0x01 : 0x00) | (useKB ? 0x02 : 0x00)]);
mjr 54:fd77a6b2f76c 629
mjr 54:fd77a6b2f76c 630 // copy the ascii bytes into the descriptor buffer, converting to unicode
mjr 54:fd77a6b2f76c 631 // 16-bit little-endian characters
mjr 54:fd77a6b2f76c 632 for (char *src = xbuf ; *src != '\0' && dst < buf + sizeof(buf) ; )
mjr 54:fd77a6b2f76c 633 {
mjr 54:fd77a6b2f76c 634 *dst++ = *src++;
mjr 54:fd77a6b2f76c 635 *dst++ = '\0';
mjr 54:fd77a6b2f76c 636 }
mjr 54:fd77a6b2f76c 637
mjr 54:fd77a6b2f76c 638 // return the buffer
mjr 54:fd77a6b2f76c 639 return buf;
mjr 3:3514575d4f86 640 }
mjr 3:3514575d4f86 641
mjr 48:058ace2aed1d 642 const uint8_t *USBJoystick::stringIproductDesc() {
mjr 48:058ace2aed1d 643 static const uint8_t stringIproductDescriptor[] = {
mjr 9:fd65b0a94720 644 0x28, /*bLength*/
mjr 3:3514575d4f86 645 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
mjr 3:3514575d4f86 646 'P',0,'i',0,'n',0,'s',0,'c',0,'a',0,'p',0,'e',0,
mjr 3:3514575d4f86 647 ' ',0,'C',0,'o',0,'n',0,'t',0,'r',0,'o',0,'l',0,
mjr 3:3514575d4f86 648 'l',0,'e',0,'r',0 /*String iProduct */
mjr 3:3514575d4f86 649 };
mjr 3:3514575d4f86 650 return stringIproductDescriptor;
mjr 3:3514575d4f86 651 }
mjr 35:e959ffba78fd 652
mjr 35:e959ffba78fd 653 #define DEFAULT_CONFIGURATION (1)
mjr 35:e959ffba78fd 654
mjr 48:058ace2aed1d 655 const uint8_t *USBJoystick::configurationDesc()
mjr 35:e959ffba78fd 656 {
mjr 62:f071ccde32a0 657 int rptlen = reportDescLength(0);
mjr 62:f071ccde32a0 658 const int cfglen =
mjr 62:f071ccde32a0 659 ((1 * CONFIGURATION_DESCRIPTOR_LENGTH)
mjr 62:f071ccde32a0 660 + (1 * INTERFACE_DESCRIPTOR_LENGTH)
mjr 62:f071ccde32a0 661 + (1 * HID_DESCRIPTOR_LENGTH)
mjr 62:f071ccde32a0 662 + (2 * ENDPOINT_DESCRIPTOR_LENGTH));
mjr 62:f071ccde32a0 663 static uint8_t configurationDescriptor[] =
mjr 35:e959ffba78fd 664 {
mjr 62:f071ccde32a0 665 // Configuration descriptor
mjr 62:f071ccde32a0 666 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
mjr 62:f071ccde32a0 667 CONFIGURATION_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 668 LSB(cfglen), // wTotalLength (LSB)
mjr 62:f071ccde32a0 669 MSB(cfglen), // wTotalLength (MSB)
mjr 62:f071ccde32a0 670 0x01, // bNumInterfaces
mjr 62:f071ccde32a0 671 DEFAULT_CONFIGURATION, // bConfigurationValue
mjr 62:f071ccde32a0 672 0x00, // iConfiguration
mjr 62:f071ccde32a0 673 C_RESERVED | C_SELF_POWERED, // bmAttributes
mjr 62:f071ccde32a0 674 C_POWER(0), // bMaxPower
mjr 62:f071ccde32a0 675
mjr 62:f071ccde32a0 676 // Interface descriptor
mjr 62:f071ccde32a0 677 INTERFACE_DESCRIPTOR_LENGTH, // bLength
mjr 62:f071ccde32a0 678 INTERFACE_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 679 0x00, // bInterfaceNumber
mjr 62:f071ccde32a0 680 0x00, // bAlternateSetting
mjr 62:f071ccde32a0 681 0x02, // bNumEndpoints
mjr 62:f071ccde32a0 682 HID_CLASS, // bInterfaceClass
mjr 62:f071ccde32a0 683 HID_SUBCLASS_NONE, // bInterfaceSubClass
mjr 62:f071ccde32a0 684 HID_PROTOCOL_NONE, // bInterfaceProtocol
mjr 62:f071ccde32a0 685 0x00, // iInterface
mjr 62:f071ccde32a0 686
mjr 62:f071ccde32a0 687 // HID descriptor, with link to report descriptor
mjr 62:f071ccde32a0 688 HID_DESCRIPTOR_LENGTH, // bLength
mjr 62:f071ccde32a0 689 HID_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 690 LSB(HID_VERSION_1_11), // bcdHID (LSB)
mjr 62:f071ccde32a0 691 MSB(HID_VERSION_1_11), // bcdHID (MSB)
mjr 62:f071ccde32a0 692 0x00, // bCountryCode
mjr 62:f071ccde32a0 693 0x01, // bNumDescriptors
mjr 62:f071ccde32a0 694 REPORT_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 695 LSB(rptlen), // wDescriptorLength (LSB)
mjr 62:f071ccde32a0 696 MSB(rptlen), // wDescriptorLength (MSB)
mjr 62:f071ccde32a0 697
mjr 62:f071ccde32a0 698 // IN endpoint descriptor
mjr 62:f071ccde32a0 699 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
mjr 62:f071ccde32a0 700 ENDPOINT_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 701 PHY_TO_DESC(EPINT_IN), // bEndpointAddress - EPINT == EP1
mjr 62:f071ccde32a0 702 E_INTERRUPT, // bmAttributes
mjr 62:f071ccde32a0 703 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
mjr 62:f071ccde32a0 704 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
mjr 62:f071ccde32a0 705 1, // bInterval (milliseconds)
mjr 62:f071ccde32a0 706
mjr 62:f071ccde32a0 707 // OUT endpoint descriptor
mjr 62:f071ccde32a0 708 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
mjr 62:f071ccde32a0 709 ENDPOINT_DESCRIPTOR, // bDescriptorType
mjr 62:f071ccde32a0 710 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress - EPINT == EP1
mjr 62:f071ccde32a0 711 E_INTERRUPT, // bmAttributes
mjr 62:f071ccde32a0 712 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
mjr 62:f071ccde32a0 713 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
mjr 62:f071ccde32a0 714 1 // bInterval (milliseconds)
mjr 62:f071ccde32a0 715 };
mjr 61:3c7e6e9ec355 716
mjr 62:f071ccde32a0 717 return configurationDescriptor;
mjr 35:e959ffba78fd 718 }
mjr 35:e959ffba78fd 719
mjr 35:e959ffba78fd 720 // Set the configuration. We need to set up the endpoints for
mjr 35:e959ffba78fd 721 // our active interfaces.
mjr 35:e959ffba78fd 722 bool USBJoystick::USBCallback_setConfiguration(uint8_t configuration)
mjr 35:e959ffba78fd 723 {
mjr 35:e959ffba78fd 724 // we only have one valid configuration
mjr 35:e959ffba78fd 725 if (configuration != DEFAULT_CONFIGURATION)
mjr 35:e959ffba78fd 726 return false;
mjr 35:e959ffba78fd 727
mjr 62:f071ccde32a0 728 // Configure endpoint 1
mjr 48:058ace2aed1d 729 addEndpoint(EPINT_IN, MAX_REPORT_JS_TX + 1);
mjr 48:058ace2aed1d 730 addEndpoint(EPINT_OUT, MAX_REPORT_JS_RX + 1);
mjr 48:058ace2aed1d 731 readStart(EPINT_OUT, MAX_REPORT_JS_TX + 1);
mjr 35:e959ffba78fd 732
mjr 35:e959ffba78fd 733 // success
mjr 35:e959ffba78fd 734 return true;
mjr 35:e959ffba78fd 735 }
mjr 35:e959ffba78fd 736
mjr 38:091e511ce8a0 737 // Handle incoming messages on the joystick/LedWiz interface = endpoint 1.
mjr 38:091e511ce8a0 738 // This interface receives LedWiz protocol commands and commands using our
mjr 38:091e511ce8a0 739 // custom LedWiz protocol extensions.
mjr 38:091e511ce8a0 740 //
mjr 38:091e511ce8a0 741 // We simply queue the messages in our circular buffer for processing in
mjr 38:091e511ce8a0 742 // the main loop. The circular buffer object is designed for safe access
mjr 38:091e511ce8a0 743 // from the interrupt handler using the rule that only the interrupt
mjr 38:091e511ce8a0 744 // handler can change the write pointer, and only the regular code can
mjr 38:091e511ce8a0 745 // change the read pointer.
mjr 38:091e511ce8a0 746 bool USBJoystick::EP1_OUT_callback()
mjr 38:091e511ce8a0 747 {
mjr 38:091e511ce8a0 748 // Read this message
mjr 62:f071ccde32a0 749 uint8_t buf[MAX_HID_REPORT_SIZE];
mjr 38:091e511ce8a0 750 uint32_t bytesRead = 0;
mjr 62:f071ccde32a0 751 USBDevice::readEP(EP1OUT, buf, &bytesRead, MAX_HID_REPORT_SIZE);
mjr 38:091e511ce8a0 752
mjr 62:f071ccde32a0 753 // check the report type
mjr 62:f071ccde32a0 754 switch (buf[0])
mjr 62:f071ccde32a0 755 {
mjr 62:f071ccde32a0 756 case REPORT_ID_JS:
mjr 62:f071ccde32a0 757 // Joystick/ledwiz. These are LedWiz or private protocol command
mjr 62:f071ccde32a0 758 // messages. Queue to the incoming LW command list.
mjr 62:f071ccde32a0 759 if (bytesRead == 9)
mjr 62:f071ccde32a0 760 lwbuf.write((LedWizMsg *)&buf[1]);
mjr 62:f071ccde32a0 761 break;
mjr 62:f071ccde32a0 762
mjr 62:f071ccde32a0 763 case REPORT_ID_KB:
mjr 62:f071ccde32a0 764 // Keyboard. These are standard USB keyboard protocol messages,
mjr 62:f071ccde32a0 765 // telling us the shift key LED status. We don't do anything with
mjr 62:f071ccde32a0 766 // these; just accept and ignore them.
mjr 62:f071ccde32a0 767 break;
mjr 62:f071ccde32a0 768
mjr 62:f071ccde32a0 769 default:
mjr 62:f071ccde32a0 770 // Other report types are unexpected; just ignore them.
mjr 62:f071ccde32a0 771 break;
mjr 62:f071ccde32a0 772 }
mjr 38:091e511ce8a0 773
mjr 38:091e511ce8a0 774 // start the next read
mjr 39:b3815a1c3802 775 return readStart(EP1OUT, MAX_HID_REPORT_SIZE);
mjr 38:091e511ce8a0 776 }