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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
USBHID.cpp
00001 /* 00002 * Copyright (c) 2018-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "stdint.h" 00019 #include "USBHID.h" 00020 #include "EndpointResolver.h" 00021 #include "usb_phy_api.h" 00022 00023 class USBHID::AsyncSend: public AsyncOp { 00024 public: 00025 AsyncSend(USBHID *hid, const HID_REPORT *report): hid(hid), report(report), result(false) 00026 { 00027 00028 } 00029 00030 virtual ~AsyncSend() 00031 { 00032 00033 } 00034 00035 virtual bool process() 00036 { 00037 if (!hid->configured()) { 00038 result = false; 00039 return true; 00040 } 00041 00042 if (hid->send_nb(report)) { 00043 result = true; 00044 return true; 00045 } 00046 00047 return false; 00048 } 00049 00050 USBHID *hid; 00051 const HID_REPORT *report; 00052 bool result; 00053 }; 00054 00055 class USBHID::AsyncRead: public AsyncOp { 00056 public: 00057 AsyncRead(USBHID *hid, HID_REPORT *report): hid(hid), report(report), result(false) 00058 { 00059 00060 } 00061 00062 virtual ~AsyncRead() 00063 { 00064 00065 } 00066 00067 virtual bool process() 00068 { 00069 if (!hid->configured()) { 00070 result = false; 00071 return true; 00072 } 00073 00074 if (hid->read_nb(report)) { 00075 result = true; 00076 return true; 00077 } 00078 00079 return false; 00080 } 00081 00082 USBHID *hid; 00083 HID_REPORT *report; 00084 bool result; 00085 }; 00086 00087 class USBHID::AsyncWait: public AsyncOp { 00088 public: 00089 AsyncWait(USBHID *hid): hid(hid) 00090 { 00091 00092 } 00093 00094 virtual ~AsyncWait() 00095 { 00096 00097 } 00098 00099 virtual bool process() 00100 { 00101 if (hid->configured()) { 00102 return true; 00103 } 00104 00105 return false; 00106 } 00107 00108 USBHID *hid; 00109 }; 00110 00111 USBHID::USBHID(bool connect_blocking, uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) 00112 : USBDevice(get_usb_phy(), vendor_id, product_id, product_release) 00113 { 00114 _init(output_report_length, input_report_length); 00115 if (connect_blocking) { 00116 connect(); 00117 wait_ready(); 00118 } else { 00119 init(); 00120 } 00121 00122 } 00123 00124 USBHID::USBHID(USBPhy *phy, uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) 00125 : USBDevice(phy, vendor_id, product_id, product_release) 00126 { 00127 _init(output_report_length, input_report_length); 00128 } 00129 00130 USBHID::~USBHID() 00131 { 00132 deinit(); 00133 } 00134 00135 void USBHID::_init(uint8_t output_report_length, uint8_t input_report_length) 00136 { 00137 EndpointResolver resolver(endpoint_table()); 00138 00139 resolver.endpoint_ctrl(64); 00140 _int_in = resolver.endpoint_in(USB_EP_TYPE_INT, MAX_HID_REPORT_SIZE); 00141 _int_out = resolver.endpoint_out(USB_EP_TYPE_INT, MAX_HID_REPORT_SIZE); 00142 MBED_ASSERT(resolver.valid()); 00143 00144 _send_idle = true; 00145 _read_idle = true; 00146 _output_length = output_report_length; 00147 _input_length = input_report_length; 00148 reportLength = 0; 00149 _input_report.length = 0; 00150 _output_report.length = 0; 00151 } 00152 00153 bool USBHID::ready() 00154 { 00155 return configured(); 00156 } 00157 00158 void USBHID::wait_ready() 00159 { 00160 lock(); 00161 00162 AsyncWait wait_op(this); 00163 _connect_list.add(&wait_op); 00164 00165 unlock(); 00166 00167 wait_op.wait(NULL); 00168 } 00169 00170 00171 bool USBHID::send(const HID_REPORT *report) 00172 { 00173 lock(); 00174 00175 AsyncSend send_op(this, report); 00176 _send_list.add(&send_op); 00177 00178 unlock(); 00179 00180 send_op.wait(NULL); 00181 return send_op.result; 00182 } 00183 00184 bool USBHID::send_nb(const HID_REPORT *report) 00185 { 00186 lock(); 00187 00188 if (!configured()) { 00189 unlock(); 00190 return false; 00191 } 00192 00193 bool success = false; 00194 if (_send_idle) { 00195 memcpy(&_input_report, report, sizeof(_input_report)); 00196 write_start(_int_in, _input_report.data, _input_report.length); 00197 _send_idle = false; 00198 success = true; 00199 } 00200 00201 unlock(); 00202 return success; 00203 } 00204 00205 bool USBHID::read(HID_REPORT *report) 00206 { 00207 lock(); 00208 00209 AsyncRead read_op(this, report); 00210 _read_list.add(&read_op); 00211 00212 unlock(); 00213 00214 read_op.wait(NULL); 00215 return read_op.result; 00216 } 00217 00218 00219 bool USBHID::read_nb(HID_REPORT *report) 00220 { 00221 lock(); 00222 00223 if (!configured()) { 00224 unlock(); 00225 return false; 00226 } 00227 00228 bool success = false; 00229 if (_read_idle) { 00230 memcpy(report, &_output_report, sizeof(_output_report)); 00231 read_start(_int_out, _output_report.data, MAX_HID_REPORT_SIZE); 00232 _read_idle = false; 00233 success = true; 00234 } 00235 00236 unlock(); 00237 return success; 00238 } 00239 00240 void USBHID::_send_isr() 00241 { 00242 assert_locked(); 00243 00244 write_finish(_int_in); 00245 _send_idle = true; 00246 00247 _send_list.process(); 00248 if (_send_idle) { 00249 report_tx(); 00250 } 00251 00252 } 00253 00254 void USBHID::_read_isr() 00255 { 00256 assert_locked(); 00257 00258 _output_report.length = read_finish(_int_out); 00259 _read_idle = true; 00260 00261 _read_list.process(); 00262 if (_read_idle) { 00263 report_rx(); 00264 } 00265 } 00266 00267 uint16_t USBHID::report_desc_length() 00268 { 00269 report_desc(); 00270 return reportLength; 00271 } 00272 00273 00274 void USBHID::callback_state_change(DeviceState new_state) 00275 { 00276 if (new_state != Configured) { 00277 if (!_send_idle) { 00278 endpoint_abort(_int_in); 00279 _send_idle = true; 00280 } 00281 if (!_read_idle) { 00282 endpoint_abort(_int_out); 00283 _read_idle = true; 00284 } 00285 } 00286 _send_list.process(); 00287 _read_list.process(); 00288 _connect_list.process(); 00289 } 00290 00291 // 00292 // Route callbacks from lower layers to class(es) 00293 // 00294 00295 00296 // Called in ISR context 00297 // Called by USBDevice on Endpoint0 request 00298 // This is used to handle extensions to standard requests 00299 // and class specific requests 00300 // Return true if class handles this request 00301 void USBHID::callback_request(const setup_packet_t *setup) 00302 { 00303 uint8_t *hidDescriptor; 00304 RequestResult result = PassThrough; 00305 uint8_t *data = NULL; 00306 uint32_t size = 0; 00307 00308 // Process additional standard requests 00309 00310 if ((setup->bmRequestType.Type == STANDARD_TYPE)) { 00311 switch (setup->bRequest) { 00312 case GET_DESCRIPTOR: 00313 switch (DESCRIPTOR_TYPE(setup->wValue)) { 00314 case REPORT_DESCRIPTOR: 00315 if ((report_desc() != NULL) \ 00316 && (report_desc_length() != 0)) { 00317 size = report_desc_length(); 00318 data = (uint8_t *)report_desc(); 00319 result = Send; 00320 } 00321 break; 00322 case HID_DESCRIPTOR: 00323 // Find the HID descriptor, after the configuration descriptor 00324 hidDescriptor = find_descriptor(HID_DESCRIPTOR); 00325 if (hidDescriptor != NULL) { 00326 size = HID_DESCRIPTOR_LENGTH; 00327 data = hidDescriptor; 00328 result = Send; 00329 } 00330 break; 00331 00332 default: 00333 break; 00334 } 00335 break; 00336 default: 00337 break; 00338 } 00339 } 00340 00341 // Process class-specific requests 00342 00343 if (setup->bmRequestType.Type == CLASS_TYPE) { 00344 switch (setup->bRequest) { 00345 case SET_REPORT: 00346 // First byte will be used for report ID 00347 _output_report.data[0] = setup->wValue & 0xff; 00348 _output_report.length = setup->wLength + 1; 00349 00350 size = sizeof(_output_report.data) - 1; 00351 data = &_output_report.data[1]; 00352 result = Send; 00353 break; 00354 default: 00355 break; 00356 } 00357 } 00358 00359 complete_request(result, data, size); 00360 } 00361 00362 void USBHID::callback_request_xfer_done(const setup_packet_t *setup, bool aborted) 00363 { 00364 (void)aborted; 00365 complete_request_xfer_done(true); 00366 } 00367 00368 00369 #define DEFAULT_CONFIGURATION (1) 00370 00371 00372 // Called in ISR context 00373 // Set configuration. Return false if the 00374 // configuration is not supported 00375 void USBHID::callback_set_configuration(uint8_t configuration) 00376 { 00377 if (configuration == DEFAULT_CONFIGURATION) { 00378 complete_set_configuration(false); 00379 } 00380 00381 // Configure endpoints > 0 00382 endpoint_add(_int_in, MAX_HID_REPORT_SIZE, USB_EP_TYPE_INT, &USBHID::_send_isr); 00383 endpoint_add(_int_out, MAX_HID_REPORT_SIZE, USB_EP_TYPE_INT, &USBHID::_read_isr); 00384 00385 // We activate the endpoint to be able to recceive data 00386 read_start(_int_out, _output_report.data, MAX_HID_REPORT_SIZE); 00387 _read_idle = false; 00388 00389 00390 complete_set_configuration(true); 00391 } 00392 00393 void USBHID::callback_set_interface(uint16_t interface, uint8_t alternate) 00394 { 00395 assert_locked(); 00396 complete_set_interface(true); 00397 } 00398 00399 00400 const uint8_t *USBHID::string_iinterface_desc() 00401 { 00402 static const uint8_t stringIinterfaceDescriptor[] = { 00403 0x08, //bLength 00404 STRING_DESCRIPTOR, //bDescriptorType 0x03 00405 'H', 0, 'I', 0, 'D', 0, //bString iInterface - HID 00406 }; 00407 return stringIinterfaceDescriptor; 00408 } 00409 00410 const uint8_t *USBHID::string_iproduct_desc() 00411 { 00412 static const uint8_t stringIproductDescriptor[] = { 00413 0x16, //bLength 00414 STRING_DESCRIPTOR, //bDescriptorType 0x03 00415 'H', 0, 'I', 0, 'D', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0 //bString iProduct - HID device 00416 }; 00417 return stringIproductDescriptor; 00418 } 00419 00420 00421 00422 const uint8_t *USBHID::report_desc() 00423 { 00424 uint8_t reportDescriptorTemp[] = { 00425 USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB), 00426 USAGE(2), LSB(0x0200), MSB(0x0200), 00427 COLLECTION(1), 0x01, // Collection (Application) 00428 00429 REPORT_SIZE(1), 0x08, // 8 bits 00430 LOGICAL_MINIMUM(1), 0x00, 00431 LOGICAL_MAXIMUM(1), 0xFF, 00432 00433 REPORT_COUNT(1), _input_length, 00434 USAGE(1), 0x01, 00435 INPUT(1), 0x02, // Data, Var, Abs 00436 00437 REPORT_COUNT(1), _output_length, 00438 USAGE(1), 0x02, 00439 OUTPUT(1), 0x02, // Data, Var, Abs 00440 00441 END_COLLECTION(0), 00442 }; 00443 reportLength = sizeof(reportDescriptor); 00444 MBED_ASSERT(sizeof(reportDescriptorTemp) == sizeof(reportDescriptor)); 00445 memcpy(reportDescriptor, reportDescriptorTemp, sizeof(reportDescriptor)); 00446 return reportDescriptor; 00447 } 00448 00449 #define DEFAULT_CONFIGURATION (1) 00450 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \ 00451 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \ 00452 + (1 * HID_DESCRIPTOR_LENGTH) \ 00453 + (2 * ENDPOINT_DESCRIPTOR_LENGTH)) 00454 00455 const uint8_t *USBHID::configuration_desc(uint8_t index) 00456 { 00457 if (index != 0) { 00458 return NULL; 00459 } 00460 00461 uint8_t configurationDescriptorTemp[] = { 00462 CONFIGURATION_DESCRIPTOR_LENGTH, // bLength 00463 CONFIGURATION_DESCRIPTOR, // bDescriptorType 00464 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) 00465 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB) 00466 0x01, // bNumInterfaces 00467 DEFAULT_CONFIGURATION, // bConfigurationValue 00468 0x00, // iConfiguration 00469 C_RESERVED | C_SELF_POWERED, // bmAttributes 00470 C_POWER(0), // bMaxPower 00471 00472 INTERFACE_DESCRIPTOR_LENGTH, // bLength 00473 INTERFACE_DESCRIPTOR, // bDescriptorType 00474 0x00, // bInterfaceNumber 00475 0x00, // bAlternateSetting 00476 0x02, // bNumEndpoints 00477 HID_CLASS, // bInterfaceClass 00478 HID_SUBCLASS_NONE, // bInterfaceSubClass 00479 HID_PROTOCOL_NONE, // bInterfaceProtocol 00480 0x00, // iInterface 00481 00482 HID_DESCRIPTOR_LENGTH, // bLength 00483 HID_DESCRIPTOR, // bDescriptorType 00484 LSB(HID_VERSION_1_11), // bcdHID (LSB) 00485 MSB(HID_VERSION_1_11), // bcdHID (MSB) 00486 0x00, // bCountryCode 00487 0x01, // bNumDescriptors 00488 REPORT_DESCRIPTOR, // bDescriptorType 00489 (uint8_t)(LSB(report_desc_length())), // wDescriptorLength (LSB) 00490 (uint8_t)(MSB(report_desc_length())), // wDescriptorLength (MSB) 00491 00492 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00493 ENDPOINT_DESCRIPTOR, // bDescriptorType 00494 _int_in, // bEndpointAddress 00495 E_INTERRUPT, // bmAttributes 00496 LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB) 00497 MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB) 00498 1, // bInterval (milliseconds) 00499 00500 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00501 ENDPOINT_DESCRIPTOR, // bDescriptorType 00502 _int_out, // bEndpointAddress 00503 E_INTERRUPT, // bmAttributes 00504 LSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (LSB) 00505 MSB(MAX_HID_REPORT_SIZE), // wMaxPacketSize (MSB) 00506 1, // bInterval (milliseconds) 00507 }; 00508 MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(_configuration_descriptor)); 00509 memcpy(_configuration_descriptor, configurationDescriptorTemp, sizeof(_configuration_descriptor)); 00510 return _configuration_descriptor; 00511 }
Generated on Tue Jul 12 2022 13:55:02 by
