USB device stack, with KL25Z fixes for USB 3.0 hosts and sleep/resume interrupt handling

Dependents:   frdm_Slider_Keyboard idd_hw2_figlax_PanType idd_hw2_appachu_finger_chording idd_hw3_AngieWangAntonioDeLimaFernandesDanielLim_BladeSymphony ... more

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHID.cpp Source File

USBHID.cpp

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #include "stdint.h"
00020 #include "USBHAL.h"
00021 #include "USBHID.h"
00022 
00023 
00024 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)
00025 {
00026     output_length = output_report_length;
00027     input_length = input_report_length;
00028     if(connect) {
00029         USBDevice::connect();
00030     }
00031 }
00032 
00033 
00034 bool USBHID::send(HID_REPORT *report)
00035 {
00036     return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
00037 }
00038 
00039 bool USBHID::sendNB(HID_REPORT *report)
00040 {
00041     return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
00042 }
00043 
00044 bool USBHID::sendTO(HID_REPORT *report, int timeout_ms)
00045 {
00046     return writeTO(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE, timeout_ms);
00047 }
00048 
00049 
00050 bool USBHID::read(HID_REPORT *report)
00051 {
00052     uint32_t bytesRead = 0;
00053     bool result;
00054     result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
00055     if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
00056         return false;
00057     report->length = bytesRead;
00058     return result;
00059 }
00060 
00061 
00062 bool USBHID::readNB(HID_REPORT *report)
00063 {
00064     uint32_t bytesRead = 0;
00065     bool result;
00066     result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
00067     // if readEP_NB did not succeed, does not issue a readStart
00068     if (!result)
00069         return false;
00070     report->length = bytesRead;
00071     if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
00072         return false;
00073     return result;
00074 }
00075 
00076 
00077 //
00078 //  Route callbacks from lower layers to class(es)
00079 //
00080 
00081 
00082 // Called in ISR context
00083 // Called by USBDevice on Endpoint0 request
00084 // This is used to handle extensions to standard requests
00085 // and class specific requests
00086 // Return true if class handles this request
00087 bool USBHID::USBCallback_request() 
00088 {
00089     bool success = false;
00090     CONTROL_TRANSFER *transfer = getTransferPtr();
00091     const uint8_t *p;
00092     uint16_t len;
00093 
00094     // Process additional standard requests
00095     if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
00096     {
00097         switch (transfer->setup.bRequest)
00098         {
00099         case GET_DESCRIPTOR:
00100             switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
00101             {
00102             case REPORT_DESCRIPTOR:
00103                 // if there's a valid descriptor, return it
00104                 if ((p = reportDesc(transfer->setup.wIndex, len)) != NULL && len != 0)
00105                 {
00106                     transfer->ptr = p;
00107                     transfer->remaining = len;
00108                     transfer->direction = DEVICE_TO_HOST;
00109                     success = true;
00110                 }
00111                 break;
00112                 
00113             case HID_DESCRIPTOR:
00114                 // Find the HID descriptor, after the configuration descriptor
00115                 p = findDescriptor(HID_DESCRIPTOR, transfer->setup.wIndex);
00116                 if (p != NULL)
00117                 {
00118                     transfer->ptr = p;
00119                     transfer->remaining = HID_DESCRIPTOR_LENGTH;
00120                     transfer->direction = DEVICE_TO_HOST;
00121                     success = true;
00122                 }
00123                 break;
00124 
00125             default:
00126                 break;
00127             }
00128             break;
00129             
00130         default:
00131             break;
00132         }
00133     }
00134 
00135     // Process class-specific requests
00136     if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
00137     {
00138         switch (transfer->setup.bRequest)
00139         {
00140         case GET_REPORT:
00141             // not implemented
00142             break;
00143             
00144         case GET_IDLE:
00145             // retrieve the idle rate from an interface
00146             idleData = getIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue));
00147             transfer->ptr = &idleData;
00148             transfer->remaining = 1;
00149             transfer->direction = DEVICE_TO_HOST;
00150             success = true;
00151             break;
00152             
00153         case GET_PROTOCOL:
00154             // not implemented
00155             break;
00156             
00157         case SET_REPORT:
00158             // First byte will be used for report ID
00159             outputReport.data[0] = transfer->setup.wValue & 0xff;
00160             outputReport.length = transfer->setup.wLength + 1;
00161 
00162             transfer->remaining = sizeof(outputReport.data) - 1;
00163             transfer->ptr = &outputReport.data[1];
00164             transfer->direction = HOST_TO_DEVICE;
00165             transfer->notify = true;
00166             success = true;
00167             break;
00168             
00169         case SET_IDLE:
00170             // Set idle time - time between INTERRUPT IN reports from the
00171             // device when there are no changes to report.  setup.wIndex
00172             // is the interface index (we're setting the idle time for the
00173             // given interface only).  MSB(setup.wValue) gives the interval
00174             // in 4ms units, with the special case that 0 means infinity.
00175             setIdleTime(transfer->setup.wIndex, LSB(transfer->setup.wValue), MSB(transfer->setup.wValue));
00176             transfer->remaining = 0;
00177             transfer->direction = DEVICE_TO_HOST;
00178             success = true;
00179             break;
00180             
00181         case SET_PROTOCOL:
00182             // not implemented
00183             break;
00184             
00185         default:
00186             break;
00187         }
00188     }
00189 
00190     return success;
00191 }
00192 
00193 
00194 #define DEFAULT_CONFIGURATION (1)
00195 
00196 
00197 // Called in ISR context
00198 // Set configuration. Return false if the
00199 // configuration is not supported
00200 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) 
00201 {
00202     if (configuration != DEFAULT_CONFIGURATION)
00203         return false;
00204 
00205     // Configure endpoints > 0
00206     addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
00207     addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00208 
00209     // We activate the endpoint to be able to recceive data
00210     readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00211     return true;
00212 }
00213 
00214 
00215 const uint8_t *USBHID::stringIinterfaceDesc() 
00216 {
00217     static const uint8_t stringIinterfaceDescriptor[] = {
00218         0x08,               //bLength
00219         STRING_DESCRIPTOR,  //bDescriptorType 0x03
00220         'H',0,'I',0,'D',0,  //bString iInterface - HID
00221     };
00222     return stringIinterfaceDescriptor;
00223 }
00224 
00225 const uint8_t *USBHID::stringIproductDesc() 
00226 {
00227     static const uint8_t stringIproductDescriptor[] = {
00228         0x16,                                                       //bLength
00229         STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
00230         'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
00231     };
00232     return stringIproductDescriptor;
00233 }
00234 
00235 
00236 
00237 const uint8_t *USBHID::reportDesc(int idx, uint16_t &len) 
00238 {
00239     static const uint8_t reportDescriptor[] = {
00240         0x06, LSB(0xFFAB), MSB(0xFFAB),
00241         0x0A, LSB(0x0200), MSB(0x0200),
00242         0xA1, 0x01,         // Collection 0x01
00243         0x75, 0x08,         // report size = 8 bits
00244         0x15, 0x00,         // logical minimum = 0
00245         0x26, 0xFF, 0x00,   // logical maximum = 255
00246         0x95, input_length, // report count
00247         0x09, 0x01,         // usage
00248         0x81, 0x02,         // Input (array)
00249         0x95, output_length,// report count
00250         0x09, 0x02,         // usage
00251         0x91, 0x02,         // Output (array)
00252         0xC0                // end collection
00253 
00254     };
00255     if (idx != 0) {
00256         len = sizeof(reportDescriptor);
00257         return reportDescriptor;
00258     }
00259     else {
00260         len = 0;
00261         return 0;
00262     }
00263 }
00264 
00265 #define DEFAULT_CONFIGURATION (1)
00266 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
00267                                + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
00268                                + (1 * HID_DESCRIPTOR_LENGTH) \
00269                                + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
00270 
00271 const uint8_t *USBHID::configurationDesc() 
00272 {
00273     const uint16_t rdl = reportDescLength(0);
00274     static const uint8_t configurationDescriptor[] = {
00275         CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
00276         CONFIGURATION_DESCRIPTOR,       // bDescriptorType
00277         LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
00278         MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
00279         0x01,                           // bNumInterfaces
00280         DEFAULT_CONFIGURATION,          // bConfigurationValue
00281         0x00,                           // iConfiguration
00282         C_RESERVED | C_SELF_POWERED,    // bmAttributes
00283         C_POWER(0),                     // bMaxPower
00284 
00285         INTERFACE_DESCRIPTOR_LENGTH,    // bLength
00286         INTERFACE_DESCRIPTOR,           // bDescriptorType
00287         0x00,                           // bInterfaceNumber
00288         0x00,                           // bAlternateSetting
00289         0x02,                           // bNumEndpoints
00290         HID_CLASS,                      // bInterfaceClass
00291         HID_SUBCLASS_NONE,              // bInterfaceSubClass
00292         HID_PROTOCOL_NONE,              // bInterfaceProtocol
00293         0x00,                           // iInterface
00294 
00295         HID_DESCRIPTOR_LENGTH,          // bLength
00296         HID_DESCRIPTOR,                 // bDescriptorType
00297         LSB(HID_VERSION_1_11),          // bcdHID (LSB)
00298         MSB(HID_VERSION_1_11),          // bcdHID (MSB)
00299         0x00,                           // bCountryCode
00300         0x01,                           // bNumDescriptors
00301         REPORT_DESCRIPTOR,              // bDescriptorType
00302         (uint8_t)(LSB(rdl)),            // wDescriptorLength (LSB)
00303         (uint8_t)(MSB(rdl)),            // wDescriptorLength (MSB)
00304 
00305         ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
00306         ENDPOINT_DESCRIPTOR,            // bDescriptorType
00307         PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
00308         E_INTERRUPT,                    // bmAttributes
00309         LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
00310         MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
00311         1,                              // bInterval (milliseconds)
00312 
00313         ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
00314         ENDPOINT_DESCRIPTOR,            // bDescriptorType
00315         PHY_TO_DESC(EPINT_OUT),         // bEndpointAddress
00316         E_INTERRUPT,                    // bmAttributes
00317         LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
00318         MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
00319         1                               // bInterval (milliseconds)
00320     };
00321     return configurationDescriptor;
00322 }