USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Fri Nov 11 15:22:53 2011 +0000
Revision:
2:27a7e7f8d399
Child:
6:126c4d980196
we have 2MB with the sdcard!!

Who changed what in which revision?

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