USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

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 
00045 bool USBHID::read(HID_REPORT *report)
00046 {
00047     uint32_t bytesRead = 0;
00048     bool result;
00049     result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
00050     if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
00051         return false;
00052     report->length = bytesRead;
00053     return result;
00054 }
00055 
00056 
00057 bool USBHID::readNB(HID_REPORT *report)
00058 {
00059     uint32_t bytesRead = 0;
00060     bool result;
00061     result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
00062     // if readEP_NB did not succeed, does not issue a readStart
00063     if (!result)
00064         return false;
00065     report->length = bytesRead;
00066     if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
00067         return false;
00068     return result;
00069 }
00070 
00071 
00072 uint16_t USBHID::reportDescLength() {
00073     reportDesc();
00074     return reportLength;
00075 }
00076 
00077 
00078 
00079 //
00080 //  Route callbacks from lower layers to class(es)
00081 //
00082 
00083 
00084 // Called in ISR context
00085 // Called by USBDevice on Endpoint0 request
00086 // This is used to handle extensions to standard requests
00087 // and class specific requests
00088 // Return true if class handles this request
00089 bool USBHID::USBCallback_request() {
00090     bool success = false;
00091     CONTROL_TRANSFER * transfer = getTransferPtr();
00092     uint8_t *hidDescriptor;
00093 
00094     // Process additional standard requests
00095 
00096     if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
00097     {
00098         switch (transfer->setup.bRequest)
00099         {
00100             case GET_DESCRIPTOR:
00101                 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
00102                 {
00103                     case REPORT_DESCRIPTOR:
00104                         if ((reportDesc() != NULL) \
00105                             && (reportDescLength() != 0))
00106                         {
00107                             transfer->remaining = reportDescLength();
00108                             transfer->ptr = reportDesc();
00109                             transfer->direction = DEVICE_TO_HOST;
00110                             success = true;
00111                         }
00112                         break;
00113                     case HID_DESCRIPTOR:
00114                             // Find the HID descriptor, after the configuration descriptor
00115                             hidDescriptor = findDescriptor(HID_DESCRIPTOR);
00116                             if (hidDescriptor != NULL)
00117                             {
00118                                 transfer->remaining = HID_DESCRIPTOR_LENGTH;
00119                                 transfer->ptr = hidDescriptor;
00120                                 transfer->direction = DEVICE_TO_HOST;
00121                                 success = true;
00122                             }
00123                             break;
00124 
00125                     default:
00126                         break;
00127                 }
00128                 break;
00129             default:
00130                 break;
00131         }
00132     }
00133 
00134     // Process class-specific requests
00135 
00136     if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
00137     {
00138         switch (transfer->setup.bRequest)
00139         {
00140              case SET_REPORT:
00141                 // First byte will be used for report ID
00142                 outputReport.data[0] = transfer->setup.wValue & 0xff;
00143                 outputReport.length = transfer->setup.wLength + 1;
00144 
00145                 transfer->remaining = sizeof(outputReport.data) - 1;
00146                 transfer->ptr = &outputReport.data[1];
00147                 transfer->direction = HOST_TO_DEVICE;
00148                 transfer->notify = true;
00149                 success = true;
00150             default:
00151                 break;
00152         }
00153     }
00154 
00155     return success;
00156 }
00157 
00158 
00159 #define DEFAULT_CONFIGURATION (1)
00160 
00161 
00162 // Called in ISR context
00163 // Set configuration. Return false if the
00164 // configuration is not supported
00165 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
00166     if (configuration != DEFAULT_CONFIGURATION) {
00167         return false;
00168     }
00169 
00170     // Configure endpoints > 0
00171     addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
00172     addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00173 
00174     // We activate the endpoint to be able to recceive data
00175     readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00176     return true;
00177 }
00178 
00179 
00180 uint8_t * USBHID::stringIinterfaceDesc() {
00181     static uint8_t stringIinterfaceDescriptor[] = {
00182         0x08,               //bLength
00183         STRING_DESCRIPTOR,  //bDescriptorType 0x03
00184         'H',0,'I',0,'D',0,  //bString iInterface - HID
00185     };
00186     return stringIinterfaceDescriptor;
00187 }
00188 
00189 uint8_t * USBHID::stringIproductDesc() {
00190     static uint8_t stringIproductDescriptor[] = {
00191         0x16,                                                       //bLength
00192         STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
00193         'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
00194     };
00195     return stringIproductDescriptor;
00196 }
00197 
00198 
00199 
00200 uint8_t * USBHID::reportDesc() {
00201     static uint8_t reportDescriptor[] = {
00202         USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB),
00203         USAGE(2), LSB(0x0200), MSB(0x0200),
00204         COLLECTION(1), 0x01, // Collection (Application)
00205 
00206         REPORT_SIZE(1), 0x08, // 8 bits
00207         LOGICAL_MINIMUM(1), 0x00,
00208         LOGICAL_MAXIMUM(1), 0xFF,
00209 
00210         REPORT_COUNT(1), input_length,
00211         USAGE(1), 0x01,
00212         INPUT(1), 0x02, // Data, Var, Abs
00213 
00214         REPORT_COUNT(1), output_length,
00215         USAGE(1), 0x02,
00216         OUTPUT(1), 0x02, // Data, Var, Abs
00217 
00218         END_COLLECTION(0),
00219     };
00220     reportLength = sizeof(reportDescriptor);
00221     return reportDescriptor;
00222 }
00223 
00224 #define DEFAULT_CONFIGURATION (1)
00225 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
00226                                + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
00227                                + (1 * HID_DESCRIPTOR_LENGTH) \
00228                                + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
00229 
00230 uint8_t * USBHID::configurationDesc() {
00231     static uint8_t configurationDescriptor[] = {
00232         CONFIGURATION_DESCRIPTOR_LENGTH,    // bLength
00233         CONFIGURATION_DESCRIPTOR,           // bDescriptorType
00234         LSB(TOTAL_DESCRIPTOR_LENGTH),       // wTotalLength (LSB)
00235         MSB(TOTAL_DESCRIPTOR_LENGTH),       // wTotalLength (MSB)
00236         0x01,                               // bNumInterfaces
00237         DEFAULT_CONFIGURATION,              // bConfigurationValue
00238         0x00,                               // iConfiguration
00239         C_RESERVED | C_SELF_POWERED,        // bmAttributes
00240         C_POWER(0),                         // bMaxPower
00241 
00242         INTERFACE_DESCRIPTOR_LENGTH,        // bLength
00243         INTERFACE_DESCRIPTOR,               // bDescriptorType
00244         0x00,                               // bInterfaceNumber
00245         0x00,                               // bAlternateSetting
00246         0x02,                               // bNumEndpoints
00247         HID_CLASS,                          // bInterfaceClass
00248         HID_SUBCLASS_NONE,                  // bInterfaceSubClass
00249         HID_PROTOCOL_NONE,                  // bInterfaceProtocol
00250         0x00,                               // iInterface
00251 
00252         HID_DESCRIPTOR_LENGTH,              // bLength
00253         HID_DESCRIPTOR,                     // bDescriptorType
00254         LSB(HID_VERSION_1_11),              // bcdHID (LSB)
00255         MSB(HID_VERSION_1_11),              // bcdHID (MSB)
00256         0x00,                               // bCountryCode
00257         0x01,                               // bNumDescriptors
00258         REPORT_DESCRIPTOR,                  // bDescriptorType
00259         (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB)
00260         (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB)
00261 
00262         ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
00263         ENDPOINT_DESCRIPTOR,                // bDescriptorType
00264         PHY_TO_DESC(EPINT_IN),              // bEndpointAddress
00265         E_INTERRUPT,                        // bmAttributes
00266         LSB(MAX_PACKET_SIZE_EPINT),         // wMaxPacketSize (LSB)
00267         MSB(MAX_PACKET_SIZE_EPINT),         // wMaxPacketSize (MSB)
00268         1,                                  // bInterval (milliseconds)
00269 
00270         ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
00271         ENDPOINT_DESCRIPTOR,                // bDescriptorType
00272         PHY_TO_DESC(EPINT_OUT),             // bEndpointAddress
00273         E_INTERRUPT,                        // bmAttributes
00274         LSB(MAX_PACKET_SIZE_EPINT),         // wMaxPacketSize (LSB)
00275         MSB(MAX_PACKET_SIZE_EPINT),         // wMaxPacketSize (MSB)
00276         1,                                  // bInterval (milliseconds)
00277     };
00278     return configurationDescriptor;
00279 }