Jafar Qutteineh / Mbed 2 deprecated RC_Simulator

Dependencies:   mbed

Committer:
j3sq
Date:
Sat Jul 02 17:27:05 2011 +0000
Revision:
0:3dbb22992c94
Revision 0.0 (This is just a demonstration)

Who changed what in which revision?

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