USB device stack - modified

Dependents:   shaun_larada

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