Setcom Corporation / USBDevice

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
setcom_001 12:a9671b78d24e 21 #include "USBEndpoints.h"
setcom_001 12:a9671b78d24e 22 #include "USBDevice.h"
setcom_001 12:a9671b78d24e 23 #include "USBDescriptor.h"
setcom_001 12:a9671b78d24e 24
setcom_001 12:a9671b78d24e 25 //#define DEBUG
setcom_001 12:a9671b78d24e 26
setcom_001 12:a9671b78d24e 27 /* Device status */
setcom_001 12:a9671b78d24e 28 #define DEVICE_STATUS_SELF_POWERED (1U<<0)
setcom_001 12:a9671b78d24e 29 #define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
setcom_001 12:a9671b78d24e 30
setcom_001 12:a9671b78d24e 31 /* Endpoint status */
setcom_001 12:a9671b78d24e 32 #define ENDPOINT_STATUS_HALT (1U<<0)
setcom_001 12:a9671b78d24e 33
setcom_001 12:a9671b78d24e 34 /* Standard feature selectors */
setcom_001 12:a9671b78d24e 35 #define DEVICE_REMOTE_WAKEUP (1)
setcom_001 12:a9671b78d24e 36 #define ENDPOINT_HALT (0)
setcom_001 12:a9671b78d24e 37
setcom_001 12:a9671b78d24e 38 /* Macro to convert wIndex endpoint number to physical endpoint number */
setcom_001 12:a9671b78d24e 39 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
setcom_001 12:a9671b78d24e 40 ((endpoint & 0x80) ? 1 : 0))
setcom_001 12:a9671b78d24e 41
setcom_001 12:a9671b78d24e 42
setcom_001 12:a9671b78d24e 43 bool USBDevice::requestGetDescriptor( void )
setcom_001 12:a9671b78d24e 44 {
setcom_001 12:a9671b78d24e 45 bool success = false;
setcom_001 12:a9671b78d24e 46 #ifdef DEBUG
setcom_001 12:a9671b78d24e 47 printf( "get descr: type: %d\r\n", DESCRIPTOR_TYPE( transfer.setup.wValue ) );
setcom_001 12:a9671b78d24e 48 #endif
setcom_001 12:a9671b78d24e 49
setcom_001 12:a9671b78d24e 50 switch ( DESCRIPTOR_TYPE( transfer.setup.wValue ) )
setcom_001 12:a9671b78d24e 51 {
setcom_001 12:a9671b78d24e 52 case DEVICE_DESCRIPTOR:
setcom_001 12:a9671b78d24e 53 if ( deviceDesc() != NULL )
setcom_001 12:a9671b78d24e 54 {
setcom_001 12:a9671b78d24e 55 if ( ( deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH ) \
setcom_001 12:a9671b78d24e 56 && ( deviceDesc()[1] == DEVICE_DESCRIPTOR ) )
setcom_001 12:a9671b78d24e 57 {
setcom_001 12:a9671b78d24e 58 #ifdef DEBUG
setcom_001 12:a9671b78d24e 59 printf( "device descr\r\n" );
setcom_001 12:a9671b78d24e 60 #endif
setcom_001 12:a9671b78d24e 61 transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
setcom_001 12:a9671b78d24e 62 transfer.ptr = deviceDesc();
setcom_001 12:a9671b78d24e 63 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 64 success = true;
setcom_001 12:a9671b78d24e 65 }
setcom_001 12:a9671b78d24e 66 }
setcom_001 12:a9671b78d24e 67
setcom_001 12:a9671b78d24e 68 break;
setcom_001 12:a9671b78d24e 69
setcom_001 12:a9671b78d24e 70 case CONFIGURATION_DESCRIPTOR:
setcom_001 12:a9671b78d24e 71 if ( configurationDesc() != NULL )
setcom_001 12:a9671b78d24e 72 {
setcom_001 12:a9671b78d24e 73 if ( ( configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH ) \
setcom_001 12:a9671b78d24e 74 && ( configurationDesc()[1] == CONFIGURATION_DESCRIPTOR ) )
setcom_001 12:a9671b78d24e 75 {
setcom_001 12:a9671b78d24e 76 #ifdef DEBUG
setcom_001 12:a9671b78d24e 77 printf( "conf descr request\r\n" );
setcom_001 12:a9671b78d24e 78 #endif
setcom_001 12:a9671b78d24e 79 /* Get wTotalLength */
setcom_001 12:a9671b78d24e 80 transfer.remaining = configurationDesc()[2] \
setcom_001 12:a9671b78d24e 81 | ( configurationDesc()[3] << 8 );
setcom_001 12:a9671b78d24e 82 transfer.ptr = configurationDesc();
setcom_001 12:a9671b78d24e 83 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 84 success = true;
setcom_001 12:a9671b78d24e 85 }
setcom_001 12:a9671b78d24e 86 }
setcom_001 12:a9671b78d24e 87
setcom_001 12:a9671b78d24e 88 break;
setcom_001 12:a9671b78d24e 89
setcom_001 12:a9671b78d24e 90 case STRING_DESCRIPTOR:
setcom_001 12:a9671b78d24e 91 #ifdef DEBUG
setcom_001 12:a9671b78d24e 92 printf( "str descriptor\r\n" );
setcom_001 12:a9671b78d24e 93 #endif
setcom_001 12:a9671b78d24e 94
setcom_001 12:a9671b78d24e 95 switch ( DESCRIPTOR_INDEX( transfer.setup.wValue ) )
setcom_001 12:a9671b78d24e 96 {
setcom_001 12:a9671b78d24e 97 case STRING_OFFSET_LANGID:
setcom_001 12:a9671b78d24e 98 #ifdef DEBUG
setcom_001 12:a9671b78d24e 99 printf( "1\r\n" );
setcom_001 12:a9671b78d24e 100 #endif
setcom_001 12:a9671b78d24e 101 transfer.remaining = stringLangidDesc()[0];
setcom_001 12:a9671b78d24e 102 transfer.ptr = stringLangidDesc();
setcom_001 12:a9671b78d24e 103 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 104 success = true;
setcom_001 12:a9671b78d24e 105 break;
setcom_001 12:a9671b78d24e 106
setcom_001 12:a9671b78d24e 107 case STRING_OFFSET_IMANUFACTURER:
setcom_001 12:a9671b78d24e 108 #ifdef DEBUG
setcom_001 12:a9671b78d24e 109 printf( "2\r\n" );
setcom_001 12:a9671b78d24e 110 #endif
setcom_001 12:a9671b78d24e 111 transfer.remaining = stringImanufacturerDesc()[0];
setcom_001 12:a9671b78d24e 112 transfer.ptr = stringImanufacturerDesc();
setcom_001 12:a9671b78d24e 113 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 114 success = true;
setcom_001 12:a9671b78d24e 115 break;
setcom_001 12:a9671b78d24e 116
setcom_001 12:a9671b78d24e 117 case STRING_OFFSET_IPRODUCT:
setcom_001 12:a9671b78d24e 118 #ifdef DEBUG
setcom_001 12:a9671b78d24e 119 printf( "3\r\n" );
setcom_001 12:a9671b78d24e 120 #endif
setcom_001 12:a9671b78d24e 121 transfer.remaining = stringIproductDesc()[0];
setcom_001 12:a9671b78d24e 122 transfer.ptr = stringIproductDesc();
setcom_001 12:a9671b78d24e 123 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 124 success = true;
setcom_001 12:a9671b78d24e 125 break;
setcom_001 12:a9671b78d24e 126
setcom_001 12:a9671b78d24e 127 case STRING_OFFSET_ISERIAL:
setcom_001 12:a9671b78d24e 128 #ifdef DEBUG
setcom_001 12:a9671b78d24e 129 printf( "4\r\n" );
setcom_001 12:a9671b78d24e 130 #endif
setcom_001 12:a9671b78d24e 131 transfer.remaining = stringIserialDesc()[0];
setcom_001 12:a9671b78d24e 132 transfer.ptr = stringIserialDesc();
setcom_001 12:a9671b78d24e 133 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 134 success = true;
setcom_001 12:a9671b78d24e 135 break;
setcom_001 12:a9671b78d24e 136
setcom_001 12:a9671b78d24e 137 case STRING_OFFSET_ICONFIGURATION:
setcom_001 12:a9671b78d24e 138 #ifdef DEBUG
setcom_001 12:a9671b78d24e 139 printf( "5\r\n" );
setcom_001 12:a9671b78d24e 140 #endif
setcom_001 12:a9671b78d24e 141 transfer.remaining = stringIConfigurationDesc()[0];
setcom_001 12:a9671b78d24e 142 transfer.ptr = stringIConfigurationDesc();
setcom_001 12:a9671b78d24e 143 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 144 success = true;
setcom_001 12:a9671b78d24e 145 break;
setcom_001 12:a9671b78d24e 146
setcom_001 12:a9671b78d24e 147 case STRING_OFFSET_IINTERFACE:
setcom_001 12:a9671b78d24e 148 #ifdef DEBUG
setcom_001 12:a9671b78d24e 149 printf( "6\r\n" );
setcom_001 12:a9671b78d24e 150 #endif
setcom_001 12:a9671b78d24e 151 transfer.remaining = stringIinterfaceDesc()[0];
setcom_001 12:a9671b78d24e 152 transfer.ptr = stringIinterfaceDesc();
setcom_001 12:a9671b78d24e 153 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 154 success = true;
setcom_001 12:a9671b78d24e 155 break;
setcom_001 12:a9671b78d24e 156 }
setcom_001 12:a9671b78d24e 157
setcom_001 12:a9671b78d24e 158 break;
setcom_001 12:a9671b78d24e 159
setcom_001 12:a9671b78d24e 160 case INTERFACE_DESCRIPTOR:
setcom_001 12:a9671b78d24e 161 #ifdef DEBUG
setcom_001 12:a9671b78d24e 162 printf( "interface descr\r\n" );
setcom_001 12:a9671b78d24e 163 #endif
setcom_001 12:a9671b78d24e 164
setcom_001 12:a9671b78d24e 165 case ENDPOINT_DESCRIPTOR:
setcom_001 12:a9671b78d24e 166 #ifdef DEBUG
setcom_001 12:a9671b78d24e 167 printf( "endpoint descr\r\n" );
setcom_001 12:a9671b78d24e 168 #endif
setcom_001 12:a9671b78d24e 169 /* TODO: Support is optional, not implemented here */
setcom_001 12:a9671b78d24e 170 break;
setcom_001 12:a9671b78d24e 171
setcom_001 12:a9671b78d24e 172 default:
setcom_001 12:a9671b78d24e 173 #ifdef DEBUG
setcom_001 12:a9671b78d24e 174 printf( "ERROR\r\n" );
setcom_001 12:a9671b78d24e 175 #endif
setcom_001 12:a9671b78d24e 176 break;
setcom_001 12:a9671b78d24e 177 }
setcom_001 12:a9671b78d24e 178
setcom_001 12:a9671b78d24e 179 return success;
setcom_001 12:a9671b78d24e 180 }
setcom_001 12:a9671b78d24e 181
setcom_001 12:a9671b78d24e 182 void USBDevice::decodeSetupPacket( uint8_t *data, SETUP_PACKET *packet )
setcom_001 12:a9671b78d24e 183 {
setcom_001 12:a9671b78d24e 184 /* Fill in the elements of a SETUP_PACKET structure from raw data */
setcom_001 12:a9671b78d24e 185 packet->bmRequestType.dataTransferDirection = ( data[0] & 0x80 ) >> 7;
setcom_001 12:a9671b78d24e 186 packet->bmRequestType.Type = ( data[0] & 0x60 ) >> 5;
setcom_001 12:a9671b78d24e 187 packet->bmRequestType.Recipient = data[0] & 0x1f;
setcom_001 12:a9671b78d24e 188 packet->bRequest = data[1];
setcom_001 12:a9671b78d24e 189 packet->wValue = ( data[2] | ( uint16_t )data[3] << 8 );
setcom_001 12:a9671b78d24e 190 packet->wIndex = ( data[4] | ( uint16_t )data[5] << 8 );
setcom_001 12:a9671b78d24e 191 packet->wLength = ( data[6] | ( uint16_t )data[7] << 8 );
setcom_001 12:a9671b78d24e 192 }
setcom_001 12:a9671b78d24e 193
setcom_001 12:a9671b78d24e 194
setcom_001 12:a9671b78d24e 195 bool USBDevice::controlOut( void )
setcom_001 12:a9671b78d24e 196 {
setcom_001 12:a9671b78d24e 197 /* Control transfer data OUT stage */
setcom_001 12:a9671b78d24e 198 uint8_t buffer[MAX_PACKET_SIZE_EP0];
setcom_001 12:a9671b78d24e 199 uint32_t packetSize;
setcom_001 12:a9671b78d24e 200
setcom_001 12:a9671b78d24e 201 /* Check we should be transferring data OUT */
setcom_001 12:a9671b78d24e 202 if ( transfer.direction != HOST_TO_DEVICE )
setcom_001 12:a9671b78d24e 203 {
setcom_001 12:a9671b78d24e 204 return false;
setcom_001 12:a9671b78d24e 205 }
setcom_001 12:a9671b78d24e 206
setcom_001 12:a9671b78d24e 207 /* Read from endpoint */
setcom_001 12:a9671b78d24e 208 packetSize = EP0getReadResult( buffer );
setcom_001 12:a9671b78d24e 209
setcom_001 12:a9671b78d24e 210 /* Check if transfer size is valid */
setcom_001 12:a9671b78d24e 211 if ( packetSize > transfer.remaining )
setcom_001 12:a9671b78d24e 212 {
setcom_001 12:a9671b78d24e 213 /* Too big */
setcom_001 12:a9671b78d24e 214 return false;
setcom_001 12:a9671b78d24e 215 }
setcom_001 12:a9671b78d24e 216
setcom_001 12:a9671b78d24e 217 /* Update transfer */
setcom_001 12:a9671b78d24e 218 transfer.ptr += packetSize;
setcom_001 12:a9671b78d24e 219 transfer.remaining -= packetSize;
setcom_001 12:a9671b78d24e 220
setcom_001 12:a9671b78d24e 221 /* Check if transfer has completed */
setcom_001 12:a9671b78d24e 222 if ( transfer.remaining == 0 )
setcom_001 12:a9671b78d24e 223 {
setcom_001 12:a9671b78d24e 224 /* Transfer completed */
setcom_001 12:a9671b78d24e 225 if ( transfer.notify )
setcom_001 12:a9671b78d24e 226 {
setcom_001 12:a9671b78d24e 227 /* Notify class layer. */
setcom_001 12:a9671b78d24e 228 USBCallback_requestCompleted( buffer, packetSize );
setcom_001 12:a9671b78d24e 229 transfer.notify = false;
setcom_001 12:a9671b78d24e 230 }
setcom_001 12:a9671b78d24e 231
setcom_001 12:a9671b78d24e 232 /* Status stage */
setcom_001 12:a9671b78d24e 233 EP0write( NULL, 0 );
setcom_001 12:a9671b78d24e 234 }
setcom_001 12:a9671b78d24e 235 else
setcom_001 12:a9671b78d24e 236 {
setcom_001 12:a9671b78d24e 237 EP0read();
setcom_001 12:a9671b78d24e 238 }
setcom_001 12:a9671b78d24e 239
setcom_001 12:a9671b78d24e 240 return true;
setcom_001 12:a9671b78d24e 241 }
setcom_001 12:a9671b78d24e 242
setcom_001 12:a9671b78d24e 243 bool USBDevice::controlIn( void )
setcom_001 12:a9671b78d24e 244 {
setcom_001 12:a9671b78d24e 245 /* Control transfer data IN stage */
setcom_001 12:a9671b78d24e 246 uint32_t packetSize;
setcom_001 12:a9671b78d24e 247
setcom_001 12:a9671b78d24e 248 /* Check if transfer has completed (status stage transactions */
setcom_001 12:a9671b78d24e 249 /* also have transfer.remaining == 0) */
setcom_001 12:a9671b78d24e 250 if ( transfer.remaining == 0 )
setcom_001 12:a9671b78d24e 251 {
setcom_001 12:a9671b78d24e 252 if ( transfer.zlp )
setcom_001 12:a9671b78d24e 253 {
setcom_001 12:a9671b78d24e 254 /* Send zero length packet */
setcom_001 12:a9671b78d24e 255 EP0write( NULL, 0 );
setcom_001 12:a9671b78d24e 256 transfer.zlp = false;
setcom_001 12:a9671b78d24e 257 }
setcom_001 12:a9671b78d24e 258
setcom_001 12:a9671b78d24e 259 /* Transfer completed */
setcom_001 12:a9671b78d24e 260 if ( transfer.notify )
setcom_001 12:a9671b78d24e 261 {
setcom_001 12:a9671b78d24e 262 /* Notify class layer. */
setcom_001 12:a9671b78d24e 263 USBCallback_requestCompleted( NULL, 0 );
setcom_001 12:a9671b78d24e 264 transfer.notify = false;
setcom_001 12:a9671b78d24e 265 }
setcom_001 12:a9671b78d24e 266
setcom_001 12:a9671b78d24e 267 EP0read();
setcom_001 12:a9671b78d24e 268 /* Completed */
setcom_001 12:a9671b78d24e 269 return true;
setcom_001 12:a9671b78d24e 270 }
setcom_001 12:a9671b78d24e 271
setcom_001 12:a9671b78d24e 272 /* Check we should be transferring data IN */
setcom_001 12:a9671b78d24e 273 if ( transfer.direction != DEVICE_TO_HOST )
setcom_001 12:a9671b78d24e 274 {
setcom_001 12:a9671b78d24e 275 return false;
setcom_001 12:a9671b78d24e 276 }
setcom_001 12:a9671b78d24e 277
setcom_001 12:a9671b78d24e 278 packetSize = transfer.remaining;
setcom_001 12:a9671b78d24e 279
setcom_001 12:a9671b78d24e 280 if ( packetSize > MAX_PACKET_SIZE_EP0 )
setcom_001 12:a9671b78d24e 281 {
setcom_001 12:a9671b78d24e 282 packetSize = MAX_PACKET_SIZE_EP0;
setcom_001 12:a9671b78d24e 283 }
setcom_001 12:a9671b78d24e 284
setcom_001 12:a9671b78d24e 285 /* Write to endpoint */
setcom_001 12:a9671b78d24e 286 EP0write( transfer.ptr, packetSize );
setcom_001 12:a9671b78d24e 287 /* Update transfer */
setcom_001 12:a9671b78d24e 288 transfer.ptr += packetSize;
setcom_001 12:a9671b78d24e 289 transfer.remaining -= packetSize;
setcom_001 12:a9671b78d24e 290 return true;
setcom_001 12:a9671b78d24e 291 }
setcom_001 12:a9671b78d24e 292
setcom_001 12:a9671b78d24e 293 bool USBDevice::requestSetAddress( void )
setcom_001 12:a9671b78d24e 294 {
setcom_001 12:a9671b78d24e 295 /* Set the device address */
setcom_001 12:a9671b78d24e 296 setAddress( transfer.setup.wValue );
setcom_001 12:a9671b78d24e 297
setcom_001 12:a9671b78d24e 298 if ( transfer.setup.wValue == 0 )
setcom_001 12:a9671b78d24e 299 {
setcom_001 12:a9671b78d24e 300 device.state = DEFAULT;
setcom_001 12:a9671b78d24e 301 }
setcom_001 12:a9671b78d24e 302 else
setcom_001 12:a9671b78d24e 303 {
setcom_001 12:a9671b78d24e 304 device.state = ADDRESS;
setcom_001 12:a9671b78d24e 305 }
setcom_001 12:a9671b78d24e 306
setcom_001 12:a9671b78d24e 307 return true;
setcom_001 12:a9671b78d24e 308 }
setcom_001 12:a9671b78d24e 309
setcom_001 12:a9671b78d24e 310 bool USBDevice::requestSetConfiguration( void )
setcom_001 12:a9671b78d24e 311 {
setcom_001 12:a9671b78d24e 312 device.configuration = transfer.setup.wValue;
setcom_001 12:a9671b78d24e 313
setcom_001 12:a9671b78d24e 314 /* Set the device configuration */
setcom_001 12:a9671b78d24e 315 if ( device.configuration == 0 )
setcom_001 12:a9671b78d24e 316 {
setcom_001 12:a9671b78d24e 317 /* Not configured */
setcom_001 12:a9671b78d24e 318 unconfigureDevice();
setcom_001 12:a9671b78d24e 319 device.state = ADDRESS;
setcom_001 12:a9671b78d24e 320 }
setcom_001 12:a9671b78d24e 321 else
setcom_001 12:a9671b78d24e 322 {
setcom_001 12:a9671b78d24e 323 if ( USBCallback_setConfiguration( device.configuration ) )
setcom_001 12:a9671b78d24e 324 {
setcom_001 12:a9671b78d24e 325 /* Valid configuration */
setcom_001 12:a9671b78d24e 326 configureDevice();
setcom_001 12:a9671b78d24e 327 device.state = CONFIGURED;
setcom_001 12:a9671b78d24e 328 }
setcom_001 12:a9671b78d24e 329 else
setcom_001 12:a9671b78d24e 330 {
setcom_001 12:a9671b78d24e 331 return false;
setcom_001 12:a9671b78d24e 332 }
setcom_001 12:a9671b78d24e 333 }
setcom_001 12:a9671b78d24e 334
setcom_001 12:a9671b78d24e 335 return true;
setcom_001 12:a9671b78d24e 336 }
setcom_001 12:a9671b78d24e 337
setcom_001 12:a9671b78d24e 338 bool USBDevice::requestGetConfiguration( void )
setcom_001 12:a9671b78d24e 339 {
setcom_001 12:a9671b78d24e 340 /* Send the device configuration */
setcom_001 12:a9671b78d24e 341 transfer.ptr = &device.configuration;
setcom_001 12:a9671b78d24e 342 transfer.remaining = sizeof( device.configuration );
setcom_001 12:a9671b78d24e 343 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 344 return true;
setcom_001 12:a9671b78d24e 345 }
setcom_001 12:a9671b78d24e 346
setcom_001 12:a9671b78d24e 347 bool USBDevice::requestGetInterface( void )
setcom_001 12:a9671b78d24e 348 {
setcom_001 12:a9671b78d24e 349 /* Return the selected alternate setting for an interface */
setcom_001 12:a9671b78d24e 350 if ( device.state != CONFIGURED )
setcom_001 12:a9671b78d24e 351 {
setcom_001 12:a9671b78d24e 352 return false;
setcom_001 12:a9671b78d24e 353 }
setcom_001 12:a9671b78d24e 354
setcom_001 12:a9671b78d24e 355 /* Send the alternate setting */
setcom_001 12:a9671b78d24e 356 transfer.setup.wIndex = currentInterface;
setcom_001 12:a9671b78d24e 357 transfer.ptr = &currentAlternate;
setcom_001 12:a9671b78d24e 358 transfer.remaining = sizeof( currentAlternate );
setcom_001 12:a9671b78d24e 359 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 360 return true;
setcom_001 12:a9671b78d24e 361 }
setcom_001 12:a9671b78d24e 362
setcom_001 12:a9671b78d24e 363 bool USBDevice::requestSetInterface( void )
setcom_001 12:a9671b78d24e 364 {
setcom_001 12:a9671b78d24e 365 bool success = false;
setcom_001 12:a9671b78d24e 366
setcom_001 12:a9671b78d24e 367 if( USBCallback_setInterface( transfer.setup.wIndex, transfer.setup.wValue ) )
setcom_001 12:a9671b78d24e 368 {
setcom_001 12:a9671b78d24e 369 success = true;
setcom_001 12:a9671b78d24e 370 currentInterface = transfer.setup.wIndex;
setcom_001 12:a9671b78d24e 371 currentAlternate = transfer.setup.wValue;
setcom_001 12:a9671b78d24e 372 }
setcom_001 12:a9671b78d24e 373
setcom_001 12:a9671b78d24e 374 return success;
setcom_001 12:a9671b78d24e 375 }
setcom_001 12:a9671b78d24e 376
setcom_001 12:a9671b78d24e 377 bool USBDevice::requestSetFeature()
setcom_001 12:a9671b78d24e 378 {
setcom_001 12:a9671b78d24e 379 bool success = false;
setcom_001 12:a9671b78d24e 380
setcom_001 12:a9671b78d24e 381 if ( device.state != CONFIGURED )
setcom_001 12:a9671b78d24e 382 {
setcom_001 12:a9671b78d24e 383 /* Endpoint or interface must be zero */
setcom_001 12:a9671b78d24e 384 if ( transfer.setup.wIndex != 0 )
setcom_001 12:a9671b78d24e 385 {
setcom_001 12:a9671b78d24e 386 return false;
setcom_001 12:a9671b78d24e 387 }
setcom_001 12:a9671b78d24e 388 }
setcom_001 12:a9671b78d24e 389
setcom_001 12:a9671b78d24e 390 switch ( transfer.setup.bmRequestType.Recipient )
setcom_001 12:a9671b78d24e 391 {
setcom_001 12:a9671b78d24e 392 case DEVICE_RECIPIENT:
setcom_001 12:a9671b78d24e 393 /* TODO: Remote wakeup feature not supported */
setcom_001 12:a9671b78d24e 394 break;
setcom_001 12:a9671b78d24e 395
setcom_001 12:a9671b78d24e 396 case ENDPOINT_RECIPIENT:
setcom_001 12:a9671b78d24e 397 if ( transfer.setup.wValue == ENDPOINT_HALT )
setcom_001 12:a9671b78d24e 398 {
setcom_001 12:a9671b78d24e 399 /* TODO: We should check that the endpoint number is valid */
setcom_001 12:a9671b78d24e 400 stallEndpoint(
setcom_001 12:a9671b78d24e 401 WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
setcom_001 12:a9671b78d24e 402 success = true;
setcom_001 12:a9671b78d24e 403 }
setcom_001 12:a9671b78d24e 404
setcom_001 12:a9671b78d24e 405 break;
setcom_001 12:a9671b78d24e 406
setcom_001 12:a9671b78d24e 407 default:
setcom_001 12:a9671b78d24e 408 break;
setcom_001 12:a9671b78d24e 409 }
setcom_001 12:a9671b78d24e 410
setcom_001 12:a9671b78d24e 411 return success;
setcom_001 12:a9671b78d24e 412 }
setcom_001 12:a9671b78d24e 413
setcom_001 12:a9671b78d24e 414 bool USBDevice::requestClearFeature()
setcom_001 12:a9671b78d24e 415 {
setcom_001 12:a9671b78d24e 416 bool success = false;
setcom_001 12:a9671b78d24e 417
setcom_001 12:a9671b78d24e 418 if ( device.state != CONFIGURED )
setcom_001 12:a9671b78d24e 419 {
setcom_001 12:a9671b78d24e 420 /* Endpoint or interface must be zero */
setcom_001 12:a9671b78d24e 421 if ( transfer.setup.wIndex != 0 )
setcom_001 12:a9671b78d24e 422 {
setcom_001 12:a9671b78d24e 423 return false;
setcom_001 12:a9671b78d24e 424 }
setcom_001 12:a9671b78d24e 425 }
setcom_001 12:a9671b78d24e 426
setcom_001 12:a9671b78d24e 427 switch ( transfer.setup.bmRequestType.Recipient )
setcom_001 12:a9671b78d24e 428 {
setcom_001 12:a9671b78d24e 429 case DEVICE_RECIPIENT:
setcom_001 12:a9671b78d24e 430 /* TODO: Remote wakeup feature not supported */
setcom_001 12:a9671b78d24e 431 break;
setcom_001 12:a9671b78d24e 432
setcom_001 12:a9671b78d24e 433 case ENDPOINT_RECIPIENT:
setcom_001 12:a9671b78d24e 434
setcom_001 12:a9671b78d24e 435 /* TODO: We should check that the endpoint number is valid */
setcom_001 12:a9671b78d24e 436 if ( transfer.setup.wValue == ENDPOINT_HALT )
setcom_001 12:a9671b78d24e 437 {
setcom_001 12:a9671b78d24e 438 unstallEndpoint( WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
setcom_001 12:a9671b78d24e 439 success = true;
setcom_001 12:a9671b78d24e 440 }
setcom_001 12:a9671b78d24e 441
setcom_001 12:a9671b78d24e 442 break;
setcom_001 12:a9671b78d24e 443
setcom_001 12:a9671b78d24e 444 default:
setcom_001 12:a9671b78d24e 445 break;
setcom_001 12:a9671b78d24e 446 }
setcom_001 12:a9671b78d24e 447
setcom_001 12:a9671b78d24e 448 return success;
setcom_001 12:a9671b78d24e 449 }
setcom_001 12:a9671b78d24e 450
setcom_001 12:a9671b78d24e 451 bool USBDevice::requestGetStatus( void )
setcom_001 12:a9671b78d24e 452 {
setcom_001 12:a9671b78d24e 453 static uint16_t status;
setcom_001 12:a9671b78d24e 454 bool success = false;
setcom_001 12:a9671b78d24e 455
setcom_001 12:a9671b78d24e 456 if ( device.state != CONFIGURED )
setcom_001 12:a9671b78d24e 457 {
setcom_001 12:a9671b78d24e 458 /* Endpoint or interface must be zero */
setcom_001 12:a9671b78d24e 459 if ( transfer.setup.wIndex != 0 )
setcom_001 12:a9671b78d24e 460 {
setcom_001 12:a9671b78d24e 461 return false;
setcom_001 12:a9671b78d24e 462 }
setcom_001 12:a9671b78d24e 463 }
setcom_001 12:a9671b78d24e 464
setcom_001 12:a9671b78d24e 465 switch ( transfer.setup.bmRequestType.Recipient )
setcom_001 12:a9671b78d24e 466 {
setcom_001 12:a9671b78d24e 467 case DEVICE_RECIPIENT:
setcom_001 12:a9671b78d24e 468 /* TODO: Currently only supports self powered devices */
setcom_001 12:a9671b78d24e 469 status = DEVICE_STATUS_SELF_POWERED;
setcom_001 12:a9671b78d24e 470 success = true;
setcom_001 12:a9671b78d24e 471 break;
setcom_001 12:a9671b78d24e 472
setcom_001 12:a9671b78d24e 473 case INTERFACE_RECIPIENT:
setcom_001 12:a9671b78d24e 474 status = 0;
setcom_001 12:a9671b78d24e 475 success = true;
setcom_001 12:a9671b78d24e 476 break;
setcom_001 12:a9671b78d24e 477
setcom_001 12:a9671b78d24e 478 case ENDPOINT_RECIPIENT:
setcom_001 12:a9671b78d24e 479
setcom_001 12:a9671b78d24e 480 /* TODO: We should check that the endpoint number is valid */
setcom_001 12:a9671b78d24e 481 if ( getEndpointStallState(
setcom_001 12:a9671b78d24e 482 WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) ) )
setcom_001 12:a9671b78d24e 483 {
setcom_001 12:a9671b78d24e 484 status = ENDPOINT_STATUS_HALT;
setcom_001 12:a9671b78d24e 485 }
setcom_001 12:a9671b78d24e 486 else
setcom_001 12:a9671b78d24e 487 {
setcom_001 12:a9671b78d24e 488 status = 0;
setcom_001 12:a9671b78d24e 489 }
setcom_001 12:a9671b78d24e 490
setcom_001 12:a9671b78d24e 491 success = true;
setcom_001 12:a9671b78d24e 492 break;
setcom_001 12:a9671b78d24e 493
setcom_001 12:a9671b78d24e 494 default:
setcom_001 12:a9671b78d24e 495 break;
setcom_001 12:a9671b78d24e 496 }
setcom_001 12:a9671b78d24e 497
setcom_001 12:a9671b78d24e 498 if ( success )
setcom_001 12:a9671b78d24e 499 {
setcom_001 12:a9671b78d24e 500 /* Send the status */
setcom_001 12:a9671b78d24e 501 transfer.ptr = ( uint8_t * )&status; /* Assumes little endian */
setcom_001 12:a9671b78d24e 502 transfer.remaining = sizeof( status );
setcom_001 12:a9671b78d24e 503 transfer.direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 504 }
setcom_001 12:a9671b78d24e 505
setcom_001 12:a9671b78d24e 506 return success;
setcom_001 12:a9671b78d24e 507 }
setcom_001 12:a9671b78d24e 508
setcom_001 12:a9671b78d24e 509 bool USBDevice::requestSetup( void )
setcom_001 12:a9671b78d24e 510 {
setcom_001 12:a9671b78d24e 511 bool success = false;
setcom_001 12:a9671b78d24e 512
setcom_001 12:a9671b78d24e 513 /* Process standard requests */
setcom_001 12:a9671b78d24e 514 if ( ( transfer.setup.bmRequestType.Type == STANDARD_TYPE ) )
setcom_001 12:a9671b78d24e 515 {
setcom_001 12:a9671b78d24e 516 switch ( transfer.setup.bRequest )
setcom_001 12:a9671b78d24e 517 {
setcom_001 12:a9671b78d24e 518 case GET_STATUS:
setcom_001 12:a9671b78d24e 519 success = requestGetStatus();
setcom_001 12:a9671b78d24e 520 break;
setcom_001 12:a9671b78d24e 521
setcom_001 12:a9671b78d24e 522 case CLEAR_FEATURE:
setcom_001 12:a9671b78d24e 523 success = requestClearFeature();
setcom_001 12:a9671b78d24e 524 break;
setcom_001 12:a9671b78d24e 525
setcom_001 12:a9671b78d24e 526 case SET_FEATURE:
setcom_001 12:a9671b78d24e 527 success = requestSetFeature();
setcom_001 12:a9671b78d24e 528 break;
setcom_001 12:a9671b78d24e 529
setcom_001 12:a9671b78d24e 530 case SET_ADDRESS:
setcom_001 12:a9671b78d24e 531 success = requestSetAddress();
setcom_001 12:a9671b78d24e 532 break;
setcom_001 12:a9671b78d24e 533
setcom_001 12:a9671b78d24e 534 case GET_DESCRIPTOR:
setcom_001 12:a9671b78d24e 535 success = requestGetDescriptor();
setcom_001 12:a9671b78d24e 536 break;
setcom_001 12:a9671b78d24e 537
setcom_001 12:a9671b78d24e 538 case SET_DESCRIPTOR:
setcom_001 12:a9671b78d24e 539 /* TODO: Support is optional, not implemented here */
setcom_001 12:a9671b78d24e 540 success = false;
setcom_001 12:a9671b78d24e 541 break;
setcom_001 12:a9671b78d24e 542
setcom_001 12:a9671b78d24e 543 case GET_CONFIGURATION:
setcom_001 12:a9671b78d24e 544 success = requestGetConfiguration();
setcom_001 12:a9671b78d24e 545 break;
setcom_001 12:a9671b78d24e 546
setcom_001 12:a9671b78d24e 547 case SET_CONFIGURATION:
setcom_001 12:a9671b78d24e 548 success = requestSetConfiguration();
setcom_001 12:a9671b78d24e 549 break;
setcom_001 12:a9671b78d24e 550
setcom_001 12:a9671b78d24e 551 case GET_INTERFACE:
setcom_001 12:a9671b78d24e 552 success = requestGetInterface();
setcom_001 12:a9671b78d24e 553 break;
setcom_001 12:a9671b78d24e 554
setcom_001 12:a9671b78d24e 555 case SET_INTERFACE:
setcom_001 12:a9671b78d24e 556 success = requestSetInterface();
setcom_001 12:a9671b78d24e 557 break;
setcom_001 12:a9671b78d24e 558
setcom_001 12:a9671b78d24e 559 default:
setcom_001 12:a9671b78d24e 560 break;
setcom_001 12:a9671b78d24e 561 }
setcom_001 12:a9671b78d24e 562 }
setcom_001 12:a9671b78d24e 563
setcom_001 12:a9671b78d24e 564 return success;
setcom_001 12:a9671b78d24e 565 }
setcom_001 12:a9671b78d24e 566
setcom_001 12:a9671b78d24e 567 bool USBDevice::controlSetup( void )
setcom_001 12:a9671b78d24e 568 {
setcom_001 12:a9671b78d24e 569 bool success = false;
setcom_001 12:a9671b78d24e 570 /* Control transfer setup stage */
setcom_001 12:a9671b78d24e 571 uint8_t buffer[MAX_PACKET_SIZE_EP0];
setcom_001 12:a9671b78d24e 572 EP0setup( buffer );
setcom_001 12:a9671b78d24e 573 /* Initialise control transfer state */
setcom_001 12:a9671b78d24e 574 decodeSetupPacket( buffer, &transfer.setup );
setcom_001 12:a9671b78d24e 575 transfer.ptr = NULL;
setcom_001 12:a9671b78d24e 576 transfer.remaining = 0;
setcom_001 12:a9671b78d24e 577 transfer.direction = 0;
setcom_001 12:a9671b78d24e 578 transfer.zlp = false;
setcom_001 12:a9671b78d24e 579 transfer.notify = false;
setcom_001 12:a9671b78d24e 580 #ifdef DEBUG
setcom_001 12:a9671b78d24e 581 printf( "dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n", transfer.setup.bmRequestType.dataTransferDirection,
setcom_001 12:a9671b78d24e 582 transfer.setup.bmRequestType.Type,
setcom_001 12:a9671b78d24e 583 transfer.setup.bmRequestType.Recipient,
setcom_001 12:a9671b78d24e 584 transfer.setup.bRequest,
setcom_001 12:a9671b78d24e 585 transfer.setup.wValue,
setcom_001 12:a9671b78d24e 586 transfer.setup.wIndex,
setcom_001 12:a9671b78d24e 587 transfer.setup.wLength );
setcom_001 12:a9671b78d24e 588 #endif
setcom_001 12:a9671b78d24e 589 /* Class / vendor specific */
setcom_001 12:a9671b78d24e 590 success = USBCallback_request();
setcom_001 12:a9671b78d24e 591
setcom_001 12:a9671b78d24e 592 if ( !success )
setcom_001 12:a9671b78d24e 593 {
setcom_001 12:a9671b78d24e 594 /* Standard requests */
setcom_001 12:a9671b78d24e 595 if ( !requestSetup() )
setcom_001 12:a9671b78d24e 596 {
setcom_001 12:a9671b78d24e 597 #ifdef DEBUG
setcom_001 12:a9671b78d24e 598 printf( "fail!!!!\r\n" );
setcom_001 12:a9671b78d24e 599 #endif
setcom_001 12:a9671b78d24e 600 return false;
setcom_001 12:a9671b78d24e 601 }
setcom_001 12:a9671b78d24e 602 }
setcom_001 12:a9671b78d24e 603
setcom_001 12:a9671b78d24e 604 /* Check transfer size and direction */
setcom_001 12:a9671b78d24e 605 if ( transfer.setup.wLength > 0 )
setcom_001 12:a9671b78d24e 606 {
setcom_001 12:a9671b78d24e 607 if ( transfer.setup.bmRequestType.dataTransferDirection \
setcom_001 12:a9671b78d24e 608 == DEVICE_TO_HOST )
setcom_001 12:a9671b78d24e 609 {
setcom_001 12:a9671b78d24e 610 /* IN data stage is required */
setcom_001 12:a9671b78d24e 611 if ( transfer.direction != DEVICE_TO_HOST )
setcom_001 12:a9671b78d24e 612 {
setcom_001 12:a9671b78d24e 613 return false;
setcom_001 12:a9671b78d24e 614 }
setcom_001 12:a9671b78d24e 615
setcom_001 12:a9671b78d24e 616 /* Transfer must be less than or equal to the size */
setcom_001 12:a9671b78d24e 617 /* requested by the host */
setcom_001 12:a9671b78d24e 618 if ( transfer.remaining > transfer.setup.wLength )
setcom_001 12:a9671b78d24e 619 {
setcom_001 12:a9671b78d24e 620 transfer.remaining = transfer.setup.wLength;
setcom_001 12:a9671b78d24e 621 }
setcom_001 12:a9671b78d24e 622 }
setcom_001 12:a9671b78d24e 623 else
setcom_001 12:a9671b78d24e 624 {
setcom_001 12:a9671b78d24e 625 /* OUT data stage is required */
setcom_001 12:a9671b78d24e 626 if ( transfer.direction != HOST_TO_DEVICE )
setcom_001 12:a9671b78d24e 627 {
setcom_001 12:a9671b78d24e 628 return false;
setcom_001 12:a9671b78d24e 629 }
setcom_001 12:a9671b78d24e 630
setcom_001 12:a9671b78d24e 631 /* Transfer must be equal to the size requested by the host */
setcom_001 12:a9671b78d24e 632 if ( transfer.remaining != transfer.setup.wLength )
setcom_001 12:a9671b78d24e 633 {
setcom_001 12:a9671b78d24e 634 return false;
setcom_001 12:a9671b78d24e 635 }
setcom_001 12:a9671b78d24e 636 }
setcom_001 12:a9671b78d24e 637 }
setcom_001 12:a9671b78d24e 638 else
setcom_001 12:a9671b78d24e 639 {
setcom_001 12:a9671b78d24e 640 /* No data stage; transfer size must be zero */
setcom_001 12:a9671b78d24e 641 if ( transfer.remaining != 0 )
setcom_001 12:a9671b78d24e 642 {
setcom_001 12:a9671b78d24e 643 return false;
setcom_001 12:a9671b78d24e 644 }
setcom_001 12:a9671b78d24e 645 }
setcom_001 12:a9671b78d24e 646
setcom_001 12:a9671b78d24e 647 /* Data or status stage if applicable */
setcom_001 12:a9671b78d24e 648 if ( transfer.setup.wLength > 0 )
setcom_001 12:a9671b78d24e 649 {
setcom_001 12:a9671b78d24e 650 if ( transfer.setup.bmRequestType.dataTransferDirection \
setcom_001 12:a9671b78d24e 651 == DEVICE_TO_HOST )
setcom_001 12:a9671b78d24e 652 {
setcom_001 12:a9671b78d24e 653 /* Check if we'll need to send a zero length packet at */
setcom_001 12:a9671b78d24e 654 /* the end of this transfer */
setcom_001 12:a9671b78d24e 655 if ( transfer.setup.wLength > transfer.remaining )
setcom_001 12:a9671b78d24e 656 {
setcom_001 12:a9671b78d24e 657 /* Device wishes to transfer less than host requested */
setcom_001 12:a9671b78d24e 658 if ( ( transfer.remaining % MAX_PACKET_SIZE_EP0 ) == 0 )
setcom_001 12:a9671b78d24e 659 {
setcom_001 12:a9671b78d24e 660 /* Transfer is a multiple of EP0 max packet size */
setcom_001 12:a9671b78d24e 661 transfer.zlp = true;
setcom_001 12:a9671b78d24e 662 }
setcom_001 12:a9671b78d24e 663 }
setcom_001 12:a9671b78d24e 664
setcom_001 12:a9671b78d24e 665 /* IN stage */
setcom_001 12:a9671b78d24e 666 controlIn();
setcom_001 12:a9671b78d24e 667 }
setcom_001 12:a9671b78d24e 668 else
setcom_001 12:a9671b78d24e 669 {
setcom_001 12:a9671b78d24e 670 /* OUT stage */
setcom_001 12:a9671b78d24e 671 EP0read();
setcom_001 12:a9671b78d24e 672 }
setcom_001 12:a9671b78d24e 673 }
setcom_001 12:a9671b78d24e 674 else
setcom_001 12:a9671b78d24e 675 {
setcom_001 12:a9671b78d24e 676 /* Status stage */
setcom_001 12:a9671b78d24e 677 EP0write( NULL, 0 );
setcom_001 12:a9671b78d24e 678 }
setcom_001 12:a9671b78d24e 679
setcom_001 12:a9671b78d24e 680 return true;
setcom_001 12:a9671b78d24e 681 }
setcom_001 12:a9671b78d24e 682
setcom_001 12:a9671b78d24e 683 void USBDevice::busReset( void )
setcom_001 12:a9671b78d24e 684 {
setcom_001 12:a9671b78d24e 685 device.state = DEFAULT;
setcom_001 12:a9671b78d24e 686 device.configuration = 0;
setcom_001 12:a9671b78d24e 687 device.suspended = false;
setcom_001 12:a9671b78d24e 688 /* Call class / vendor specific busReset function */
setcom_001 12:a9671b78d24e 689 USBCallback_busReset();
setcom_001 12:a9671b78d24e 690 }
setcom_001 12:a9671b78d24e 691
setcom_001 12:a9671b78d24e 692 void USBDevice::EP0setupCallback( void )
setcom_001 12:a9671b78d24e 693 {
setcom_001 12:a9671b78d24e 694 /* Endpoint 0 setup event */
setcom_001 12:a9671b78d24e 695 if ( !controlSetup() )
setcom_001 12:a9671b78d24e 696 {
setcom_001 12:a9671b78d24e 697 /* Protocol stall */
setcom_001 12:a9671b78d24e 698 EP0stall();
setcom_001 12:a9671b78d24e 699 }
setcom_001 12:a9671b78d24e 700
setcom_001 12:a9671b78d24e 701 /* Return true if an OUT data stage is expected */
setcom_001 12:a9671b78d24e 702 }
setcom_001 12:a9671b78d24e 703
setcom_001 12:a9671b78d24e 704 void USBDevice::EP0out( void )
setcom_001 12:a9671b78d24e 705 {
setcom_001 12:a9671b78d24e 706 /* Endpoint 0 OUT data event */
setcom_001 12:a9671b78d24e 707 if ( !controlOut() )
setcom_001 12:a9671b78d24e 708 {
setcom_001 12:a9671b78d24e 709 /* Protocol stall; this will stall both endpoints */
setcom_001 12:a9671b78d24e 710 EP0stall();
setcom_001 12:a9671b78d24e 711 }
setcom_001 12:a9671b78d24e 712 }
setcom_001 12:a9671b78d24e 713
setcom_001 12:a9671b78d24e 714 void USBDevice::EP0in( void )
setcom_001 12:a9671b78d24e 715 {
setcom_001 12:a9671b78d24e 716 #ifdef DEBUG
setcom_001 12:a9671b78d24e 717 printf( "EP0IN\r\n" );
setcom_001 12:a9671b78d24e 718 #endif
setcom_001 12:a9671b78d24e 719
setcom_001 12:a9671b78d24e 720 /* Endpoint 0 IN data event */
setcom_001 12:a9671b78d24e 721 if ( !controlIn() )
setcom_001 12:a9671b78d24e 722 {
setcom_001 12:a9671b78d24e 723 /* Protocol stall; this will stall both endpoints */
setcom_001 12:a9671b78d24e 724 EP0stall();
setcom_001 12:a9671b78d24e 725 }
setcom_001 12:a9671b78d24e 726 }
setcom_001 12:a9671b78d24e 727
setcom_001 12:a9671b78d24e 728 bool USBDevice::configured( void )
setcom_001 12:a9671b78d24e 729 {
setcom_001 12:a9671b78d24e 730 /* Returns true if device is in the CONFIGURED state */
setcom_001 12:a9671b78d24e 731 return ( device.state == CONFIGURED );
setcom_001 12:a9671b78d24e 732 }
setcom_001 12:a9671b78d24e 733
setcom_001 12:a9671b78d24e 734 void USBDevice::connect( void )
setcom_001 12:a9671b78d24e 735 {
setcom_001 12:a9671b78d24e 736 /* Connect device */
setcom_001 12:a9671b78d24e 737 USBHAL::connect();
setcom_001 12:a9671b78d24e 738
setcom_001 12:a9671b78d24e 739 /* Block if not configured */
setcom_001 12:a9671b78d24e 740 while ( !configured() );
setcom_001 12:a9671b78d24e 741 }
setcom_001 12:a9671b78d24e 742
setcom_001 12:a9671b78d24e 743 void USBDevice::disconnect( void )
setcom_001 12:a9671b78d24e 744 {
setcom_001 12:a9671b78d24e 745 /* Disconnect device */
setcom_001 12:a9671b78d24e 746 USBHAL::disconnect();
setcom_001 12:a9671b78d24e 747 }
setcom_001 12:a9671b78d24e 748
setcom_001 12:a9671b78d24e 749 CONTROL_TRANSFER *USBDevice::getTransferPtr( void )
setcom_001 12:a9671b78d24e 750 {
setcom_001 12:a9671b78d24e 751 return &transfer;
setcom_001 12:a9671b78d24e 752 }
setcom_001 12:a9671b78d24e 753
setcom_001 12:a9671b78d24e 754 bool USBDevice::addEndpoint( uint8_t endpoint, uint32_t maxPacket )
setcom_001 12:a9671b78d24e 755 {
setcom_001 12:a9671b78d24e 756 return realiseEndpoint( endpoint, maxPacket, 0 );
setcom_001 12:a9671b78d24e 757 }
setcom_001 12:a9671b78d24e 758
setcom_001 12:a9671b78d24e 759 bool USBDevice::addRateFeedbackEndpoint( uint8_t endpoint, uint32_t maxPacket )
setcom_001 12:a9671b78d24e 760 {
setcom_001 12:a9671b78d24e 761 /* For interrupt endpoints only */
setcom_001 12:a9671b78d24e 762 return realiseEndpoint( endpoint, maxPacket, RATE_FEEDBACK_MODE );
setcom_001 12:a9671b78d24e 763 }
setcom_001 12:a9671b78d24e 764
setcom_001 12:a9671b78d24e 765 uint8_t *USBDevice::findDescriptor( uint8_t descriptorType )
setcom_001 12:a9671b78d24e 766 {
setcom_001 12:a9671b78d24e 767 /* Find a descriptor within the list of descriptors */
setcom_001 12:a9671b78d24e 768 /* following a configuration descriptor. */
setcom_001 12:a9671b78d24e 769 uint16_t wTotalLength;
setcom_001 12:a9671b78d24e 770 uint8_t *ptr;
setcom_001 12:a9671b78d24e 771
setcom_001 12:a9671b78d24e 772 if ( configurationDesc() == NULL )
setcom_001 12:a9671b78d24e 773 {
setcom_001 12:a9671b78d24e 774 return NULL;
setcom_001 12:a9671b78d24e 775 }
setcom_001 12:a9671b78d24e 776
setcom_001 12:a9671b78d24e 777 /* Check this is a configuration descriptor */
setcom_001 12:a9671b78d24e 778 if ( ( configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH ) \
setcom_001 12:a9671b78d24e 779 || ( configurationDesc()[1] != CONFIGURATION_DESCRIPTOR ) )
setcom_001 12:a9671b78d24e 780 {
setcom_001 12:a9671b78d24e 781 return NULL;
setcom_001 12:a9671b78d24e 782 }
setcom_001 12:a9671b78d24e 783
setcom_001 12:a9671b78d24e 784 wTotalLength = configurationDesc()[2] | ( configurationDesc()[3] << 8 );
setcom_001 12:a9671b78d24e 785
setcom_001 12:a9671b78d24e 786 /* Check there are some more descriptors to follow */
setcom_001 12:a9671b78d24e 787 if ( wTotalLength <= ( CONFIGURATION_DESCRIPTOR_LENGTH + 2 ) )
setcom_001 12:a9671b78d24e 788 /* +2 is for bLength and bDescriptorType of next descriptor */
setcom_001 12:a9671b78d24e 789 {
setcom_001 12:a9671b78d24e 790 return false;
setcom_001 12:a9671b78d24e 791 }
setcom_001 12:a9671b78d24e 792
setcom_001 12:a9671b78d24e 793 /* Start at first descriptor after the configuration descriptor */
setcom_001 12:a9671b78d24e 794 ptr = &( configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH] );
setcom_001 12:a9671b78d24e 795
setcom_001 12:a9671b78d24e 796 do
setcom_001 12:a9671b78d24e 797 {
setcom_001 12:a9671b78d24e 798 if ( ptr[1] /* bDescriptorType */ == descriptorType )
setcom_001 12:a9671b78d24e 799 {
setcom_001 12:a9671b78d24e 800 /* Found */
setcom_001 12:a9671b78d24e 801 return ptr;
setcom_001 12:a9671b78d24e 802 }
setcom_001 12:a9671b78d24e 803
setcom_001 12:a9671b78d24e 804 /* Skip to next descriptor */
setcom_001 12:a9671b78d24e 805 ptr += ptr[0]; /* bLength */
setcom_001 12:a9671b78d24e 806 }
setcom_001 12:a9671b78d24e 807 while ( ptr < ( configurationDesc() + wTotalLength ) );
setcom_001 12:a9671b78d24e 808
setcom_001 12:a9671b78d24e 809 /* Reached end of the descriptors - not found */
setcom_001 12:a9671b78d24e 810 return NULL;
setcom_001 12:a9671b78d24e 811 }
setcom_001 12:a9671b78d24e 812
setcom_001 12:a9671b78d24e 813
setcom_001 12:a9671b78d24e 814 void USBDevice::connectStateChanged( unsigned int connected )
setcom_001 12:a9671b78d24e 815 {
setcom_001 12:a9671b78d24e 816 }
setcom_001 12:a9671b78d24e 817
setcom_001 12:a9671b78d24e 818 void USBDevice::suspendStateChanged( unsigned int suspended )
setcom_001 12:a9671b78d24e 819 {
setcom_001 12:a9671b78d24e 820 }
setcom_001 12:a9671b78d24e 821
setcom_001 12:a9671b78d24e 822
setcom_001 12:a9671b78d24e 823 USBDevice::USBDevice( uint16_t vendor_id, uint16_t product_id, uint16_t product_release )
setcom_001 12:a9671b78d24e 824 {
setcom_001 12:a9671b78d24e 825 VENDOR_ID = vendor_id;
setcom_001 12:a9671b78d24e 826 PRODUCT_ID = product_id;
setcom_001 12:a9671b78d24e 827 PRODUCT_RELEASE = product_release;
setcom_001 12:a9671b78d24e 828 /* Set initial device state */
setcom_001 12:a9671b78d24e 829 device.state = POWERED;
setcom_001 12:a9671b78d24e 830 device.configuration = 0;
setcom_001 12:a9671b78d24e 831 device.suspended = false;
setcom_001 12:a9671b78d24e 832 };
setcom_001 12:a9671b78d24e 833
setcom_001 12:a9671b78d24e 834
setcom_001 12:a9671b78d24e 835 bool USBDevice::readStart( uint8_t endpoint, uint32_t maxSize )
setcom_001 12:a9671b78d24e 836 {
setcom_001 12:a9671b78d24e 837 return endpointRead( endpoint, maxSize ) == EP_PENDING;
setcom_001 12:a9671b78d24e 838 }
setcom_001 12:a9671b78d24e 839
setcom_001 12:a9671b78d24e 840
setcom_001 12:a9671b78d24e 841 bool USBDevice::write( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
setcom_001 12:a9671b78d24e 842 {
setcom_001 12:a9671b78d24e 843 EP_STATUS result;
setcom_001 12:a9671b78d24e 844
setcom_001 12:a9671b78d24e 845 if ( size > maxSize )
setcom_001 12:a9671b78d24e 846 {
setcom_001 12:a9671b78d24e 847 return false;
setcom_001 12:a9671b78d24e 848 }
setcom_001 12:a9671b78d24e 849
setcom_001 12:a9671b78d24e 850 if( !configured() )
setcom_001 12:a9671b78d24e 851 {
setcom_001 12:a9671b78d24e 852 return false;
setcom_001 12:a9671b78d24e 853 }
setcom_001 12:a9671b78d24e 854
setcom_001 12:a9671b78d24e 855 /* Send report */
setcom_001 12:a9671b78d24e 856 result = endpointWrite( endpoint, buffer, size );
setcom_001 12:a9671b78d24e 857
setcom_001 12:a9671b78d24e 858 if ( result != EP_PENDING )
setcom_001 12:a9671b78d24e 859 {
setcom_001 12:a9671b78d24e 860 return false;
setcom_001 12:a9671b78d24e 861 }
setcom_001 12:a9671b78d24e 862
setcom_001 12:a9671b78d24e 863 /* Wait for completion */
setcom_001 12:a9671b78d24e 864 do
setcom_001 12:a9671b78d24e 865 {
setcom_001 12:a9671b78d24e 866 result = endpointWriteResult( endpoint );
setcom_001 12:a9671b78d24e 867 }
setcom_001 12:a9671b78d24e 868 while ( ( result == EP_PENDING ) && configured() );
setcom_001 12:a9671b78d24e 869
setcom_001 12:a9671b78d24e 870 return ( result == EP_COMPLETED );
setcom_001 12:a9671b78d24e 871 }
setcom_001 12:a9671b78d24e 872
setcom_001 12:a9671b78d24e 873
setcom_001 12:a9671b78d24e 874 bool USBDevice::writeNB( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
setcom_001 12:a9671b78d24e 875 {
setcom_001 12:a9671b78d24e 876 EP_STATUS result;
setcom_001 12:a9671b78d24e 877
setcom_001 12:a9671b78d24e 878 if ( size > maxSize )
setcom_001 12:a9671b78d24e 879 {
setcom_001 12:a9671b78d24e 880 return false;
setcom_001 12:a9671b78d24e 881 }
setcom_001 12:a9671b78d24e 882
setcom_001 12:a9671b78d24e 883 if( !configured() )
setcom_001 12:a9671b78d24e 884 {
setcom_001 12:a9671b78d24e 885 return false;
setcom_001 12:a9671b78d24e 886 }
setcom_001 12:a9671b78d24e 887
setcom_001 12:a9671b78d24e 888 /* Send report */
setcom_001 12:a9671b78d24e 889 result = endpointWrite( endpoint, buffer, size );
setcom_001 12:a9671b78d24e 890
setcom_001 12:a9671b78d24e 891 if ( result != EP_PENDING )
setcom_001 12:a9671b78d24e 892 {
setcom_001 12:a9671b78d24e 893 return false;
setcom_001 12:a9671b78d24e 894 }
setcom_001 12:a9671b78d24e 895
setcom_001 12:a9671b78d24e 896 result = endpointWriteResult( endpoint );
setcom_001 12:a9671b78d24e 897 return ( result == EP_COMPLETED );
setcom_001 12:a9671b78d24e 898 }
setcom_001 12:a9671b78d24e 899
setcom_001 12:a9671b78d24e 900
setcom_001 12:a9671b78d24e 901
setcom_001 12:a9671b78d24e 902 bool USBDevice::readEP( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
setcom_001 12:a9671b78d24e 903 {
setcom_001 12:a9671b78d24e 904 EP_STATUS result;
setcom_001 12:a9671b78d24e 905
setcom_001 12:a9671b78d24e 906 if( !configured() )
setcom_001 12:a9671b78d24e 907 {
setcom_001 12:a9671b78d24e 908 return false;
setcom_001 12:a9671b78d24e 909 }
setcom_001 12:a9671b78d24e 910
setcom_001 12:a9671b78d24e 911 /* Wait for completion */
setcom_001 12:a9671b78d24e 912 do
setcom_001 12:a9671b78d24e 913 {
setcom_001 12:a9671b78d24e 914 result = endpointReadResult( endpoint, buffer, size );
setcom_001 12:a9671b78d24e 915 }
setcom_001 12:a9671b78d24e 916 while ( ( result == EP_PENDING ) && configured() );
setcom_001 12:a9671b78d24e 917
setcom_001 12:a9671b78d24e 918 return ( result == EP_COMPLETED );
setcom_001 12:a9671b78d24e 919 }
setcom_001 12:a9671b78d24e 920
setcom_001 12:a9671b78d24e 921
setcom_001 12:a9671b78d24e 922 bool USBDevice::readEP_NB( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
setcom_001 12:a9671b78d24e 923 {
setcom_001 12:a9671b78d24e 924 EP_STATUS result;
setcom_001 12:a9671b78d24e 925
setcom_001 12:a9671b78d24e 926 if( !configured() )
setcom_001 12:a9671b78d24e 927 {
setcom_001 12:a9671b78d24e 928 return false;
setcom_001 12:a9671b78d24e 929 }
setcom_001 12:a9671b78d24e 930
setcom_001 12:a9671b78d24e 931 result = endpointReadResult( endpoint, buffer, size );
setcom_001 12:a9671b78d24e 932 return ( result == EP_COMPLETED );
setcom_001 12:a9671b78d24e 933 }
setcom_001 12:a9671b78d24e 934
setcom_001 12:a9671b78d24e 935
setcom_001 12:a9671b78d24e 936
setcom_001 12:a9671b78d24e 937 uint8_t *USBDevice::deviceDesc()
setcom_001 12:a9671b78d24e 938 {
setcom_001 12:a9671b78d24e 939 static uint8_t deviceDescriptor[] =
setcom_001 12:a9671b78d24e 940 {
setcom_001 12:a9671b78d24e 941 DEVICE_DESCRIPTOR_LENGTH, /* bLength */
setcom_001 12:a9671b78d24e 942 DEVICE_DESCRIPTOR, /* bDescriptorType */
setcom_001 12:a9671b78d24e 943 LSB( USB_VERSION_2_0 ), /* bcdUSB (LSB) */
setcom_001 12:a9671b78d24e 944 MSB( USB_VERSION_2_0 ), /* bcdUSB (MSB) */
setcom_001 12:a9671b78d24e 945 0x00, /* bDeviceClass */
setcom_001 12:a9671b78d24e 946 0x00, /* bDeviceSubClass */
setcom_001 12:a9671b78d24e 947 0x00, /* bDeviceprotocol */
setcom_001 12:a9671b78d24e 948 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
setcom_001 12:a9671b78d24e 949 LSB( VENDOR_ID ), /* idVendor (LSB) */
setcom_001 12:a9671b78d24e 950 MSB( VENDOR_ID ), /* idVendor (MSB) */
setcom_001 12:a9671b78d24e 951 LSB( PRODUCT_ID ), /* idProduct (LSB) */
setcom_001 12:a9671b78d24e 952 MSB( PRODUCT_ID ), /* idProduct (MSB) */
setcom_001 12:a9671b78d24e 953 LSB( PRODUCT_RELEASE ), /* bcdDevice (LSB) */
setcom_001 12:a9671b78d24e 954 MSB( PRODUCT_RELEASE ), /* bcdDevice (MSB) */
setcom_001 12:a9671b78d24e 955 STRING_OFFSET_IMANUFACTURER, /* iManufacturer */
setcom_001 12:a9671b78d24e 956 STRING_OFFSET_IPRODUCT, /* iProduct */
setcom_001 12:a9671b78d24e 957 STRING_OFFSET_ISERIAL, /* iSerialNumber */
setcom_001 12:a9671b78d24e 958 0x01 /* bNumConfigurations */
setcom_001 12:a9671b78d24e 959 };
setcom_001 12:a9671b78d24e 960 return deviceDescriptor;
setcom_001 12:a9671b78d24e 961 }
setcom_001 12:a9671b78d24e 962
setcom_001 12:a9671b78d24e 963 uint8_t *USBDevice::stringLangidDesc()
setcom_001 12:a9671b78d24e 964 {
setcom_001 12:a9671b78d24e 965 static uint8_t stringLangidDescriptor[] =
setcom_001 12:a9671b78d24e 966 {
setcom_001 12:a9671b78d24e 967 0x04, /*bLength*/
setcom_001 12:a9671b78d24e 968 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 969 0x09, 0x00, /*bString Lang ID - 0x009 - English*/
setcom_001 12:a9671b78d24e 970 };
setcom_001 12:a9671b78d24e 971 return stringLangidDescriptor;
setcom_001 12:a9671b78d24e 972 }
setcom_001 12:a9671b78d24e 973
setcom_001 12:a9671b78d24e 974 uint8_t *USBDevice::stringImanufacturerDesc()
setcom_001 12:a9671b78d24e 975 {
setcom_001 12:a9671b78d24e 976 static uint8_t stringImanufacturerDescriptor[] =
setcom_001 12:a9671b78d24e 977 {
setcom_001 12:a9671b78d24e 978 0x12, /*bLength*/
setcom_001 12:a9671b78d24e 979 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 980 'm', 0, 'b', 0, 'e', 0, 'd', 0, '.', 0, 'o', 0, 'r', 0, 'g', 0, /*bString iManufacturer - mbed.org*/
setcom_001 12:a9671b78d24e 981 };
setcom_001 12:a9671b78d24e 982 return stringImanufacturerDescriptor;
setcom_001 12:a9671b78d24e 983 }
setcom_001 12:a9671b78d24e 984
setcom_001 12:a9671b78d24e 985 uint8_t *USBDevice::stringIserialDesc()
setcom_001 12:a9671b78d24e 986 {
setcom_001 12:a9671b78d24e 987 static uint8_t stringIserialDescriptor[] =
setcom_001 12:a9671b78d24e 988 {
setcom_001 12:a9671b78d24e 989 0x16, /*bLength*/
setcom_001 12:a9671b78d24e 990 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 991 '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0, '9', 0, /*bString iSerial - 0123456789*/
setcom_001 12:a9671b78d24e 992 };
setcom_001 12:a9671b78d24e 993 return stringIserialDescriptor;
setcom_001 12:a9671b78d24e 994 }
setcom_001 12:a9671b78d24e 995
setcom_001 12:a9671b78d24e 996 uint8_t *USBDevice::stringIConfigurationDesc()
setcom_001 12:a9671b78d24e 997 {
setcom_001 12:a9671b78d24e 998 static uint8_t stringIconfigurationDescriptor[] =
setcom_001 12:a9671b78d24e 999 {
setcom_001 12:a9671b78d24e 1000 0x06, /*bLength*/
setcom_001 12:a9671b78d24e 1001 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 1002 '0', 0, '1', 0, /*bString iConfiguration - 01*/
setcom_001 12:a9671b78d24e 1003 };
setcom_001 12:a9671b78d24e 1004 return stringIconfigurationDescriptor;
setcom_001 12:a9671b78d24e 1005 }
setcom_001 12:a9671b78d24e 1006
setcom_001 12:a9671b78d24e 1007 uint8_t *USBDevice::stringIinterfaceDesc()
setcom_001 12:a9671b78d24e 1008 {
setcom_001 12:a9671b78d24e 1009 static uint8_t stringIinterfaceDescriptor[] =
setcom_001 12:a9671b78d24e 1010 {
setcom_001 12:a9671b78d24e 1011 0x08, /*bLength*/
setcom_001 12:a9671b78d24e 1012 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 1013 'U', 0, 'S', 0, 'B', 0, /*bString iInterface - USB*/
setcom_001 12:a9671b78d24e 1014 };
setcom_001 12:a9671b78d24e 1015 return stringIinterfaceDescriptor;
setcom_001 12:a9671b78d24e 1016 }
setcom_001 12:a9671b78d24e 1017
setcom_001 12:a9671b78d24e 1018 uint8_t *USBDevice::stringIproductDesc()
setcom_001 12:a9671b78d24e 1019 {
setcom_001 12:a9671b78d24e 1020 static uint8_t stringIproductDescriptor[] =
setcom_001 12:a9671b78d24e 1021 {
setcom_001 12:a9671b78d24e 1022 0x16, /*bLength*/
setcom_001 12:a9671b78d24e 1023 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
setcom_001 12:a9671b78d24e 1024 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0 /*bString iProduct - USB DEVICE*/
setcom_001 12:a9671b78d24e 1025 };
setcom_001 12:a9671b78d24e 1026 return stringIproductDescriptor;
setcom_001 12:a9671b78d24e 1027 }
setcom_001 12:a9671b78d24e 1028