A optical beam breaker detector that appears to aPC as a USB keyboard, typing characters when the beam is broken

Dependencies:   mbed

Committer:
chris
Date:
Thu May 12 16:46:53 2011 +0000
Revision:
1:45de28d7be8e
Parent:
0:9d0f47bc66da

        

Who changed what in which revision?

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