kekw

Dependencies:   mbed C12832_lcd MMA7660

Committer:
gri
Date:
Sun Jan 19 14:57:41 2020 +0000
Revision:
2:b07d155d316c
KEKw

Who changed what in which revision?

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