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.
Fork of USBDevice by
USBHID.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "stdint.h" 00020 #include "USBHAL.h" 00021 #include "USBHID.h" 00022 00023 /* new constructor 00024 This constructor adds the ability toset the feature_report length. This constructor is not the default constructor to maintain backward compatibility. 00025 */ 00026 USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint8_t feature_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect): USBDevice(vendor_id, product_id, product_release) 00027 { 00028 output_length = output_report_length; 00029 input_length = input_report_length; 00030 feature_length = feature_report_length; 00031 inputReport.length=input_length; 00032 outputReport.length=output_length; 00033 featureReport.length=feature_length; 00034 00035 callbackSetInputReport = &HID_callbackSetReport; 00036 callbackGetInputReport = &HID_callbackGetReport; 00037 callbackSetOutputReport = &HID_callbackSetReport; 00038 callbackGetOutputReport = &HID_callbackGetReport; 00039 callbackSetFeatureReport = &HID_callbackSetReport; 00040 callbackGetFeatureReport = &HID_callbackGetReport; 00041 00042 reportIdleRateInt=0x0; 00043 reportIdleRate=0.0; 00044 00045 protocolState=1; 00046 00047 if(connect) { 00048 USBDevice::connect(); 00049 } 00050 } 00051 00052 /*Original constructor 00053 The original constructor, modified to set the defautls for new features 00054 Feature report will be disabled if the old/default constructor is used. 00055 */ 00056 00057 USBHID::USBHID(uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect): USBDevice(vendor_id, product_id, product_release) 00058 { 00059 output_length = output_report_length; 00060 input_length = input_report_length; 00061 feature_length = 0; 00062 inputReport.length=input_length; 00063 outputReport.length=output_length; 00064 featureReport.length=feature_length+1; 00065 00066 callbackSetInputReport = &HID_callbackSetReport; 00067 callbackGetInputReport = &HID_callbackGetReport; 00068 callbackSetOutputReport = &HID_callbackSetReport; 00069 callbackGetOutputReport = &HID_callbackGetReport; 00070 callbackSetFeatureReport = &HID_callbackSetReport; 00071 callbackGetFeatureReport = &HID_callbackGetReport; 00072 00073 reportIdleRateInt=0x0; 00074 reportIdleRate=0.0; 00075 00076 if(connect) { 00077 USBDevice::connect(); 00078 } 00079 } 00080 00081 /* IdlePeriodReSend is called when the IDLE rate is non-zero and the ticker period expires. 00082 By default: Windows will issue a set-idle rate to Zero when a device is connected. 00083 WARNING: The deviceIOcontrol commands for the poll rate get/set do not seem to be implemented in the windows hid driver. 00084 When the set_idle rate is greater than zero an input report will be resent every idle period even if there is no change. If the input report 00085 changes via the FillReport command, the change is sent and the Ticker is reset. 00086 */ 00087 void USBHID::IdlePeriodReSend(void) { 00088 //Disable the Tickers during the function kicked off from the ticker. 00089 NVIC_DisableIRQ(TIMER3_IRQn); 00090 SendReport(); 00091 NVIC_EnableIRQ(TIMER3_IRQn); 00092 } 00093 00094 /* ResetIdleTicker 00095 Arms the ticker function in the idle period is greater than zero, otherwise the ticker is disarmed. 00096 If a changed report is sent, this command is used to Arm the ticker agian before it has triggered, effectively reseting the countdown. 00097 */ 00098 void USBHID::ResetIdleTicker() { 00099 if( reportIdleRateInt > 0 ) 00100 countDownToReportTrigger.attach(this,&USBHID::IdlePeriodReSend,reportIdleRate); 00101 else 00102 countDownToReportTrigger.detach(); 00103 } 00104 00105 /* SetReportIdle handles the SET_IDLE controlTransfer. The idle rate is a minimum of 4ms when enabled. 00106 The float conversion to seconds is computerd and the Ticker is armed or disarmed. 00107 */ 00108 void USBHID::SetReportIdle(uint16_t wValue){ 00109 reportIdleRateInt=(wValue>>8); 00110 reportIdleRate= reportIdleRateInt * 0.004; 00111 00112 #ifdef DEBUG 00113 printf("IDLE: %f\r\n",reportIdleRate); 00114 #endif 00115 ResetIdleTicker(); 00116 } 00117 00118 00119 /* Legacy method --> No change */ 00120 bool USBHID::send(HID_REPORT *report) 00121 { 00122 return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE); 00123 } 00124 00125 /* Legacy method --> No change */ 00126 bool USBHID::sendNB(HID_REPORT *report) 00127 { 00128 return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE); 00129 } 00130 00131 /* Legacy method --> No change */ 00132 bool USBHID::read(HID_REPORT *report) 00133 { 00134 uint32_t bytesRead = 0; 00135 bool result; 00136 result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE); 00137 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) 00138 return false; 00139 report->length = bytesRead; 00140 return result; 00141 } 00142 00143 00144 /* Legacy method --> No change */ 00145 bool USBHID::readNB(HID_REPORT *report) 00146 { 00147 uint32_t bytesRead = 0; 00148 bool result; 00149 result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE); 00150 report->length = bytesRead; 00151 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) 00152 return false; 00153 return result; 00154 } 00155 00156 /* FillInputReport should be the main function that HID developers call. The develop sets a HID report with thier data. And pass it to FillInputReport 00157 The procedure will 1) Copy the HID report data to the input_report 2) check to see if the data has changed. 00158 Action #1 is important due to USB HID conformance.HID devices are required to implement the GET_REPORT control transfer. This transfer can be used to obtain the input report at any time. 00159 With the legacy HID methods, GET_REPORT was not implemented and SET_REPORT always wrote into the output_report. this means the contents of input_report would not be read by a control transfer. 00160 Action #2 is important for the IDLE RATE. Windows will set the IDLE rate to 0 for HID devices. Which means that reports should only be sent when the data changes. 00161 With the legacy HID methods, A send would always send a HID_REPORT even if it had not changed. 00162 */ 00163 bool USBHID::FillInputReport(HID_REPORT *report) 00164 { 00165 bool changed=false; 00166 00167 for(int i =0; i<input_length; i++) 00168 if(inputReport.data[i] != report->data[i]) { 00169 inputReport.data[i] = report->data[i]; 00170 changed=true; 00171 } 00172 00173 if (changed) 00174 return SendReport(); 00175 else 00176 return true; 00177 } 00178 00179 00180 bool USBHID::FillFeatureReport(HID_REPORT *report) 00181 { 00182 for(int i =0; i<feature_length; i++) 00183 featureReport.data[i] = report->data[i]; 00184 return true; 00185 } 00186 /* SendReport is called by FillReport if the data has changed. It performs 3 action 00187 * 1) Trigger an exposed CallBack This call back is called if a control transfer or interrupt transfer wants to get a INPUT_REPORT 00188 * This functions may be useful to notify your device when a transfer of the input_report is executed. NOTE: The call back occurs BEFORE the actual transfer. 00189 * 2) Reset the IDLE ticker. IF the IDEL rate is not zero, the tickerneeds to be reset since we are sending a changed report. 00190 * 3) Send the Report via NB transfer on the interupt endpoint. 00191 */ 00192 bool USBHID::SendReport() 00193 { 00194 bool result=false; 00195 00196 if ((*callbackGetInputReport)(&inputReport)) { 00197 ResetIdleTicker(); 00198 result=writeNB(EPINT_IN, inputReport.data, inputReport.length, MAX_HID_REPORT_SIZE); 00199 } 00200 return result; 00201 } 00202 00203 00204 00205 /* Legacy method --> No change */ 00206 uint16_t USBHID::reportDescLength() { 00207 //TODO: Is this a bug? reportDesc() is called and a value that isn't changed is returned. Why execute the function 00208 reportDesc(); 00209 return reportLength; 00210 } 00211 00212 /* GetReportTargetPointer: HID class control transfers Set_report and Get_report require a pointer to the report to write and read data 00213 The actual read and write logic is the same only the target report is different. Given the wvalue which has a value of MSB(TYPE) LSB(reportID), a point to a report can be returned. 00214 Multi report is not implemented in this release, but a small change in this function will allow support of multiple reports via control transfers. 00215 00216 If a value of 0 for a report was entered when the HID class was instantiated, a NULL report pointer is return which will cause a E0STALL for get/set report action on that type. 00217 */ 00218 00219 HID_REPORT * USBHID::GetReportTargetPointer(uint16_t wValue){ 00220 //TODO: Add support for multiple reports. 00221 HID_REPORT *targetPtr=NULL; 00222 switch(wValue>>8) { 00223 case 0x01: if (input_length >0) 00224 targetPtr=&inputReport; 00225 break; 00226 case 0x03: if (feature_length >0) 00227 targetPtr=&featureReport; 00228 break; 00229 case 0x02: 00230 default: if (output_length >0) 00231 targetPtr=&outputReport; 00232 break; 00233 } 00234 return targetPtr; 00235 } 00236 00237 00238 // 00239 // Route callbacks from lower layers to class(es) 00240 // 00241 00242 // Called in ISR context 00243 // Called by USBDevice on Endpoint0 request 00244 // This is used to handle extensions to standard requests 00245 // and class specific requests 00246 // Return true if class handles this request 00247 //Legacy method-->modified to include GET_REPORT, GET_IDLE, SET_IDLE transfers 00248 // modified the function of SET_REPORT for multiple types(INPUT,OUTPUT,FEATURE) 00249 bool USBHID::USBCallback_request() { 00250 bool success = false; 00251 CONTROL_TRANSFER * transfer = getTransferPtr(); 00252 uint8_t *hidDescriptor; 00253 00254 // Process additional standard requests 00255 00256 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) 00257 { 00258 switch (transfer->setup.bRequest) 00259 { 00260 case GET_DESCRIPTOR: 00261 switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) 00262 { 00263 case REPORT_DESCRIPTOR: 00264 if ((reportDesc() != NULL) \ 00265 && (reportDescLength() != 0)) 00266 { 00267 transfer->remaining = reportDescLength(); 00268 transfer->ptr = reportDesc(); 00269 transfer->direction = DEVICE_TO_HOST; 00270 success = true; 00271 } 00272 break; 00273 case HID_DESCRIPTOR: 00274 // Find the HID descriptor, after the configuration descriptor 00275 hidDescriptor = findDescriptor(HID_DESCRIPTOR); 00276 if (hidDescriptor != NULL) 00277 { 00278 transfer->remaining = HID_DESCRIPTOR_LENGTH; 00279 transfer->ptr = hidDescriptor; 00280 transfer->direction = DEVICE_TO_HOST; 00281 success = true; 00282 } 00283 break; 00284 00285 default: 00286 break; 00287 } 00288 break; 00289 default: 00290 break; 00291 } 00292 } 00293 00294 // Process class-specific requests 00295 00296 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) 00297 { 00298 00299 HID_REPORT *targetPtr=NULL; 00300 // printf("ReportID: %x\r\n", transfer->setup.wValue & 0xff ); 00301 switch (transfer->setup.bRequest) 00302 { 00303 case SET_REPORT: 00304 targetPtr=GetReportTargetPointer(transfer->setup.wValue); 00305 if (targetPtr==NULL) 00306 break; 00307 // First byte will be used for report ID 00308 // BUG: In a control transfer the first byte is the reportid and deviceiocontrol does transmit this byte 00309 // But the interupt transfer strips the reportid byte 00310 targetPtr->data[0] = transfer->setup.wValue & 0xff; 00311 targetPtr->length = transfer->setup.wLength + 1; 00312 if(transfer->remaining >= sizeof(targetPtr->data) - 1) 00313 transfer->remaining = sizeof(targetPtr->data) - 1; 00314 else 00315 transfer->remaining = transfer->setup.wLength; 00316 transfer->ptr = &targetPtr->data[1]; 00317 transfer->direction = HOST_TO_DEVICE; 00318 transfer->notify = true; 00319 success = true; 00320 break; 00321 case GET_REPORT: 00322 // Required by section 7.2 of the HID Device Class Definition: Mandatory implementation by all devices 00323 targetPtr=GetReportTargetPointer(transfer->setup.wValue); 00324 if (targetPtr==NULL) 00325 break; 00326 // First byte will be used for report ID 00327 // BUG: In a control transfer the first byte is the reportid and deviceiocontrol does transmit this byte 00328 // But the interupt transfer strips the reportid byte 00329 transfer->setup.wLength = targetPtr->length - 1; 00330 if(transfer->remaining >= sizeof(targetPtr->data) - 1) 00331 transfer->remaining = sizeof(targetPtr->data) - 1; 00332 else 00333 transfer->remaining = transfer->setup.wLength; 00334 transfer->ptr = &targetPtr->data[1]; 00335 transfer->direction = DEVICE_TO_HOST; 00336 transfer->notify = true; 00337 //Provide a hook for developers to provide thier own call back for Get_Report, prior to the report data is sentin response to a 00338 // Control IN. 00339 success =HIDCallback_GetReportHandler(targetPtr); 00340 break; 00341 00342 case SET_IDLE: 00343 //SET_IDLE works very well, Microsoft is able to use this to set the IDLE rate to 0. Durring testing the default rate was set to 0x80. 00344 // Normal default setting is zero. 00345 // The microsoft HID driver will throw an invlid function error when IOCTL_HID_GET_POLL_FREQUENCY_MSEC is used. 00346 // wValue {duration:ReportID} 00347 //TODO: To support multipe reports, a HID_REPORT Class should be defined. The ticker and idle methods and objects should be included. 00348 SetReportIdle(transfer->setup.wValue); 00349 transfer->setup.wLength = 0; 00350 transfer->direction = HOST_TO_DEVICE; 00351 transfer->remaining = transfer->setup.wLength; 00352 transfer->notify = true; 00353 success=true; 00354 case GET_IDLE: 00355 //This functionality has not been tested. The microsoft HID driver will throw an invlid function error when IOCTL_HID_GET_POLL_FREQUENCY_MSEC is used. 00356 transfer->remaining = 1; 00357 transfer->ptr = getReportIdlePtr(transfer->setup.wValue & 0xff); 00358 transfer->direction = DEVICE_TO_HOST; 00359 transfer->notify = true; 00360 success=true; 00361 break; 00362 case SET_PROTOCOL: 00363 //This functionality has not been tested. 00364 protocolState=transfer->setup.wValue; 00365 success=true; 00366 break; 00367 case GET_PROTOCOL: 00368 //This functionality has not been tested. 00369 transfer->remaining = 1; 00370 transfer->ptr = &protocolState; 00371 transfer->direction = DEVICE_TO_HOST; 00372 transfer->notify = true; 00373 success=true; 00374 break; 00375 default: 00376 break; 00377 } 00378 } 00379 00380 return success; 00381 } 00382 00383 /* HIDCallback_GetReportHandler provides a useful set of callbacks for the getting of each type in a report. 00384 This can be used to generate the data on the fly(Useful for a feature report) or notification that a report was sent for the device. 00385 NOTE: CALLBACKS happen before the actuall data for the report is transmitted. 00386 */ 00387 bool USBHID::HIDCallback_GetReportHandler(HID_REPORT *targetPtr) { 00388 bool (*callbackGetReport)(HID_REPORT *report); 00389 CONTROL_TRANSFER * transfer = getTransferPtr(); 00390 00391 switch(transfer->setup.wValue>>8) { 00392 case HID_INPUT_REPORT_TYPE: 00393 callbackGetReport=callbackGetInputReport; 00394 break; 00395 case HID_OUTPUT_REPORT_TYPE: 00396 callbackGetReport=callbackGetOutputReport; 00397 break; 00398 case HID_FEATURE_REPORT_TYPE: 00399 callbackGetReport=callbackGetFeatureReport; 00400 break; 00401 default: 00402 return false; 00403 } 00404 return (*callbackGetReport)(targetPtr); 00405 } 00406 00407 /* HIDCallback_SetReportHandler provides a useful set of callbacks for the setting of each type in a report. 00408 This can be used to update displays after a value is change(Example:NUM lock LED change). 00409 NOTE: CALLBACKS happen after the actuall data for the report is recieved. 00410 */ 00411 00412 bool USBHID::HIDCallback_SetReportHandler(HID_REPORT *targetPtr) { 00413 void (*callbackSetReport)(HID_REPORT *report); 00414 CONTROL_TRANSFER * transfer = getTransferPtr(); 00415 00416 switch(transfer->setup.wValue>>8) { 00417 case HID_INPUT_REPORT_TYPE: 00418 callbackSetReport=callbackSetInputReport; 00419 break; 00420 case HID_OUTPUT_REPORT_TYPE: 00421 callbackSetReport=callbackSetOutputReport; 00422 break; 00423 case HID_FEATURE_REPORT_TYPE: 00424 callbackSetReport=callbackSetFeatureReport; 00425 break; 00426 default: 00427 return false; 00428 } 00429 (*callbackSetReport)(targetPtr); 00430 return true; 00431 00432 } 00433 00434 /* USBCallback_requestCompleted To implement the set_report call back ability we need to override the requestCompleted function to provide the callback handler hook 00435 */ 00436 void USBHID::USBCallback_requestCompleted(uint8_t * buf, uint32_t length){ 00437 CONTROL_TRANSFER * transfer; 00438 HID_REPORT *targetPtr; 00439 00440 transfer = getTransferPtr(); 00441 targetPtr = GetReportTargetPointer(transfer->setup.wValue); 00442 USBDevice::USBCallback_requestCompleted(buf, length); 00443 //Provide a callback hook for developer use of set_report, called after the completion of the control transfer. 00444 if(transfer->setup.bRequest==SET_REPORT) { 00445 HIDCallback_SetReportHandler(targetPtr); 00446 } 00447 } 00448 00449 /* To ensure that the output report is updated on a writeFile interupt transfer, the EP1_OUT_callback is overridden. 00450 * additionally a callback for setOutputReport type is trigger 00451 */ 00452 bool USBHID::EP1_OUT_callback(){ 00453 uint32_t bytesRead = 0; 00454 bool result; 00455 //TODO: Is there a buffer over run issue here? 00456 //read to Buffer and copy just the report data to the HID_REPORT. 00457 result = endpointReadResult(EPINT_OUT, outputReport.data, &bytesRead); 00458 // outputReport.length = bytesRead; 00459 (*callbackSetOutputReport)(&outputReport); 00460 return result; 00461 } 00462 00463 00464 #define DEFAULT_CONFIGURATION (1) 00465 00466 00467 // Called in ISR context 00468 // Set configuration. Return false if the 00469 // configuration is not supported 00470 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) { 00471 if (configuration != DEFAULT_CONFIGURATION) { 00472 return false; 00473 } 00474 00475 // Configure endpoints > 0 00476 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); 00477 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT); 00478 00479 // We activate the endpoint to be able to recceive data 00480 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT); 00481 return true; 00482 } 00483 00484 00485 uint8_t * USBHID::stringIinterfaceDesc() { 00486 static uint8_t stringIinterfaceDescriptor[] = { 00487 0x08, //bLength 00488 STRING_DESCRIPTOR, //bDescriptorType 0x03 00489 'H',0,'I',0,'D',0, //bString iInterface - HID 00490 }; 00491 return stringIinterfaceDescriptor; 00492 } 00493 00494 uint8_t * USBHID::stringIproductDesc() { 00495 static uint8_t stringIproductDescriptor[] = { 00496 0x16, //bLength 00497 STRING_DESCRIPTOR, //bDescriptorType 0x03 00498 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device 00499 }; 00500 return stringIproductDescriptor; 00501 } 00502 00503 00504 /* legacy method .. Modified 00505 * 1) Added feature report 00506 * 2) Used KEYWORDS for added user readability. 00507 */ 00508 uint8_t * USBHID::reportDesc() { 00509 static uint8_t reportDescriptor[] = { 00510 USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB), 00511 USAGE(2), LSB(0x0200), MSB(0x0200), 00512 COLLECTION(1), 0x01, // Collection 0x01 00513 REPORT_SIZE(1), 0x08, // report size = 8 bits 00514 LOGICAL_MINIMUM(1), 0x00, // logical minimum = 0 00515 LOGICAL_MAXIMUM(2), 0xFF, 0x00, // logical maximum = 255 00516 REPORT_COUNT(1), input_length, // report count 00517 USAGE(1), 0x01, // usage 00518 INPUT(1), 0x02, // Input (array) 00519 REPORT_COUNT(1), output_length, // report count 00520 USAGE(1), 0x02, // usage 00521 OUTPUT(1), 0x02, // Output (array) 00522 REPORT_COUNT(1), feature_length, 00523 USAGE(1), 0x03, 00524 FEATURE(2), 0x02, 0x01, 00525 END_COLLECTION(0) // end collection 00526 }; 00527 reportLength = sizeof(reportDescriptor); 00528 return reportDescriptor; 00529 } 00530 00531 #define DEFAULT_CONFIGURATION (1) 00532 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ 00533 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \ 00534 + (1 * HID_DESCRIPTOR_LENGTH) \ 00535 + (2 * ENDPOINT_DESCRIPTOR_LENGTH)) 00536 00537 uint8_t * USBHID::configurationDesc() { 00538 static uint8_t configurationDescriptor[] = { 00539 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength 00540 CONFIGURATION_DESCRIPTOR, // bDescriptorType 00541 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) 00542 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) 00543 0x01, // bNumInterfaces 00544 DEFAULT_CONFIGURATION, // bConfigurationValue 00545 0x00, // iConfiguration 00546 C_RESERVED | C_SELF_POWERED, // bmAttributes 00547 C_POWER(0), // bMaxPower 00548 00549 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00550 INTERFACE_DESCRIPTOR, // bDescriptorType 00551 0x00, // bInterfaceNumber 00552 0x00, // bAlternateSetting 00553 0x02, // bNumEndpoints 00554 HID_CLASS, // bInterfaceClass 00555 HID_SUBCLASS_NONE, // bInterfaceSubClass 00556 HID_PROTOCOL_NONE, // bInterfaceProtocol 00557 0x00, // iInterface 00558 00559 HID_DESCRIPTOR_LENGTH, // bLength 00560 HID_DESCRIPTOR, // bDescriptorType 00561 LSB(HID_VERSION_1_11), // bcdHID (LSB) 00562 MSB(HID_VERSION_1_11), // bcdHID (MSB) 00563 0x00, // bCountryCode 00564 0x01, // bNumDescriptors 00565 REPORT_DESCRIPTOR, // bDescriptorType 00566 LSB(this->reportDescLength()), // wDescriptorLength (LSB) 00567 MSB(this->reportDescLength()), // wDescriptorLength (MSB) 00568 00569 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00570 ENDPOINT_DESCRIPTOR, // bDescriptorType 00571 PHY_TO_DESC(EPINT_IN), // bEndpointAddress 00572 E_INTERRUPT, // bmAttributes 00573 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00574 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00575 1, // bInterval (milliseconds) 00576 00577 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00578 ENDPOINT_DESCRIPTOR, // bDescriptorType 00579 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress 00580 E_INTERRUPT, // bmAttributes 00581 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00582 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00583 1, // bInterval (milliseconds) 00584 }; 00585 return configurationDescriptor; 00586 }
Generated on Tue Jul 12 2022 20:53:38 by
1.7.2
