USBMouse Example

Dependencies:   mbed

Committer:
simon
Date:
Wed Apr 07 13:42:47 2010 +0000
Revision:
1:eb68149218fd

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 1:eb68149218fd 1 /* usbdevice.cpp */
simon 1:eb68149218fd 2 /* Generic USB device */
simon 1:eb68149218fd 3 /* Copyright (c) Phil Wright 2008 */
simon 1:eb68149218fd 4
simon 1:eb68149218fd 5 #include "mbed.h"
simon 1:eb68149218fd 6 #include "usbdevice.h"
simon 1:eb68149218fd 7
simon 1:eb68149218fd 8 /* Standard requests */
simon 1:eb68149218fd 9 #define GET_STATUS (0)
simon 1:eb68149218fd 10 #define CLEAR_FEATURE (1)
simon 1:eb68149218fd 11 #define SET_FEATURE (3)
simon 1:eb68149218fd 12 #define SET_ADDRESS (5)
simon 1:eb68149218fd 13 #define GET_DESCRIPTOR (6)
simon 1:eb68149218fd 14 #define SET_DESCRIPTOR (7)
simon 1:eb68149218fd 15 #define GET_CONFIGURATION (8)
simon 1:eb68149218fd 16 #define SET_CONFIGURATION (9)
simon 1:eb68149218fd 17 #define GET_INTERFACE (10)
simon 1:eb68149218fd 18 #define SET_INTERFACE (11)
simon 1:eb68149218fd 19
simon 1:eb68149218fd 20 /* Device status */
simon 1:eb68149218fd 21 #define DEVICE_STATUS_SELF_POWERED (1<<0)
simon 1:eb68149218fd 22 #define DEVICE_STATUS_REMOTE_WAKEUP (1<<1)
simon 1:eb68149218fd 23
simon 1:eb68149218fd 24 /* Endpoint status */
simon 1:eb68149218fd 25 #define ENDPOINT_STATUS_HALT (1<<0)
simon 1:eb68149218fd 26
simon 1:eb68149218fd 27 /* Standard feature selectors */
simon 1:eb68149218fd 28 #define DEVICE_REMOTE_WAKEUP (1)
simon 1:eb68149218fd 29 #define ENDPOINT_HALT (0)
simon 1:eb68149218fd 30
simon 1:eb68149218fd 31 /* Macro to convert wIndex endpoint number to physical endpoint number */
simon 1:eb68149218fd 32 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + ((endpoint & 0x80) ? 1 : 0))
simon 1:eb68149218fd 33
simon 1:eb68149218fd 34 CONTROL_TRANSFER transfer;
simon 1:eb68149218fd 35 USB_DEVICE device;
simon 1:eb68149218fd 36
simon 1:eb68149218fd 37 usbdevice::usbdevice()
simon 1:eb68149218fd 38 {
simon 1:eb68149218fd 39 /* Set initial device state */
simon 1:eb68149218fd 40 device.state = POWERED;
simon 1:eb68149218fd 41 device.configuration = 0;
simon 1:eb68149218fd 42 device.suspended = false;
simon 1:eb68149218fd 43
simon 1:eb68149218fd 44 /* Set the maximum packet size for the control endpoints */
simon 1:eb68149218fd 45 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0);
simon 1:eb68149218fd 46 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0);
simon 1:eb68149218fd 47
simon 1:eb68149218fd 48 /* Enable endpoint events for EP0 */
simon 1:eb68149218fd 49 enableEndpointEvent(EP0IN);
simon 1:eb68149218fd 50 enableEndpointEvent(EP0OUT);
simon 1:eb68149218fd 51 }
simon 1:eb68149218fd 52
simon 1:eb68149218fd 53 void usbdevice::endpointEventEP0Setup(void)
simon 1:eb68149218fd 54 {
simon 1:eb68149218fd 55 /* Endpoint 0 setup event */
simon 1:eb68149218fd 56 if (!controlSetup())
simon 1:eb68149218fd 57 {
simon 1:eb68149218fd 58 /* Protocol stall; this will stall both endpoints */
simon 1:eb68149218fd 59 stallEndpoint(EP0OUT);
simon 1:eb68149218fd 60 }
simon 1:eb68149218fd 61 }
simon 1:eb68149218fd 62
simon 1:eb68149218fd 63 void usbdevice::endpointEventEP0Out(void)
simon 1:eb68149218fd 64 {
simon 1:eb68149218fd 65 /* Endpoint 0 OUT data event */
simon 1:eb68149218fd 66 if (!controlOut())
simon 1:eb68149218fd 67 {
simon 1:eb68149218fd 68 /* Protocol stall; this will stall both endpoints */
simon 1:eb68149218fd 69 stallEndpoint(EP0OUT);
simon 1:eb68149218fd 70 }
simon 1:eb68149218fd 71 }
simon 1:eb68149218fd 72
simon 1:eb68149218fd 73 void usbdevice::endpointEventEP0In(void)
simon 1:eb68149218fd 74 {
simon 1:eb68149218fd 75 /* Endpoint 0 IN data event */
simon 1:eb68149218fd 76 if (!controlIn())
simon 1:eb68149218fd 77 {
simon 1:eb68149218fd 78 /* Protocol stall; this will stall both endpoints */
simon 1:eb68149218fd 79 stallEndpoint(EP0OUT);
simon 1:eb68149218fd 80 }
simon 1:eb68149218fd 81 }
simon 1:eb68149218fd 82
simon 1:eb68149218fd 83 void usbdevice::deviceEventReset(void)
simon 1:eb68149218fd 84 {
simon 1:eb68149218fd 85 device.state = DEFAULT;
simon 1:eb68149218fd 86 device.configuration = 0;
simon 1:eb68149218fd 87 device.suspended = false;
simon 1:eb68149218fd 88 }
simon 1:eb68149218fd 89
simon 1:eb68149218fd 90 void usbdevice::decodeSetupPacket(unsigned char *data, SETUP_PACKET *packet)
simon 1:eb68149218fd 91 {
simon 1:eb68149218fd 92 /* Fill in the elements of a SETUP_PACKET structure from raw data */
simon 1:eb68149218fd 93 packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
simon 1:eb68149218fd 94 packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
simon 1:eb68149218fd 95 packet->bmRequestType.Recipient = data[0] & 0x1f;
simon 1:eb68149218fd 96 packet->bRequest = data[1];
simon 1:eb68149218fd 97 packet->wValue = (data[2] | (unsigned short)data[3] << 8);
simon 1:eb68149218fd 98 packet->wIndex = (data[4] | (unsigned short)data[5] << 8);
simon 1:eb68149218fd 99 packet->wLength = (data[6] | (unsigned short)data[7] << 8);
simon 1:eb68149218fd 100 }
simon 1:eb68149218fd 101
simon 1:eb68149218fd 102 bool usbdevice::controlSetup(void)
simon 1:eb68149218fd 103 {
simon 1:eb68149218fd 104 /* Control transfer setup stage */
simon 1:eb68149218fd 105 unsigned char buffer[MAX_PACKET_SIZE_EP0];
simon 1:eb68149218fd 106 unsigned long count;
simon 1:eb68149218fd 107
simon 1:eb68149218fd 108 count = endpointRead(EP0OUT, buffer);
simon 1:eb68149218fd 109
simon 1:eb68149218fd 110 /* Must be 8 bytes of data */
simon 1:eb68149218fd 111 if (count != 8)
simon 1:eb68149218fd 112 {
simon 1:eb68149218fd 113 return false;
simon 1:eb68149218fd 114 }
simon 1:eb68149218fd 115
simon 1:eb68149218fd 116 /* Initialise control transfer state */
simon 1:eb68149218fd 117 decodeSetupPacket(buffer, &transfer.setup);
simon 1:eb68149218fd 118 transfer.ptr = NULL;
simon 1:eb68149218fd 119 transfer.remaining = 0;
simon 1:eb68149218fd 120 transfer.direction = 0;
simon 1:eb68149218fd 121 transfer.zlp = false;
simon 1:eb68149218fd 122
simon 1:eb68149218fd 123 /* Process request */
simon 1:eb68149218fd 124 if (!requestSetup())
simon 1:eb68149218fd 125 {
simon 1:eb68149218fd 126 return false;
simon 1:eb68149218fd 127 }
simon 1:eb68149218fd 128
simon 1:eb68149218fd 129 /* Check transfer size and direction */
simon 1:eb68149218fd 130 if (transfer.setup.wLength>0)
simon 1:eb68149218fd 131 {
simon 1:eb68149218fd 132 if (transfer.setup.bmRequestType.dataTransferDirection==DEVICE_TO_HOST)
simon 1:eb68149218fd 133 {
simon 1:eb68149218fd 134 /* IN data stage is required */
simon 1:eb68149218fd 135 if (transfer.direction != DEVICE_TO_HOST)
simon 1:eb68149218fd 136 {
simon 1:eb68149218fd 137 return false;
simon 1:eb68149218fd 138 }
simon 1:eb68149218fd 139
simon 1:eb68149218fd 140 /* Transfer must be less than or equal to the size requested by the host */
simon 1:eb68149218fd 141 if (transfer.remaining > transfer.setup.wLength)
simon 1:eb68149218fd 142 {
simon 1:eb68149218fd 143 transfer.remaining = transfer.setup.wLength;
simon 1:eb68149218fd 144 }
simon 1:eb68149218fd 145 }
simon 1:eb68149218fd 146 else
simon 1:eb68149218fd 147 {
simon 1:eb68149218fd 148 /* OUT data stage is required */
simon 1:eb68149218fd 149 if (transfer.direction != HOST_TO_DEVICE)
simon 1:eb68149218fd 150 {
simon 1:eb68149218fd 151 return false;
simon 1:eb68149218fd 152 }
simon 1:eb68149218fd 153
simon 1:eb68149218fd 154 /* Transfer must be equal to the size requested by the host */
simon 1:eb68149218fd 155 if (transfer.remaining != transfer.setup.wLength)
simon 1:eb68149218fd 156 {
simon 1:eb68149218fd 157 return false;
simon 1:eb68149218fd 158 }
simon 1:eb68149218fd 159 }
simon 1:eb68149218fd 160 }
simon 1:eb68149218fd 161 else
simon 1:eb68149218fd 162 {
simon 1:eb68149218fd 163 /* No data stage; transfer size must be zero */
simon 1:eb68149218fd 164 if (transfer.remaining != 0)
simon 1:eb68149218fd 165 {
simon 1:eb68149218fd 166 return false;
simon 1:eb68149218fd 167 }
simon 1:eb68149218fd 168 }
simon 1:eb68149218fd 169
simon 1:eb68149218fd 170 /* Data or status stage if applicable */
simon 1:eb68149218fd 171 if (transfer.setup.wLength>0)
simon 1:eb68149218fd 172 {
simon 1:eb68149218fd 173 if (transfer.setup.bmRequestType.dataTransferDirection==DEVICE_TO_HOST)
simon 1:eb68149218fd 174 {
simon 1:eb68149218fd 175 /* Check if we'll need to send a zero length packet at the end of this transfer */
simon 1:eb68149218fd 176 if (transfer.setup.wLength > transfer.remaining)
simon 1:eb68149218fd 177 {
simon 1:eb68149218fd 178 /* Device wishes to transfer less than host requested */
simon 1:eb68149218fd 179 if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
simon 1:eb68149218fd 180 {
simon 1:eb68149218fd 181 /* Transfer is a multiple of EP0 max packet size */
simon 1:eb68149218fd 182 transfer.zlp = true;
simon 1:eb68149218fd 183 }
simon 1:eb68149218fd 184 }
simon 1:eb68149218fd 185
simon 1:eb68149218fd 186 /* IN stage */
simon 1:eb68149218fd 187 controlIn();
simon 1:eb68149218fd 188 }
simon 1:eb68149218fd 189 }
simon 1:eb68149218fd 190 else
simon 1:eb68149218fd 191 {
simon 1:eb68149218fd 192 /* Status stage */
simon 1:eb68149218fd 193 endpointWrite(EP0IN, NULL, 0);
simon 1:eb68149218fd 194 }
simon 1:eb68149218fd 195
simon 1:eb68149218fd 196 return true;
simon 1:eb68149218fd 197 }
simon 1:eb68149218fd 198
simon 1:eb68149218fd 199 bool usbdevice::controlOut(void)
simon 1:eb68149218fd 200 {
simon 1:eb68149218fd 201 /* Control transfer data OUT stage */
simon 1:eb68149218fd 202 unsigned char buffer[MAX_PACKET_SIZE_EP0];
simon 1:eb68149218fd 203 unsigned long packetSize;
simon 1:eb68149218fd 204
simon 1:eb68149218fd 205 /* Check we should be transferring data OUT */
simon 1:eb68149218fd 206 if (transfer.direction != HOST_TO_DEVICE)
simon 1:eb68149218fd 207 {
simon 1:eb68149218fd 208 return false;
simon 1:eb68149218fd 209 }
simon 1:eb68149218fd 210
simon 1:eb68149218fd 211 /* Read from endpoint */
simon 1:eb68149218fd 212 packetSize = endpointRead(EP0OUT, buffer);
simon 1:eb68149218fd 213
simon 1:eb68149218fd 214 /* Check if transfer size is valid */
simon 1:eb68149218fd 215 if (packetSize > transfer.remaining)
simon 1:eb68149218fd 216 {
simon 1:eb68149218fd 217 /* Too big */
simon 1:eb68149218fd 218 return false;
simon 1:eb68149218fd 219 }
simon 1:eb68149218fd 220
simon 1:eb68149218fd 221 /* Update transfer */
simon 1:eb68149218fd 222 transfer.ptr += packetSize;
simon 1:eb68149218fd 223 transfer.remaining -= packetSize;
simon 1:eb68149218fd 224
simon 1:eb68149218fd 225 /* Check if transfer has completed */
simon 1:eb68149218fd 226 if (transfer.remaining == 0)
simon 1:eb68149218fd 227 {
simon 1:eb68149218fd 228 /* Process request */
simon 1:eb68149218fd 229 if (!requestOut())
simon 1:eb68149218fd 230 {
simon 1:eb68149218fd 231 return false;
simon 1:eb68149218fd 232 }
simon 1:eb68149218fd 233
simon 1:eb68149218fd 234 /* Status stage */
simon 1:eb68149218fd 235 endpointWrite(EP0IN, NULL, 0);
simon 1:eb68149218fd 236 }
simon 1:eb68149218fd 237
simon 1:eb68149218fd 238 return true;
simon 1:eb68149218fd 239 }
simon 1:eb68149218fd 240
simon 1:eb68149218fd 241 bool usbdevice::controlIn(void)
simon 1:eb68149218fd 242 {
simon 1:eb68149218fd 243 /* Control transfer data IN stage */
simon 1:eb68149218fd 244 unsigned packetSize;
simon 1:eb68149218fd 245
simon 1:eb68149218fd 246 /* Check if transfer has completed (status stage transactions also have transfer.remaining == 0) */
simon 1:eb68149218fd 247 if (transfer.remaining == 0)
simon 1:eb68149218fd 248 {
simon 1:eb68149218fd 249 if (transfer.zlp)
simon 1:eb68149218fd 250 {
simon 1:eb68149218fd 251 /* Send zero length packet */
simon 1:eb68149218fd 252 endpointWrite(EP0IN, NULL, 0);
simon 1:eb68149218fd 253 transfer.zlp = false;
simon 1:eb68149218fd 254 }
simon 1:eb68149218fd 255
simon 1:eb68149218fd 256 /* Completed */
simon 1:eb68149218fd 257 return true;
simon 1:eb68149218fd 258 }
simon 1:eb68149218fd 259
simon 1:eb68149218fd 260 /* Check we should be transferring data IN */
simon 1:eb68149218fd 261 if (transfer.direction != DEVICE_TO_HOST)
simon 1:eb68149218fd 262 {
simon 1:eb68149218fd 263 return false;
simon 1:eb68149218fd 264 }
simon 1:eb68149218fd 265
simon 1:eb68149218fd 266 packetSize = transfer.remaining;
simon 1:eb68149218fd 267
simon 1:eb68149218fd 268 if (packetSize > MAX_PACKET_SIZE_EP0)
simon 1:eb68149218fd 269 {
simon 1:eb68149218fd 270 packetSize = MAX_PACKET_SIZE_EP0;
simon 1:eb68149218fd 271 }
simon 1:eb68149218fd 272
simon 1:eb68149218fd 273 /* Write to endpoint */
simon 1:eb68149218fd 274 endpointWrite(EP0IN, transfer.ptr, packetSize);
simon 1:eb68149218fd 275
simon 1:eb68149218fd 276 /* Update transfer */
simon 1:eb68149218fd 277 transfer.ptr += packetSize;
simon 1:eb68149218fd 278 transfer.remaining -= packetSize;
simon 1:eb68149218fd 279
simon 1:eb68149218fd 280 return true;
simon 1:eb68149218fd 281 }
simon 1:eb68149218fd 282
simon 1:eb68149218fd 283 bool usbdevice::requestSetup(void)
simon 1:eb68149218fd 284 {
simon 1:eb68149218fd 285 bool success = false;
simon 1:eb68149218fd 286
simon 1:eb68149218fd 287 /* Process standard requests */
simon 1:eb68149218fd 288 if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
simon 1:eb68149218fd 289 {
simon 1:eb68149218fd 290 switch (transfer.setup.bRequest)
simon 1:eb68149218fd 291 {
simon 1:eb68149218fd 292 case GET_STATUS:
simon 1:eb68149218fd 293 success = requestGetStatus();
simon 1:eb68149218fd 294 break;
simon 1:eb68149218fd 295 case CLEAR_FEATURE:
simon 1:eb68149218fd 296 success = requestClearFeature();
simon 1:eb68149218fd 297 break;
simon 1:eb68149218fd 298 case SET_FEATURE:
simon 1:eb68149218fd 299 success = requestSetFeature();
simon 1:eb68149218fd 300 break;
simon 1:eb68149218fd 301 case SET_ADDRESS:
simon 1:eb68149218fd 302 success = requestSetAddress();
simon 1:eb68149218fd 303 break;
simon 1:eb68149218fd 304 case GET_DESCRIPTOR:
simon 1:eb68149218fd 305 success = requestGetDescriptor();
simon 1:eb68149218fd 306 break;
simon 1:eb68149218fd 307 case SET_DESCRIPTOR:
simon 1:eb68149218fd 308 /* TODO: Support is optional, not implemented here */
simon 1:eb68149218fd 309 success = false;
simon 1:eb68149218fd 310 break;
simon 1:eb68149218fd 311 case GET_CONFIGURATION:
simon 1:eb68149218fd 312 success = requestGetConfiguration();
simon 1:eb68149218fd 313 break;
simon 1:eb68149218fd 314 case SET_CONFIGURATION:
simon 1:eb68149218fd 315 success = requestSetConfiguration();
simon 1:eb68149218fd 316 break;
simon 1:eb68149218fd 317 case GET_INTERFACE:
simon 1:eb68149218fd 318 success = requestGetInterface();
simon 1:eb68149218fd 319 break;
simon 1:eb68149218fd 320 case SET_INTERFACE:
simon 1:eb68149218fd 321 success = requestSetInterface();
simon 1:eb68149218fd 322 break;
simon 1:eb68149218fd 323 default:
simon 1:eb68149218fd 324 break;
simon 1:eb68149218fd 325 }
simon 1:eb68149218fd 326 }
simon 1:eb68149218fd 327
simon 1:eb68149218fd 328 return success;
simon 1:eb68149218fd 329 }
simon 1:eb68149218fd 330
simon 1:eb68149218fd 331 bool usbdevice::requestOut(void)
simon 1:eb68149218fd 332 {
simon 1:eb68149218fd 333 return true;
simon 1:eb68149218fd 334 }
simon 1:eb68149218fd 335
simon 1:eb68149218fd 336 bool usbdevice::requestSetAddress(void)
simon 1:eb68149218fd 337 {
simon 1:eb68149218fd 338 /* Set the device address */
simon 1:eb68149218fd 339 setAddress(transfer.setup.wValue);
simon 1:eb68149218fd 340
simon 1:eb68149218fd 341 if (transfer.setup.wValue == 0)
simon 1:eb68149218fd 342 {
simon 1:eb68149218fd 343 device.state = DEFAULT;
simon 1:eb68149218fd 344 }
simon 1:eb68149218fd 345 else
simon 1:eb68149218fd 346 {
simon 1:eb68149218fd 347 device.state = ADDRESS;
simon 1:eb68149218fd 348 }
simon 1:eb68149218fd 349
simon 1:eb68149218fd 350 return true;
simon 1:eb68149218fd 351 }
simon 1:eb68149218fd 352
simon 1:eb68149218fd 353 bool usbdevice::requestSetConfiguration(void)
simon 1:eb68149218fd 354 {
simon 1:eb68149218fd 355 /* Set the device configuration */
simon 1:eb68149218fd 356 if (transfer.setup.wValue == 0)
simon 1:eb68149218fd 357 {
simon 1:eb68149218fd 358 /* Not configured */
simon 1:eb68149218fd 359 unconfigureDevice();
simon 1:eb68149218fd 360 device.state = ADDRESS;
simon 1:eb68149218fd 361 }
simon 1:eb68149218fd 362 else
simon 1:eb68149218fd 363 {
simon 1:eb68149218fd 364 configureDevice();
simon 1:eb68149218fd 365 device.state = CONFIGURED;
simon 1:eb68149218fd 366 }
simon 1:eb68149218fd 367
simon 1:eb68149218fd 368 /* TODO: We do not currently support multiple configurations, just keep a record of the configuration value */
simon 1:eb68149218fd 369 device.configuration = transfer.setup.wValue;
simon 1:eb68149218fd 370
simon 1:eb68149218fd 371 return true;
simon 1:eb68149218fd 372 }
simon 1:eb68149218fd 373
simon 1:eb68149218fd 374 bool usbdevice::requestGetConfiguration(void)
simon 1:eb68149218fd 375 {
simon 1:eb68149218fd 376 /* Send the device configuration */
simon 1:eb68149218fd 377 transfer.ptr = &device.configuration;
simon 1:eb68149218fd 378 transfer.remaining = sizeof(device.configuration);
simon 1:eb68149218fd 379 transfer.direction = DEVICE_TO_HOST;
simon 1:eb68149218fd 380 return true;
simon 1:eb68149218fd 381 }
simon 1:eb68149218fd 382
simon 1:eb68149218fd 383 bool usbdevice::requestGetInterface(void)
simon 1:eb68149218fd 384 {
simon 1:eb68149218fd 385 static unsigned char alternateSetting;
simon 1:eb68149218fd 386
simon 1:eb68149218fd 387 /* Return the selected alternate setting for an interface */
simon 1:eb68149218fd 388
simon 1:eb68149218fd 389 if (device.state != CONFIGURED)
simon 1:eb68149218fd 390 {
simon 1:eb68149218fd 391 return false;
simon 1:eb68149218fd 392 }
simon 1:eb68149218fd 393
simon 1:eb68149218fd 394 /* TODO: We currently do not support alternate settings so always return zero */
simon 1:eb68149218fd 395 /* TODO: Should check that the interface number is valid */
simon 1:eb68149218fd 396 alternateSetting = 0;
simon 1:eb68149218fd 397
simon 1:eb68149218fd 398 /* Send the alternate setting */
simon 1:eb68149218fd 399 transfer.ptr = &alternateSetting;
simon 1:eb68149218fd 400 transfer.remaining = sizeof(alternateSetting);
simon 1:eb68149218fd 401 transfer.direction = DEVICE_TO_HOST;
simon 1:eb68149218fd 402 return true;
simon 1:eb68149218fd 403 }
simon 1:eb68149218fd 404
simon 1:eb68149218fd 405 bool usbdevice::requestSetInterface(void)
simon 1:eb68149218fd 406 {
simon 1:eb68149218fd 407 /* TODO: We currently do not support alternate settings, return false */
simon 1:eb68149218fd 408 return false;
simon 1:eb68149218fd 409 }
simon 1:eb68149218fd 410
simon 1:eb68149218fd 411 bool usbdevice::requestSetFeature()
simon 1:eb68149218fd 412 {
simon 1:eb68149218fd 413 bool success = false;
simon 1:eb68149218fd 414
simon 1:eb68149218fd 415 if (device.state != CONFIGURED)
simon 1:eb68149218fd 416 {
simon 1:eb68149218fd 417 /* Endpoint or interface must be zero */
simon 1:eb68149218fd 418 if (transfer.setup.wIndex != 0)
simon 1:eb68149218fd 419 {
simon 1:eb68149218fd 420 return false;
simon 1:eb68149218fd 421 }
simon 1:eb68149218fd 422 }
simon 1:eb68149218fd 423
simon 1:eb68149218fd 424 switch (transfer.setup.bmRequestType.Recipient)
simon 1:eb68149218fd 425 {
simon 1:eb68149218fd 426 case DEVICE_RECIPIENT:
simon 1:eb68149218fd 427 /* TODO: Remote wakeup feature not supported */
simon 1:eb68149218fd 428 break;
simon 1:eb68149218fd 429 case ENDPOINT_RECIPIENT:
simon 1:eb68149218fd 430 if (transfer.setup.wValue == ENDPOINT_HALT)
simon 1:eb68149218fd 431 {
simon 1:eb68149218fd 432 /* TODO: We should check that the endpoint number is valid */
simon 1:eb68149218fd 433 stallEndpoint(WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
simon 1:eb68149218fd 434 success = true;
simon 1:eb68149218fd 435 }
simon 1:eb68149218fd 436 break;
simon 1:eb68149218fd 437 default:
simon 1:eb68149218fd 438 break;
simon 1:eb68149218fd 439 }
simon 1:eb68149218fd 440
simon 1:eb68149218fd 441 return success;
simon 1:eb68149218fd 442 }
simon 1:eb68149218fd 443
simon 1:eb68149218fd 444 bool usbdevice::requestClearFeature()
simon 1:eb68149218fd 445 {
simon 1:eb68149218fd 446 bool success = false;
simon 1:eb68149218fd 447
simon 1:eb68149218fd 448 if (device.state != CONFIGURED)
simon 1:eb68149218fd 449 {
simon 1:eb68149218fd 450 /* Endpoint or interface must be zero */
simon 1:eb68149218fd 451 if (transfer.setup.wIndex != 0)
simon 1:eb68149218fd 452 {
simon 1:eb68149218fd 453 return false;
simon 1:eb68149218fd 454 }
simon 1:eb68149218fd 455 }
simon 1:eb68149218fd 456
simon 1:eb68149218fd 457 switch (transfer.setup.bmRequestType.Recipient)
simon 1:eb68149218fd 458 {
simon 1:eb68149218fd 459 case DEVICE_RECIPIENT:
simon 1:eb68149218fd 460 /* TODO: Remote wakeup feature not supported */
simon 1:eb68149218fd 461 break;
simon 1:eb68149218fd 462 case ENDPOINT_RECIPIENT:
simon 1:eb68149218fd 463 /* TODO: We should check that the endpoint number is valid */
simon 1:eb68149218fd 464 if (transfer.setup.wValue == ENDPOINT_HALT)
simon 1:eb68149218fd 465 {
simon 1:eb68149218fd 466 unstallEndpoint(WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
simon 1:eb68149218fd 467 success = true;
simon 1:eb68149218fd 468 }
simon 1:eb68149218fd 469 break;
simon 1:eb68149218fd 470 default:
simon 1:eb68149218fd 471 break;
simon 1:eb68149218fd 472 }
simon 1:eb68149218fd 473
simon 1:eb68149218fd 474 return success;
simon 1:eb68149218fd 475 }
simon 1:eb68149218fd 476
simon 1:eb68149218fd 477 bool usbdevice::requestGetStatus(void)
simon 1:eb68149218fd 478 {
simon 1:eb68149218fd 479 static unsigned short status;
simon 1:eb68149218fd 480 bool success = false;
simon 1:eb68149218fd 481
simon 1:eb68149218fd 482 if (device.state != CONFIGURED)
simon 1:eb68149218fd 483 {
simon 1:eb68149218fd 484 /* Endpoint or interface must be zero */
simon 1:eb68149218fd 485 if (transfer.setup.wIndex != 0)
simon 1:eb68149218fd 486 {
simon 1:eb68149218fd 487 return false;
simon 1:eb68149218fd 488 }
simon 1:eb68149218fd 489 }
simon 1:eb68149218fd 490
simon 1:eb68149218fd 491 switch (transfer.setup.bmRequestType.Recipient)
simon 1:eb68149218fd 492 {
simon 1:eb68149218fd 493 case DEVICE_RECIPIENT:
simon 1:eb68149218fd 494 /* TODO: Currently only supports self powered devices */
simon 1:eb68149218fd 495 status = DEVICE_STATUS_SELF_POWERED;
simon 1:eb68149218fd 496 success = true;
simon 1:eb68149218fd 497 break;
simon 1:eb68149218fd 498 case INTERFACE_RECIPIENT:
simon 1:eb68149218fd 499 status = 0;
simon 1:eb68149218fd 500 success = true;
simon 1:eb68149218fd 501 break;
simon 1:eb68149218fd 502 case ENDPOINT_RECIPIENT:
simon 1:eb68149218fd 503 /* TODO: We should check that the endpoint number is valid */
simon 1:eb68149218fd 504 if (getEndpointStallState(WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
simon 1:eb68149218fd 505 {
simon 1:eb68149218fd 506 status = ENDPOINT_STATUS_HALT;
simon 1:eb68149218fd 507 }
simon 1:eb68149218fd 508 else
simon 1:eb68149218fd 509 {
simon 1:eb68149218fd 510 status = 0;
simon 1:eb68149218fd 511 }
simon 1:eb68149218fd 512 success = true;
simon 1:eb68149218fd 513 break;
simon 1:eb68149218fd 514 default:
simon 1:eb68149218fd 515 break;
simon 1:eb68149218fd 516 }
simon 1:eb68149218fd 517
simon 1:eb68149218fd 518 if (success)
simon 1:eb68149218fd 519 {
simon 1:eb68149218fd 520 /* Send the status */
simon 1:eb68149218fd 521 transfer.ptr = (unsigned char *)&status; /* Assumes little endian */
simon 1:eb68149218fd 522 transfer.remaining = sizeof(status);
simon 1:eb68149218fd 523 transfer.direction = DEVICE_TO_HOST;
simon 1:eb68149218fd 524 }
simon 1:eb68149218fd 525
simon 1:eb68149218fd 526 return success;
simon 1:eb68149218fd 527 }
simon 1:eb68149218fd 528
simon 1:eb68149218fd 529 bool usbdevice::requestGetDescriptor(void)
simon 1:eb68149218fd 530 {
simon 1:eb68149218fd 531 return false;
simon 1:eb68149218fd 532 }