Forked to make modifications to bring the USBHID into USB compliance and add additional features.

Dependents:   HW4_AudioControl

Fork of USBDevice by mbed official

As of Revision 18 everything in the USBHID specification is now implemented, except Multi-reports.

Revision comments for changelist 18

USBHID.cpp

  • Added SET_PROTOCOL support
  • Added GET_PROTOCOL support
  • protocolSate is set to 1 by default to match USB HID specification. This variable should be checked to determine which format theinput report should have. 1 - Use the user specified report format. 0 - Use the BOOT protocol report format.

Revision comments for changelist 16

  • HID_REPORT transformed from structure to class. This was done for several reasons.
  1. When multiple reports are used the 64 byte size for every report becomes a problem.
  2. The length value should always remain the same for a report, Make the constructor set the vale at the same time it allocates memory for the DATA area.
  • By default the data will be an array of MAX_HID_REPORT_SIZE like the structure,
  • When given a length argument, the hid_report.length will be set, and hid_report.data will be an array of the size given.
  • Length zero causes data to be NULL
  • Mostly backwards compatible. The definition of a destructor caused a compiler error in USBMouse::update and USBMousekeyboard::update. This error was caused by instatiation of HID_REPORT in the middle of an IF logic statement. These files have been modified. The error complained that the logic skipped object initialization. The HID_REPORT has been moved to the class definition. Since both ABSOLUTE and RELATIVE modes used the HID_REPORT, this seems to make more sense. Previously the hid_report would be instatiated in <class>::mousesend and <class>::update.

Revision comments for changelist 14

USBdevice.cpp

  • Modified USB device state to change from Configure when disconnect is called.
  • Modified the call back function for when the suspend state changes. This should be used to turn off peripherals to conserve power.

Revision comments for changelist 13

USBdevice.cpp

  • ) Changed DEBUG messages to be more descriptive for string descriptor
  • ) Bug fix: Control Transfers did not actually transfer the data from Buffer to transfer->ptr

USBHIDTypes.h

  • ) Added ALL CLASS request to KEYWORD list
  • ) Added KEYWORDS for report type

USBHID.h

  • ) Added a new constructor to specify size of feature report
  • ) Added HID_REPORT inputReport and featureReport
  • ) Added data structures to support IDLE rate
  • ) Added data structures to support callback functions

USBHID.cpp

  • ) Changed constructor to initialize new feature data structures
  • ) Implemented Set_IDLE/GET_IDLE and the periodic resend of non-changed data
  • ) Implemented HID specification required control transfer GET_REPORT
  • ) Fixed issue where Intreput transfers and control transfers did not access the same data structures.
  • ) Implemented Feature reports
  • ) Implemented Callback Hooks for get_report/set_report actions.
  • ) Added callback hooks for interupt actions in the new functions.
  • ) interupt transfer can now write to outputReport
  • ) Modified SET_REPORT code to function for multiple types.
  • ) Refactored some code in preperation to add multi report support
