Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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