Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHID.cpp Source File

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 }