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:
Thu Aug 08 07:44:36 2013 +0000
Revision:
17:cf5d77f1026a
Parent:
15:2b2a28dc6ed5
Child:
18:cb3afa532fcd
Added SET_PROTOCOL and GET_PROTOCOL support Only multiple report IDs remain to be implemented.

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