Igor Martinovski
/
USBJoystick
N64 to USB HID interface
Embed:
(wiki syntax)
Show/hide line numbers
usbhid.cpp
00001 /* usbhid.cpp */ 00002 /* USB HID class device */ 00003 /* Copyright (c) Phil Wright 2008 */ 00004 00005 /* modified by Shinichiro Oba <http://mbed.org/users/bricklife/> */ 00006 00007 #include "mbed.h" 00008 #include "usbhid.h" 00009 #include "asciihid.h" 00010 00011 /* Endpoint packet sizes */ 00012 #define MAX_PACKET_SIZE_EP1 (64) 00013 00014 /* HID Class */ 00015 #define HID_CLASS (3) 00016 #define HID_SUBCLASS_NONE (0) 00017 #define HID_PROTOCOL_NONE (0) 00018 #define HID_DESCRIPTOR (33) 00019 #define REPORT_DESCRIPTOR (34) 00020 00021 /* Class requests */ 00022 #define GET_REPORT (0x1) 00023 #define GET_IDLE (0x2) 00024 #define SET_REPORT (0x9) 00025 #define SET_IDLE (0xa) 00026 00027 /* Descriptors */ 00028 unsigned char deviceDescriptor[] = { 00029 0x12, /* bLength */ 00030 DEVICE_DESCRIPTOR, /* bDescriptorType */ 00031 0x00, /* bcdUSB (LSB) */ 00032 0x02, /* bcdUSB (MSB) */ 00033 0x00, /* bDeviceClass */ 00034 0x00, /* bDeviceSubClass */ 00035 0x00, /* bDeviceprotocol */ 00036 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */ 00037 0x28, /* idVendor (LSB) */ 00038 0x0d, /* idVendor (MSB) */ 00039 0x05, /* idProduct (LSB) */ 00040 0x02, /* idProduct (MSB) */ 00041 0x00, /* bcdDevice (LSB) */ 00042 0x00, /* bcdDevice (MSB) */ 00043 0x00, /* iManufacturer */ 00044 0x00, /* iProduct */ 00045 0x00, /* iSerialNumber */ 00046 0x01 /* bNumConfigurations */ 00047 }; 00048 00049 unsigned char configurationDescriptor[] = { 00050 0x09, /* bLength */ 00051 CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ 00052 0x09+0x09+0x09+0x07, /* wTotalLength (LSB) */ 00053 0x00, /* wTotalLength (MSB) */ 00054 0x01, /* bNumInterfaces */ 00055 0x01, /* bConfigurationValue */ 00056 0x00, /* iConfiguration */ 00057 0xc0, /* bmAttributes */ 00058 0x00, /* bMaxPower */ 00059 00060 0x09, /* bLength */ 00061 INTERFACE_DESCRIPTOR, /* bDescriptorType */ 00062 0x00, /* bInterfaceNumber */ 00063 0x00, /* bAlternateSetting */ 00064 0x01, /* bNumEndpoints */ 00065 HID_CLASS, /* bInterfaceClass */ 00066 HID_SUBCLASS_NONE, /* bInterfaceSubClass */ 00067 HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 00068 0x00, /* iInterface */ 00069 00070 0x09, /* bLength */ 00071 HID_DESCRIPTOR, /* bDescriptorType */ 00072 0x11, /* bcdHID (LSB) */ 00073 0x01, /* bcdHID (MSB) */ 00074 0x00, /* bCountryCode */ 00075 0x01, /* bNumDescriptors */ 00076 REPORT_DESCRIPTOR, /* bDescriptorType */ 00077 0x79, /* wDescriptorLength (LSB) */ 00078 0x00, /* wDescriptorLength (MSB) */ 00079 00080 0x07, /* bLength */ 00081 ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 00082 0x81, /* bEndpointAddress */ 00083 0x03, /* bmAttributes */ 00084 MAX_PACKET_SIZE_EP1, /* wMaxPacketSize (LSB) */ 00085 0x00, /* wMaxPacketSize (MSB) */ 00086 0x0a, /* bInterval */ 00087 }; 00088 00089 /* HID Class Report Descriptor */ 00090 /* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes of data as per HID Class standard */ 00091 00092 /* Main items */ 00093 #define INPUT(size) (0x80 | size) 00094 #define OUTPUT(size) (0x90 | size) 00095 #define FEATURE(size) (0xb0 | size) 00096 #define COLLECTION(size) (0xa0 | size) 00097 #define END_COLLECTION(size) (0xc0 | size) 00098 00099 /* Global items */ 00100 #define USAGE_PAGE(size) (0x04 | size) 00101 #define LOGICAL_MIN(size) (0x14 | size) 00102 #define LOGICAL_MAX(size) (0x24 | size) 00103 #define PHYSICAL_MIN(size) (0x34 | size) 00104 #define PHYSICAL_MAX(size) (0x44 | size) 00105 #define UNIT_EXPONENT(size) (0x54 | size) 00106 #define UNIT(size) (0x64 | size) 00107 #define REPORT_SIZE(size) (0x74 | size) 00108 #define REPORT_ID(size) (0x84 | size) 00109 #define REPORT_COUNT(size) (0x94 | size) 00110 #define PUSH(size) (0xa4 | size) 00111 #define POP(size) (0xb4 | size) 00112 00113 /* Local items */ 00114 #define USAGE(size) (0x08 | size) 00115 #define USAGE_MIN(size) (0x18 | size) 00116 #define USAGE_MAX(size) (0x28 | size) 00117 #define DESIGNATOR_INDEX(size) (0x38 | size) 00118 #define DESIGNATOR_MIN(size) (0x48 | size) 00119 #define DESIGNATOR_MAX(size) (0x58 | size) 00120 #define STRING_INDEX(size) (0x78 | size) 00121 #define STRING_MIN(size) (0x88 | size) 00122 #define STRING_MAX(size) (0x98 | size) 00123 #define DELIMITER(size) (0xa8 | size) 00124 00125 #define REPORT_ID_KEYBOARD (1) 00126 #define REPORT_ID_MOUSE (2) 00127 00128 #define MAX_REPORT_SIZE (8) 00129 00130 unsigned char reportDescriptor[] = { 00131 /* Keyboard */ 00132 USAGE_PAGE(1), 0x01, 00133 USAGE(1), 0x06, 00134 COLLECTION(1), 0x01, 00135 REPORT_ID(1), REPORT_ID_KEYBOARD, 00136 USAGE_PAGE(1), 0x07, 00137 USAGE_MIN(1), 0xE0, 00138 USAGE_MAX(1), 0xE7, 00139 LOGICAL_MIN(1), 0x00, 00140 LOGICAL_MAX(1), 0x01, 00141 REPORT_SIZE(1), 0x01, 00142 REPORT_COUNT(1), 0x08, 00143 INPUT(1), 0x02, 00144 REPORT_COUNT(1), 0x01, 00145 REPORT_SIZE(1), 0x08, 00146 INPUT(1), 0x01, 00147 REPORT_COUNT(1), 0x05, 00148 REPORT_SIZE(1), 0x01, 00149 USAGE_PAGE(1), 0x08, 00150 USAGE_MIN(1), 0x01, 00151 USAGE_MAX(1), 0x05, 00152 OUTPUT(1), 0x02, 00153 REPORT_COUNT(1), 0x01, 00154 REPORT_SIZE(1), 0x03, 00155 OUTPUT(1), 0x01, 00156 REPORT_COUNT(1), 0x06, 00157 REPORT_SIZE(1), 0x08, 00158 LOGICAL_MIN(1), 0x00, 00159 LOGICAL_MAX(2), 0xff, 0x00, 00160 USAGE_PAGE(1), 0x07, 00161 USAGE_MIN(1), 0x00, 00162 USAGE_MAX(2), 0xff, 0x00, 00163 INPUT(1), 0x00, 00164 END_COLLECTION(0), 00165 00166 /* Mouse */ 00167 USAGE_PAGE(1), 0x01, 00168 USAGE(1), 0x02, 00169 COLLECTION(1), 0x01, 00170 USAGE(1), 0x01, 00171 COLLECTION(1), 0x00, 00172 REPORT_ID(1), REPORT_ID_MOUSE, 00173 REPORT_COUNT(1), 0x03, 00174 REPORT_SIZE(1), 0x01, 00175 USAGE_PAGE(1), 0x09, 00176 USAGE_MIN(1), 0x1, 00177 USAGE_MAX(1), 0x3, 00178 LOGICAL_MIN(1), 0x00, 00179 LOGICAL_MAX(1), 0x01, 00180 INPUT(1), 0x02, 00181 REPORT_COUNT(1), 0x01, 00182 REPORT_SIZE(1), 0x05, 00183 INPUT(1), 0x01, 00184 REPORT_COUNT(1), 0x03, 00185 REPORT_SIZE(1), 0x08, 00186 USAGE_PAGE(1), 0x01, 00187 USAGE(1), 0x30, 00188 USAGE(1), 0x31, 00189 USAGE(1), 0x38, 00190 LOGICAL_MIN(1), 0x81, 00191 LOGICAL_MAX(1), 0x7f, 00192 INPUT(1), 0x06, 00193 END_COLLECTION(0), 00194 END_COLLECTION(0), 00195 }; 00196 00197 volatile bool complete; 00198 volatile bool configured; 00199 unsigned char outputReport[MAX_REPORT_SIZE]; 00200 00201 usbhid::usbhid() { 00202 configured = false; 00203 connect(); 00204 } 00205 00206 void usbhid::deviceEventReset() { 00207 configured = false; 00208 00209 /* Must call base class */ 00210 usbdevice::deviceEventReset(); 00211 } 00212 00213 bool usbhid::requestSetConfiguration(void) { 00214 bool result; 00215 00216 /* Configure IN interrupt endpoint */ 00217 realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1); 00218 enableEndpointEvent(EP1IN); 00219 00220 /* Must call base class */ 00221 result = usbdevice::requestSetConfiguration(); 00222 00223 if (result) { 00224 /* Now configured */ 00225 configured = true; 00226 } 00227 00228 return result; 00229 } 00230 00231 bool usbhid::requestGetDescriptor(void) { 00232 bool success = false; 00233 00234 switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { 00235 case DEVICE_DESCRIPTOR: 00236 transfer.remaining = sizeof(deviceDescriptor); 00237 transfer.ptr = deviceDescriptor; 00238 transfer.direction = DEVICE_TO_HOST; 00239 success = true; 00240 break; 00241 case CONFIGURATION_DESCRIPTOR: 00242 transfer.remaining = sizeof(configurationDescriptor); 00243 transfer.ptr = configurationDescriptor; 00244 transfer.direction = DEVICE_TO_HOST; 00245 success = true; 00246 break; 00247 case STRING_DESCRIPTOR: 00248 case INTERFACE_DESCRIPTOR: 00249 case ENDPOINT_DESCRIPTOR: 00250 /* TODO: Support is optional, not implemented here */ 00251 break; 00252 case HID_DESCRIPTOR: 00253 transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */ 00254 transfer.ptr = &configurationDescriptor[18]; 00255 transfer.direction = DEVICE_TO_HOST; 00256 success = true; 00257 break; 00258 case REPORT_DESCRIPTOR: 00259 transfer.remaining = sizeof(reportDescriptor); 00260 transfer.ptr = reportDescriptor; 00261 transfer.direction = DEVICE_TO_HOST; 00262 success = true; 00263 break; 00264 default: 00265 break; 00266 } 00267 00268 return success; 00269 } 00270 00271 bool usbhid::requestSetup(void) { 00272 /* Process class requests */ 00273 bool success = false; 00274 00275 if (transfer.setup.bmRequestType.Type == CLASS_TYPE) { 00276 switch (transfer.setup.bRequest) { 00277 case SET_REPORT: 00278 switch (transfer.setup.wValue & 0xff) { 00279 case REPORT_ID_KEYBOARD: 00280 /* TODO: LED state */ 00281 transfer.remaining = sizeof(outputReport); 00282 transfer.ptr = outputReport; 00283 transfer.direction = HOST_TO_DEVICE; 00284 success = true; 00285 break; 00286 default: 00287 break; 00288 } 00289 break; 00290 default: 00291 break; 00292 } 00293 } 00294 00295 if (success) { 00296 /* We've handled this request */ 00297 return true; 00298 } 00299 00300 return usbdevice::requestSetup(); 00301 } 00302 00303 bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size) { 00304 /* Send an Input Report */ 00305 /* If data is NULL an all zero report is sent */ 00306 00307 static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */ 00308 unsigned char i; 00309 00310 if (size > MAX_REPORT_SIZE) { 00311 return false; 00312 } 00313 00314 /* Add report ID */ 00315 report[0]=id; 00316 00317 /* Add report data */ 00318 if (data != NULL) { 00319 for (i=0; i<size; i++) { 00320 report[i+1] = *data++; 00321 } 00322 } else { 00323 for (i=0; i<size; i++) { 00324 report[i+1] = 0; 00325 } 00326 } 00327 00328 /* Block if not configured */ 00329 while (!configured); 00330 00331 /* Send report */ 00332 complete = false; 00333 disableEvents(); 00334 endpointWrite(EP1IN, report, size+1); /* +1 for report ID */ 00335 enableEvents(); 00336 00337 /* Wait for completion */ 00338 while (!complete && configured); 00339 return true; 00340 } 00341 00342 void usbhid::endpointEventEP1In(void) { 00343 complete = true; 00344 } 00345 00346 bool usbhid::keyboard(char c) { 00347 /* Send a simulated keyboard keypress. Returns true if successful. */ 00348 unsigned char report[8]={0,0,0,0,0,0,0,0}; 00349 00350 report[0] = keymap[c].modifier; 00351 report[2] = keymap[c].usage; 00352 00353 /* Key down */ 00354 if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8)) { 00355 return false; 00356 } 00357 00358 /* Key up */ 00359 if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8)) { 00360 return false; 00361 } 00362 00363 return true; 00364 } 00365 00366 bool usbhid::keyboard(char *string) { 00367 /* Send a string of characters. Returns true if successful. */ 00368 do { 00369 if (!keyboard(*string++)) { 00370 return false; 00371 } 00372 } while (*string != '\0'); 00373 00374 return true; 00375 } 00376 00377 bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel) { 00378 /* Send a simulated mouse event. Returns true if successful. */ 00379 unsigned char report[4]={0,0,0,0}; 00380 00381 report[0] = buttons; 00382 report[1] = x; 00383 report[2] = y; 00384 report[3] = wheel; 00385 00386 if (!sendInputReport(REPORT_ID_MOUSE, report, 4)) { 00387 return false; 00388 } 00389 00390 return true; 00391 } 00392 00393 00394 // 00395 // USBJoystick 00396 // 00397 00398 unsigned char reportDescriptorJoystick[] = { 00399 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 00400 0x09, 0x05, // USAGE (Game Pad) 00401 0xa1, 0x01, // COLLECTION (Application) 00402 0xa1, 0x00, // COLLECTION (Physical) 00403 0x05, 0x09, // USAGE_PAGE (Button) 00404 0x19, 0x01, // USAGE_MINIMUM (Button 1) 00405 0x29, 0x05, // USAGE_MAXIMUM (Button 5) 00406 0x15, 0x00, // LOGICAL_MINIMUM (0) 00407 0x25, 0x01, // LOGICAL_MAXIMUM (1) 00408 0x95, 0x05, // REPORT_COUNT (5) 00409 0x75, 0x01, // REPORT_SIZE (1) 00410 0x81, 0x02, // INPUT (Data,Var,Abs) 00411 0x75, 0x03, // REPORT_SIZE (3) 00412 0x95, 0x01, // REPORT_COUNT (1) 00413 0x81, 0x03, // INPUT (Cnst,Var,Abs) 00414 0x19, 0x06, // USAGE_MINIMUM (Button 6) 00415 0x29, 0x0c, // USAGE_MAXIMUM (Button 12) 00416 0x15, 0x00, // LOGICAL_MINIMUM (0) 00417 0x25, 0x01, // LOGICAL_MAXIMUM (1) 00418 0x95, 0x07, // REPORT_COUNT (7) 00419 0x75, 0x01, // REPORT_SIZE (1) 00420 0x81, 0x02, // INPUT (Data,Var,Abs) 00421 0x95, 0x01, // REPORT_COUNT (1) 00422 0x75, 0x01, // REPORT_SIZE (1) 00423 0x81, 0x03, // INPUT (Cnst,Var,Abs) 00424 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 00425 0x09, 0x30, // USAGE (X) 00426 0x09, 0x31, // USAGE (Y) 00427 0x09, 0x33, // USAGE (Rx) 00428 0x09, 0x34, // USAGE (Ry) 00429 0x15, 0x81, // LOGICAL_MINIMUM (-127) 00430 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 00431 0x75, 0x08, // REPORT_SIZE (8) 00432 0x95, 0x04, // REPORT_COUNT (4) 00433 0x81, 0x02, // INPUT (Data,Var,Abs) 00434 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 00435 0x09, 0x36, // USAGE (Slider) 00436 0x09, 0x37, // USAGE (Dial) 00437 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 00438 0x15, 0x00, // LOGICAL_MINIMUM (0) 00439 0x75, 0x08, // REPORT_SIZE (8) 00440 0x95, 0x02, // REPORT_COUNT (2) 00441 0x81, 0x02, // INPUT (Data,Var,Abs) 00442 0xc0, // END_COLLECTION 00443 0xc0 // END_COLLECTION 00444 }; 00445 00446 USBJoystick::USBJoystick() { 00447 int reportDescriptorSize = sizeof(reportDescriptorJoystick); 00448 configurationDescriptor[25] = reportDescriptorSize & 0xff; 00449 configurationDescriptor[26] = (reportDescriptorSize >> 8) & 0xff; 00450 } 00451 00452 bool USBJoystick::requestGetDescriptor(void) { 00453 bool success = false; 00454 00455 switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { 00456 case REPORT_DESCRIPTOR: 00457 transfer.remaining = sizeof(reportDescriptorJoystick); 00458 transfer.ptr = reportDescriptorJoystick; 00459 transfer.direction = DEVICE_TO_HOST; 00460 success = true; 00461 break; 00462 default: 00463 success = usbhid::requestGetDescriptor(); 00464 break; 00465 } 00466 00467 return success; 00468 } 00469 00470 bool USBJoystick::sendInputReport(unsigned char *data, unsigned char size) { 00471 /* Send an Input Report */ 00472 /* If data is NULL an all zero report is sent */ 00473 00474 static unsigned char report[MAX_REPORT_SIZE]; 00475 unsigned char i; 00476 00477 if (size > MAX_REPORT_SIZE) { 00478 return false; 00479 } 00480 00481 /* Add report data */ 00482 if (data != NULL) { 00483 for (i=0; i<size; i++) { 00484 report[i] = *data++; 00485 } 00486 } else { 00487 for (i=0; i<size; i++) { 00488 report[i] = 0; 00489 } 00490 } 00491 00492 /* Block if not configured */ 00493 while (!configured); 00494 00495 /* Send report */ 00496 complete = false; 00497 disableEvents(); 00498 endpointWrite(EP1IN, report, size); 00499 enableEvents(); 00500 00501 /* Wait for completion */ 00502 while (!complete && configured); 00503 return true; 00504 } 00505 00506 bool USBJoystick::joystick(unsigned char buttons1, unsigned short buttons2, signed char x, signed char y, signed char cx, signed char cy, unsigned char L, unsigned char R) { 00507 unsigned char report[9] = {0, 0, 0, 0, 0, 0, 0, 0}; 00508 report[0] = buttons1; 00509 report[1] = buttons2; 00510 report[2] = x ; 00511 report[3] = -y ; 00512 report[4] = cx ; 00513 report[5] = cy ; 00514 report[6] = L ; 00515 report[7] = R ; 00516 00517 00518 if (!sendInputReport(report, 8)) { 00519 return false; 00520 } 00521 00522 return true; 00523 } 00524
Generated on Tue Jul 12 2022 21:12:15 by 1.7.2