Joystick enabled version of USBHID -library. Has full Playstation 3 functionality including button pressures and a working home-button implementation, while maintaining full PC/MAC/linux -compatibility. basic operation of the lib: #include "mbed.h" #include "usbhid.h" USBJoystick joystick; int main() { while(1) { char dpad = 0xf; /*only the rightmost 4 bits matter*/ short button = 0xff; /*only the rightmost 13 bits matter*/ /*buttons are square, cross, circle, triangle, l1, r1, l2, r2, l3, r3, home.*/ char stick1x = 0; char stick1y = 0; char stick2x = 0; char stick2y = 0; joystick.joystick(dpad, buttons, stick1x, stick1y, stick2x, stick2y); wait_ms(5); } }

Committer:
innocopter
Date:
Fri May 11 13:35:59 2012 +0000
Revision:
0:237d5ef643e9

        

Who changed what in which revision?

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