Modified for PS3 Joystick

Dependents:   NiseKabuto

Fork of USBDevice by Samuel Mokrani

Committer:
sankichi
Date:
Sat Jul 27 14:05:26 2013 +0000
Revision:
1:ac5cca60029a
Parent:
0:140cdf8e2d60
First Release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:140cdf8e2d60 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 0:140cdf8e2d60 2 *
samux 0:140cdf8e2d60 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 0:140cdf8e2d60 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 0:140cdf8e2d60 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 0:140cdf8e2d60 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 0:140cdf8e2d60 7 * Software is furnished to do so, subject to the following conditions:
samux 0:140cdf8e2d60 8 *
samux 0:140cdf8e2d60 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 0:140cdf8e2d60 10 * substantial portions of the Software.
samux 0:140cdf8e2d60 11 *
samux 0:140cdf8e2d60 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 0:140cdf8e2d60 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 0:140cdf8e2d60 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 0:140cdf8e2d60 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 0:140cdf8e2d60 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 0:140cdf8e2d60 17 */
samux 0:140cdf8e2d60 18
samux 0:140cdf8e2d60 19 #include "stdint.h"
samux 0:140cdf8e2d60 20 #include "USBHAL.h"
samux 0:140cdf8e2d60 21 #include "USBHID.h"
samux 0:140cdf8e2d60 22
sankichi 1:ac5cca60029a 23 //////// for PS3 magic bytes
sankichi 1:ac5cca60029a 24 unsigned char magic_init_bytes[] = {0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00}; // PS3 will request these bytes as a class type report 0x0300
sankichi 1:ac5cca60029a 25 ////////
samux 0:140cdf8e2d60 26
samux 0:140cdf8e2d60 27 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)
samux 0:140cdf8e2d60 28 {
samux 0:140cdf8e2d60 29 output_length = output_report_length;
samux 0:140cdf8e2d60 30 input_length = input_report_length;
samux 0:140cdf8e2d60 31 if(connect) {
samux 0:140cdf8e2d60 32 USBDevice::connect();
samux 0:140cdf8e2d60 33 }
samux 0:140cdf8e2d60 34 }
samux 0:140cdf8e2d60 35
samux 0:140cdf8e2d60 36
samux 0:140cdf8e2d60 37 bool USBHID::send(HID_REPORT *report)
samux 0:140cdf8e2d60 38 {
samux 0:140cdf8e2d60 39 return write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
samux 0:140cdf8e2d60 40 }
samux 0:140cdf8e2d60 41
samux 0:140cdf8e2d60 42 bool USBHID::sendNB(HID_REPORT *report)
samux 0:140cdf8e2d60 43 {
samux 0:140cdf8e2d60 44 return writeNB(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
samux 0:140cdf8e2d60 45 }
samux 0:140cdf8e2d60 46
samux 0:140cdf8e2d60 47
samux 0:140cdf8e2d60 48 bool USBHID::read(HID_REPORT *report)
samux 0:140cdf8e2d60 49 {
samux 0:140cdf8e2d60 50 uint32_t bytesRead = 0;
samux 0:140cdf8e2d60 51 bool result;
samux 0:140cdf8e2d60 52 result = USBDevice::readEP(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 0:140cdf8e2d60 53 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 0:140cdf8e2d60 54 return false;
samux 0:140cdf8e2d60 55 report->length = bytesRead;
samux 0:140cdf8e2d60 56 return result;
samux 0:140cdf8e2d60 57 }
samux 0:140cdf8e2d60 58
samux 0:140cdf8e2d60 59
samux 0:140cdf8e2d60 60 bool USBHID::readNB(HID_REPORT *report)
samux 0:140cdf8e2d60 61 {
samux 0:140cdf8e2d60 62 uint32_t bytesRead = 0;
samux 0:140cdf8e2d60 63 bool result;
samux 0:140cdf8e2d60 64 result = USBDevice::readEP_NB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 0:140cdf8e2d60 65 report->length = bytesRead;
samux 0:140cdf8e2d60 66 if(!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 0:140cdf8e2d60 67 return false;
samux 0:140cdf8e2d60 68 return result;
samux 0:140cdf8e2d60 69 }
samux 0:140cdf8e2d60 70
samux 0:140cdf8e2d60 71
samux 0:140cdf8e2d60 72 uint16_t USBHID::reportDescLength() {
samux 0:140cdf8e2d60 73 reportDesc();
samux 0:140cdf8e2d60 74 return reportLength;
samux 0:140cdf8e2d60 75 }
samux 0:140cdf8e2d60 76
samux 0:140cdf8e2d60 77
samux 0:140cdf8e2d60 78
samux 0:140cdf8e2d60 79 //
samux 0:140cdf8e2d60 80 // Route callbacks from lower layers to class(es)
samux 0:140cdf8e2d60 81 //
samux 0:140cdf8e2d60 82
samux 0:140cdf8e2d60 83
samux 0:140cdf8e2d60 84 // Called in ISR context
samux 0:140cdf8e2d60 85 // Called by USBDevice on Endpoint0 request
samux 0:140cdf8e2d60 86 // This is used to handle extensions to standard requests
samux 0:140cdf8e2d60 87 // and class specific requests
samux 0:140cdf8e2d60 88 // Return true if class handles this request
samux 0:140cdf8e2d60 89 bool USBHID::USBCallback_request() {
samux 0:140cdf8e2d60 90 bool success = false;
samux 0:140cdf8e2d60 91 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 0:140cdf8e2d60 92 uint8_t *hidDescriptor;
samux 0:140cdf8e2d60 93
samux 0:140cdf8e2d60 94 // Process additional standard requests
samux 0:140cdf8e2d60 95
samux 0:140cdf8e2d60 96 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
samux 0:140cdf8e2d60 97 {
samux 0:140cdf8e2d60 98 switch (transfer->setup.bRequest)
samux 0:140cdf8e2d60 99 {
samux 0:140cdf8e2d60 100 case GET_DESCRIPTOR:
samux 0:140cdf8e2d60 101 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
samux 0:140cdf8e2d60 102 {
samux 0:140cdf8e2d60 103 case REPORT_DESCRIPTOR:
samux 0:140cdf8e2d60 104 if ((reportDesc() != NULL) \
samux 0:140cdf8e2d60 105 && (reportDescLength() != 0))
samux 0:140cdf8e2d60 106 {
samux 0:140cdf8e2d60 107 transfer->remaining = reportDescLength();
samux 0:140cdf8e2d60 108 transfer->ptr = reportDesc();
samux 0:140cdf8e2d60 109 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 110 success = true;
samux 0:140cdf8e2d60 111 }
samux 0:140cdf8e2d60 112 break;
samux 0:140cdf8e2d60 113 case HID_DESCRIPTOR:
samux 0:140cdf8e2d60 114 // Find the HID descriptor, after the configuration descriptor
samux 0:140cdf8e2d60 115 hidDescriptor = findDescriptor(HID_DESCRIPTOR);
samux 0:140cdf8e2d60 116 if (hidDescriptor != NULL)
samux 0:140cdf8e2d60 117 {
samux 0:140cdf8e2d60 118 transfer->remaining = HID_DESCRIPTOR_LENGTH;
samux 0:140cdf8e2d60 119 transfer->ptr = hidDescriptor;
samux 0:140cdf8e2d60 120 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 121 success = true;
samux 0:140cdf8e2d60 122 }
samux 0:140cdf8e2d60 123 break;
samux 0:140cdf8e2d60 124
samux 0:140cdf8e2d60 125 default:
samux 0:140cdf8e2d60 126 break;
samux 0:140cdf8e2d60 127 }
samux 0:140cdf8e2d60 128 break;
sankichi 1:ac5cca60029a 129
samux 0:140cdf8e2d60 130 default:
samux 0:140cdf8e2d60 131 break;
samux 0:140cdf8e2d60 132 }
samux 0:140cdf8e2d60 133 }
samux 0:140cdf8e2d60 134
samux 0:140cdf8e2d60 135 // Process class-specific requests
samux 0:140cdf8e2d60 136
samux 0:140cdf8e2d60 137 if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
samux 0:140cdf8e2d60 138 {
samux 0:140cdf8e2d60 139 switch (transfer->setup.bRequest)
samux 0:140cdf8e2d60 140 {
samux 0:140cdf8e2d60 141 case SET_REPORT:
samux 0:140cdf8e2d60 142 // First byte will be used for report ID
samux 0:140cdf8e2d60 143 outputReport.data[0] = transfer->setup.wValue & 0xff;
samux 0:140cdf8e2d60 144 outputReport.length = transfer->setup.wLength + 1;
samux 0:140cdf8e2d60 145
samux 0:140cdf8e2d60 146 transfer->remaining = sizeof(outputReport.data) - 1;
samux 0:140cdf8e2d60 147 transfer->ptr = &outputReport.data[1];
samux 0:140cdf8e2d60 148 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 149 transfer->notify = true;
samux 0:140cdf8e2d60 150 success = true;
sankichi 1:ac5cca60029a 151 //////// for PS3 magic bytes
sankichi 1:ac5cca60029a 152 case GET_REPORT:
sankichi 1:ac5cca60029a 153 switch (transfer->setup.wValue & 0xffff)
sankichi 1:ac5cca60029a 154 {
sankichi 1:ac5cca60029a 155 case 0x0300: //vendor specific request
sankichi 1:ac5cca60029a 156
sankichi 1:ac5cca60029a 157 transfer->ptr = (unsigned char*)magic_init_bytes;
sankichi 1:ac5cca60029a 158 transfer->remaining = sizeof(magic_init_bytes);
sankichi 1:ac5cca60029a 159 transfer->direction = DEVICE_TO_HOST;
sankichi 1:ac5cca60029a 160 success = true;
sankichi 1:ac5cca60029a 161
sankichi 1:ac5cca60029a 162 break;
sankichi 1:ac5cca60029a 163 default:
sankichi 1:ac5cca60029a 164 break;
sankichi 1:ac5cca60029a 165 }
sankichi 1:ac5cca60029a 166 break;
sankichi 1:ac5cca60029a 167 ////////
sankichi 1:ac5cca60029a 168
samux 0:140cdf8e2d60 169 default:
samux 0:140cdf8e2d60 170 break;
samux 0:140cdf8e2d60 171 }
samux 0:140cdf8e2d60 172 }
samux 0:140cdf8e2d60 173
samux 0:140cdf8e2d60 174 return success;
samux 0:140cdf8e2d60 175 }
samux 0:140cdf8e2d60 176
samux 0:140cdf8e2d60 177
samux 0:140cdf8e2d60 178 #define DEFAULT_CONFIGURATION (1)
samux 0:140cdf8e2d60 179
samux 0:140cdf8e2d60 180
samux 0:140cdf8e2d60 181 // Called in ISR context
samux 0:140cdf8e2d60 182 // Set configuration. Return false if the
samux 0:140cdf8e2d60 183 // configuration is not supported
samux 0:140cdf8e2d60 184 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
samux 0:140cdf8e2d60 185 if (configuration != DEFAULT_CONFIGURATION) {
samux 0:140cdf8e2d60 186 return false;
samux 0:140cdf8e2d60 187 }
samux 0:140cdf8e2d60 188
samux 0:140cdf8e2d60 189 // Configure endpoints > 0
samux 0:140cdf8e2d60 190 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
samux 0:140cdf8e2d60 191 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 0:140cdf8e2d60 192
samux 0:140cdf8e2d60 193 // We activate the endpoint to be able to recceive data
samux 0:140cdf8e2d60 194 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 0:140cdf8e2d60 195 return true;
samux 0:140cdf8e2d60 196 }
samux 0:140cdf8e2d60 197
samux 0:140cdf8e2d60 198
samux 0:140cdf8e2d60 199 uint8_t * USBHID::stringIinterfaceDesc() {
samux 0:140cdf8e2d60 200 static uint8_t stringIinterfaceDescriptor[] = {
samux 0:140cdf8e2d60 201 0x08, //bLength
samux 0:140cdf8e2d60 202 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 0:140cdf8e2d60 203 'H',0,'I',0,'D',0, //bString iInterface - HID
samux 0:140cdf8e2d60 204 };
samux 0:140cdf8e2d60 205 return stringIinterfaceDescriptor;
samux 0:140cdf8e2d60 206 }
samux 0:140cdf8e2d60 207
samux 0:140cdf8e2d60 208 uint8_t * USBHID::stringIproductDesc() {
samux 0:140cdf8e2d60 209 static uint8_t stringIproductDescriptor[] = {
samux 0:140cdf8e2d60 210 0x16, //bLength
samux 0:140cdf8e2d60 211 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 0:140cdf8e2d60 212 'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
samux 0:140cdf8e2d60 213 };
samux 0:140cdf8e2d60 214 return stringIproductDescriptor;
samux 0:140cdf8e2d60 215 }
samux 0:140cdf8e2d60 216
samux 0:140cdf8e2d60 217
samux 0:140cdf8e2d60 218
samux 0:140cdf8e2d60 219 uint8_t * USBHID::reportDesc() {
samux 0:140cdf8e2d60 220 static uint8_t reportDescriptor[] = {
samux 0:140cdf8e2d60 221 0x06, LSB(0xFFAB), MSB(0xFFAB),
samux 0:140cdf8e2d60 222 0x0A, LSB(0x0200), MSB(0x0200),
samux 0:140cdf8e2d60 223 0xA1, 0x01, // Collection 0x01
samux 0:140cdf8e2d60 224 0x75, 0x08, // report size = 8 bits
samux 0:140cdf8e2d60 225 0x15, 0x00, // logical minimum = 0
samux 0:140cdf8e2d60 226 0x26, 0xFF, 0x00, // logical maximum = 255
samux 0:140cdf8e2d60 227 0x95, input_length, // report count
samux 0:140cdf8e2d60 228 0x09, 0x01, // usage
samux 0:140cdf8e2d60 229 0x81, 0x02, // Input (array)
samux 0:140cdf8e2d60 230 0x95, output_length, // report count
samux 0:140cdf8e2d60 231 0x09, 0x02, // usage
samux 0:140cdf8e2d60 232 0x91, 0x02, // Output (array)
samux 0:140cdf8e2d60 233 0xC0 // end collection
samux 0:140cdf8e2d60 234
samux 0:140cdf8e2d60 235 };
samux 0:140cdf8e2d60 236 reportLength = sizeof(reportDescriptor);
samux 0:140cdf8e2d60 237 return reportDescriptor;
samux 0:140cdf8e2d60 238 }
samux 0:140cdf8e2d60 239
samux 0:140cdf8e2d60 240 #define DEFAULT_CONFIGURATION (1)
samux 0:140cdf8e2d60 241 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 242 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 243 + (1 * HID_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 244 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
samux 0:140cdf8e2d60 245
samux 0:140cdf8e2d60 246 uint8_t * USBHID::configurationDesc() {
samux 0:140cdf8e2d60 247 static uint8_t configurationDescriptor[] = {
samux 0:140cdf8e2d60 248 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
samux 0:140cdf8e2d60 249 CONFIGURATION_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 250 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
samux 0:140cdf8e2d60 251 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
samux 0:140cdf8e2d60 252 0x01, // bNumInterfaces
samux 0:140cdf8e2d60 253 DEFAULT_CONFIGURATION, // bConfigurationValue
samux 0:140cdf8e2d60 254 0x00, // iConfiguration
samux 0:140cdf8e2d60 255 C_RESERVED | C_SELF_POWERED, // bmAttributes
samux 0:140cdf8e2d60 256 C_POWER(0), // bMaxPower
samux 0:140cdf8e2d60 257
samux 0:140cdf8e2d60 258 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 259 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 260 0x00, // bInterfaceNumber
samux 0:140cdf8e2d60 261 0x00, // bAlternateSetting
samux 0:140cdf8e2d60 262 0x02, // bNumEndpoints
samux 0:140cdf8e2d60 263 HID_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 264 HID_SUBCLASS_NONE, // bInterfaceSubClass
samux 0:140cdf8e2d60 265 HID_PROTOCOL_NONE, // bInterfaceProtocol
samux 0:140cdf8e2d60 266 0x00, // iInterface
samux 0:140cdf8e2d60 267
samux 0:140cdf8e2d60 268 HID_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 269 HID_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 270 LSB(HID_VERSION_1_11), // bcdHID (LSB)
samux 0:140cdf8e2d60 271 MSB(HID_VERSION_1_11), // bcdHID (MSB)
samux 0:140cdf8e2d60 272 0x00, // bCountryCode
samux 0:140cdf8e2d60 273 0x01, // bNumDescriptors
samux 0:140cdf8e2d60 274 REPORT_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 275 LSB(this->reportDescLength()), // wDescriptorLength (LSB)
samux 0:140cdf8e2d60 276 MSB(this->reportDescLength()), // wDescriptorLength (MSB)
samux 0:140cdf8e2d60 277
samux 0:140cdf8e2d60 278 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 279 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 280 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
samux 0:140cdf8e2d60 281 E_INTERRUPT, // bmAttributes
samux 0:140cdf8e2d60 282 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 0:140cdf8e2d60 283 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 0:140cdf8e2d60 284 1, // bInterval (milliseconds)
samux 0:140cdf8e2d60 285
samux 0:140cdf8e2d60 286 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 287 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 288 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
samux 0:140cdf8e2d60 289 E_INTERRUPT, // bmAttributes
samux 0:140cdf8e2d60 290 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 0:140cdf8e2d60 291 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 0:140cdf8e2d60 292 1, // bInterval (milliseconds)
samux 0:140cdf8e2d60 293 };
samux 0:140cdf8e2d60 294 return configurationDescriptor;
samux 0:140cdf8e2d60 295 }