RC_Simulator.....By Jafar Qutteineh with mods to connect my Futaba 9C to \'RC Helicopter\' by http://www.alphamacsoftware.com/
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 DigitalOut errorLED (LED1); 00201 DigitalOut okLED (LED2); 00202 00203 usbhid::usbhid() { 00204 configured = false; 00205 connect(); 00206 00207 } 00208 00209 void usbhid::deviceEventReset() { 00210 configured = false; 00211 00212 /* Must call base class */ 00213 usbdevice::deviceEventReset(); 00214 } 00215 00216 bool usbhid::requestSetConfiguration(void) { 00217 bool result; 00218 00219 /* Configure IN interrupt endpoint */ 00220 realiseEndpoint(EP1IN, MAX_PACKET_SIZE_EP1); 00221 enableEndpointEvent(EP1IN); 00222 00223 /* Must call base class */ 00224 result = usbdevice::requestSetConfiguration(); 00225 00226 if (result) { 00227 /* Now configured */ 00228 configured = true; 00229 } 00230 00231 return result; 00232 } 00233 00234 bool usbhid::requestGetDescriptor(void) { 00235 bool success = false; 00236 00237 switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { 00238 case DEVICE_DESCRIPTOR: 00239 transfer.remaining = sizeof(deviceDescriptor); 00240 transfer.ptr = deviceDescriptor; 00241 transfer.direction = DEVICE_TO_HOST; 00242 success = true; 00243 break; 00244 case CONFIGURATION_DESCRIPTOR: 00245 transfer.remaining = sizeof(configurationDescriptor); 00246 transfer.ptr = configurationDescriptor; 00247 transfer.direction = DEVICE_TO_HOST; 00248 success = true; 00249 break; 00250 case STRING_DESCRIPTOR: 00251 case INTERFACE_DESCRIPTOR: 00252 case ENDPOINT_DESCRIPTOR: 00253 /* TODO: Support is optional, not implemented here */ 00254 break; 00255 case HID_DESCRIPTOR: 00256 transfer.remaining = 0x09; /* TODO: Fix hard coded size/offset */ 00257 transfer.ptr = &configurationDescriptor[18]; 00258 transfer.direction = DEVICE_TO_HOST; 00259 success = true; 00260 break; 00261 case REPORT_DESCRIPTOR: 00262 transfer.remaining = sizeof(reportDescriptor); 00263 transfer.ptr = reportDescriptor; 00264 transfer.direction = DEVICE_TO_HOST; 00265 success = true; 00266 break; 00267 default: 00268 break; 00269 } 00270 00271 return success; 00272 } 00273 00274 bool usbhid::requestSetup(void) { 00275 /* Process class requests */ 00276 bool success = false; 00277 00278 if (transfer.setup.bmRequestType.Type == CLASS_TYPE) { 00279 switch (transfer.setup.bRequest) { 00280 case SET_REPORT: 00281 switch (transfer.setup.wValue & 0xff) { 00282 case REPORT_ID_KEYBOARD: 00283 /* TODO: LED state */ 00284 transfer.remaining = sizeof(outputReport); 00285 transfer.ptr = outputReport; 00286 transfer.direction = HOST_TO_DEVICE; 00287 success = true; 00288 break; 00289 default: 00290 break; 00291 } 00292 break; 00293 default: 00294 break; 00295 } 00296 } 00297 00298 if (success) { 00299 /* We've handled this request */ 00300 return true; 00301 } 00302 00303 return usbdevice::requestSetup(); 00304 } 00305 00306 bool usbhid::sendInputReport(unsigned char id, unsigned char *data, unsigned char size) { 00307 /* Send an Input Report */ 00308 /* If data is NULL an all zero report is sent */ 00309 00310 static unsigned char report[MAX_REPORT_SIZE+1]; /* +1 for report ID */ 00311 unsigned char i; 00312 00313 if (size > MAX_REPORT_SIZE) { 00314 return false; 00315 } 00316 00317 /* Add report ID */ 00318 report[0]=id; 00319 00320 /* Add report data */ 00321 if (data != NULL) { 00322 for (i=0; i<size; i++) { 00323 report[i+1] = *data++; 00324 } 00325 } else { 00326 for (i=0; i<size; i++) { 00327 report[i+1] = 0; 00328 } 00329 } 00330 00331 /* Block if not configured */ 00332 while (!configured); 00333 00334 /* Send report */ 00335 complete = false; 00336 disableEvents(); 00337 endpointWrite(EP1IN, report, size+1); /* +1 for report ID */ 00338 enableEvents(); 00339 00340 /* Wait for completion */ 00341 while (!complete && configured); 00342 return true; 00343 } 00344 00345 void usbhid::endpointEventEP1In(void) { 00346 complete = true; 00347 } 00348 00349 bool usbhid::keyboard(char c) { 00350 /* Send a simulated keyboard keypress. Returns true if successful. */ 00351 unsigned char report[8]={0,0,0,0,0,0,0,0}; 00352 00353 report[0] = keymap[c].modifier; 00354 report[2] = keymap[c].usage; 00355 00356 /* Key down */ 00357 if (!sendInputReport(REPORT_ID_KEYBOARD, report, 8)) { 00358 return false; 00359 } 00360 00361 /* Key up */ 00362 if (!sendInputReport(REPORT_ID_KEYBOARD, NULL, 8)) { 00363 return false; 00364 } 00365 00366 return true; 00367 } 00368 00369 bool usbhid::keyboard(char *string) { 00370 /* Send a string of characters. Returns true if successful. */ 00371 do { 00372 if (!keyboard(*string++)) { 00373 return false; 00374 } 00375 } while (*string != '\0'); 00376 00377 return true; 00378 } 00379 00380 bool usbhid::mouse(signed char x, signed char y, unsigned char buttons, signed char wheel) { 00381 /* Send a simulated mouse event. Returns true if successful. */ 00382 unsigned char report[4]={0,0,0,0}; 00383 00384 report[0] = buttons; 00385 report[1] = x; 00386 report[2] = y; 00387 report[3] = wheel; 00388 00389 if (!sendInputReport(REPORT_ID_MOUSE, report, 4)) { 00390 return false; 00391 } 00392 00393 return true; 00394 } 00395 00396 00397 // 00398 // USBJoystick 00399 // Edit for different configurations (channels) 00400 00401 unsigned char reportDescriptorJoystick[] = { 00402 USAGE_PAGE(1), 0x01, //Generic Desktop 00403 USAGE(1), 0x04, //Joystiq 00404 COLLECTION(1), 0x01, //Application 00405 USAGE(1), 0x01,//Pointer 00406 COLLECTION(1), 0x00,//Physical 00407 00408 USAGE_PAGE(1), 0x09,//Buttons 00409 USAGE_MIN(1), 0x01,//Button 1 00410 USAGE_MAX(1), 0x02,//Button 12 .....Changed here 00411 LOGICAL_MIN(1), 0x00,//00 00412 LOGICAL_MAX(1), 0x01,//01 00413 PHYSICAL_MIN(1), 0x00,//00 00414 PHYSICAL_MAX(1), 0x01,//01 00415 REPORT_SIZE(1), 0x01,// 1 Bit size 00416 REPORT_COUNT(1), 0x02,// 2 report 00417 INPUT(1), 0x02,// Data , Var , Abs 00418 00419 REPORT_SIZE(1), 0x06,// 6 padding bits 00420 REPORT_COUNT(1), 0x01, 00421 INPUT(1), 0x03,// cnst , Vsr , Abs 00422 00423 //USAGE_PAGE(1), 0x01, //Generic Desktop 00424 //USAGE(1), 0x39,// Hat switch 00425 //LOGICAL_MIN(1), 0x00,// 00 00426 //LOGICAL_MAX(1), 0x07,//07 00427 //PHYSICAL_MIN(1), 0x00,//00 00428 //PHYSICAL_MAX(2), 0x3B, 0x01,//315 00429 //UNIT(1), 0x14,//English Rotation : Angular Position 00430 //REPORT_SIZE(1), 0x04,//04 00431 //REPORT_COUNT(1), 0x01,//01 00432 //INPUT(1), 0x42,//Data, Var, Abs, Null 00433 /* 00434 0x05, 0x02, // USAGE_PAGE (Simulation Controls) 00435 0x09, 0xbb, // USAGE (Throttle) 00436 0x09, 0xba, // USAGE (rudder) 00437 0x15, 0x00, // LOGICAL_MINIMUM (0) 00438 0x26, 0xff,0x00, // LOGICAL_MAXIMUM (255) 00439 0x75, 0x08, // REPORT_SIZE (8) 00440 0x95, 0x02, // REPORT_COUNT (2) 00441 0x81, 0x02, // INPUT (Data,Var,Abs) 00442 */ 00443 USAGE_PAGE(1), 0x01,//Generic Desktop 00444 USAGE(1), 0x32,//z 00445 USAGE(1), 0x35,//Rz 00446 USAGE(1), 0x30,//x 00447 USAGE(1), 0x31,//y 00448 LOGICAL_MIN(1), 0x00,//00 00449 LOGICAL_MAX(2), 0xff, 0x00,//255 00450 PHYSICAL_MIN(1), 0x00,//00 00451 PHYSICAL_MAX(2), 0xff, 0x00,//255 00452 UNIT(2), 0x00, 0x00,//None 2 bytes 00453 REPORT_SIZE(1), 0x08,//8 bits 00454 REPORT_COUNT(1), 0x04,//4 reports (channels) 00455 INPUT(1), 0x02,//Data, Var , Abs 00456 00457 END_COLLECTION(0), 00458 END_COLLECTION(0), 00459 }; 00460 00461 USBJoystick::USBJoystick() { 00462 int reportDescriptorSize = sizeof(reportDescriptorJoystick); 00463 configurationDescriptor[25] = reportDescriptorSize & 0xff; 00464 configurationDescriptor[26] = (reportDescriptorSize >> 8) & 0xff; 00465 00466 } 00467 00468 bool USBJoystick::requestGetDescriptor(void) { 00469 00470 bool success = false; 00471 00472 switch (DESCRIPTOR_TYPE(transfer.setup.wValue)) { 00473 case REPORT_DESCRIPTOR: 00474 transfer.remaining = sizeof(reportDescriptorJoystick); 00475 transfer.ptr = reportDescriptorJoystick; 00476 transfer.direction = DEVICE_TO_HOST; 00477 success = true; 00478 break; 00479 default: 00480 success = usbhid::requestGetDescriptor(); 00481 break; 00482 } 00483 00484 return success; 00485 } 00486 00487 bool USBJoystick::sendInputReport(unsigned char *data, unsigned char size) { 00488 /* Send an Input Report */ 00489 /* If data is NULL an all zero report is sent */ 00490 00491 static unsigned char report[MAX_REPORT_SIZE]; 00492 unsigned char i; 00493 00494 if (size > MAX_REPORT_SIZE) { 00495 return false; 00496 } 00497 00498 /* Add report data */ 00499 if (data != NULL) { 00500 for (i=0; i<size; i++) { 00501 report[i] = *data++; 00502 } 00503 } else { 00504 for (i=0; i<size; i++) { 00505 report[i] = 0; 00506 } 00507 } 00508 00509 /* Block if not configured */ 00510 while (!configured) { 00511 //errorLED=1; delete here 00512 } 00513 //okLED=1; delete here 00514 /* Send report */ 00515 complete = false; 00516 disableEvents(); 00517 endpointWrite(EP1IN, report, size); 00518 enableEvents(); 00519 00520 /* Wait for completion */ 00521 while (!complete && configured); 00522 return true; 00523 } 00524 00525 bool USBJoystick::joystick(unsigned char throttle, unsigned char rudder, unsigned char x, unsigned char y, bool button1, bool button2) { 00526 00527 unsigned char report[6] = {0, 0, 0, 0, 0,0}; 00528 unsigned char buttons=0x00; 00529 00530 if (button1) buttons= buttons | 0x01; 00531 if (button2) buttons= buttons | 0x02; 00532 report[0] = buttons;//Buttons 00533 report[1] = throttle; //Throttle 00534 report[2] = rudder; //Rudder 00535 report[3] = x; //X 00536 report[4] = y;//Y 00537 00538 00539 00540 if (!sendInputReport(report, 5)) { 00541 00542 return false; 00543 00544 } 00545 // okLED=1;.....Delete here 00546 return true; 00547 } 00548
Generated on Tue Jul 12 2022 20:25:32 by
1.7.2