ADC Niose test Connect four analog signals to your MBED. and then run the Windows app. The four traces are displayed on an oscilloscope like display. I have used a USB HID DEVICE link, so connections to D+, D- are required. The MBED code is otherwise quite basic, So you can modify it to your own test needs. Additionaly, there is a 16 bit count value, in my MBED code Mainly to test if MSB & LSB are correct.

Dependencies:   mbed

Committer:
ceri
Date:
Sat Nov 19 22:54:22 2011 +0000
Revision:
0:cbe01b678bd4
just enough to work

Who changed what in which revision?

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