EA BaseBoard, playing wav, PC see\'s SD-card through USB port.

Dependencies:   mbed

Committer:
Lerche
Date:
Tue Nov 22 05:45:58 2011 +0000
Revision:
0:fef366d2ed20
Thanks to those who provided EA_WavPlayer and USB_MSC

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Lerche 0:fef366d2ed20 1 /* USBDevice.c */
Lerche 0:fef366d2ed20 2 /* Generic USB device */
Lerche 0:fef366d2ed20 3 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
Lerche 0:fef366d2ed20 4
Lerche 0:fef366d2ed20 5 /* Reference: */
Lerche 0:fef366d2ed20 6 /* Universal Serial Bus Specification Revision 2.0, Chapter 9 "USB Device Framework" */
Lerche 0:fef366d2ed20 7
Lerche 0:fef366d2ed20 8 //#define DEBUG
Lerche 0:fef366d2ed20 9 #include "dbg.h"
Lerche 0:fef366d2ed20 10 #include "stdint.h"
Lerche 0:fef366d2ed20 11
Lerche 0:fef366d2ed20 12 #include "USBEndpoints.h"
Lerche 0:fef366d2ed20 13 #include "USBDevice.h"
Lerche 0:fef366d2ed20 14 #include "USBDescriptor.h"
Lerche 0:fef366d2ed20 15 #include "USBHID_Types.h"
Lerche 0:fef366d2ed20 16
Lerche 0:fef366d2ed20 17
Lerche 0:fef366d2ed20 18 /* Device status */
Lerche 0:fef366d2ed20 19 #define DEVICE_STATUS_SELF_POWERED (1U<<0)
Lerche 0:fef366d2ed20 20 #define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
Lerche 0:fef366d2ed20 21
Lerche 0:fef366d2ed20 22 /* Endpoint status */
Lerche 0:fef366d2ed20 23 #define ENDPOINT_STATUS_HALT (1U<<0)
Lerche 0:fef366d2ed20 24
Lerche 0:fef366d2ed20 25 /* Standard feature selectors */
Lerche 0:fef366d2ed20 26 #define DEVICE_REMOTE_WAKEUP (1)
Lerche 0:fef366d2ed20 27 #define ENDPOINT_HALT (0)
Lerche 0:fef366d2ed20 28
Lerche 0:fef366d2ed20 29 /* Macro to convert wIndex endpoint number to physical endpoint number */
Lerche 0:fef366d2ed20 30 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
Lerche 0:fef366d2ed20 31 ((endpoint & 0x80) ? 1 : 0))
Lerche 0:fef366d2ed20 32
Lerche 0:fef366d2ed20 33
Lerche 0:fef366d2ed20 34 bool USBDevice::requestGetDescriptor(void)
Lerche 0:fef366d2ed20 35 {
Lerche 0:fef366d2ed20 36 bool success = false;
Lerche 0:fef366d2ed20 37
Lerche 0:fef366d2ed20 38 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
Lerche 0:fef366d2ed20 39 {
Lerche 0:fef366d2ed20 40 case DEVICE_DESCRIPTOR:
Lerche 0:fef366d2ed20 41 case QUALIFIER_DESCRIPTOR:
Lerche 0:fef366d2ed20 42 if (deviceDesc() != NULL)
Lerche 0:fef366d2ed20 43 {
Lerche 0:fef366d2ed20 44 if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
Lerche 0:fef366d2ed20 45 && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
Lerche 0:fef366d2ed20 46 {
Lerche 0:fef366d2ed20 47 transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
Lerche 0:fef366d2ed20 48 transfer.ptr = deviceDesc();
Lerche 0:fef366d2ed20 49 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 50 success = true;
Lerche 0:fef366d2ed20 51 }
Lerche 0:fef366d2ed20 52 }
Lerche 0:fef366d2ed20 53 break;
Lerche 0:fef366d2ed20 54 case CONFIGURATION_DESCRIPTOR:
Lerche 0:fef366d2ed20 55 if (configurationDesc() != NULL)
Lerche 0:fef366d2ed20 56 {
Lerche 0:fef366d2ed20 57 if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
Lerche 0:fef366d2ed20 58 && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
Lerche 0:fef366d2ed20 59 {
Lerche 0:fef366d2ed20 60 /* Get wTotalLength */
Lerche 0:fef366d2ed20 61 transfer.remaining = configurationDesc()[2] \
Lerche 0:fef366d2ed20 62 | (configurationDesc()[3] << 8);
Lerche 0:fef366d2ed20 63
Lerche 0:fef366d2ed20 64 transfer.ptr = configurationDesc();
Lerche 0:fef366d2ed20 65 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 66 success = true;
Lerche 0:fef366d2ed20 67 }
Lerche 0:fef366d2ed20 68 }
Lerche 0:fef366d2ed20 69 break;
Lerche 0:fef366d2ed20 70 case STRING_DESCRIPTOR:
Lerche 0:fef366d2ed20 71 switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
Lerche 0:fef366d2ed20 72 {
Lerche 0:fef366d2ed20 73 case STRING_OFFSET_LANGID:
Lerche 0:fef366d2ed20 74 transfer.remaining = stringLangidDesc()[0];
Lerche 0:fef366d2ed20 75 transfer.ptr = stringLangidDesc();
Lerche 0:fef366d2ed20 76 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 77 success = true;
Lerche 0:fef366d2ed20 78 break;
Lerche 0:fef366d2ed20 79 case STRING_OFFSET_IMANUFACTURER:
Lerche 0:fef366d2ed20 80 transfer.remaining = stringImanufacturerDesc()[0];
Lerche 0:fef366d2ed20 81 transfer.ptr = stringImanufacturerDesc();
Lerche 0:fef366d2ed20 82 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 83 success = true;
Lerche 0:fef366d2ed20 84 break;
Lerche 0:fef366d2ed20 85 case STRING_OFFSET_IPRODUCT:
Lerche 0:fef366d2ed20 86 transfer.remaining = stringIproductDesc()[0];
Lerche 0:fef366d2ed20 87 transfer.ptr = stringIproductDesc();
Lerche 0:fef366d2ed20 88 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 89 success = true;
Lerche 0:fef366d2ed20 90 break;
Lerche 0:fef366d2ed20 91 case STRING_OFFSET_ISERIAL:
Lerche 0:fef366d2ed20 92 transfer.remaining = stringIserialDesc()[0];
Lerche 0:fef366d2ed20 93 transfer.ptr = stringIserialDesc();
Lerche 0:fef366d2ed20 94 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 95 success = true;
Lerche 0:fef366d2ed20 96 break;
Lerche 0:fef366d2ed20 97 case STRING_OFFSET_ICONFIGURATION:
Lerche 0:fef366d2ed20 98 transfer.remaining = stringIConfigurationDesc()[0];
Lerche 0:fef366d2ed20 99 transfer.ptr = stringIConfigurationDesc();
Lerche 0:fef366d2ed20 100 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 101 success = true;
Lerche 0:fef366d2ed20 102 break;
Lerche 0:fef366d2ed20 103 case STRING_OFFSET_IINTERFACE:
Lerche 0:fef366d2ed20 104 transfer.remaining = stringIinterfaceDesc()[0];
Lerche 0:fef366d2ed20 105 transfer.ptr = stringIinterfaceDesc();
Lerche 0:fef366d2ed20 106 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 107 success = true;
Lerche 0:fef366d2ed20 108 break;
Lerche 0:fef366d2ed20 109 }
Lerche 0:fef366d2ed20 110 break;
Lerche 0:fef366d2ed20 111 case INTERFACE_DESCRIPTOR:
Lerche 0:fef366d2ed20 112 case ENDPOINT_DESCRIPTOR:
Lerche 0:fef366d2ed20 113 /* TODO: Support is optional, not implemented here */
Lerche 0:fef366d2ed20 114 break;
Lerche 0:fef366d2ed20 115 default:
Lerche 0:fef366d2ed20 116 break;
Lerche 0:fef366d2ed20 117 }
Lerche 0:fef366d2ed20 118
Lerche 0:fef366d2ed20 119 return success;
Lerche 0:fef366d2ed20 120 }
Lerche 0:fef366d2ed20 121
Lerche 0:fef366d2ed20 122 void USBDevice::decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet)
Lerche 0:fef366d2ed20 123 {
Lerche 0:fef366d2ed20 124 /* Fill in the elements of a SETUP_PACKET structure from raw data */
Lerche 0:fef366d2ed20 125 packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
Lerche 0:fef366d2ed20 126 packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
Lerche 0:fef366d2ed20 127 packet->bmRequestType.Recipient = data[0] & 0x1f;
Lerche 0:fef366d2ed20 128 packet->bRequest = data[1];
Lerche 0:fef366d2ed20 129 packet->wValue = (data[2] | (uint16_t)data[3] << 8);
Lerche 0:fef366d2ed20 130 packet->wIndex = (data[4] | (uint16_t)data[5] << 8);
Lerche 0:fef366d2ed20 131 packet->wLength = (data[6] | (uint16_t)data[7] << 8);
Lerche 0:fef366d2ed20 132 }
Lerche 0:fef366d2ed20 133
Lerche 0:fef366d2ed20 134
Lerche 0:fef366d2ed20 135 bool USBDevice::controlOut(void)
Lerche 0:fef366d2ed20 136 {
Lerche 0:fef366d2ed20 137 /* Control transfer data OUT stage */
Lerche 0:fef366d2ed20 138 uint8_t buffer[MAX_PACKET_SIZE_EP0];
Lerche 0:fef366d2ed20 139 uint32_t packetSize;
Lerche 0:fef366d2ed20 140
Lerche 0:fef366d2ed20 141 /* Check we should be transferring data OUT */
Lerche 0:fef366d2ed20 142 if (transfer.direction != HOST_TO_DEVICE)
Lerche 0:fef366d2ed20 143 {
Lerche 0:fef366d2ed20 144 return false;
Lerche 0:fef366d2ed20 145 }
Lerche 0:fef366d2ed20 146
Lerche 0:fef366d2ed20 147 /* Read from endpoint */
Lerche 0:fef366d2ed20 148 packetSize = EP0getReadResult(buffer);
Lerche 0:fef366d2ed20 149
Lerche 0:fef366d2ed20 150 /* Check if transfer size is valid */
Lerche 0:fef366d2ed20 151 if (packetSize > transfer.remaining)
Lerche 0:fef366d2ed20 152 {
Lerche 0:fef366d2ed20 153 /* Too big */
Lerche 0:fef366d2ed20 154 return false;
Lerche 0:fef366d2ed20 155 }
Lerche 0:fef366d2ed20 156
Lerche 0:fef366d2ed20 157 /* Update transfer */
Lerche 0:fef366d2ed20 158 transfer.ptr += packetSize;
Lerche 0:fef366d2ed20 159 transfer.remaining -= packetSize;
Lerche 0:fef366d2ed20 160
Lerche 0:fef366d2ed20 161 /* Check if transfer has completed */
Lerche 0:fef366d2ed20 162 if (transfer.remaining == 0)
Lerche 0:fef366d2ed20 163 {
Lerche 0:fef366d2ed20 164 /* Transfer completed */
Lerche 0:fef366d2ed20 165 if (transfer.notify)
Lerche 0:fef366d2ed20 166 {
Lerche 0:fef366d2ed20 167 /* Notify class layer. */
Lerche 0:fef366d2ed20 168 USBCallback_requestCompleted();
Lerche 0:fef366d2ed20 169 transfer.notify = false;
Lerche 0:fef366d2ed20 170 }
Lerche 0:fef366d2ed20 171 /* Status stage */
Lerche 0:fef366d2ed20 172 EP0write(NULL, 0);
Lerche 0:fef366d2ed20 173 }
Lerche 0:fef366d2ed20 174 else
Lerche 0:fef366d2ed20 175 {
Lerche 0:fef366d2ed20 176 EP0read();
Lerche 0:fef366d2ed20 177 }
Lerche 0:fef366d2ed20 178
Lerche 0:fef366d2ed20 179 return true;
Lerche 0:fef366d2ed20 180 }
Lerche 0:fef366d2ed20 181
Lerche 0:fef366d2ed20 182 bool USBDevice::controlIn(void)
Lerche 0:fef366d2ed20 183 {
Lerche 0:fef366d2ed20 184 /* Control transfer data IN stage */
Lerche 0:fef366d2ed20 185 uint32_t packetSize;
Lerche 0:fef366d2ed20 186
Lerche 0:fef366d2ed20 187 /* Check if transfer has completed (status stage transactions */
Lerche 0:fef366d2ed20 188 /* also have transfer.remaining == 0) */
Lerche 0:fef366d2ed20 189 if (transfer.remaining == 0)
Lerche 0:fef366d2ed20 190 {
Lerche 0:fef366d2ed20 191 if (transfer.zlp)
Lerche 0:fef366d2ed20 192 {
Lerche 0:fef366d2ed20 193 /* Send zero length packet */
Lerche 0:fef366d2ed20 194 EP0write(NULL, 0);
Lerche 0:fef366d2ed20 195 transfer.zlp = false;
Lerche 0:fef366d2ed20 196 }
Lerche 0:fef366d2ed20 197
Lerche 0:fef366d2ed20 198 /* Transfer completed */
Lerche 0:fef366d2ed20 199 if (transfer.notify)
Lerche 0:fef366d2ed20 200 {
Lerche 0:fef366d2ed20 201 /* Notify class layer. */
Lerche 0:fef366d2ed20 202 USBCallback_requestCompleted();
Lerche 0:fef366d2ed20 203 transfer.notify = false;
Lerche 0:fef366d2ed20 204 }
Lerche 0:fef366d2ed20 205
Lerche 0:fef366d2ed20 206 EP0read();
Lerche 0:fef366d2ed20 207
Lerche 0:fef366d2ed20 208 /* Completed */
Lerche 0:fef366d2ed20 209 return true;
Lerche 0:fef366d2ed20 210 }
Lerche 0:fef366d2ed20 211
Lerche 0:fef366d2ed20 212 /* Check we should be transferring data IN */
Lerche 0:fef366d2ed20 213 if (transfer.direction != DEVICE_TO_HOST)
Lerche 0:fef366d2ed20 214 {
Lerche 0:fef366d2ed20 215 return false;
Lerche 0:fef366d2ed20 216 }
Lerche 0:fef366d2ed20 217
Lerche 0:fef366d2ed20 218 packetSize = transfer.remaining;
Lerche 0:fef366d2ed20 219
Lerche 0:fef366d2ed20 220 if (packetSize > MAX_PACKET_SIZE_EP0)
Lerche 0:fef366d2ed20 221 {
Lerche 0:fef366d2ed20 222 packetSize = MAX_PACKET_SIZE_EP0;
Lerche 0:fef366d2ed20 223 }
Lerche 0:fef366d2ed20 224
Lerche 0:fef366d2ed20 225 /* Write to endpoint */
Lerche 0:fef366d2ed20 226 EP0write(transfer.ptr, packetSize);
Lerche 0:fef366d2ed20 227
Lerche 0:fef366d2ed20 228 /* Update transfer */
Lerche 0:fef366d2ed20 229 transfer.ptr += packetSize;
Lerche 0:fef366d2ed20 230 transfer.remaining -= packetSize;
Lerche 0:fef366d2ed20 231
Lerche 0:fef366d2ed20 232 return true;
Lerche 0:fef366d2ed20 233 }
Lerche 0:fef366d2ed20 234
Lerche 0:fef366d2ed20 235 bool USBDevice::requestSetAddress(void)
Lerche 0:fef366d2ed20 236 {
Lerche 0:fef366d2ed20 237 /* Set the device address */
Lerche 0:fef366d2ed20 238 setAddress(transfer.setup.wValue);
Lerche 0:fef366d2ed20 239
Lerche 0:fef366d2ed20 240 if (transfer.setup.wValue == 0)
Lerche 0:fef366d2ed20 241 {
Lerche 0:fef366d2ed20 242 device.state = DEFAULT;
Lerche 0:fef366d2ed20 243 }
Lerche 0:fef366d2ed20 244 else
Lerche 0:fef366d2ed20 245 {
Lerche 0:fef366d2ed20 246 device.state = ADDRESS;
Lerche 0:fef366d2ed20 247 }
Lerche 0:fef366d2ed20 248
Lerche 0:fef366d2ed20 249 return true;
Lerche 0:fef366d2ed20 250 }
Lerche 0:fef366d2ed20 251
Lerche 0:fef366d2ed20 252 bool USBDevice::requestSetConfiguration(void)
Lerche 0:fef366d2ed20 253 {
Lerche 0:fef366d2ed20 254
Lerche 0:fef366d2ed20 255 device.configuration = transfer.setup.wValue;
Lerche 0:fef366d2ed20 256 /* Set the device configuration */
Lerche 0:fef366d2ed20 257 if (device.configuration == 0)
Lerche 0:fef366d2ed20 258 {
Lerche 0:fef366d2ed20 259 /* Not configured */
Lerche 0:fef366d2ed20 260 unconfigureDevice();
Lerche 0:fef366d2ed20 261 device.state = ADDRESS;
Lerche 0:fef366d2ed20 262 }
Lerche 0:fef366d2ed20 263 else
Lerche 0:fef366d2ed20 264 {
Lerche 0:fef366d2ed20 265 if (USBCallback_setConfiguration(device.configuration))
Lerche 0:fef366d2ed20 266 {
Lerche 0:fef366d2ed20 267 /* Valid configuration */
Lerche 0:fef366d2ed20 268 configureDevice();
Lerche 0:fef366d2ed20 269 device.state = CONFIGURED;
Lerche 0:fef366d2ed20 270 }
Lerche 0:fef366d2ed20 271 else
Lerche 0:fef366d2ed20 272 {
Lerche 0:fef366d2ed20 273 return false;
Lerche 0:fef366d2ed20 274 }
Lerche 0:fef366d2ed20 275 }
Lerche 0:fef366d2ed20 276
Lerche 0:fef366d2ed20 277 return true;
Lerche 0:fef366d2ed20 278 }
Lerche 0:fef366d2ed20 279
Lerche 0:fef366d2ed20 280 bool USBDevice::requestGetConfiguration(void)
Lerche 0:fef366d2ed20 281 {
Lerche 0:fef366d2ed20 282 /* Send the device configuration */
Lerche 0:fef366d2ed20 283 transfer.ptr = &device.configuration;
Lerche 0:fef366d2ed20 284 transfer.remaining = sizeof(device.configuration);
Lerche 0:fef366d2ed20 285 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 286 return true;
Lerche 0:fef366d2ed20 287 }
Lerche 0:fef366d2ed20 288
Lerche 0:fef366d2ed20 289 bool USBDevice::requestGetInterface(void)
Lerche 0:fef366d2ed20 290 {
Lerche 0:fef366d2ed20 291 static uint8_t alternateSetting;
Lerche 0:fef366d2ed20 292
Lerche 0:fef366d2ed20 293 /* Return the selected alternate setting for an interface */
Lerche 0:fef366d2ed20 294
Lerche 0:fef366d2ed20 295 if (device.state != CONFIGURED)
Lerche 0:fef366d2ed20 296 {
Lerche 0:fef366d2ed20 297 return false;
Lerche 0:fef366d2ed20 298 }
Lerche 0:fef366d2ed20 299
Lerche 0:fef366d2ed20 300 /* TODO: We currently do not support alternate settings */
Lerche 0:fef366d2ed20 301 /* so always return zero */
Lerche 0:fef366d2ed20 302 /* TODO: Should check that the interface number is valid */
Lerche 0:fef366d2ed20 303 alternateSetting = 0;
Lerche 0:fef366d2ed20 304
Lerche 0:fef366d2ed20 305 /* Send the alternate setting */
Lerche 0:fef366d2ed20 306 transfer.ptr = &alternateSetting;
Lerche 0:fef366d2ed20 307 transfer.remaining = sizeof(alternateSetting);
Lerche 0:fef366d2ed20 308 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 309 return true;
Lerche 0:fef366d2ed20 310 }
Lerche 0:fef366d2ed20 311
Lerche 0:fef366d2ed20 312 bool USBDevice::requestSetInterface(void)
Lerche 0:fef366d2ed20 313 {
Lerche 0:fef366d2ed20 314 /* TODO: We currently do not support alternate settings, return false */
Lerche 0:fef366d2ed20 315 return false;
Lerche 0:fef366d2ed20 316 }
Lerche 0:fef366d2ed20 317
Lerche 0:fef366d2ed20 318 bool USBDevice::requestSetFeature()
Lerche 0:fef366d2ed20 319 {
Lerche 0:fef366d2ed20 320 bool success = false;
Lerche 0:fef366d2ed20 321
Lerche 0:fef366d2ed20 322 if (device.state != CONFIGURED)
Lerche 0:fef366d2ed20 323 {
Lerche 0:fef366d2ed20 324 /* Endpoint or interface must be zero */
Lerche 0:fef366d2ed20 325 if (transfer.setup.wIndex != 0)
Lerche 0:fef366d2ed20 326 {
Lerche 0:fef366d2ed20 327 return false;
Lerche 0:fef366d2ed20 328 }
Lerche 0:fef366d2ed20 329 }
Lerche 0:fef366d2ed20 330
Lerche 0:fef366d2ed20 331 switch (transfer.setup.bmRequestType.Recipient)
Lerche 0:fef366d2ed20 332 {
Lerche 0:fef366d2ed20 333 case DEVICE_RECIPIENT:
Lerche 0:fef366d2ed20 334 /* TODO: Remote wakeup feature not supported */
Lerche 0:fef366d2ed20 335 break;
Lerche 0:fef366d2ed20 336 case ENDPOINT_RECIPIENT:
Lerche 0:fef366d2ed20 337 if (transfer.setup.wValue == ENDPOINT_HALT)
Lerche 0:fef366d2ed20 338 {
Lerche 0:fef366d2ed20 339 /* TODO: We should check that the endpoint number is valid */
Lerche 0:fef366d2ed20 340 stallEndpoint(
Lerche 0:fef366d2ed20 341 WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
Lerche 0:fef366d2ed20 342 success = true;
Lerche 0:fef366d2ed20 343 }
Lerche 0:fef366d2ed20 344 break;
Lerche 0:fef366d2ed20 345 default:
Lerche 0:fef366d2ed20 346 break;
Lerche 0:fef366d2ed20 347 }
Lerche 0:fef366d2ed20 348
Lerche 0:fef366d2ed20 349 return success;
Lerche 0:fef366d2ed20 350 }
Lerche 0:fef366d2ed20 351
Lerche 0:fef366d2ed20 352 bool USBDevice::requestClearFeature()
Lerche 0:fef366d2ed20 353 {
Lerche 0:fef366d2ed20 354 bool success = false;
Lerche 0:fef366d2ed20 355
Lerche 0:fef366d2ed20 356 if (device.state != CONFIGURED)
Lerche 0:fef366d2ed20 357 {
Lerche 0:fef366d2ed20 358 /* Endpoint or interface must be zero */
Lerche 0:fef366d2ed20 359 if (transfer.setup.wIndex != 0)
Lerche 0:fef366d2ed20 360 {
Lerche 0:fef366d2ed20 361 return false;
Lerche 0:fef366d2ed20 362 }
Lerche 0:fef366d2ed20 363 }
Lerche 0:fef366d2ed20 364
Lerche 0:fef366d2ed20 365 switch (transfer.setup.bmRequestType.Recipient)
Lerche 0:fef366d2ed20 366 {
Lerche 0:fef366d2ed20 367 case DEVICE_RECIPIENT:
Lerche 0:fef366d2ed20 368 /* TODO: Remote wakeup feature not supported */
Lerche 0:fef366d2ed20 369 break;
Lerche 0:fef366d2ed20 370 case ENDPOINT_RECIPIENT:
Lerche 0:fef366d2ed20 371 /* TODO: We should check that the endpoint number is valid */
Lerche 0:fef366d2ed20 372 if (transfer.setup.wValue == ENDPOINT_HALT)
Lerche 0:fef366d2ed20 373 {
Lerche 0:fef366d2ed20 374 unstallEndpoint(
Lerche 0:fef366d2ed20 375 WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
Lerche 0:fef366d2ed20 376 success = true;
Lerche 0:fef366d2ed20 377 }
Lerche 0:fef366d2ed20 378 break;
Lerche 0:fef366d2ed20 379 default:
Lerche 0:fef366d2ed20 380 break;
Lerche 0:fef366d2ed20 381 }
Lerche 0:fef366d2ed20 382
Lerche 0:fef366d2ed20 383 return success;
Lerche 0:fef366d2ed20 384 }
Lerche 0:fef366d2ed20 385
Lerche 0:fef366d2ed20 386 bool USBDevice::requestGetStatus(void)
Lerche 0:fef366d2ed20 387 {
Lerche 0:fef366d2ed20 388 static uint16_t status;
Lerche 0:fef366d2ed20 389 bool success = false;
Lerche 0:fef366d2ed20 390
Lerche 0:fef366d2ed20 391 if (device.state != CONFIGURED)
Lerche 0:fef366d2ed20 392 {
Lerche 0:fef366d2ed20 393 /* Endpoint or interface must be zero */
Lerche 0:fef366d2ed20 394 if (transfer.setup.wIndex != 0)
Lerche 0:fef366d2ed20 395 {
Lerche 0:fef366d2ed20 396 return false;
Lerche 0:fef366d2ed20 397 }
Lerche 0:fef366d2ed20 398 }
Lerche 0:fef366d2ed20 399
Lerche 0:fef366d2ed20 400 switch (transfer.setup.bmRequestType.Recipient)
Lerche 0:fef366d2ed20 401 {
Lerche 0:fef366d2ed20 402 case DEVICE_RECIPIENT:
Lerche 0:fef366d2ed20 403 /* TODO: Currently only supports self powered devices */
Lerche 0:fef366d2ed20 404 status = DEVICE_STATUS_SELF_POWERED;
Lerche 0:fef366d2ed20 405 success = true;
Lerche 0:fef366d2ed20 406 break;
Lerche 0:fef366d2ed20 407 case INTERFACE_RECIPIENT:
Lerche 0:fef366d2ed20 408 status = 0;
Lerche 0:fef366d2ed20 409 success = true;
Lerche 0:fef366d2ed20 410 break;
Lerche 0:fef366d2ed20 411 case ENDPOINT_RECIPIENT:
Lerche 0:fef366d2ed20 412 /* TODO: We should check that the endpoint number is valid */
Lerche 0:fef366d2ed20 413 if (getEndpointStallState(
Lerche 0:fef366d2ed20 414 WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
Lerche 0:fef366d2ed20 415 {
Lerche 0:fef366d2ed20 416 status = ENDPOINT_STATUS_HALT;
Lerche 0:fef366d2ed20 417 }
Lerche 0:fef366d2ed20 418 else
Lerche 0:fef366d2ed20 419 {
Lerche 0:fef366d2ed20 420 status = 0;
Lerche 0:fef366d2ed20 421 }
Lerche 0:fef366d2ed20 422 success = true;
Lerche 0:fef366d2ed20 423 break;
Lerche 0:fef366d2ed20 424 default:
Lerche 0:fef366d2ed20 425 break;
Lerche 0:fef366d2ed20 426 }
Lerche 0:fef366d2ed20 427
Lerche 0:fef366d2ed20 428 if (success)
Lerche 0:fef366d2ed20 429 {
Lerche 0:fef366d2ed20 430 /* Send the status */
Lerche 0:fef366d2ed20 431 transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
Lerche 0:fef366d2ed20 432 transfer.remaining = sizeof(status);
Lerche 0:fef366d2ed20 433 transfer.direction = DEVICE_TO_HOST;
Lerche 0:fef366d2ed20 434 }
Lerche 0:fef366d2ed20 435
Lerche 0:fef366d2ed20 436 return success;
Lerche 0:fef366d2ed20 437 }
Lerche 0:fef366d2ed20 438
Lerche 0:fef366d2ed20 439 bool USBDevice::requestSetup(void)
Lerche 0:fef366d2ed20 440 {
Lerche 0:fef366d2ed20 441 bool success = false;
Lerche 0:fef366d2ed20 442
Lerche 0:fef366d2ed20 443 /* Process standard requests */
Lerche 0:fef366d2ed20 444 if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
Lerche 0:fef366d2ed20 445 {
Lerche 0:fef366d2ed20 446 switch (transfer.setup.bRequest)
Lerche 0:fef366d2ed20 447 {
Lerche 0:fef366d2ed20 448 case GET_STATUS:
Lerche 0:fef366d2ed20 449 success = requestGetStatus();
Lerche 0:fef366d2ed20 450 break;
Lerche 0:fef366d2ed20 451 case CLEAR_FEATURE:
Lerche 0:fef366d2ed20 452 success = requestClearFeature();
Lerche 0:fef366d2ed20 453 break;
Lerche 0:fef366d2ed20 454 case SET_FEATURE:
Lerche 0:fef366d2ed20 455 success = requestSetFeature();
Lerche 0:fef366d2ed20 456 break;
Lerche 0:fef366d2ed20 457 case SET_ADDRESS:
Lerche 0:fef366d2ed20 458 success = requestSetAddress();
Lerche 0:fef366d2ed20 459 break;
Lerche 0:fef366d2ed20 460 case GET_DESCRIPTOR:
Lerche 0:fef366d2ed20 461 success = requestGetDescriptor();
Lerche 0:fef366d2ed20 462 break;
Lerche 0:fef366d2ed20 463 case SET_DESCRIPTOR:
Lerche 0:fef366d2ed20 464 /* TODO: Support is optional, not implemented here */
Lerche 0:fef366d2ed20 465 success = false;
Lerche 0:fef366d2ed20 466 break;
Lerche 0:fef366d2ed20 467 case GET_CONFIGURATION:
Lerche 0:fef366d2ed20 468 success = requestGetConfiguration();
Lerche 0:fef366d2ed20 469 break;
Lerche 0:fef366d2ed20 470 case SET_CONFIGURATION:
Lerche 0:fef366d2ed20 471 success = requestSetConfiguration();
Lerche 0:fef366d2ed20 472 break;
Lerche 0:fef366d2ed20 473 case GET_INTERFACE:
Lerche 0:fef366d2ed20 474 success = requestGetInterface();
Lerche 0:fef366d2ed20 475 break;
Lerche 0:fef366d2ed20 476 case SET_INTERFACE:
Lerche 0:fef366d2ed20 477 success = requestSetInterface();
Lerche 0:fef366d2ed20 478 break;
Lerche 0:fef366d2ed20 479 default:
Lerche 0:fef366d2ed20 480 break;
Lerche 0:fef366d2ed20 481 }
Lerche 0:fef366d2ed20 482 }
Lerche 0:fef366d2ed20 483
Lerche 0:fef366d2ed20 484 return success;
Lerche 0:fef366d2ed20 485 }
Lerche 0:fef366d2ed20 486
Lerche 0:fef366d2ed20 487 bool USBDevice::controlSetup(void)
Lerche 0:fef366d2ed20 488 {
Lerche 0:fef366d2ed20 489 bool success = false;
Lerche 0:fef366d2ed20 490
Lerche 0:fef366d2ed20 491 /* Control transfer setup stage */
Lerche 0:fef366d2ed20 492 uint8_t buffer[MAX_PACKET_SIZE_EP0];
Lerche 0:fef366d2ed20 493
Lerche 0:fef366d2ed20 494 EP0setup(buffer);
Lerche 0:fef366d2ed20 495
Lerche 0:fef366d2ed20 496 /* Initialise control transfer state */
Lerche 0:fef366d2ed20 497 decodeSetupPacket(buffer, &transfer.setup);
Lerche 0:fef366d2ed20 498 transfer.ptr = NULL;
Lerche 0:fef366d2ed20 499 transfer.remaining = 0;
Lerche 0:fef366d2ed20 500 transfer.direction = 0;
Lerche 0:fef366d2ed20 501 transfer.zlp = false;
Lerche 0:fef366d2ed20 502 transfer.notify = false;
Lerche 0:fef366d2ed20 503
Lerche 0:fef366d2ed20 504 /* Process request */
Lerche 0:fef366d2ed20 505
Lerche 0:fef366d2ed20 506 /* Class / vendor specific */
Lerche 0:fef366d2ed20 507 success = USBCallback_request();
Lerche 0:fef366d2ed20 508
Lerche 0:fef366d2ed20 509 if (!success)
Lerche 0:fef366d2ed20 510 {
Lerche 0:fef366d2ed20 511 /* Standard requests */
Lerche 0:fef366d2ed20 512 if (!requestSetup())
Lerche 0:fef366d2ed20 513 {
Lerche 0:fef366d2ed20 514 return false;
Lerche 0:fef366d2ed20 515 }
Lerche 0:fef366d2ed20 516 }
Lerche 0:fef366d2ed20 517
Lerche 0:fef366d2ed20 518 /* Check transfer size and direction */
Lerche 0:fef366d2ed20 519 if (transfer.setup.wLength>0)
Lerche 0:fef366d2ed20 520 {
Lerche 0:fef366d2ed20 521 if (transfer.setup.bmRequestType.dataTransferDirection \
Lerche 0:fef366d2ed20 522 == DEVICE_TO_HOST)
Lerche 0:fef366d2ed20 523 {
Lerche 0:fef366d2ed20 524 /* IN data stage is required */
Lerche 0:fef366d2ed20 525 if (transfer.direction != DEVICE_TO_HOST)
Lerche 0:fef366d2ed20 526 {
Lerche 0:fef366d2ed20 527 return false;
Lerche 0:fef366d2ed20 528 }
Lerche 0:fef366d2ed20 529
Lerche 0:fef366d2ed20 530 /* Transfer must be less than or equal to the size */
Lerche 0:fef366d2ed20 531 /* requested by the host */
Lerche 0:fef366d2ed20 532 if (transfer.remaining > transfer.setup.wLength)
Lerche 0:fef366d2ed20 533 {
Lerche 0:fef366d2ed20 534 transfer.remaining = transfer.setup.wLength;
Lerche 0:fef366d2ed20 535 }
Lerche 0:fef366d2ed20 536 }
Lerche 0:fef366d2ed20 537 else
Lerche 0:fef366d2ed20 538 {
Lerche 0:fef366d2ed20 539
Lerche 0:fef366d2ed20 540 /* OUT data stage is required */
Lerche 0:fef366d2ed20 541 if (transfer.direction != HOST_TO_DEVICE)
Lerche 0:fef366d2ed20 542 {
Lerche 0:fef366d2ed20 543 return false;
Lerche 0:fef366d2ed20 544 }
Lerche 0:fef366d2ed20 545
Lerche 0:fef366d2ed20 546 /* Transfer must be equal to the size requested by the host */
Lerche 0:fef366d2ed20 547 if (transfer.remaining != transfer.setup.wLength)
Lerche 0:fef366d2ed20 548 {
Lerche 0:fef366d2ed20 549 return false;
Lerche 0:fef366d2ed20 550 }
Lerche 0:fef366d2ed20 551 }
Lerche 0:fef366d2ed20 552 }
Lerche 0:fef366d2ed20 553 else
Lerche 0:fef366d2ed20 554 {
Lerche 0:fef366d2ed20 555 /* No data stage; transfer size must be zero */
Lerche 0:fef366d2ed20 556 if (transfer.remaining != 0)
Lerche 0:fef366d2ed20 557 {
Lerche 0:fef366d2ed20 558 return false;
Lerche 0:fef366d2ed20 559 }
Lerche 0:fef366d2ed20 560 }
Lerche 0:fef366d2ed20 561
Lerche 0:fef366d2ed20 562 /* Data or status stage if applicable */
Lerche 0:fef366d2ed20 563 if (transfer.setup.wLength>0)
Lerche 0:fef366d2ed20 564 {
Lerche 0:fef366d2ed20 565 if (transfer.setup.bmRequestType.dataTransferDirection \
Lerche 0:fef366d2ed20 566 == DEVICE_TO_HOST)
Lerche 0:fef366d2ed20 567 {
Lerche 0:fef366d2ed20 568 /* Check if we'll need to send a zero length packet at */
Lerche 0:fef366d2ed20 569 /* the end of this transfer */
Lerche 0:fef366d2ed20 570 if (transfer.setup.wLength > transfer.remaining)
Lerche 0:fef366d2ed20 571 {
Lerche 0:fef366d2ed20 572 /* Device wishes to transfer less than host requested */
Lerche 0:fef366d2ed20 573 if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
Lerche 0:fef366d2ed20 574 {
Lerche 0:fef366d2ed20 575 /* Transfer is a multiple of EP0 max packet size */
Lerche 0:fef366d2ed20 576 transfer.zlp = true;
Lerche 0:fef366d2ed20 577 }
Lerche 0:fef366d2ed20 578 }
Lerche 0:fef366d2ed20 579
Lerche 0:fef366d2ed20 580 /* IN stage */
Lerche 0:fef366d2ed20 581 controlIn();
Lerche 0:fef366d2ed20 582 }
Lerche 0:fef366d2ed20 583 else
Lerche 0:fef366d2ed20 584 {
Lerche 0:fef366d2ed20 585 /* OUT stage */
Lerche 0:fef366d2ed20 586 EP0read();
Lerche 0:fef366d2ed20 587 }
Lerche 0:fef366d2ed20 588 }
Lerche 0:fef366d2ed20 589 else
Lerche 0:fef366d2ed20 590 {
Lerche 0:fef366d2ed20 591 /* Status stage */
Lerche 0:fef366d2ed20 592 EP0write(NULL, 0);
Lerche 0:fef366d2ed20 593 }
Lerche 0:fef366d2ed20 594
Lerche 0:fef366d2ed20 595 return true;
Lerche 0:fef366d2ed20 596 }
Lerche 0:fef366d2ed20 597
Lerche 0:fef366d2ed20 598 void USBDevice::busReset(void)
Lerche 0:fef366d2ed20 599 {
Lerche 0:fef366d2ed20 600 device.state = DEFAULT;
Lerche 0:fef366d2ed20 601 device.configuration = 0;
Lerche 0:fef366d2ed20 602 device.suspended = false;
Lerche 0:fef366d2ed20 603
Lerche 0:fef366d2ed20 604 /* Call class / vendor specific busReset function */
Lerche 0:fef366d2ed20 605 USBCallback_busReset();
Lerche 0:fef366d2ed20 606 }
Lerche 0:fef366d2ed20 607
Lerche 0:fef366d2ed20 608 void USBDevice::EP0setupCallback(void)
Lerche 0:fef366d2ed20 609 {
Lerche 0:fef366d2ed20 610 /* Endpoint 0 setup event */
Lerche 0:fef366d2ed20 611 if (!controlSetup())
Lerche 0:fef366d2ed20 612 {
Lerche 0:fef366d2ed20 613 /* Protocol stall */
Lerche 0:fef366d2ed20 614 EP0stall();
Lerche 0:fef366d2ed20 615 }
Lerche 0:fef366d2ed20 616
Lerche 0:fef366d2ed20 617 /* Return true if an OUT data stage is expected */
Lerche 0:fef366d2ed20 618 }
Lerche 0:fef366d2ed20 619
Lerche 0:fef366d2ed20 620 void USBDevice::EP0out(void)
Lerche 0:fef366d2ed20 621 {
Lerche 0:fef366d2ed20 622 /* Endpoint 0 OUT data event */
Lerche 0:fef366d2ed20 623 if (!controlOut())
Lerche 0:fef366d2ed20 624 {
Lerche 0:fef366d2ed20 625 /* Protocol stall; this will stall both endpoints */
Lerche 0:fef366d2ed20 626 EP0stall();
Lerche 0:fef366d2ed20 627 }
Lerche 0:fef366d2ed20 628 }
Lerche 0:fef366d2ed20 629
Lerche 0:fef366d2ed20 630 void USBDevice::EP0in(void)
Lerche 0:fef366d2ed20 631 {
Lerche 0:fef366d2ed20 632 /* Endpoint 0 IN data event */
Lerche 0:fef366d2ed20 633 if (!controlIn())
Lerche 0:fef366d2ed20 634 {
Lerche 0:fef366d2ed20 635 /* Protocol stall; this will stall both endpoints */
Lerche 0:fef366d2ed20 636 EP0stall();
Lerche 0:fef366d2ed20 637 }
Lerche 0:fef366d2ed20 638 }
Lerche 0:fef366d2ed20 639
Lerche 0:fef366d2ed20 640 bool USBDevice::configured(void)
Lerche 0:fef366d2ed20 641 {
Lerche 0:fef366d2ed20 642 /* Returns true if device is in the CONFIGURED state */
Lerche 0:fef366d2ed20 643 return (device.state == CONFIGURED);
Lerche 0:fef366d2ed20 644 }
Lerche 0:fef366d2ed20 645
Lerche 0:fef366d2ed20 646 void USBDevice::connect(void)
Lerche 0:fef366d2ed20 647 {
Lerche 0:fef366d2ed20 648 /* Connect device */
Lerche 0:fef366d2ed20 649 USBHAL::connect();
Lerche 0:fef366d2ed20 650 }
Lerche 0:fef366d2ed20 651
Lerche 0:fef366d2ed20 652 void USBDevice::disconnect(void)
Lerche 0:fef366d2ed20 653 {
Lerche 0:fef366d2ed20 654 /* Disconnect device */
Lerche 0:fef366d2ed20 655 USBHAL::disconnect();
Lerche 0:fef366d2ed20 656 }
Lerche 0:fef366d2ed20 657
Lerche 0:fef366d2ed20 658 CONTROL_TRANSFER * USBDevice::getTransferPtr(void)
Lerche 0:fef366d2ed20 659 {
Lerche 0:fef366d2ed20 660 return &transfer;
Lerche 0:fef366d2ed20 661 }
Lerche 0:fef366d2ed20 662
Lerche 0:fef366d2ed20 663 bool USBDevice::addEndpoint(uint8_t endpoint, uint32_t maxPacket)
Lerche 0:fef366d2ed20 664 {
Lerche 0:fef366d2ed20 665 return realiseEndpoint(endpoint, maxPacket, 0);
Lerche 0:fef366d2ed20 666 }
Lerche 0:fef366d2ed20 667
Lerche 0:fef366d2ed20 668 bool USBDevice::addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket)
Lerche 0:fef366d2ed20 669 {
Lerche 0:fef366d2ed20 670 /* For interrupt endpoints only */
Lerche 0:fef366d2ed20 671 return realiseEndpoint(endpoint, maxPacket, RATE_FEEDBACK_MODE);
Lerche 0:fef366d2ed20 672 }
Lerche 0:fef366d2ed20 673
Lerche 0:fef366d2ed20 674 uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
Lerche 0:fef366d2ed20 675 {
Lerche 0:fef366d2ed20 676 /* Find a descriptor within the list of descriptors */
Lerche 0:fef366d2ed20 677 /* following a configuration descriptor. */
Lerche 0:fef366d2ed20 678 uint16_t wTotalLength;
Lerche 0:fef366d2ed20 679 uint8_t *ptr;
Lerche 0:fef366d2ed20 680
Lerche 0:fef366d2ed20 681 if (configurationDesc() == NULL)
Lerche 0:fef366d2ed20 682 {
Lerche 0:fef366d2ed20 683 return NULL;
Lerche 0:fef366d2ed20 684 }
Lerche 0:fef366d2ed20 685
Lerche 0:fef366d2ed20 686 /* Check this is a configuration descriptor */
Lerche 0:fef366d2ed20 687 if ((configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
Lerche 0:fef366d2ed20 688 || (configurationDesc()[1] != CONFIGURATION_DESCRIPTOR))
Lerche 0:fef366d2ed20 689 {
Lerche 0:fef366d2ed20 690 return NULL;
Lerche 0:fef366d2ed20 691 }
Lerche 0:fef366d2ed20 692
Lerche 0:fef366d2ed20 693 wTotalLength = configurationDesc()[2] | (configurationDesc()[3] << 8);
Lerche 0:fef366d2ed20 694
Lerche 0:fef366d2ed20 695 /* Check there are some more descriptors to follow */
Lerche 0:fef366d2ed20 696 if (wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
Lerche 0:fef366d2ed20 697 /* +2 is for bLength and bDescriptorType of next descriptor */
Lerche 0:fef366d2ed20 698 {
Lerche 0:fef366d2ed20 699 return false;
Lerche 0:fef366d2ed20 700 }
Lerche 0:fef366d2ed20 701
Lerche 0:fef366d2ed20 702 /* Start at first descriptor after the configuration descriptor */
Lerche 0:fef366d2ed20 703 ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
Lerche 0:fef366d2ed20 704
Lerche 0:fef366d2ed20 705 do {
Lerche 0:fef366d2ed20 706 if (ptr[1] /* bDescriptorType */ == descriptorType)
Lerche 0:fef366d2ed20 707 {
Lerche 0:fef366d2ed20 708 /* Found */
Lerche 0:fef366d2ed20 709 return ptr;
Lerche 0:fef366d2ed20 710 }
Lerche 0:fef366d2ed20 711
Lerche 0:fef366d2ed20 712 /* Skip to next descriptor */
Lerche 0:fef366d2ed20 713 ptr += ptr[0]; /* bLength */
Lerche 0:fef366d2ed20 714 } while (ptr < (configurationDesc() + wTotalLength));
Lerche 0:fef366d2ed20 715
Lerche 0:fef366d2ed20 716 /* Reached end of the descriptors - not found */
Lerche 0:fef366d2ed20 717 return NULL;
Lerche 0:fef366d2ed20 718 }
Lerche 0:fef366d2ed20 719
Lerche 0:fef366d2ed20 720 void USBDevice::SOF(int frameNumber)
Lerche 0:fef366d2ed20 721 {
Lerche 0:fef366d2ed20 722 }
Lerche 0:fef366d2ed20 723
Lerche 0:fef366d2ed20 724 void USBDevice::connectStateChanged(unsigned int connected)
Lerche 0:fef366d2ed20 725 {
Lerche 0:fef366d2ed20 726 }
Lerche 0:fef366d2ed20 727
Lerche 0:fef366d2ed20 728 void USBDevice::suspendStateChanged(unsigned int suspended)
Lerche 0:fef366d2ed20 729 {
Lerche 0:fef366d2ed20 730 }
Lerche 0:fef366d2ed20 731
Lerche 0:fef366d2ed20 732
Lerche 0:fef366d2ed20 733 USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
Lerche 0:fef366d2ed20 734 VENDOR_ID = vendor_id;
Lerche 0:fef366d2ed20 735 PRODUCT_ID = product_id;
Lerche 0:fef366d2ed20 736 PRODUCT_RELEASE = product_release;
Lerche 0:fef366d2ed20 737
Lerche 0:fef366d2ed20 738 /* Set initial device state */
Lerche 0:fef366d2ed20 739 device.state = POWERED;
Lerche 0:fef366d2ed20 740 device.configuration = 0;
Lerche 0:fef366d2ed20 741 device.suspended = false;
Lerche 0:fef366d2ed20 742
Lerche 0:fef366d2ed20 743 connect();
Lerche 0:fef366d2ed20 744 };
Lerche 0:fef366d2ed20 745
Lerche 0:fef366d2ed20 746
Lerche 0:fef366d2ed20 747 bool USBDevice::readStart(uint8_t endpoint, uint16_t maxSize)
Lerche 0:fef366d2ed20 748 {
Lerche 0:fef366d2ed20 749 return endpointRead(endpoint, maxSize) == EP_PENDING;
Lerche 0:fef366d2ed20 750 }
Lerche 0:fef366d2ed20 751
Lerche 0:fef366d2ed20 752
Lerche 0:fef366d2ed20 753 bool USBDevice::write(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize)
Lerche 0:fef366d2ed20 754 {
Lerche 0:fef366d2ed20 755 EP_STATUS result;
Lerche 0:fef366d2ed20 756
Lerche 0:fef366d2ed20 757 if (size > maxSize)
Lerche 0:fef366d2ed20 758 {
Lerche 0:fef366d2ed20 759 return false;
Lerche 0:fef366d2ed20 760 }
Lerche 0:fef366d2ed20 761
Lerche 0:fef366d2ed20 762 /* Block if not configured */
Lerche 0:fef366d2ed20 763 while (!configured());
Lerche 0:fef366d2ed20 764
Lerche 0:fef366d2ed20 765 /* Send report */
Lerche 0:fef366d2ed20 766 result = endpointWrite(endpoint, buffer, size);
Lerche 0:fef366d2ed20 767
Lerche 0:fef366d2ed20 768 if (result != EP_PENDING)
Lerche 0:fef366d2ed20 769 {
Lerche 0:fef366d2ed20 770 return false;
Lerche 0:fef366d2ed20 771 }
Lerche 0:fef366d2ed20 772
Lerche 0:fef366d2ed20 773 /* Wait for completion */
Lerche 0:fef366d2ed20 774 do {
Lerche 0:fef366d2ed20 775 result = endpointWriteResult(endpoint);
Lerche 0:fef366d2ed20 776 } while ((result == EP_PENDING) && configured());
Lerche 0:fef366d2ed20 777
Lerche 0:fef366d2ed20 778 return (result == EP_COMPLETED);
Lerche 0:fef366d2ed20 779 }
Lerche 0:fef366d2ed20 780
Lerche 0:fef366d2ed20 781
Lerche 0:fef366d2ed20 782 bool USBDevice::writeNB(uint8_t endpoint, uint8_t * buffer, uint16_t size, uint16_t maxSize)
Lerche 0:fef366d2ed20 783 {
Lerche 0:fef366d2ed20 784 EP_STATUS result;
Lerche 0:fef366d2ed20 785
Lerche 0:fef366d2ed20 786 if (size > maxSize)
Lerche 0:fef366d2ed20 787 {
Lerche 0:fef366d2ed20 788 return false;
Lerche 0:fef366d2ed20 789 }
Lerche 0:fef366d2ed20 790
Lerche 0:fef366d2ed20 791 /* Block if not configured */
Lerche 0:fef366d2ed20 792 while (!configured());
Lerche 0:fef366d2ed20 793
Lerche 0:fef366d2ed20 794 /* Send report */
Lerche 0:fef366d2ed20 795 result = endpointWrite(endpoint, buffer, size);
Lerche 0:fef366d2ed20 796
Lerche 0:fef366d2ed20 797 if (result != EP_PENDING)
Lerche 0:fef366d2ed20 798 {
Lerche 0:fef366d2ed20 799 return false;
Lerche 0:fef366d2ed20 800 }
Lerche 0:fef366d2ed20 801
Lerche 0:fef366d2ed20 802 result = endpointWriteResult(endpoint);
Lerche 0:fef366d2ed20 803
Lerche 0:fef366d2ed20 804 return (result == EP_COMPLETED);
Lerche 0:fef366d2ed20 805 }
Lerche 0:fef366d2ed20 806
Lerche 0:fef366d2ed20 807
Lerche 0:fef366d2ed20 808
Lerche 0:fef366d2ed20 809 bool USBDevice::read(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize)
Lerche 0:fef366d2ed20 810 {
Lerche 0:fef366d2ed20 811 EP_STATUS result;
Lerche 0:fef366d2ed20 812
Lerche 0:fef366d2ed20 813 /* Block if not configured */
Lerche 0:fef366d2ed20 814 while (!configured());
Lerche 0:fef366d2ed20 815
Lerche 0:fef366d2ed20 816 /* Wait for completion */
Lerche 0:fef366d2ed20 817 do {
Lerche 0:fef366d2ed20 818 result = endpointReadResult(endpoint, buffer, (uint32_t *)size);
Lerche 0:fef366d2ed20 819 } while ((result == EP_PENDING) && configured());
Lerche 0:fef366d2ed20 820
Lerche 0:fef366d2ed20 821 return (result == EP_COMPLETED);
Lerche 0:fef366d2ed20 822 }
Lerche 0:fef366d2ed20 823
Lerche 0:fef366d2ed20 824
Lerche 0:fef366d2ed20 825 bool USBDevice::readNB(uint8_t endpoint, uint8_t * buffer, uint16_t * size, uint16_t maxSize)
Lerche 0:fef366d2ed20 826 {
Lerche 0:fef366d2ed20 827 EP_STATUS result;
Lerche 0:fef366d2ed20 828
Lerche 0:fef366d2ed20 829 /* Block if not configured */
Lerche 0:fef366d2ed20 830 while (!configured());
Lerche 0:fef366d2ed20 831
Lerche 0:fef366d2ed20 832 result = endpointReadResult(endpoint, buffer, (uint32_t *)size);
Lerche 0:fef366d2ed20 833
Lerche 0:fef366d2ed20 834 return (result == EP_COMPLETED);
Lerche 0:fef366d2ed20 835 }
Lerche 0:fef366d2ed20 836
Lerche 0:fef366d2ed20 837
Lerche 0:fef366d2ed20 838
Lerche 0:fef366d2ed20 839 uint8_t * USBDevice::deviceDesc() {
Lerche 0:fef366d2ed20 840 static uint8_t deviceDescriptor[] = {
Lerche 0:fef366d2ed20 841 DEVICE_DESCRIPTOR_LENGTH, /* bLength */
Lerche 0:fef366d2ed20 842 DEVICE_DESCRIPTOR, /* bDescriptorType */
Lerche 0:fef366d2ed20 843 LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
Lerche 0:fef366d2ed20 844 MSB(USB_VERSION_2_0), /* bcdUSB (MSB) */
Lerche 0:fef366d2ed20 845 0x00, /* bDeviceClass */
Lerche 0:fef366d2ed20 846 0x00, /* bDeviceSubClass */
Lerche 0:fef366d2ed20 847 0x00, /* bDeviceprotocol */
Lerche 0:fef366d2ed20 848 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
Lerche 0:fef366d2ed20 849 LSB(VENDOR_ID), /* idVendor (LSB) */
Lerche 0:fef366d2ed20 850 MSB(VENDOR_ID), /* idVendor (MSB) */
Lerche 0:fef366d2ed20 851 LSB(PRODUCT_ID), /* idProduct (LSB) */
Lerche 0:fef366d2ed20 852 MSB(PRODUCT_ID), /* idProduct (MSB) */
Lerche 0:fef366d2ed20 853 LSB(PRODUCT_RELEASE), /* bcdDevice (LSB) */
Lerche 0:fef366d2ed20 854 MSB(PRODUCT_RELEASE), /* bcdDevice (MSB) */
Lerche 0:fef366d2ed20 855 STRING_OFFSET_IMANUFACTURER, /* iManufacturer */
Lerche 0:fef366d2ed20 856 STRING_OFFSET_IPRODUCT, /* iProduct */
Lerche 0:fef366d2ed20 857 STRING_OFFSET_ISERIAL, /* iSerialNumber */
Lerche 0:fef366d2ed20 858 0x01 /* bNumConfigurations */
Lerche 0:fef366d2ed20 859 };
Lerche 0:fef366d2ed20 860 return deviceDescriptor;
Lerche 0:fef366d2ed20 861 }
Lerche 0:fef366d2ed20 862
Lerche 0:fef366d2ed20 863 uint8_t * USBDevice::stringLangidDesc() {
Lerche 0:fef366d2ed20 864 static uint8_t stringLangidDescriptor[] = {
Lerche 0:fef366d2ed20 865 0x04, /*bLength*/
Lerche 0:fef366d2ed20 866 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 867 0x09,0x00, /*bString Lang ID - 0x009 - English*/
Lerche 0:fef366d2ed20 868 };
Lerche 0:fef366d2ed20 869 return stringLangidDescriptor;
Lerche 0:fef366d2ed20 870 }
Lerche 0:fef366d2ed20 871
Lerche 0:fef366d2ed20 872 uint8_t * USBDevice::stringImanufacturerDesc() {
Lerche 0:fef366d2ed20 873 static uint8_t stringImanufacturerDescriptor[] = {
Lerche 0:fef366d2ed20 874 0x12, /*bLength*/
Lerche 0:fef366d2ed20 875 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 876 'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
Lerche 0:fef366d2ed20 877 };
Lerche 0:fef366d2ed20 878 return stringImanufacturerDescriptor;
Lerche 0:fef366d2ed20 879 }
Lerche 0:fef366d2ed20 880
Lerche 0:fef366d2ed20 881 uint8_t * USBDevice::stringIserialDesc() {
Lerche 0:fef366d2ed20 882 static uint8_t stringIserialDescriptor[] = {
Lerche 0:fef366d2ed20 883 0x16, /*bLength*/
Lerche 0:fef366d2ed20 884 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 885 '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/
Lerche 0:fef366d2ed20 886 };
Lerche 0:fef366d2ed20 887 return stringIserialDescriptor;
Lerche 0:fef366d2ed20 888 }
Lerche 0:fef366d2ed20 889
Lerche 0:fef366d2ed20 890 uint8_t * USBDevice::stringIConfigurationDesc() {
Lerche 0:fef366d2ed20 891 static uint8_t stringIconfigurationDescriptor[] = {
Lerche 0:fef366d2ed20 892 0x06, /*bLength*/
Lerche 0:fef366d2ed20 893 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 894 '0',0,'1',0, /*bString iConfiguration - 01*/
Lerche 0:fef366d2ed20 895 };
Lerche 0:fef366d2ed20 896 return stringIconfigurationDescriptor;
Lerche 0:fef366d2ed20 897 }
Lerche 0:fef366d2ed20 898
Lerche 0:fef366d2ed20 899 uint8_t * USBDevice::stringIinterfaceDesc() {
Lerche 0:fef366d2ed20 900 static uint8_t stringIinterfaceDescriptor[] = {
Lerche 0:fef366d2ed20 901 0x08, /*bLength*/
Lerche 0:fef366d2ed20 902 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 903 'U',0,'S',0,'B',0, /*bString iInterface - USB*/
Lerche 0:fef366d2ed20 904 };
Lerche 0:fef366d2ed20 905 return stringIinterfaceDescriptor;
Lerche 0:fef366d2ed20 906 }
Lerche 0:fef366d2ed20 907
Lerche 0:fef366d2ed20 908 uint8_t * USBDevice::stringIproductDesc() {
Lerche 0:fef366d2ed20 909 static uint8_t stringIproductDescriptor[] = {
Lerche 0:fef366d2ed20 910 0x16, /*bLength*/
Lerche 0:fef366d2ed20 911 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
Lerche 0:fef366d2ed20 912 'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/
Lerche 0:fef366d2ed20 913 };
Lerche 0:fef366d2ed20 914 return stringIproductDescriptor;
Lerche 0:fef366d2ed20 915 }