USBDevice stack

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