Test NumberTest DescriptionTest ResultNotes
1Use USBmouse to verify backward compatibility of constructor and methodsPass
2Test SET_REPORT can set a feature reportPass
3Test GET_REPORT can retrieve a feature reportPass
4Test SET_IDLE sets up a reoccuring triggerPassIOCTL_SET_POLL_FREQUENCY_MSEC does not function for the windows HID driver. A Special test program is used to rearm the IDLE rate after windows sets it to zero
5Test SET_IDLE disables a triggerPassWindows automatically sends this command to a HID device when it is inserted.
6Enabled DEBUG in USBDevice.cpp and generated str descriptor requests.Pass
7Test SET_REPORT can set an output reportPass
8Test GET_REPORT can retrieve an output reportPass
9ReadFile, accesses the input_reportPass
10WriteFile accesses the output_report, via interupt transfer when ep1_out is used.Pass
11WriteFile accesses the output_report, via control transfer when ep1_out is NOT used.Not Tested
12Callback hooks trigger independently for each type of set_report/get_reportPass
13New constructor sets feature_report sizePass
14Control transfer SET_REPORT and writeFile access the same data structureBUGThe same data structure is accessed, but the data transfer size is different. The writeFile strips the leading byte which is the report ID, The Control transfer keeps the byte.
15Control transfer GET_REPORT and readFile access the same data structureBUGThe same dtat structure is accessed, but the data transfer size is different. The readFile strips the leading byte which is the report ID, The Control transfer keeps the byte.
16Test GET_IDLE retrieves the IDLE rateUnknownWindows HID driver does not implement IOCTL_HID_GET_POLL_FREQUENCY_MSEC
Committer:
jakowisp
Date:
Tue Jul 30 22:34:54 2013 +0000
Revision:
14:00cd29199e0e
Parent:
12:590d5be7b7f4
Child:
15:2b2a28dc6ed5
USBAudiControl Functional
;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 1:80ab0d068708 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 1:80ab0d068708 2 *
samux 1:80ab0d068708 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 1:80ab0d068708 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 1:80ab0d068708 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 1:80ab0d068708 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 1:80ab0d068708 7 * Software is furnished to do so, subject to the following conditions:
samux 1:80ab0d068708 8 *
samux 1:80ab0d068708 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 1:80ab0d068708 10 * substantial portions of the Software.
samux 1:80ab0d068708 11 *
samux 1:80ab0d068708 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 1:80ab0d068708 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 1:80ab0d068708 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 1:80ab0d068708 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 1:80ab0d068708 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 1:80ab0d068708 17 */
samux 1:80ab0d068708 18
samux 1:80ab0d068708 19 #include "stdint.h"
samux 1:80ab0d068708 20 #include "USBHAL.h"
samux 1:80ab0d068708 21 #include "USBHID.h"
samux 1:80ab0d068708 22
jakowisp 12:590d5be7b7f4 23 /* new constructor
jakowisp 12:590d5be7b7f4 24 This constructor adds the ability toset the feature_report length. This constructor is not the default constructor to maintain backward compatibility.
jakowisp 12:590d5be7b7f4 25 */
jakowisp 12:590d5be7b7f4 26 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)
samux 1:80ab0d068708 27 {
samux 1:80ab0d068708 28 output_length = output_report_length;
samux 1:80ab0d068708 29 input_length = input_report_length;
jakowisp 12:590d5be7b7f4 30 feature_length = feature_report_length;
jakowisp 12:590d5be7b7f4 31 inputReport.length=input_length;
jakowisp 12:590d5be7b7f4 32 outputReport.length=output_length;
jakowisp 12:590d5be7b7f4 33 featureReport.length=feature_length;
jakowisp 12:590d5be7b7f4 34
jakowisp 12:590d5be7b7f4 35 callbackSetInputReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 36 callbackGetInputReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 37 callbackSetOutputReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 38 callbackGetOutputReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 39 callbackSetFeatureReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 40 callbackGetFeatureReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 41
jakowisp 12:590d5be7b7f4 42 reportIdleRateInt=0x0;
jakowisp 12:590d5be7b7f4 43 reportIdleRate=0.0;
jakowisp 12:590d5be7b7f4 44
samux 1:80ab0d068708 45 if(connect) {
samux 1:80ab0d068708 46 USBDevice::connect();
samux 1:80ab0d068708 47 }
samux 1:80ab0d068708 48 }
samux 1:80ab0d068708 49
jakowisp 12:590d5be7b7f4 50 /*Original constructor
jakowisp 12:590d5be7b7f4 51 The original constructor, modified to set the defautls for new features
jakowisp 12:590d5be7b7f4 52 Feature report will be disabled if the old/default constructor is used.
jakowisp 12:590d5be7b7f4 53 */
samux 1:80ab0d068708 54
jakowisp 12:590d5be7b7f4 55 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)
jakowisp 12:590d5be7b7f4 56 {
jakowisp 12:590d5be7b7f4 57 output_length = output_report_length;
jakowisp 12:590d5be7b7f4 58 input_length = input_report_length;
jakowisp 12:590d5be7b7f4 59 feature_length = 0;
jakowisp 12:590d5be7b7f4 60 inputReport.length=input_length;
jakowisp 12:590d5be7b7f4 61 outputReport.length=output_length;
jakowisp 14:00cd29199e0e 62 featureReport.length=feature_length+1;
jakowisp 12:590d5be7b7f4 63
jakowisp 12:590d5be7b7f4 64 callbackSetInputReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 65 callbackGetInputReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 66 callbackSetOutputReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 67 callbackGetOutputReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 68 callbackSetFeatureReport = &HID_callbackSetReport;
jakowisp 12:590d5be7b7f4 69 callbackGetFeatureReport = &HID_callbackGetReport;
jakowisp 12:590d5be7b7f4 70
jakowisp 12:590d5be7b7f4 71 reportIdleRateInt=0x0;
jakowisp 12:590d5be7b7f4 72 reportIdleRate=0.0;
jakowisp 12:590d5be7b7f4 73
jakowisp 12:590d5be7b7f4 74 if(connect) {
jakowisp 12:590d5be7b7f4 75 USBDevice::connect();
jakowisp 12:590d5be7b7f4 76 }
jakowisp 12:590d5be7b7f4 77 }
jakowisp 12:590d5be7b7f4 78
jakowisp 12:590d5be7b7f4 79 /* IdlePeriodReSend is called when the IDLE rate is non-zero and the ticker period expires.
jakowisp 12:590d5be7b7f4 80 By default: Windows will issue a set-idle rate to Zero when a device is connected.
jakowisp 12:590d5be7b7f4 81 WARNING: The deviceIOcontrol commands for the poll rate get/set do not seem to be implemented in the windows hid driver.
jakowisp 12:590d5be7b7f4 82 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
jakowisp 12:590d5be7b7f4 83 changes via the FillReport command, the change is sent and the Ticker is reset.
jakowisp 12:590d5be7b7f4 84 */
jakowisp 12:590d5be7b7f4 85 void USBHID::IdlePeriodReSend(void) {
jakowisp 12:590d5be7b7f4 86 //Disable the Tickers during the function kicked off from the ticker.
jakowisp 12:590d5be7b7f4 87 NVIC_DisableIRQ(TIMER3_IRQn);
jakowisp 12:590d5be7b7f4 88 SendReport();
jakowisp 12:590d5be7b7f4 89 NVIC_EnableIRQ(TIMER3_IRQn);
jakowisp 12:590d5be7b7f4 90 }
jakowisp 12:590d5be7b7f4 91
jakowisp 12:590d5be7b7f4 92 /* ResetIdleTicker
jakowisp 12:590d5be7b7f4 93 Arms the ticker function in the idle period is greater than zero, otherwise the ticker is disarmed.
jakowisp 12:590d5be7b7f4 94 If a changed report is sent, this command is used to Arm the ticker agian before it has triggered, effectively reseting the countdown.
jakowisp 12:590d5be7b7f4 95 */
jakowisp 12:590d5be7b7f4 96 void USBHID::ResetIdleTicker() {
jakowisp 12:590d5be7b7f4 97 if( reportIdleRateInt > 0 )
jakowisp 12:590d5be7b7f4 98 countDownToReportTrigger.attach(this,&USBHID::IdlePeriodReSend,reportIdleRate);
jakowisp 12:590d5be7b7f4 99 else
jakowisp 12:590d5be7b7f4 100 countDownToReportTrigger.detach();
jakowisp 12:590d5be7b7f4 101 }
jakowisp 12:590d5be7b7f4 102
jakowisp 12:590d5be7b7f4 103 /* SetReportIdle handles the SET_IDLE controlTransfer. The idle rate is a minimum of 4ms when enabled.
jakowisp 12:590d5be7b7f4 104 The float conversion to seconds is computerd and the Ticker is armed or disarmed.
jakowisp 12:590d5be7b7f4 105 */
jakowisp 12:590d5be7b7f4 106 void USBHID::SetReportIdle(uint16_t wValue){
jakowisp 12:590d5be7b7f4 107 reportIdleRateInt=(wValue>>8);
jakowisp 12:590d5be7b7f4 108 reportIdleRate= reportIdleRateInt * 0.004;
jakowisp 12:590d5be7b7f4 109
jakowisp 12:590d5be7b7f4 110 #ifdef DEBUG
jakowisp 12:590d5be7b7f4 111 printf("IDLE: %f\r\n",reportIdleRate);
jakowisp 12:590d5be7b7f4 112 #endif
jakowisp 12:590d5be7b7f4 113 ResetIdleTicker();
jakowisp 12:590d5be7b7f4 114 }
jakowisp 12:590d5be7b7f4 115
jakowisp 12:590d5be7b7f4 116
jakowisp 12:590d5be7b7f4 117 /* Legacy method --> No change */
samux 1:80ab0d068708 118 bool USBHID::send(HID_REPORT *report)
jakowisp 12:590d5be7b7f4 119 {
samux 1:80ab0d068708 120 return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
samux 1:80ab0d068708 121 }
samux 1:80ab0d068708 122
jakowisp 12:590d5be7b7f4 123 /* Legacy method --> No change */
samux 1:80ab0d068708 124 bool USBHID::sendNB(HID_REPORT *report)
samux 1:80ab0d068708 125 {
samux 1:80ab0d068708 126 return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
samux 1:80ab0d068708 127 }
samux 1:80ab0d068708 128
jakowisp 12:590d5be7b7f4 129 /* Legacy method --> No change */
samux 1:80ab0d068708 130 bool USBHID::read(HID_REPORT *report)
samux 1:80ab0d068708 131 {
samux 1:80ab0d068708 132 uint32_t bytesRead = 0;
samux 1:80ab0d068708 133 bool result;
samux 1:80ab0d068708 134 result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 1:80ab0d068708 135 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 1:80ab0d068708 136 return false;
samux 1:80ab0d068708 137 report->length = bytesRead;
samux 1:80ab0d068708 138 return result;
samux 1:80ab0d068708 139 }
samux 1:80ab0d068708 140
samux 1:80ab0d068708 141
jakowisp 12:590d5be7b7f4 142 /* Legacy method --> No change */
samux 1:80ab0d068708 143 bool USBHID::readNB(HID_REPORT *report)
samux 1:80ab0d068708 144 {
samux 1:80ab0d068708 145 uint32_t bytesRead = 0;
samux 1:80ab0d068708 146 bool result;
samux 1:80ab0d068708 147 result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 1:80ab0d068708 148 report->length = bytesRead;
samux 1:80ab0d068708 149 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 1:80ab0d068708 150 return false;
samux 1:80ab0d068708 151 return result;
samux 1:80ab0d068708 152 }
samux 1:80ab0d068708 153
jakowisp 12:590d5be7b7f4 154 /* FillInputReport should be the main function that HID developers call. The develop sets a HID report with thier data. And pass it to FillInputReport
jakowisp 12:590d5be7b7f4 155 The procedure will 1) Copy the HID report data to the input_report 2) check to see if the data has changed.
jakowisp 12:590d5be7b7f4 156 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.
jakowisp 12:590d5be7b7f4 157 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.
jakowisp 12:590d5be7b7f4 158 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.
jakowisp 12:590d5be7b7f4 159 With the legacy HID methods, A send would always send a HID_REPORT even if it had not changed.
jakowisp 12:590d5be7b7f4 160 */
jakowisp 12:590d5be7b7f4 161 bool USBHID::FillInputReport(HID_REPORT *report)
jakowisp 12:590d5be7b7f4 162 {
jakowisp 12:590d5be7b7f4 163 bool changed=false;
jakowisp 12:590d5be7b7f4 164
jakowisp 12:590d5be7b7f4 165 for(int i =0; i<input_length; i++)
jakowisp 12:590d5be7b7f4 166 if(inputReport.data[i] != report->data[i]) {
jakowisp 12:590d5be7b7f4 167 inputReport.data[i] = report->data[i];
jakowisp 12:590d5be7b7f4 168 changed=true;
jakowisp 12:590d5be7b7f4 169 }
jakowisp 12:590d5be7b7f4 170
jakowisp 12:590d5be7b7f4 171 if (changed)
jakowisp 12:590d5be7b7f4 172 return SendReport();
jakowisp 12:590d5be7b7f4 173 else
jakowisp 12:590d5be7b7f4 174 return true;
jakowisp 12:590d5be7b7f4 175 }
samux 1:80ab0d068708 176
jakowisp 12:590d5be7b7f4 177
jakowisp 12:590d5be7b7f4 178 bool USBHID::FillFeatureReport(HID_REPORT *report)
jakowisp 12:590d5be7b7f4 179 {
jakowisp 12:590d5be7b7f4 180 for(int i =0; i<feature_length; i++)
jakowisp 12:590d5be7b7f4 181 featureReport.data[i] = report->data[i];
jakowisp 12:590d5be7b7f4 182 return true;
jakowisp 12:590d5be7b7f4 183 }
jakowisp 12:590d5be7b7f4 184 /* SendReport is called by FillReport if the data has changed. It performs 3 action
jakowisp 12:590d5be7b7f4 185 * 1) Trigger an exposed CallBack This call back is called if a control transfer or interrupt transfer wants to get a INPUT_REPORT
jakowisp 12:590d5be7b7f4 186 * 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.
jakowisp 12:590d5be7b7f4 187 * 2) Reset the IDLE ticker. IF the IDEL rate is not zero, the tickerneeds to be reset since we are sending a changed report.
jakowisp 12:590d5be7b7f4 188 * 3) Send the Report via NB transfer on the interupt endpoint.
jakowisp 12:590d5be7b7f4 189 */
jakowisp 12:590d5be7b7f4 190 bool USBHID::SendReport()
jakowisp 12:590d5be7b7f4 191 {
jakowisp 12:590d5be7b7f4 192 bool result=false;
jakowisp 12:590d5be7b7f4 193
jakowisp 12:590d5be7b7f4 194 if ((*callbackGetInputReport)(&inputReport)) {
jakowisp 12:590d5be7b7f4 195 ResetIdleTicker();
jakowisp 12:590d5be7b7f4 196 result=writeNB(EPINT_IN, inputReport.data, inputReport.length, MAX_HID_REPORT_SIZE);
jakowisp 12:590d5be7b7f4 197 }
jakowisp 12:590d5be7b7f4 198 return result;
jakowisp 12:590d5be7b7f4 199 }
jakowisp 12:590d5be7b7f4 200
jakowisp 12:590d5be7b7f4 201
jakowisp 12:590d5be7b7f4 202
jakowisp 12:590d5be7b7f4 203 /* Legacy method --> No change */
samux 1:80ab0d068708 204 uint16_t USBHID::reportDescLength() {
jakowisp 12:590d5be7b7f4 205 //TODO: Is this a bug? reportDesc() is called and a value that isn't changed is returned. Why execute the function
samux 1:80ab0d068708 206 reportDesc();
samux 1:80ab0d068708 207 return reportLength;
samux 1:80ab0d068708 208 }
samux 1:80ab0d068708 209
jakowisp 12:590d5be7b7f4 210 /* GetReportTargetPointer: HID class control transfers Set_report and Get_report require a pointer to the report to write and read data
jakowisp 12:590d5be7b7f4 211 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.
jakowisp 12:590d5be7b7f4 212 Multi report is not implemented in this release, but a small change in this function will allow support of multiple reports via control transfers.
jakowisp 12:590d5be7b7f4 213
jakowisp 12:590d5be7b7f4 214 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.
jakowisp 12:590d5be7b7f4 215 */
jakowisp 12:590d5be7b7f4 216
jakowisp 12:590d5be7b7f4 217 HID_REPORT * USBHID::GetReportTargetPointer(uint16_t wValue){
jakowisp 12:590d5be7b7f4 218 //TODO: Add support for multiple reports.
jakowisp 12:590d5be7b7f4 219 HID_REPORT *targetPtr=NULL;
jakowisp 12:590d5be7b7f4 220 switch(wValue>>8) {
jakowisp 12:590d5be7b7f4 221 case 0x01: if (input_length >0)
jakowisp 12:590d5be7b7f4 222 targetPtr=&inputReport;
jakowisp 12:590d5be7b7f4 223 break;
jakowisp 12:590d5be7b7f4 224 case 0x03: if (feature_length >0)
jakowisp 12:590d5be7b7f4 225 targetPtr=&featureReport;
jakowisp 12:590d5be7b7f4 226 break;
jakowisp 12:590d5be7b7f4 227 case 0x02:
jakowisp 12:590d5be7b7f4 228 default: if (output_length >0)
jakowisp 12:590d5be7b7f4 229 targetPtr=&outputReport;
jakowisp 12:590d5be7b7f4 230 break;
jakowisp 12:590d5be7b7f4 231 }
jakowisp 12:590d5be7b7f4 232 return targetPtr;
jakowisp 12:590d5be7b7f4 233 }
samux 1:80ab0d068708 234
samux 1:80ab0d068708 235
samux 1:80ab0d068708 236 //
samux 1:80ab0d068708 237 // Route callbacks from lower layers to class(es)
samux 1:80ab0d068708 238 //
samux 1:80ab0d068708 239
samux 1:80ab0d068708 240 // Called in ISR context
samux 1:80ab0d068708 241 // Called by USBDevice on Endpoint0 request
samux 1:80ab0d068708 242 // This is used to handle extensions to standard requests
samux 1:80ab0d068708 243 // and class specific requests
samux 1:80ab0d068708 244 // Return true if class handles this request
jakowisp 12:590d5be7b7f4 245 //Legacy method-->modified to include GET_REPORT, GET_IDLE, SET_IDLE transfers
jakowisp 12:590d5be7b7f4 246 // modified the function of SET_REPORT for multiple types(INPUT,OUTPUT,FEATURE)
samux 1:80ab0d068708 247 bool USBHID::USBCallback_request() {
samux 1:80ab0d068708 248 bool success = false;
samux 1:80ab0d068708 249 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 1:80ab0d068708 250 uint8_t *hidDescriptor;
samux 1:80ab0d068708 251
samux 1:80ab0d068708 252 // Process additional standard requests
samux 1:80ab0d068708 253
samux 1:80ab0d068708 254 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
samux 1:80ab0d068708 255 {
samux 1:80ab0d068708 256 switch (transfer->setup.bRequest)
samux 1:80ab0d068708 257 {
samux 1:80ab0d068708 258 case GET_DESCRIPTOR:
samux 1:80ab0d068708 259 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
samux 1:80ab0d068708 260 {
samux 1:80ab0d068708 261 case REPORT_DESCRIPTOR:
samux 1:80ab0d068708 262 if ((reportDesc() != NULL) \
samux 1:80ab0d068708 263 && (reportDescLength() != 0))
samux 1:80ab0d068708 264 {
samux 1:80ab0d068708 265 transfer->remaining = reportDescLength();
samux 1:80ab0d068708 266 transfer->ptr = reportDesc();
samux 1:80ab0d068708 267 transfer->direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 268 success = true;
samux 1:80ab0d068708 269 }
samux 1:80ab0d068708 270 break;
samux 1:80ab0d068708 271 case HID_DESCRIPTOR:
samux 1:80ab0d068708 272 // Find the HID descriptor, after the configuration descriptor
samux 1:80ab0d068708 273 hidDescriptor = findDescriptor(HID_DESCRIPTOR);
samux 1:80ab0d068708 274 if (hidDescriptor != NULL)
samux 1:80ab0d068708 275 {
samux 1:80ab0d068708 276 transfer->remaining = HID_DESCRIPTOR_LENGTH;
samux 1:80ab0d068708 277 transfer->ptr = hidDescriptor;
samux 1:80ab0d068708 278 transfer->direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 279 success = true;
samux 1:80ab0d068708 280 }
samux 1:80ab0d068708 281 break;
samux 1:80ab0d068708 282
samux 1:80ab0d068708 283 default:
samux 1:80ab0d068708 284 break;
samux 1:80ab0d068708 285 }
samux 1:80ab0d068708 286 break;
samux 1:80ab0d068708 287 default:
samux 1:80ab0d068708 288 break;
samux 1:80ab0d068708 289 }
samux 1:80ab0d068708 290 }
samux 1:80ab0d068708 291
samux 1:80ab0d068708 292 // Process class-specific requests
samux 1:80ab0d068708 293
samux 1:80ab0d068708 294 if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
samux 1:80ab0d068708 295 {
jakowisp 12:590d5be7b7f4 296
jakowisp 12:590d5be7b7f4 297 HID_REPORT *targetPtr=NULL;
jakowisp 12:590d5be7b7f4 298 printf("ReportID: %x\r\n", transfer->setup.wValue & 0xff );
samux 1:80ab0d068708 299 switch (transfer->setup.bRequest)
samux 1:80ab0d068708 300 {
samux 1:80ab0d068708 301 case SET_REPORT:
jakowisp 12:590d5be7b7f4 302 targetPtr=GetReportTargetPointer(transfer->setup.wValue);
jakowisp 12:590d5be7b7f4 303 if (targetPtr==NULL)
jakowisp 12:590d5be7b7f4 304 break;
samux 1:80ab0d068708 305 // First byte will be used for report ID
jakowisp 12:590d5be7b7f4 306 // BUG: In a control transfer the first byte is the reportid and deviceiocontrol does transmit this byte
jakowisp 12:590d5be7b7f4 307 // But the interupt transfer strips the reportid byte
jakowisp 12:590d5be7b7f4 308 targetPtr->data[0] = transfer->setup.wValue & 0xff;
jakowisp 12:590d5be7b7f4 309 targetPtr->length = transfer->setup.wLength + 1;
jakowisp 12:590d5be7b7f4 310 if(transfer->remaining >= sizeof(targetPtr->data) - 1)
jakowisp 12:590d5be7b7f4 311 transfer->remaining = sizeof(targetPtr->data) - 1;
jakowisp 12:590d5be7b7f4 312 else
jakowisp 12:590d5be7b7f4 313 transfer->remaining = transfer->setup.wLength;
jakowisp 12:590d5be7b7f4 314 transfer->ptr = &targetPtr->data[1];
samux 1:80ab0d068708 315 transfer->direction = HOST_TO_DEVICE;
samux 1:80ab0d068708 316 transfer->notify = true;
samux 1:80ab0d068708 317 success = true;
jakowisp 12:590d5be7b7f4 318 break;
jakowisp 12:590d5be7b7f4 319 case GET_REPORT:
jakowisp 12:590d5be7b7f4 320 // Required by section 7.2 of the HID Device Class Definition: Mandatory implementation by all devices
jakowisp 12:590d5be7b7f4 321 targetPtr=GetReportTargetPointer(transfer->setup.wValue);
jakowisp 12:590d5be7b7f4 322 if (targetPtr==NULL)
jakowisp 12:590d5be7b7f4 323 break;
jakowisp 12:590d5be7b7f4 324 // First byte will be used for report ID
jakowisp 12:590d5be7b7f4 325 // BUG: In a control transfer the first byte is the reportid and deviceiocontrol does transmit this byte
jakowisp 12:590d5be7b7f4 326 // But the interupt transfer strips the reportid byte
jakowisp 12:590d5be7b7f4 327 transfer->setup.wLength = targetPtr->length - 1;
jakowisp 12:590d5be7b7f4 328 if(transfer->remaining >= sizeof(targetPtr->data) - 1)
jakowisp 12:590d5be7b7f4 329 transfer->remaining = sizeof(targetPtr->data) - 1;
jakowisp 12:590d5be7b7f4 330 else
jakowisp 12:590d5be7b7f4 331 transfer->remaining = transfer->setup.wLength;
jakowisp 12:590d5be7b7f4 332 transfer->ptr = &targetPtr->data[1];
jakowisp 12:590d5be7b7f4 333 transfer->direction = DEVICE_TO_HOST;
jakowisp 12:590d5be7b7f4 334 transfer->notify = true;
jakowisp 12:590d5be7b7f4 335 //Provide a hook for developers to provide thier own call back for Get_Report, prior to the report data is sentin response to a
jakowisp 12:590d5be7b7f4 336 // Control IN.
jakowisp 12:590d5be7b7f4 337 success =HIDCallback_GetReportHandler(targetPtr);
jakowisp 12:590d5be7b7f4 338 break;
jakowisp 12:590d5be7b7f4 339
jakowisp 12:590d5be7b7f4 340 case SET_IDLE:
jakowisp 12:590d5be7b7f4 341 //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.
jakowisp 12:590d5be7b7f4 342 // Normal default setting is zero.
jakowisp 12:590d5be7b7f4 343 // The microsoft HID driver will throw an invlid function error when IOCTL_HID_GET_POLL_FREQUENCY_MSEC is used.
jakowisp 12:590d5be7b7f4 344 // wValue {duration:ReportID}
jakowisp 12:590d5be7b7f4 345 //TODO: To support multipe reports, a HID_REPORT Class should be defined. The ticker and idle methods and objects should be included.
jakowisp 12:590d5be7b7f4 346 SetReportIdle(transfer->setup.wValue);
jakowisp 12:590d5be7b7f4 347 transfer->setup.wLength = 0;
jakowisp 12:590d5be7b7f4 348 transfer->direction = HOST_TO_DEVICE;
jakowisp 12:590d5be7b7f4 349 transfer->remaining = transfer->setup.wLength;
jakowisp 12:590d5be7b7f4 350 transfer->notify = true;
jakowisp 12:590d5be7b7f4 351 success=true;
jakowisp 12:590d5be7b7f4 352 case GET_IDLE:
jakowisp 12:590d5be7b7f4 353 //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.
jakowisp 12:590d5be7b7f4 354 transfer->setup.wLength = 1;
jakowisp 12:590d5be7b7f4 355 transfer->remaining = transfer->setup.wLength;
jakowisp 12:590d5be7b7f4 356 transfer->ptr = getReportIdlePtr(transfer->setup.wValue & 0xff);
jakowisp 12:590d5be7b7f4 357 transfer->direction = DEVICE_TO_HOST;
jakowisp 12:590d5be7b7f4 358 transfer->notify = true;
jakowisp 12:590d5be7b7f4 359 success=true;
jakowisp 12:590d5be7b7f4 360 break;
jakowisp 12:590d5be7b7f4 361 case GET_PROTOCOL:
jakowisp 12:590d5be7b7f4 362 //TODO: Implement to support BOOT type HIDs
jakowisp 12:590d5be7b7f4 363 //wValue = 0
jakowisp 12:590d5be7b7f4 364 case SET_PROTOCOL:
jakowisp 12:590d5be7b7f4 365 //TODO: Implement to support BOOT type HIDs
jakowisp 12:590d5be7b7f4 366 //wValue = 0 or 1
samux 1:80ab0d068708 367 default:
samux 1:80ab0d068708 368 break;
samux 1:80ab0d068708 369 }
samux 1:80ab0d068708 370 }
samux 1:80ab0d068708 371
samux 1:80ab0d068708 372 return success;
samux 1:80ab0d068708 373 }
samux 1:80ab0d068708 374
jakowisp 12:590d5be7b7f4 375 /* HIDCallback_GetReportHandler provides a useful set of callbacks for the getting of each type in a report.
jakowisp 12:590d5be7b7f4 376 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.
jakowisp 12:590d5be7b7f4 377 NOTE: CALLBACKS happen before the actuall data for the report is transmitted.
jakowisp 12:590d5be7b7f4 378 */
jakowisp 12:590d5be7b7f4 379 bool USBHID::HIDCallback_GetReportHandler(HID_REPORT *targetPtr) {
jakowisp 12:590d5be7b7f4 380 bool (*callbackGetReport)(HID_REPORT *report);
jakowisp 12:590d5be7b7f4 381 CONTROL_TRANSFER * transfer = getTransferPtr();
jakowisp 12:590d5be7b7f4 382
jakowisp 12:590d5be7b7f4 383 switch(transfer->setup.wValue>>8) {
jakowisp 12:590d5be7b7f4 384 case HID_INPUT_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 385 callbackGetReport=callbackGetInputReport;
jakowisp 12:590d5be7b7f4 386 break;
jakowisp 12:590d5be7b7f4 387 case HID_OUTPUT_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 388 callbackGetReport=callbackGetOutputReport;
jakowisp 12:590d5be7b7f4 389 break;
jakowisp 12:590d5be7b7f4 390 case HID_FEATURE_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 391 callbackGetReport=callbackGetFeatureReport;
jakowisp 12:590d5be7b7f4 392 break;
jakowisp 12:590d5be7b7f4 393 default:
jakowisp 12:590d5be7b7f4 394 return false;
jakowisp 12:590d5be7b7f4 395 }
jakowisp 12:590d5be7b7f4 396 return (*callbackGetReport)(targetPtr);
jakowisp 12:590d5be7b7f4 397 }
jakowisp 12:590d5be7b7f4 398
jakowisp 12:590d5be7b7f4 399 /* HIDCallback_SetReportHandler provides a useful set of callbacks for the setting of each type in a report.
jakowisp 12:590d5be7b7f4 400 This can be used to update displays after a value is change(Example:NUM lock LED change).
jakowisp 12:590d5be7b7f4 401 NOTE: CALLBACKS happen after the actuall data for the report is recieved.
jakowisp 12:590d5be7b7f4 402 */
jakowisp 12:590d5be7b7f4 403
jakowisp 12:590d5be7b7f4 404 bool USBHID::HIDCallback_SetReportHandler(HID_REPORT *targetPtr) {
jakowisp 12:590d5be7b7f4 405 void (*callbackSetReport)(HID_REPORT *report);
jakowisp 12:590d5be7b7f4 406 CONTROL_TRANSFER * transfer = getTransferPtr();
jakowisp 12:590d5be7b7f4 407
jakowisp 12:590d5be7b7f4 408 switch(transfer->setup.wValue>>8) {
jakowisp 12:590d5be7b7f4 409 case HID_INPUT_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 410 callbackSetReport=callbackSetInputReport;
jakowisp 12:590d5be7b7f4 411 break;
jakowisp 12:590d5be7b7f4 412 case HID_OUTPUT_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 413 callbackSetReport=callbackSetOutputReport;
jakowisp 12:590d5be7b7f4 414 break;
jakowisp 12:590d5be7b7f4 415 case HID_FEATURE_REPORT_TYPE:
jakowisp 12:590d5be7b7f4 416 callbackSetReport=callbackSetFeatureReport;
jakowisp 12:590d5be7b7f4 417 break;
jakowisp 12:590d5be7b7f4 418 default:
jakowisp 12:590d5be7b7f4 419 return false;
jakowisp 12:590d5be7b7f4 420 }
jakowisp 12:590d5be7b7f4 421 (*callbackSetReport)(targetPtr);
jakowisp 12:590d5be7b7f4 422 return true;
jakowisp 12:590d5be7b7f4 423
jakowisp 12:590d5be7b7f4 424 }
jakowisp 12:590d5be7b7f4 425
jakowisp 12:590d5be7b7f4 426 /* USBCallback_requestCompleted To implement the set_report call back ability we need to override the requestCompleted function to provide the callback handler hook
jakowisp 12:590d5be7b7f4 427 */
jakowisp 12:590d5be7b7f4 428 void USBHID::USBCallback_requestCompleted(uint8_t * buf, uint32_t length){
jakowisp 12:590d5be7b7f4 429 CONTROL_TRANSFER * transfer;
jakowisp 12:590d5be7b7f4 430 HID_REPORT *targetPtr;
jakowisp 12:590d5be7b7f4 431
jakowisp 12:590d5be7b7f4 432 transfer = getTransferPtr();
jakowisp 12:590d5be7b7f4 433 targetPtr = GetReportTargetPointer(transfer->setup.wValue);
jakowisp 12:590d5be7b7f4 434 USBDevice::USBCallback_requestCompleted(buf, length);
jakowisp 12:590d5be7b7f4 435 //Provide a callback hook for developer use of set_report, called after the completion of the control transfer.
jakowisp 12:590d5be7b7f4 436 if(transfer->setup.bRequest==SET_REPORT) {
jakowisp 12:590d5be7b7f4 437 HIDCallback_SetReportHandler(targetPtr);
jakowisp 12:590d5be7b7f4 438 }
jakowisp 12:590d5be7b7f4 439 }
jakowisp 12:590d5be7b7f4 440
jakowisp 12:590d5be7b7f4 441 /* To ensure that the output report is updated on a writeFile interupt transfer, the EP1_OUT_callback is overridden.
jakowisp 12:590d5be7b7f4 442 * additionally a callback for setOutputReport type is trigger
jakowisp 12:590d5be7b7f4 443 */
jakowisp 12:590d5be7b7f4 444 bool USBHID::EP1_OUT_callback(){
jakowisp 12:590d5be7b7f4 445 uint32_t bytesRead = 0;
jakowisp 12:590d5be7b7f4 446 bool result;
jakowisp 12:590d5be7b7f4 447 //TODO: Is there a buffer over run issue here?
jakowisp 12:590d5be7b7f4 448 result = endpointReadResult(EPINT_OUT, outputReport.data, &bytesRead);
jakowisp 12:590d5be7b7f4 449 outputReport.length = bytesRead;
jakowisp 12:590d5be7b7f4 450 (*callbackSetOutputReport)(&outputReport);
jakowisp 12:590d5be7b7f4 451 return result;
jakowisp 12:590d5be7b7f4 452 }
jakowisp 12:590d5be7b7f4 453
samux 1:80ab0d068708 454
samux 1:80ab0d068708 455 #define DEFAULT_CONFIGURATION (1)
samux 1:80ab0d068708 456
samux 1:80ab0d068708 457
samux 1:80ab0d068708 458 // Called in ISR context
samux 1:80ab0d068708 459 // Set configuration. Return false if the
samux 1:80ab0d068708 460 // configuration is not supported
samux 1:80ab0d068708 461 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
samux 1:80ab0d068708 462 if (configuration != DEFAULT_CONFIGURATION) {
samux 1:80ab0d068708 463 return false;
samux 1:80ab0d068708 464 }
samux 1:80ab0d068708 465
samux 1:80ab0d068708 466 // Configure endpoints > 0
samux 1:80ab0d068708 467 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
samux 1:80ab0d068708 468 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 1:80ab0d068708 469
samux 1:80ab0d068708 470 // We activate the endpoint to be able to recceive data
samux 1:80ab0d068708 471 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 1:80ab0d068708 472 return true;
samux 1:80ab0d068708 473 }
samux 1:80ab0d068708 474
samux 1:80ab0d068708 475
samux 1:80ab0d068708 476 uint8_t * USBHID::stringIinterfaceDesc() {
samux 1:80ab0d068708 477 static uint8_t stringIinterfaceDescriptor[] = {
samux 1:80ab0d068708 478 0x08, //bLength
samux 1:80ab0d068708 479 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 1:80ab0d068708 480 'H',0,'I',0,'D',0, //bString iInterface - HID
samux 1:80ab0d068708 481 };
samux 1:80ab0d068708 482 return stringIinterfaceDescriptor;
samux 1:80ab0d068708 483 }
samux 1:80ab0d068708 484
samux 1:80ab0d068708 485 uint8_t * USBHID::stringIproductDesc() {
samux 1:80ab0d068708 486 static uint8_t stringIproductDescriptor[] = {
samux 1:80ab0d068708 487 0x16, //bLength
samux 1:80ab0d068708 488 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 1:80ab0d068708 489 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
samux 1:80ab0d068708 490 };
samux 1:80ab0d068708 491 return stringIproductDescriptor;
samux 1:80ab0d068708 492 }
samux 1:80ab0d068708 493
samux 1:80ab0d068708 494
jakowisp 12:590d5be7b7f4 495 /* legacy method .. Modified
jakowisp 12:590d5be7b7f4 496 * 1) Added feature report
jakowisp 12:590d5be7b7f4 497 * 2) Used KEYWORDS for added user readability.
jakowisp 12:590d5be7b7f4 498 */
samux 1:80ab0d068708 499 uint8_t * USBHID::reportDesc() {
samux 1:80ab0d068708 500 static uint8_t reportDescriptor[] = {
jakowisp 12:590d5be7b7f4 501 USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB),
jakowisp 12:590d5be7b7f4 502 USAGE(2), LSB(0x0200), MSB(0x0200),
jakowisp 12:590d5be7b7f4 503 COLLECTION(1), 0x01, // Collection 0x01
jakowisp 12:590d5be7b7f4 504 REPORT_SIZE(1), 0x08, // report size = 8 bits
jakowisp 12:590d5be7b7f4 505 LOGICAL_MINIMUM(1), 0x00, // logical minimum = 0
jakowisp 12:590d5be7b7f4 506 LOGICAL_MAXIMUM(2), 0xFF, 0x00, // logical maximum = 255
jakowisp 12:590d5be7b7f4 507 REPORT_COUNT(1), input_length, // report count
jakowisp 12:590d5be7b7f4 508 USAGE(1), 0x01, // usage
jakowisp 12:590d5be7b7f4 509 INPUT(1), 0x02, // Input (array)
jakowisp 12:590d5be7b7f4 510 REPORT_COUNT(1), output_length, // report count
jakowisp 12:590d5be7b7f4 511 USAGE(1), 0x02, // usage
jakowisp 12:590d5be7b7f4 512 OUTPUT(1), 0x02, // Output (array)
jakowisp 12:590d5be7b7f4 513 REPORT_COUNT(1), feature_length,
jakowisp 12:590d5be7b7f4 514 USAGE(1), 0x03,
jakowisp 12:590d5be7b7f4 515 FEATURE(2), 0x02, 0x01,
jakowisp 12:590d5be7b7f4 516 END_COLLECTION(0) // end collection
samux 1:80ab0d068708 517 };
samux 1:80ab0d068708 518 reportLength = sizeof(reportDescriptor);
samux 1:80ab0d068708 519 return reportDescriptor;
samux 1:80ab0d068708 520 }
samux 1:80ab0d068708 521
samux 1:80ab0d068708 522 #define DEFAULT_CONFIGURATION (1)
samux 1:80ab0d068708 523 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 524 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 525 + (1 * HID_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 526 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
samux 1:80ab0d068708 527
samux 1:80ab0d068708 528 uint8_t * USBHID::configurationDesc() {
samux 1:80ab0d068708 529 static uint8_t configurationDescriptor[] = {
samux 1:80ab0d068708 530 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
samux 1:80ab0d068708 531 CONFIGURATION_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 532 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
samux 1:80ab0d068708 533 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
samux 1:80ab0d068708 534 0x01, // bNumInterfaces
samux 1:80ab0d068708 535 DEFAULT_CONFIGURATION, // bConfigurationValue
samux 1:80ab0d068708 536 0x00, // iConfiguration
samux 1:80ab0d068708 537 C_RESERVED | C_SELF_POWERED, // bmAttributes
samux 1:80ab0d068708 538 C_POWER(0), // bMaxPower
samux 1:80ab0d068708 539
samux 1:80ab0d068708 540 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 1:80ab0d068708 541 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 542 0x00, // bInterfaceNumber
samux 1:80ab0d068708 543 0x00, // bAlternateSetting
samux 1:80ab0d068708 544 0x02, // bNumEndpoints
samux 1:80ab0d068708 545 HID_CLASS, // bInterfaceClass
samux 1:80ab0d068708 546 HID_SUBCLASS_NONE, // bInterfaceSubClass
samux 1:80ab0d068708 547 HID_PROTOCOL_NONE, // bInterfaceProtocol
samux 1:80ab0d068708 548 0x00, // iInterface
samux 1:80ab0d068708 549
samux 1:80ab0d068708 550 HID_DESCRIPTOR_LENGTH, // bLength
samux 1:80ab0d068708 551 HID_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 552 LSB(HID_VERSION_1_11), // bcdHID (LSB)
samux 1:80ab0d068708 553 MSB(HID_VERSION_1_11), // bcdHID (MSB)
samux 1:80ab0d068708 554 0x00, // bCountryCode
samux 1:80ab0d068708 555 0x01, // bNumDescriptors
samux 1:80ab0d068708 556 REPORT_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 557 LSB(this->reportDescLength()), // wDescriptorLength (LSB)
samux 1:80ab0d068708 558 MSB(this->reportDescLength()), // wDescriptorLength (MSB)
samux 1:80ab0d068708 559
samux 1:80ab0d068708 560 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 1:80ab0d068708 561 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 562 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
samux 1:80ab0d068708 563 E_INTERRUPT, // bmAttributes
samux 1:80ab0d068708 564 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 1:80ab0d068708 565 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 1:80ab0d068708 566 1, // bInterval (milliseconds)
samux 1:80ab0d068708 567
samux 1:80ab0d068708 568 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 1:80ab0d068708 569 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 1:80ab0d068708 570 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
samux 1:80ab0d068708 571 E_INTERRUPT, // bmAttributes
samux 1:80ab0d068708 572 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 1:80ab0d068708 573 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 1:80ab0d068708 574 1, // bInterval (milliseconds)
samux 1:80ab0d068708 575 };
samux 1:80ab0d068708 576 return configurationDescriptor;
samux 1:80ab0d068708 577 }