N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Wed Dec 10 14:22:30 2014 +0000
Revision:
5:eb93a4f91396
Parent:
0:547c5459faa6
Initial Release

Who changed what in which revision?

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