Based on USBKeyboardMouse example. I added USB String Descriptor so mbed reports itself to host not only with VID & PID but also with name of manufacturer, product name, serial number, configuration number and interface name. These can be changed to matching Yours in USBhid.cpp file on lines 88 - 122.

Dependencies:   mbed

Committer:
llumpu
Date:
Thu Sep 08 15:01:33 2011 +0000
Revision:
0:f97b1f255167
Added USB String Descriptor

Who changed what in which revision?

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