Modified for PS3 Joystick

Dependents:   NiseKabuto

Fork of USBDevice by Samuel Mokrani

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 //////// for PS3 magic bytes
00024 unsigned char magic_init_bytes[] = {0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00}; // PS3 will request these bytes as a class type report 0x0300
00025 ////////
00026 
00027 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)
00028 {
00029     output_length = output_report_length;
00030     input_length = input_report_length;
00031     if(connect) {
00032         USBDevice::connect();
00033     }
00034 }
00035 
00036 
00037 bool USBHID::send(HID_REPORT *report)
00038 {
00039     return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
00040 }
00041 
00042 bool USBHID::sendNB(HID_REPORT *report)
00043 {
00044     return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
00045 }
00046 
00047 
00048 bool USBHID::read(HID_REPORT *report)
00049 {
00050     uint32_t bytesRead = 0;
00051     bool result;
00052     result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
00053     if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
00054         return false;
00055     report->length = bytesRead;
00056     return result;
00057 }
00058 
00059 
00060 bool USBHID::readNB(HID_REPORT *report)
00061 {
00062     uint32_t bytesRead = 0;
00063     bool result;
00064     result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
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             
00130             default:
00131                 break;
00132         }
00133     }
00134 
00135     // Process class-specific requests
00136 
00137     if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
00138     {
00139         switch (transfer->setup.bRequest)
00140         {
00141              case SET_REPORT:
00142                 // First byte will be used for report ID
00143                 outputReport.data[0] = transfer->setup.wValue & 0xff;
00144                 outputReport.length = transfer->setup.wLength + 1;
00145 
00146                 transfer->remaining = sizeof(outputReport.data) - 1;
00147                 transfer->ptr = &outputReport.data[1];
00148                 transfer->direction = HOST_TO_DEVICE;
00149                 transfer->notify = true;
00150                 success = true;
00151             //////// for PS3 magic bytes
00152              case GET_REPORT:
00153                  switch (transfer->setup.wValue & 0xffff)
00154                  {
00155                     case 0x0300:    //vendor specific request
00156                     
00157                         transfer->ptr = (unsigned char*)magic_init_bytes;
00158                         transfer->remaining = sizeof(magic_init_bytes);
00159                         transfer->direction = DEVICE_TO_HOST;
00160                         success = true;
00161                         
00162                         break;
00163                     default:
00164                         break;
00165                  }
00166                  break;
00167             ////////
00168             
00169             default:
00170                 break;
00171         }
00172     }
00173 
00174     return success;
00175 }
00176 
00177 
00178 #define DEFAULT_CONFIGURATION (1)
00179 
00180 
00181 // Called in ISR context
00182 // Set configuration. Return false if the
00183 // configuration is not supported
00184 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
00185     if (configuration != DEFAULT_CONFIGURATION) {
00186         return false;
00187     }
00188 
00189     // Configure endpoints > 0
00190     addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
00191     addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00192 
00193     // We activate the endpoint to be able to recceive data
00194     readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
00195     return true;
00196 }
00197 
00198 
00199 uint8_t * USBHID::stringIinterfaceDesc() {
00200     static uint8_t stringIinterfaceDescriptor[] = {
00201         0x08,               //bLength
00202         STRING_DESCRIPTOR,  //bDescriptorType 0x03
00203         'H',0,'I',0,'D',0,  //bString iInterface - HID
00204     };
00205     return stringIinterfaceDescriptor;
00206 }
00207 
00208 uint8_t * USBHID::stringIproductDesc() {
00209     static uint8_t stringIproductDescriptor[] = {
00210         0x16,                                                       //bLength
00211         STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
00212         'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
00213     };
00214     return stringIproductDescriptor;
00215 }
00216 
00217 
00218 
00219 uint8_t * USBHID::reportDesc() {
00220     static uint8_t reportDescriptor[] = {
00221         0x06, LSB(0xFFAB), MSB(0xFFAB),
00222         0x0A, LSB(0x0200), MSB(0x0200),
00223         0xA1, 0x01,         // Collection 0x01
00224         0x75, 0x08,         // report size = 8 bits
00225         0x15, 0x00,         // logical minimum = 0
00226         0x26, 0xFF, 0x00,   // logical maximum = 255
00227         0x95, input_length,           // report count
00228         0x09, 0x01,         // usage
00229         0x81, 0x02,         // Input (array)
00230         0x95, output_length,           // report count
00231         0x09, 0x02,         // usage
00232         0x91, 0x02,         // Output (array)
00233         0xC0                // end collection
00234 
00235     };
00236     reportLength = sizeof(reportDescriptor);
00237     return reportDescriptor;
00238 }
00239 
00240 #define DEFAULT_CONFIGURATION (1)
00241 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
00242                                + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
00243                                + (1 * HID_DESCRIPTOR_LENGTH) \
00244                                + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
00245 
00246 uint8_t * USBHID::configurationDesc() {
00247     static uint8_t configurationDescriptor[] = {
00248         CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
00249         CONFIGURATION_DESCRIPTOR,       // bDescriptorType
00250         LSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (LSB)
00251         MSB(TOTAL_DESCRIPTOR_LENGTH),   // wTotalLength (MSB)
00252         0x01,                           // bNumInterfaces
00253         DEFAULT_CONFIGURATION,          // bConfigurationValue
00254         0x00,                           // iConfiguration
00255         C_RESERVED | C_SELF_POWERED,    // bmAttributes
00256         C_POWER(0),                     // bMaxPower
00257 
00258         INTERFACE_DESCRIPTOR_LENGTH,    // bLength
00259         INTERFACE_DESCRIPTOR,           // bDescriptorType
00260         0x00,                           // bInterfaceNumber
00261         0x00,                           // bAlternateSetting
00262         0x02,                           // bNumEndpoints
00263         HID_CLASS,                      // bInterfaceClass
00264         HID_SUBCLASS_NONE,              // bInterfaceSubClass
00265         HID_PROTOCOL_NONE,              // bInterfaceProtocol
00266         0x00,                           // iInterface
00267 
00268         HID_DESCRIPTOR_LENGTH,          // bLength
00269         HID_DESCRIPTOR,                 // bDescriptorType
00270         LSB(HID_VERSION_1_11),          // bcdHID (LSB)
00271         MSB(HID_VERSION_1_11),          // bcdHID (MSB)
00272         0x00,                           // bCountryCode
00273         0x01,                           // bNumDescriptors
00274         REPORT_DESCRIPTOR,              // bDescriptorType
00275         LSB(this->reportDescLength()),  // wDescriptorLength (LSB)
00276         MSB(this->reportDescLength()),  // wDescriptorLength (MSB)
00277 
00278         ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
00279         ENDPOINT_DESCRIPTOR,            // bDescriptorType
00280         PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
00281         E_INTERRUPT,                    // bmAttributes
00282         LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
00283         MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
00284         1,                             // bInterval (milliseconds)
00285 
00286         ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
00287         ENDPOINT_DESCRIPTOR,            // bDescriptorType
00288         PHY_TO_DESC(EPINT_OUT),          // bEndpointAddress
00289         E_INTERRUPT,                    // bmAttributes
00290         LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
00291         MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
00292         1,                             // bInterval (milliseconds)
00293     };
00294     return configurationDescriptor;
00295 }