USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Committer:
setcom_001
Date:
Mon Jul 22 21:16:27 2013 +0000
Revision:
12:a9671b78d24e
docs update

Who changed what in which revision?

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