USB HID Joystick Example (modified USBMouse)

Dependencies:   mbed

Committer:
bricklife
Date:
Wed Jan 19 11:27:13 2011 +0000
Revision:
1:ec6deffecbd3
Parent:
0:d450e82033a1

        

Who changed what in which revision?

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