Acts a USB HID keyboard, and socket server. Forwards characters from TCP ip socket to keyboard

Dependencies:   mbed EthernetNetIf

Committer:
henryeherman
Date:
Fri Dec 14 01:15:44 2018 +0000
Revision:
1:d866a9d23e49
Parent:
0:beb124b81ef5
init

Who changed what in which revision?

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