Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/

Fork of STM32_USBDevice by Bradley Scott

Committer:
Troels Nilsson
Date:
Wed Jul 25 14:04:48 2018 +0200
Revision:
79:d28244984385
Parent:
76:eef92651f52f
Merge feature_WebUSB into default

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 1:80ab0d068708 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 1:80ab0d068708 2 *
samux 1:80ab0d068708 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 1:80ab0d068708 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 1:80ab0d068708 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 1:80ab0d068708 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 1:80ab0d068708 7 * Software is furnished to do so, subject to the following conditions:
samux 1:80ab0d068708 8 *
samux 1:80ab0d068708 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 1:80ab0d068708 10 * substantial portions of the Software.
samux 1:80ab0d068708 11 *
samux 1:80ab0d068708 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 1:80ab0d068708 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 1:80ab0d068708 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 1:80ab0d068708 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 1:80ab0d068708 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 1:80ab0d068708 17 */
samux 1:80ab0d068708 18
samux 1:80ab0d068708 19 #include "stdint.h"
samux 1:80ab0d068708 20
samux 1:80ab0d068708 21 #include "USBEndpoints.h"
samux 1:80ab0d068708 22 #include "USBDevice.h"
samux 1:80ab0d068708 23 #include "USBDescriptor.h"
samux 1:80ab0d068708 24
samux 1:80ab0d068708 25 //#define DEBUG
samux 1:80ab0d068708 26
samux 1:80ab0d068708 27 /* Device status */
samux 1:80ab0d068708 28 #define DEVICE_STATUS_SELF_POWERED (1U<<0)
samux 1:80ab0d068708 29 #define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
samux 1:80ab0d068708 30
samux 1:80ab0d068708 31 /* Endpoint status */
samux 1:80ab0d068708 32 #define ENDPOINT_STATUS_HALT (1U<<0)
samux 1:80ab0d068708 33
samux 1:80ab0d068708 34 /* Standard feature selectors */
samux 1:80ab0d068708 35 #define DEVICE_REMOTE_WAKEUP (1)
samux 1:80ab0d068708 36 #define ENDPOINT_HALT (0)
samux 1:80ab0d068708 37
samux 1:80ab0d068708 38 /* Macro to convert wIndex endpoint number to physical endpoint number */
samux 1:80ab0d068708 39 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
samux 1:80ab0d068708 40 ((endpoint & 0x80) ? 1 : 0))
samux 1:80ab0d068708 41
samux 1:80ab0d068708 42
samux 1:80ab0d068708 43 bool USBDevice::requestGetDescriptor(void)
samux 1:80ab0d068708 44 {
samux 1:80ab0d068708 45 bool success = false;
samux 1:80ab0d068708 46 #ifdef DEBUG
samux 1:80ab0d068708 47 printf("get descr: type: %d\r\n", DESCRIPTOR_TYPE(transfer.setup.wValue));
samux 1:80ab0d068708 48 #endif
samux 1:80ab0d068708 49 switch (DESCRIPTOR_TYPE(transfer.setup.wValue))
samux 1:80ab0d068708 50 {
samux 1:80ab0d068708 51 case DEVICE_DESCRIPTOR:
samux 1:80ab0d068708 52 if (deviceDesc() != NULL)
samux 1:80ab0d068708 53 {
samux 1:80ab0d068708 54 if ((deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 55 && (deviceDesc()[1] == DEVICE_DESCRIPTOR))
samux 1:80ab0d068708 56 {
samux 1:80ab0d068708 57 #ifdef DEBUG
samux 1:80ab0d068708 58 printf("device descr\r\n");
samux 1:80ab0d068708 59 #endif
samux 1:80ab0d068708 60 transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
samux 1:80ab0d068708 61 transfer.ptr = deviceDesc();
samux 1:80ab0d068708 62 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 63 success = true;
samux 1:80ab0d068708 64 }
samux 1:80ab0d068708 65 }
samux 1:80ab0d068708 66 break;
samux 1:80ab0d068708 67 case CONFIGURATION_DESCRIPTOR:
samux 1:80ab0d068708 68 if (configurationDesc() != NULL)
samux 1:80ab0d068708 69 {
samux 1:80ab0d068708 70 if ((configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 71 && (configurationDesc()[1] == CONFIGURATION_DESCRIPTOR))
samux 1:80ab0d068708 72 {
samux 1:80ab0d068708 73 #ifdef DEBUG
samux 1:80ab0d068708 74 printf("conf descr request\r\n");
samux 1:80ab0d068708 75 #endif
samux 1:80ab0d068708 76 /* Get wTotalLength */
samux 1:80ab0d068708 77 transfer.remaining = configurationDesc()[2] \
samux 1:80ab0d068708 78 | (configurationDesc()[3] << 8);
samux 1:80ab0d068708 79
samux 1:80ab0d068708 80 transfer.ptr = configurationDesc();
samux 1:80ab0d068708 81 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 82 success = true;
samux 1:80ab0d068708 83 }
samux 1:80ab0d068708 84 }
samux 1:80ab0d068708 85 break;
samux 1:80ab0d068708 86 case STRING_DESCRIPTOR:
samux 1:80ab0d068708 87 #ifdef DEBUG
samux 1:80ab0d068708 88 printf("str descriptor\r\n");
samux 1:80ab0d068708 89 #endif
samux 1:80ab0d068708 90 switch (DESCRIPTOR_INDEX(transfer.setup.wValue))
samux 1:80ab0d068708 91 {
samux 1:80ab0d068708 92 case STRING_OFFSET_LANGID:
samux 1:80ab0d068708 93 #ifdef DEBUG
samux 1:80ab0d068708 94 printf("1\r\n");
samux 1:80ab0d068708 95 #endif
samux 1:80ab0d068708 96 transfer.remaining = stringLangidDesc()[0];
samux 1:80ab0d068708 97 transfer.ptr = stringLangidDesc();
samux 1:80ab0d068708 98 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 99 success = true;
samux 1:80ab0d068708 100 break;
samux 1:80ab0d068708 101 case STRING_OFFSET_IMANUFACTURER:
samux 1:80ab0d068708 102 #ifdef DEBUG
samux 1:80ab0d068708 103 printf("2\r\n");
samux 1:80ab0d068708 104 #endif
samux 1:80ab0d068708 105 transfer.remaining = stringImanufacturerDesc()[0];
samux 1:80ab0d068708 106 transfer.ptr = stringImanufacturerDesc();
samux 1:80ab0d068708 107 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 108 success = true;
mbed_official 25:7c72828865f3 109 break;
samux 1:80ab0d068708 110 case STRING_OFFSET_IPRODUCT:
samux 1:80ab0d068708 111 #ifdef DEBUG
samux 1:80ab0d068708 112 printf("3\r\n");
samux 1:80ab0d068708 113 #endif
samux 1:80ab0d068708 114 transfer.remaining = stringIproductDesc()[0];
samux 1:80ab0d068708 115 transfer.ptr = stringIproductDesc();
samux 1:80ab0d068708 116 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 117 success = true;
mbed_official 25:7c72828865f3 118 break;
samux 1:80ab0d068708 119 case STRING_OFFSET_ISERIAL:
samux 1:80ab0d068708 120 #ifdef DEBUG
samux 1:80ab0d068708 121 printf("4\r\n");
samux 1:80ab0d068708 122 #endif
samux 1:80ab0d068708 123 transfer.remaining = stringIserialDesc()[0];
samux 1:80ab0d068708 124 transfer.ptr = stringIserialDesc();
samux 1:80ab0d068708 125 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 126 success = true;
mbed_official 25:7c72828865f3 127 break;
samux 1:80ab0d068708 128 case STRING_OFFSET_ICONFIGURATION:
samux 1:80ab0d068708 129 #ifdef DEBUG
samux 1:80ab0d068708 130 printf("5\r\n");
samux 1:80ab0d068708 131 #endif
samux 1:80ab0d068708 132 transfer.remaining = stringIConfigurationDesc()[0];
samux 1:80ab0d068708 133 transfer.ptr = stringIConfigurationDesc();
samux 1:80ab0d068708 134 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 135 success = true;
mbed_official 25:7c72828865f3 136 break;
samux 1:80ab0d068708 137 case STRING_OFFSET_IINTERFACE:
samux 1:80ab0d068708 138 #ifdef DEBUG
samux 1:80ab0d068708 139 printf("6\r\n");
samux 1:80ab0d068708 140 #endif
samux 1:80ab0d068708 141 transfer.remaining = stringIinterfaceDesc()[0];
samux 1:80ab0d068708 142 transfer.ptr = stringIinterfaceDesc();
samux 1:80ab0d068708 143 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 144 success = true;
mbed_official 25:7c72828865f3 145 break;
samux 1:80ab0d068708 146 }
samux 1:80ab0d068708 147 break;
samux 1:80ab0d068708 148 case INTERFACE_DESCRIPTOR:
samux 1:80ab0d068708 149 #ifdef DEBUG
samux 1:80ab0d068708 150 printf("interface descr\r\n");
samux 1:80ab0d068708 151 #endif
samux 1:80ab0d068708 152 case ENDPOINT_DESCRIPTOR:
samux 1:80ab0d068708 153 #ifdef DEBUG
samux 1:80ab0d068708 154 printf("endpoint descr\r\n");
samux 1:80ab0d068708 155 #endif
samux 1:80ab0d068708 156 /* TODO: Support is optional, not implemented here */
samux 1:80ab0d068708 157 break;
Troels Nilsson 76:eef92651f52f 158
Troels Nilsson 76:eef92651f52f 159 case BOS_DESCRIPTOR:
Troels Nilsson 76:eef92651f52f 160 #ifdef DEBUG
Troels Nilsson 76:eef92651f52f 161 printf("BOS descr\r\n");
Troels Nilsson 76:eef92651f52f 162 #endif
Troels Nilsson 76:eef92651f52f 163 {
Troels Nilsson 76:eef92651f52f 164 uint8_t *descriptor = bosDesc();
Troels Nilsson 76:eef92651f52f 165 if (descriptor)
Troels Nilsson 76:eef92651f52f 166 {
Troels Nilsson 76:eef92651f52f 167 /* Get wTotalLength */
Troels Nilsson 76:eef92651f52f 168 transfer.remaining = descriptor[2] | (descriptor[3] << 8);
Troels Nilsson 76:eef92651f52f 169 transfer.ptr = descriptor;
Troels Nilsson 76:eef92651f52f 170 transfer.direction = DEVICE_TO_HOST;
Troels Nilsson 76:eef92651f52f 171 success = true;
Troels Nilsson 76:eef92651f52f 172 }
Troels Nilsson 76:eef92651f52f 173 }
Troels Nilsson 76:eef92651f52f 174 break;
Troels Nilsson 76:eef92651f52f 175
samux 1:80ab0d068708 176 default:
samux 1:80ab0d068708 177 #ifdef DEBUG
samux 1:80ab0d068708 178 printf("ERROR\r\n");
samux 1:80ab0d068708 179 #endif
samux 1:80ab0d068708 180 break;
samux 1:80ab0d068708 181 }
samux 1:80ab0d068708 182
samux 1:80ab0d068708 183 return success;
samux 1:80ab0d068708 184 }
samux 1:80ab0d068708 185
samux 1:80ab0d068708 186 void USBDevice::decodeSetupPacket(uint8_t *data, SETUP_PACKET *packet)
samux 1:80ab0d068708 187 {
samux 1:80ab0d068708 188 /* Fill in the elements of a SETUP_PACKET structure from raw data */
samux 1:80ab0d068708 189 packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
samux 1:80ab0d068708 190 packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
samux 1:80ab0d068708 191 packet->bmRequestType.Recipient = data[0] & 0x1f;
samux 1:80ab0d068708 192 packet->bRequest = data[1];
samux 1:80ab0d068708 193 packet->wValue = (data[2] | (uint16_t)data[3] << 8);
samux 1:80ab0d068708 194 packet->wIndex = (data[4] | (uint16_t)data[5] << 8);
samux 1:80ab0d068708 195 packet->wLength = (data[6] | (uint16_t)data[7] << 8);
samux 1:80ab0d068708 196 }
samux 1:80ab0d068708 197
samux 1:80ab0d068708 198
samux 1:80ab0d068708 199 bool USBDevice::controlOut(void)
samux 1:80ab0d068708 200 {
samux 1:80ab0d068708 201 /* Control transfer data OUT stage */
samux 1:80ab0d068708 202 uint8_t buffer[MAX_PACKET_SIZE_EP0];
samux 1:80ab0d068708 203 uint32_t packetSize;
samux 1:80ab0d068708 204
samux 1:80ab0d068708 205 /* Check we should be transferring data OUT */
samux 1:80ab0d068708 206 if (transfer.direction != HOST_TO_DEVICE)
samux 1:80ab0d068708 207 {
mbed_official 43:c0605f23f916 208 #if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
mbed_official 28:c09a0c9bf425 209 /*
mbed_official 28:c09a0c9bf425 210 * We seem to have a pending device-to-host transfer. The host must have
mbed_official 28:c09a0c9bf425 211 * sent a new control request without waiting for us to finish processing
Geir Inge Tellnes 73:fa395f2d24ba 212 * the previous one. This appears to happen when we're connected to certain
mbed_official 28:c09a0c9bf425 213 * USB 3.0 host chip set. Do a zeor-length send to tell the host we're not
mbed_official 28:c09a0c9bf425 214 * ready for the new request - that'll make it resend - and then just
mbed_official 28:c09a0c9bf425 215 * pretend we were successful here so that the pending transfer can finish.
mbed_official 28:c09a0c9bf425 216 */
mbed_official 28:c09a0c9bf425 217 uint8_t buf[1] = { 0 };
mbed_official 28:c09a0c9bf425 218 EP0write(buf, 0);
Geir Inge Tellnes 73:fa395f2d24ba 219
mbed_official 28:c09a0c9bf425 220 /* execute our pending ttransfer */
mbed_official 28:c09a0c9bf425 221 controlIn();
Geir Inge Tellnes 73:fa395f2d24ba 222
mbed_official 28:c09a0c9bf425 223 /* indicate success */
mbed_official 28:c09a0c9bf425 224 return true;
mbed_official 28:c09a0c9bf425 225 #else
mbed_official 28:c09a0c9bf425 226 /* for other platforms, count on the HAL to handle this case */
mbed_official 28:c09a0c9bf425 227 return false;
mbed_official 28:c09a0c9bf425 228 #endif
samux 1:80ab0d068708 229 }
samux 1:80ab0d068708 230
samux 1:80ab0d068708 231 /* Read from endpoint */
samux 1:80ab0d068708 232 packetSize = EP0getReadResult(buffer);
samux 1:80ab0d068708 233
samux 1:80ab0d068708 234 /* Check if transfer size is valid */
samux 1:80ab0d068708 235 if (packetSize > transfer.remaining)
samux 1:80ab0d068708 236 {
samux 1:80ab0d068708 237 /* Too big */
samux 1:80ab0d068708 238 return false;
samux 1:80ab0d068708 239 }
samux 1:80ab0d068708 240
samux 1:80ab0d068708 241 /* Update transfer */
samux 1:80ab0d068708 242 transfer.ptr += packetSize;
samux 1:80ab0d068708 243 transfer.remaining -= packetSize;
samux 1:80ab0d068708 244
samux 1:80ab0d068708 245 /* Check if transfer has completed */
samux 1:80ab0d068708 246 if (transfer.remaining == 0)
samux 1:80ab0d068708 247 {
samux 1:80ab0d068708 248 /* Transfer completed */
samux 1:80ab0d068708 249 if (transfer.notify)
samux 1:80ab0d068708 250 {
samux 1:80ab0d068708 251 /* Notify class layer. */
samux 1:80ab0d068708 252 USBCallback_requestCompleted(buffer, packetSize);
samux 1:80ab0d068708 253 transfer.notify = false;
samux 1:80ab0d068708 254 }
samux 1:80ab0d068708 255 /* Status stage */
samux 1:80ab0d068708 256 EP0write(NULL, 0);
samux 1:80ab0d068708 257 }
samux 1:80ab0d068708 258 else
samux 1:80ab0d068708 259 {
samux 1:80ab0d068708 260 EP0read();
samux 1:80ab0d068708 261 }
samux 1:80ab0d068708 262
samux 1:80ab0d068708 263 return true;
samux 1:80ab0d068708 264 }
samux 1:80ab0d068708 265
samux 1:80ab0d068708 266 bool USBDevice::controlIn(void)
samux 1:80ab0d068708 267 {
samux 1:80ab0d068708 268 /* Control transfer data IN stage */
samux 1:80ab0d068708 269 uint32_t packetSize;
samux 1:80ab0d068708 270
samux 1:80ab0d068708 271 /* Check if transfer has completed (status stage transactions */
samux 1:80ab0d068708 272 /* also have transfer.remaining == 0) */
samux 1:80ab0d068708 273 if (transfer.remaining == 0)
samux 1:80ab0d068708 274 {
samux 1:80ab0d068708 275 if (transfer.zlp)
samux 1:80ab0d068708 276 {
samux 1:80ab0d068708 277 /* Send zero length packet */
samux 1:80ab0d068708 278 EP0write(NULL, 0);
samux 1:80ab0d068708 279 transfer.zlp = false;
samux 1:80ab0d068708 280 }
samux 1:80ab0d068708 281
samux 1:80ab0d068708 282 /* Transfer completed */
samux 1:80ab0d068708 283 if (transfer.notify)
samux 1:80ab0d068708 284 {
samux 1:80ab0d068708 285 /* Notify class layer. */
samux 1:80ab0d068708 286 USBCallback_requestCompleted(NULL, 0);
samux 1:80ab0d068708 287 transfer.notify = false;
samux 1:80ab0d068708 288 }
samux 1:80ab0d068708 289
samux 1:80ab0d068708 290 EP0read();
samux 8:335f2506f422 291 EP0readStage();
samux 1:80ab0d068708 292
samux 1:80ab0d068708 293 /* Completed */
samux 1:80ab0d068708 294 return true;
samux 1:80ab0d068708 295 }
samux 1:80ab0d068708 296
samux 1:80ab0d068708 297 /* Check we should be transferring data IN */
samux 1:80ab0d068708 298 if (transfer.direction != DEVICE_TO_HOST)
samux 1:80ab0d068708 299 {
samux 1:80ab0d068708 300 return false;
samux 1:80ab0d068708 301 }
samux 1:80ab0d068708 302
samux 1:80ab0d068708 303 packetSize = transfer.remaining;
samux 1:80ab0d068708 304
samux 1:80ab0d068708 305 if (packetSize > MAX_PACKET_SIZE_EP0)
samux 1:80ab0d068708 306 {
samux 1:80ab0d068708 307 packetSize = MAX_PACKET_SIZE_EP0;
samux 1:80ab0d068708 308 }
samux 1:80ab0d068708 309
samux 1:80ab0d068708 310 /* Write to endpoint */
samux 1:80ab0d068708 311 EP0write(transfer.ptr, packetSize);
samux 1:80ab0d068708 312
samux 1:80ab0d068708 313 /* Update transfer */
samux 1:80ab0d068708 314 transfer.ptr += packetSize;
samux 1:80ab0d068708 315 transfer.remaining -= packetSize;
samux 1:80ab0d068708 316
samux 1:80ab0d068708 317 return true;
samux 1:80ab0d068708 318 }
samux 1:80ab0d068708 319
samux 1:80ab0d068708 320 bool USBDevice::requestSetAddress(void)
samux 1:80ab0d068708 321 {
samux 1:80ab0d068708 322 /* Set the device address */
samux 1:80ab0d068708 323 setAddress(transfer.setup.wValue);
samux 1:80ab0d068708 324
samux 1:80ab0d068708 325 if (transfer.setup.wValue == 0)
samux 1:80ab0d068708 326 {
samux 1:80ab0d068708 327 device.state = DEFAULT;
samux 1:80ab0d068708 328 }
samux 1:80ab0d068708 329 else
samux 1:80ab0d068708 330 {
samux 1:80ab0d068708 331 device.state = ADDRESS;
samux 1:80ab0d068708 332 }
samux 1:80ab0d068708 333
samux 1:80ab0d068708 334 return true;
samux 1:80ab0d068708 335 }
samux 1:80ab0d068708 336
samux 1:80ab0d068708 337 bool USBDevice::requestSetConfiguration(void)
samux 1:80ab0d068708 338 {
samux 1:80ab0d068708 339
samux 1:80ab0d068708 340 device.configuration = transfer.setup.wValue;
samux 1:80ab0d068708 341 /* Set the device configuration */
samux 1:80ab0d068708 342 if (device.configuration == 0)
samux 1:80ab0d068708 343 {
samux 1:80ab0d068708 344 /* Not configured */
samux 1:80ab0d068708 345 unconfigureDevice();
samux 1:80ab0d068708 346 device.state = ADDRESS;
samux 1:80ab0d068708 347 }
samux 1:80ab0d068708 348 else
samux 1:80ab0d068708 349 {
samux 1:80ab0d068708 350 if (USBCallback_setConfiguration(device.configuration))
samux 1:80ab0d068708 351 {
samux 1:80ab0d068708 352 /* Valid configuration */
samux 1:80ab0d068708 353 configureDevice();
samux 1:80ab0d068708 354 device.state = CONFIGURED;
samux 1:80ab0d068708 355 }
samux 1:80ab0d068708 356 else
samux 1:80ab0d068708 357 {
samux 1:80ab0d068708 358 return false;
samux 1:80ab0d068708 359 }
samux 1:80ab0d068708 360 }
samux 1:80ab0d068708 361
samux 1:80ab0d068708 362 return true;
samux 1:80ab0d068708 363 }
samux 1:80ab0d068708 364
samux 1:80ab0d068708 365 bool USBDevice::requestGetConfiguration(void)
samux 1:80ab0d068708 366 {
samux 1:80ab0d068708 367 /* Send the device configuration */
samux 1:80ab0d068708 368 transfer.ptr = &device.configuration;
samux 1:80ab0d068708 369 transfer.remaining = sizeof(device.configuration);
samux 1:80ab0d068708 370 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 371 return true;
samux 1:80ab0d068708 372 }
samux 1:80ab0d068708 373
samux 1:80ab0d068708 374 bool USBDevice::requestGetInterface(void)
samux 1:80ab0d068708 375 {
samux 1:80ab0d068708 376 /* Return the selected alternate setting for an interface */
samux 1:80ab0d068708 377
samux 1:80ab0d068708 378 if (device.state != CONFIGURED)
samux 1:80ab0d068708 379 {
samux 1:80ab0d068708 380 return false;
samux 1:80ab0d068708 381 }
samux 1:80ab0d068708 382
samux 1:80ab0d068708 383 /* Send the alternate setting */
samux 1:80ab0d068708 384 transfer.setup.wIndex = currentInterface;
samux 1:80ab0d068708 385 transfer.ptr = &currentAlternate;
samux 1:80ab0d068708 386 transfer.remaining = sizeof(currentAlternate);
samux 1:80ab0d068708 387 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 388 return true;
samux 1:80ab0d068708 389 }
samux 1:80ab0d068708 390
samux 1:80ab0d068708 391 bool USBDevice::requestSetInterface(void)
samux 1:80ab0d068708 392 {
samux 1:80ab0d068708 393 bool success = false;
samux 1:80ab0d068708 394 if(USBCallback_setInterface(transfer.setup.wIndex, transfer.setup.wValue))
samux 1:80ab0d068708 395 {
samux 1:80ab0d068708 396 success = true;
samux 1:80ab0d068708 397 currentInterface = transfer.setup.wIndex;
mbed_official 25:7c72828865f3 398 currentAlternate = transfer.setup.wValue;
samux 1:80ab0d068708 399 }
samux 1:80ab0d068708 400 return success;
samux 1:80ab0d068708 401 }
samux 1:80ab0d068708 402
samux 1:80ab0d068708 403 bool USBDevice::requestSetFeature()
samux 1:80ab0d068708 404 {
samux 1:80ab0d068708 405 bool success = false;
samux 1:80ab0d068708 406
samux 1:80ab0d068708 407 if (device.state != CONFIGURED)
samux 1:80ab0d068708 408 {
samux 1:80ab0d068708 409 /* Endpoint or interface must be zero */
samux 1:80ab0d068708 410 if (transfer.setup.wIndex != 0)
samux 1:80ab0d068708 411 {
samux 1:80ab0d068708 412 return false;
samux 1:80ab0d068708 413 }
samux 1:80ab0d068708 414 }
samux 1:80ab0d068708 415
samux 1:80ab0d068708 416 switch (transfer.setup.bmRequestType.Recipient)
samux 1:80ab0d068708 417 {
samux 1:80ab0d068708 418 case DEVICE_RECIPIENT:
samux 1:80ab0d068708 419 /* TODO: Remote wakeup feature not supported */
samux 1:80ab0d068708 420 break;
samux 1:80ab0d068708 421 case ENDPOINT_RECIPIENT:
samux 1:80ab0d068708 422 if (transfer.setup.wValue == ENDPOINT_HALT)
samux 1:80ab0d068708 423 {
samux 1:80ab0d068708 424 /* TODO: We should check that the endpoint number is valid */
samux 1:80ab0d068708 425 stallEndpoint(
samux 1:80ab0d068708 426 WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
samux 1:80ab0d068708 427 success = true;
samux 1:80ab0d068708 428 }
samux 1:80ab0d068708 429 break;
samux 1:80ab0d068708 430 default:
samux 1:80ab0d068708 431 break;
samux 1:80ab0d068708 432 }
samux 1:80ab0d068708 433
samux 1:80ab0d068708 434 return success;
samux 1:80ab0d068708 435 }
samux 1:80ab0d068708 436
samux 1:80ab0d068708 437 bool USBDevice::requestClearFeature()
samux 1:80ab0d068708 438 {
samux 1:80ab0d068708 439 bool success = false;
samux 1:80ab0d068708 440
samux 1:80ab0d068708 441 if (device.state != CONFIGURED)
samux 1:80ab0d068708 442 {
samux 1:80ab0d068708 443 /* Endpoint or interface must be zero */
samux 1:80ab0d068708 444 if (transfer.setup.wIndex != 0)
samux 1:80ab0d068708 445 {
samux 1:80ab0d068708 446 return false;
samux 1:80ab0d068708 447 }
samux 1:80ab0d068708 448 }
samux 1:80ab0d068708 449
samux 1:80ab0d068708 450 switch (transfer.setup.bmRequestType.Recipient)
samux 1:80ab0d068708 451 {
samux 1:80ab0d068708 452 case DEVICE_RECIPIENT:
samux 1:80ab0d068708 453 /* TODO: Remote wakeup feature not supported */
samux 1:80ab0d068708 454 break;
samux 1:80ab0d068708 455 case ENDPOINT_RECIPIENT:
samux 1:80ab0d068708 456 /* TODO: We should check that the endpoint number is valid */
samux 1:80ab0d068708 457 if (transfer.setup.wValue == ENDPOINT_HALT)
samux 1:80ab0d068708 458 {
samux 1:80ab0d068708 459 unstallEndpoint( WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
samux 1:80ab0d068708 460 success = true;
samux 1:80ab0d068708 461 }
samux 1:80ab0d068708 462 break;
samux 1:80ab0d068708 463 default:
samux 1:80ab0d068708 464 break;
samux 1:80ab0d068708 465 }
samux 1:80ab0d068708 466
samux 1:80ab0d068708 467 return success;
samux 1:80ab0d068708 468 }
samux 1:80ab0d068708 469
samux 1:80ab0d068708 470 bool USBDevice::requestGetStatus(void)
samux 1:80ab0d068708 471 {
samux 1:80ab0d068708 472 static uint16_t status;
samux 1:80ab0d068708 473 bool success = false;
samux 1:80ab0d068708 474
samux 1:80ab0d068708 475 if (device.state != CONFIGURED)
samux 1:80ab0d068708 476 {
samux 1:80ab0d068708 477 /* Endpoint or interface must be zero */
samux 1:80ab0d068708 478 if (transfer.setup.wIndex != 0)
samux 1:80ab0d068708 479 {
samux 1:80ab0d068708 480 return false;
samux 1:80ab0d068708 481 }
samux 1:80ab0d068708 482 }
samux 1:80ab0d068708 483
samux 1:80ab0d068708 484 switch (transfer.setup.bmRequestType.Recipient)
samux 1:80ab0d068708 485 {
samux 1:80ab0d068708 486 case DEVICE_RECIPIENT:
samux 1:80ab0d068708 487 /* TODO: Currently only supports self powered devices */
samux 1:80ab0d068708 488 status = DEVICE_STATUS_SELF_POWERED;
samux 1:80ab0d068708 489 success = true;
samux 1:80ab0d068708 490 break;
samux 1:80ab0d068708 491 case INTERFACE_RECIPIENT:
samux 1:80ab0d068708 492 status = 0;
samux 1:80ab0d068708 493 success = true;
samux 1:80ab0d068708 494 break;
samux 1:80ab0d068708 495 case ENDPOINT_RECIPIENT:
samux 1:80ab0d068708 496 /* TODO: We should check that the endpoint number is valid */
samux 1:80ab0d068708 497 if (getEndpointStallState(
samux 1:80ab0d068708 498 WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
samux 1:80ab0d068708 499 {
samux 1:80ab0d068708 500 status = ENDPOINT_STATUS_HALT;
samux 1:80ab0d068708 501 }
samux 1:80ab0d068708 502 else
samux 1:80ab0d068708 503 {
samux 1:80ab0d068708 504 status = 0;
samux 1:80ab0d068708 505 }
samux 1:80ab0d068708 506 success = true;
samux 1:80ab0d068708 507 break;
samux 1:80ab0d068708 508 default:
samux 1:80ab0d068708 509 break;
samux 1:80ab0d068708 510 }
samux 1:80ab0d068708 511
samux 1:80ab0d068708 512 if (success)
samux 1:80ab0d068708 513 {
mbed_official 25:7c72828865f3 514 /* Send the status */
samux 1:80ab0d068708 515 transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
samux 1:80ab0d068708 516 transfer.remaining = sizeof(status);
samux 1:80ab0d068708 517 transfer.direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 518 }
mbed_official 25:7c72828865f3 519
samux 1:80ab0d068708 520 return success;
samux 1:80ab0d068708 521 }
samux 1:80ab0d068708 522
samux 1:80ab0d068708 523 bool USBDevice::requestSetup(void)
samux 1:80ab0d068708 524 {
samux 1:80ab0d068708 525 bool success = false;
samux 1:80ab0d068708 526
samux 1:80ab0d068708 527 /* Process standard requests */
samux 1:80ab0d068708 528 if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
samux 1:80ab0d068708 529 {
samux 1:80ab0d068708 530 switch (transfer.setup.bRequest)
samux 1:80ab0d068708 531 {
samux 1:80ab0d068708 532 case GET_STATUS:
samux 1:80ab0d068708 533 success = requestGetStatus();
samux 1:80ab0d068708 534 break;
samux 1:80ab0d068708 535 case CLEAR_FEATURE:
samux 1:80ab0d068708 536 success = requestClearFeature();
samux 1:80ab0d068708 537 break;
samux 1:80ab0d068708 538 case SET_FEATURE:
samux 1:80ab0d068708 539 success = requestSetFeature();
samux 1:80ab0d068708 540 break;
samux 1:80ab0d068708 541 case SET_ADDRESS:
samux 1:80ab0d068708 542 success = requestSetAddress();
samux 1:80ab0d068708 543 break;
samux 1:80ab0d068708 544 case GET_DESCRIPTOR:
samux 1:80ab0d068708 545 success = requestGetDescriptor();
samux 1:80ab0d068708 546 break;
samux 1:80ab0d068708 547 case SET_DESCRIPTOR:
samux 1:80ab0d068708 548 /* TODO: Support is optional, not implemented here */
samux 1:80ab0d068708 549 success = false;
samux 1:80ab0d068708 550 break;
samux 1:80ab0d068708 551 case GET_CONFIGURATION:
samux 1:80ab0d068708 552 success = requestGetConfiguration();
samux 1:80ab0d068708 553 break;
samux 1:80ab0d068708 554 case SET_CONFIGURATION:
samux 1:80ab0d068708 555 success = requestSetConfiguration();
samux 1:80ab0d068708 556 break;
samux 1:80ab0d068708 557 case GET_INTERFACE:
samux 1:80ab0d068708 558 success = requestGetInterface();
samux 1:80ab0d068708 559 break;
samux 1:80ab0d068708 560 case SET_INTERFACE:
samux 1:80ab0d068708 561 success = requestSetInterface();
samux 1:80ab0d068708 562 break;
samux 1:80ab0d068708 563 default:
samux 1:80ab0d068708 564 break;
samux 1:80ab0d068708 565 }
samux 1:80ab0d068708 566 }
samux 1:80ab0d068708 567
samux 1:80ab0d068708 568 return success;
samux 1:80ab0d068708 569 }
samux 1:80ab0d068708 570
samux 1:80ab0d068708 571 bool USBDevice::controlSetup(void)
samux 1:80ab0d068708 572 {
samux 1:80ab0d068708 573 bool success = false;
samux 1:80ab0d068708 574
samux 1:80ab0d068708 575 /* Control transfer setup stage */
samux 1:80ab0d068708 576 uint8_t buffer[MAX_PACKET_SIZE_EP0];
samux 1:80ab0d068708 577
samux 1:80ab0d068708 578 EP0setup(buffer);
samux 1:80ab0d068708 579
samux 1:80ab0d068708 580 /* Initialise control transfer state */
samux 1:80ab0d068708 581 decodeSetupPacket(buffer, &transfer.setup);
samux 1:80ab0d068708 582 transfer.ptr = NULL;
samux 1:80ab0d068708 583 transfer.remaining = 0;
samux 1:80ab0d068708 584 transfer.direction = 0;
samux 1:80ab0d068708 585 transfer.zlp = false;
samux 1:80ab0d068708 586 transfer.notify = false;
mbed_official 25:7c72828865f3 587
samux 1:80ab0d068708 588 #ifdef DEBUG
samux 1:80ab0d068708 589 printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection,
samux 1:80ab0d068708 590 transfer.setup.bmRequestType.Type,
samux 1:80ab0d068708 591 transfer.setup.bmRequestType.Recipient,
samux 1:80ab0d068708 592 transfer.setup.bRequest,
samux 1:80ab0d068708 593 transfer.setup.wValue,
samux 1:80ab0d068708 594 transfer.setup.wIndex,
samux 1:80ab0d068708 595 transfer.setup.wLength);
samux 1:80ab0d068708 596 #endif
samux 1:80ab0d068708 597
samux 1:80ab0d068708 598 /* Class / vendor specific */
samux 1:80ab0d068708 599 success = USBCallback_request();
samux 1:80ab0d068708 600
samux 1:80ab0d068708 601 if (!success)
samux 1:80ab0d068708 602 {
samux 1:80ab0d068708 603 /* Standard requests */
samux 1:80ab0d068708 604 if (!requestSetup())
samux 1:80ab0d068708 605 {
samux 1:80ab0d068708 606 #ifdef DEBUG
samux 1:80ab0d068708 607 printf("fail!!!!\r\n");
samux 1:80ab0d068708 608 #endif
samux 1:80ab0d068708 609 return false;
samux 1:80ab0d068708 610 }
samux 1:80ab0d068708 611 }
samux 1:80ab0d068708 612
samux 1:80ab0d068708 613 /* Check transfer size and direction */
samux 1:80ab0d068708 614 if (transfer.setup.wLength>0)
samux 1:80ab0d068708 615 {
samux 1:80ab0d068708 616 if (transfer.setup.bmRequestType.dataTransferDirection \
samux 1:80ab0d068708 617 == DEVICE_TO_HOST)
samux 1:80ab0d068708 618 {
samux 1:80ab0d068708 619 /* IN data stage is required */
samux 1:80ab0d068708 620 if (transfer.direction != DEVICE_TO_HOST)
samux 1:80ab0d068708 621 {
samux 1:80ab0d068708 622 return false;
samux 1:80ab0d068708 623 }
samux 1:80ab0d068708 624
samux 1:80ab0d068708 625 /* Transfer must be less than or equal to the size */
samux 1:80ab0d068708 626 /* requested by the host */
samux 1:80ab0d068708 627 if (transfer.remaining > transfer.setup.wLength)
samux 1:80ab0d068708 628 {
samux 1:80ab0d068708 629 transfer.remaining = transfer.setup.wLength;
samux 1:80ab0d068708 630 }
samux 1:80ab0d068708 631 }
samux 1:80ab0d068708 632 else
samux 1:80ab0d068708 633 {
mbed_official 25:7c72828865f3 634
samux 1:80ab0d068708 635 /* OUT data stage is required */
samux 1:80ab0d068708 636 if (transfer.direction != HOST_TO_DEVICE)
samux 1:80ab0d068708 637 {
samux 1:80ab0d068708 638 return false;
samux 1:80ab0d068708 639 }
samux 1:80ab0d068708 640
samux 1:80ab0d068708 641 /* Transfer must be equal to the size requested by the host */
samux 1:80ab0d068708 642 if (transfer.remaining != transfer.setup.wLength)
samux 1:80ab0d068708 643 {
samux 1:80ab0d068708 644 return false;
samux 1:80ab0d068708 645 }
samux 1:80ab0d068708 646 }
samux 1:80ab0d068708 647 }
samux 1:80ab0d068708 648 else
samux 1:80ab0d068708 649 {
samux 1:80ab0d068708 650 /* No data stage; transfer size must be zero */
samux 1:80ab0d068708 651 if (transfer.remaining != 0)
samux 1:80ab0d068708 652 {
samux 1:80ab0d068708 653 return false;
samux 1:80ab0d068708 654 }
samux 1:80ab0d068708 655 }
samux 1:80ab0d068708 656
samux 1:80ab0d068708 657 /* Data or status stage if applicable */
samux 1:80ab0d068708 658 if (transfer.setup.wLength>0)
samux 1:80ab0d068708 659 {
samux 1:80ab0d068708 660 if (transfer.setup.bmRequestType.dataTransferDirection \
samux 1:80ab0d068708 661 == DEVICE_TO_HOST)
samux 1:80ab0d068708 662 {
samux 1:80ab0d068708 663 /* Check if we'll need to send a zero length packet at */
samux 1:80ab0d068708 664 /* the end of this transfer */
samux 1:80ab0d068708 665 if (transfer.setup.wLength > transfer.remaining)
samux 1:80ab0d068708 666 {
samux 1:80ab0d068708 667 /* Device wishes to transfer less than host requested */
samux 1:80ab0d068708 668 if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
samux 1:80ab0d068708 669 {
samux 1:80ab0d068708 670 /* Transfer is a multiple of EP0 max packet size */
samux 1:80ab0d068708 671 transfer.zlp = true;
samux 1:80ab0d068708 672 }
samux 1:80ab0d068708 673 }
samux 1:80ab0d068708 674
samux 1:80ab0d068708 675 /* IN stage */
samux 1:80ab0d068708 676 controlIn();
samux 1:80ab0d068708 677 }
samux 1:80ab0d068708 678 else
samux 1:80ab0d068708 679 {
samux 1:80ab0d068708 680 /* OUT stage */
samux 1:80ab0d068708 681 EP0read();
samux 1:80ab0d068708 682 }
samux 1:80ab0d068708 683 }
samux 1:80ab0d068708 684 else
samux 1:80ab0d068708 685 {
samux 1:80ab0d068708 686 /* Status stage */
samux 1:80ab0d068708 687 EP0write(NULL, 0);
samux 1:80ab0d068708 688 }
samux 1:80ab0d068708 689
samux 1:80ab0d068708 690 return true;
samux 1:80ab0d068708 691 }
samux 1:80ab0d068708 692
samux 1:80ab0d068708 693 void USBDevice::busReset(void)
samux 1:80ab0d068708 694 {
samux 1:80ab0d068708 695 device.state = DEFAULT;
samux 1:80ab0d068708 696 device.configuration = 0;
samux 1:80ab0d068708 697 device.suspended = false;
samux 1:80ab0d068708 698
samux 1:80ab0d068708 699 /* Call class / vendor specific busReset function */
samux 1:80ab0d068708 700 USBCallback_busReset();
samux 1:80ab0d068708 701 }
samux 1:80ab0d068708 702
samux 1:80ab0d068708 703 void USBDevice::EP0setupCallback(void)
samux 1:80ab0d068708 704 {
samux 1:80ab0d068708 705 /* Endpoint 0 setup event */
samux 1:80ab0d068708 706 if (!controlSetup())
samux 1:80ab0d068708 707 {
samux 1:80ab0d068708 708 /* Protocol stall */
samux 1:80ab0d068708 709 EP0stall();
samux 1:80ab0d068708 710 }
samux 1:80ab0d068708 711
samux 1:80ab0d068708 712 /* Return true if an OUT data stage is expected */
samux 1:80ab0d068708 713 }
samux 1:80ab0d068708 714
samux 1:80ab0d068708 715 void USBDevice::EP0out(void)
samux 1:80ab0d068708 716 {
samux 1:80ab0d068708 717 /* Endpoint 0 OUT data event */
samux 1:80ab0d068708 718 if (!controlOut())
samux 1:80ab0d068708 719 {
samux 1:80ab0d068708 720 /* Protocol stall; this will stall both endpoints */
samux 1:80ab0d068708 721 EP0stall();
samux 1:80ab0d068708 722 }
samux 1:80ab0d068708 723 }
samux 1:80ab0d068708 724
samux 1:80ab0d068708 725 void USBDevice::EP0in(void)
samux 1:80ab0d068708 726 {
samux 1:80ab0d068708 727 #ifdef DEBUG
samux 1:80ab0d068708 728 printf("EP0IN\r\n");
samux 1:80ab0d068708 729 #endif
samux 1:80ab0d068708 730 /* Endpoint 0 IN data event */
samux 1:80ab0d068708 731 if (!controlIn())
samux 1:80ab0d068708 732 {
samux 1:80ab0d068708 733 /* Protocol stall; this will stall both endpoints */
samux 1:80ab0d068708 734 EP0stall();
samux 1:80ab0d068708 735 }
samux 1:80ab0d068708 736 }
samux 1:80ab0d068708 737
samux 1:80ab0d068708 738 bool USBDevice::configured(void)
samux 1:80ab0d068708 739 {
samux 1:80ab0d068708 740 /* Returns true if device is in the CONFIGURED state */
samux 1:80ab0d068708 741 return (device.state == CONFIGURED);
samux 1:80ab0d068708 742 }
samux 1:80ab0d068708 743
mbed_official 18:78bdbce94509 744 void USBDevice::connect(bool blocking)
samux 1:80ab0d068708 745 {
samux 1:80ab0d068708 746 /* Connect device */
samux 1:80ab0d068708 747 USBHAL::connect();
mbed_official 25:7c72828865f3 748
mbed_official 18:78bdbce94509 749 if (blocking) {
mbed_official 18:78bdbce94509 750 /* Block if not configured */
mbed_official 18:78bdbce94509 751 while (!configured());
mbed_official 18:78bdbce94509 752 }
samux 1:80ab0d068708 753 }
samux 1:80ab0d068708 754
samux 1:80ab0d068708 755 void USBDevice::disconnect(void)
samux 1:80ab0d068708 756 {
samux 1:80ab0d068708 757 /* Disconnect device */
samux 1:80ab0d068708 758 USBHAL::disconnect();
Geir Inge Tellnes 73:fa395f2d24ba 759
mbed_official 26:8ef73dd868a0 760 /* Set initial device state */
mbed_official 26:8ef73dd868a0 761 device.state = POWERED;
mbed_official 26:8ef73dd868a0 762 device.configuration = 0;
mbed_official 26:8ef73dd868a0 763 device.suspended = false;
samux 1:80ab0d068708 764 }
samux 1:80ab0d068708 765
samux 1:80ab0d068708 766 CONTROL_TRANSFER * USBDevice::getTransferPtr(void)
samux 1:80ab0d068708 767 {
samux 1:80ab0d068708 768 return &transfer;
samux 1:80ab0d068708 769 }
samux 1:80ab0d068708 770
samux 1:80ab0d068708 771 bool USBDevice::addEndpoint(uint8_t endpoint, uint32_t maxPacket)
samux 1:80ab0d068708 772 {
samux 1:80ab0d068708 773 return realiseEndpoint(endpoint, maxPacket, 0);
samux 1:80ab0d068708 774 }
samux 1:80ab0d068708 775
samux 1:80ab0d068708 776 bool USBDevice::addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket)
samux 1:80ab0d068708 777 {
samux 1:80ab0d068708 778 /* For interrupt endpoints only */
samux 1:80ab0d068708 779 return realiseEndpoint(endpoint, maxPacket, RATE_FEEDBACK_MODE);
samux 1:80ab0d068708 780 }
samux 1:80ab0d068708 781
samux 1:80ab0d068708 782 uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
samux 1:80ab0d068708 783 {
samux 1:80ab0d068708 784 /* Find a descriptor within the list of descriptors */
samux 1:80ab0d068708 785 /* following a configuration descriptor. */
samux 1:80ab0d068708 786 uint16_t wTotalLength;
samux 1:80ab0d068708 787 uint8_t *ptr;
samux 1:80ab0d068708 788
samux 1:80ab0d068708 789 if (configurationDesc() == NULL)
samux 1:80ab0d068708 790 {
samux 1:80ab0d068708 791 return NULL;
samux 1:80ab0d068708 792 }
samux 1:80ab0d068708 793
samux 1:80ab0d068708 794 /* Check this is a configuration descriptor */
samux 1:80ab0d068708 795 if ((configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 1:80ab0d068708 796 || (configurationDesc()[1] != CONFIGURATION_DESCRIPTOR))
samux 1:80ab0d068708 797 {
samux 1:80ab0d068708 798 return NULL;
samux 1:80ab0d068708 799 }
samux 1:80ab0d068708 800
samux 1:80ab0d068708 801 wTotalLength = configurationDesc()[2] | (configurationDesc()[3] << 8);
samux 1:80ab0d068708 802
samux 1:80ab0d068708 803 /* Check there are some more descriptors to follow */
samux 1:80ab0d068708 804 if (wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
samux 1:80ab0d068708 805 /* +2 is for bLength and bDescriptorType of next descriptor */
samux 1:80ab0d068708 806 {
bogdanm 11:eeb3cbbaa996 807 return NULL;
samux 1:80ab0d068708 808 }
samux 1:80ab0d068708 809
samux 1:80ab0d068708 810 /* Start at first descriptor after the configuration descriptor */
samux 1:80ab0d068708 811 ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
samux 1:80ab0d068708 812
samux 1:80ab0d068708 813 do {
samux 1:80ab0d068708 814 if (ptr[1] /* bDescriptorType */ == descriptorType)
samux 1:80ab0d068708 815 {
samux 1:80ab0d068708 816 /* Found */
samux 1:80ab0d068708 817 return ptr;
samux 1:80ab0d068708 818 }
samux 1:80ab0d068708 819
samux 1:80ab0d068708 820 /* Skip to next descriptor */
samux 1:80ab0d068708 821 ptr += ptr[0]; /* bLength */
samux 1:80ab0d068708 822 } while (ptr < (configurationDesc() + wTotalLength));
samux 1:80ab0d068708 823
samux 1:80ab0d068708 824 /* Reached end of the descriptors - not found */
samux 1:80ab0d068708 825 return NULL;
samux 1:80ab0d068708 826 }
samux 1:80ab0d068708 827
samux 1:80ab0d068708 828
samux 1:80ab0d068708 829 void USBDevice::connectStateChanged(unsigned int connected)
samux 1:80ab0d068708 830 {
samux 1:80ab0d068708 831 }
samux 1:80ab0d068708 832
samux 1:80ab0d068708 833 void USBDevice::suspendStateChanged(unsigned int suspended)
samux 1:80ab0d068708 834 {
samux 1:80ab0d068708 835 }
samux 1:80ab0d068708 836
samux 1:80ab0d068708 837
samux 1:80ab0d068708 838 USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
mbed_official 25:7c72828865f3 839 VENDOR_ID = vendor_id;
mbed_official 25:7c72828865f3 840 PRODUCT_ID = product_id;
samux 1:80ab0d068708 841 PRODUCT_RELEASE = product_release;
samux 1:80ab0d068708 842
samux 1:80ab0d068708 843 /* Set initial device state */
samux 1:80ab0d068708 844 device.state = POWERED;
samux 1:80ab0d068708 845 device.configuration = 0;
samux 1:80ab0d068708 846 device.suspended = false;
samux 1:80ab0d068708 847 };
samux 1:80ab0d068708 848
samux 1:80ab0d068708 849
samux 1:80ab0d068708 850 bool USBDevice::readStart(uint8_t endpoint, uint32_t maxSize)
samux 1:80ab0d068708 851 {
samux 1:80ab0d068708 852 return endpointRead(endpoint, maxSize) == EP_PENDING;
samux 1:80ab0d068708 853 }
samux 1:80ab0d068708 854
samux 1:80ab0d068708 855
Troels Nilsson 76:eef92651f52f 856 bool USBDevice::write(uint8_t endpoint, const uint8_t * buffer, uint32_t size, uint32_t maxSize)
samux 1:80ab0d068708 857 {
samux 1:80ab0d068708 858 EP_STATUS result;
samux 1:80ab0d068708 859
samux 1:80ab0d068708 860 if (size > maxSize)
samux 1:80ab0d068708 861 {
samux 1:80ab0d068708 862 return false;
samux 1:80ab0d068708 863 }
mbed_official 25:7c72828865f3 864
mbed_official 25:7c72828865f3 865
samux 1:80ab0d068708 866 if(!configured()) {
samux 1:80ab0d068708 867 return false;
samux 1:80ab0d068708 868 }
mbed_official 25:7c72828865f3 869
samux 1:80ab0d068708 870 /* Send report */
samux 1:80ab0d068708 871 result = endpointWrite(endpoint, buffer, size);
samux 1:80ab0d068708 872
samux 1:80ab0d068708 873 if (result != EP_PENDING)
samux 1:80ab0d068708 874 {
samux 1:80ab0d068708 875 return false;
samux 1:80ab0d068708 876 }
samux 1:80ab0d068708 877
Geir Inge Tellnes 73:fa395f2d24ba 878 #if (USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS != 0)
Geir Inge Tellnes 73:fa395f2d24ba 879 uint32_t tstart = osKernelGetTickCount();
Geir Inge Tellnes 73:fa395f2d24ba 880 #endif
samux 1:80ab0d068708 881 /* Wait for completion */
samux 1:80ab0d068708 882 do {
samux 1:80ab0d068708 883 result = endpointWriteResult(endpoint);
Geir Inge Tellnes 73:fa395f2d24ba 884
Geir Inge Tellnes 73:fa395f2d24ba 885 #if (USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS != 0)
Geir Inge Tellnes 73:fa395f2d24ba 886 /* Escape blocking write if blocking write timeout is configured */
Geir Inge Tellnes 73:fa395f2d24ba 887 if ((osKernelGetTickCount()-tstart) > (USB_DEVICE_WRITE_BLOCKING_TIMEOUT_MS)) {
Geir Inge Tellnes 74:8e2832c1046a 888 busReset();
Geir Inge Tellnes 73:fa395f2d24ba 889 }
Geir Inge Tellnes 73:fa395f2d24ba 890 #endif
samux 1:80ab0d068708 891 } while ((result == EP_PENDING) && configured());
samux 1:80ab0d068708 892
samux 1:80ab0d068708 893 return (result == EP_COMPLETED);
samux 1:80ab0d068708 894 }
samux 1:80ab0d068708 895
samux 1:80ab0d068708 896
Troels Nilsson 76:eef92651f52f 897 bool USBDevice::writeNB(uint8_t endpoint, const uint8_t * buffer, uint32_t size, uint32_t maxSize)
samux 1:80ab0d068708 898 {
samux 1:80ab0d068708 899 EP_STATUS result;
samux 1:80ab0d068708 900
samux 1:80ab0d068708 901 if (size > maxSize)
samux 1:80ab0d068708 902 {
samux 1:80ab0d068708 903 return false;
samux 1:80ab0d068708 904 }
mbed_official 25:7c72828865f3 905
samux 1:80ab0d068708 906 if(!configured()) {
samux 1:80ab0d068708 907 return false;
samux 1:80ab0d068708 908 }
samux 1:80ab0d068708 909
samux 1:80ab0d068708 910 /* Send report */
samux 1:80ab0d068708 911 result = endpointWrite(endpoint, buffer, size);
samux 1:80ab0d068708 912
samux 1:80ab0d068708 913 if (result != EP_PENDING)
samux 1:80ab0d068708 914 {
samux 1:80ab0d068708 915 return false;
samux 1:80ab0d068708 916 }
samux 1:80ab0d068708 917
samux 1:80ab0d068708 918 result = endpointWriteResult(endpoint);
samux 1:80ab0d068708 919
samux 1:80ab0d068708 920 return (result == EP_COMPLETED);
samux 1:80ab0d068708 921 }
samux 1:80ab0d068708 922
samux 1:80ab0d068708 923
samux 1:80ab0d068708 924
samux 1:80ab0d068708 925 bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
samux 1:80ab0d068708 926 {
samux 1:80ab0d068708 927 EP_STATUS result;
mbed_official 25:7c72828865f3 928
samux 1:80ab0d068708 929 if(!configured()) {
samux 1:80ab0d068708 930 return false;
samux 1:80ab0d068708 931 }
samux 1:80ab0d068708 932
samux 1:80ab0d068708 933 /* Wait for completion */
samux 1:80ab0d068708 934 do {
samux 1:80ab0d068708 935 result = endpointReadResult(endpoint, buffer, size);
samux 1:80ab0d068708 936 } while ((result == EP_PENDING) && configured());
samux 1:80ab0d068708 937
samux 1:80ab0d068708 938 return (result == EP_COMPLETED);
samux 1:80ab0d068708 939 }
samux 1:80ab0d068708 940
samux 1:80ab0d068708 941
samux 1:80ab0d068708 942 bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
samux 1:80ab0d068708 943 {
samux 1:80ab0d068708 944 EP_STATUS result;
mbed_official 25:7c72828865f3 945
samux 1:80ab0d068708 946 if(!configured()) {
samux 1:80ab0d068708 947 return false;
samux 1:80ab0d068708 948 }
samux 1:80ab0d068708 949
samux 1:80ab0d068708 950 result = endpointReadResult(endpoint, buffer, size);
mbed_official 25:7c72828865f3 951
samux 1:80ab0d068708 952 return (result == EP_COMPLETED);
samux 1:80ab0d068708 953 }
samux 1:80ab0d068708 954
samux 1:80ab0d068708 955
samux 1:80ab0d068708 956
samux 1:80ab0d068708 957 uint8_t * USBDevice::deviceDesc() {
samux 1:80ab0d068708 958 static uint8_t deviceDescriptor[] = {
samux 1:80ab0d068708 959 DEVICE_DESCRIPTOR_LENGTH, /* bLength */
samux 1:80ab0d068708 960 DEVICE_DESCRIPTOR, /* bDescriptorType */
samux 1:80ab0d068708 961 LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
samux 1:80ab0d068708 962 MSB(USB_VERSION_2_0), /* bcdUSB (MSB) */
samux 1:80ab0d068708 963 0x00, /* bDeviceClass */
samux 1:80ab0d068708 964 0x00, /* bDeviceSubClass */
samux 1:80ab0d068708 965 0x00, /* bDeviceprotocol */
samux 1:80ab0d068708 966 MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
bogdanm 11:eeb3cbbaa996 967 (uint8_t)(LSB(VENDOR_ID)), /* idVendor (LSB) */
bogdanm 11:eeb3cbbaa996 968 (uint8_t)(MSB(VENDOR_ID)), /* idVendor (MSB) */
bogdanm 11:eeb3cbbaa996 969 (uint8_t)(LSB(PRODUCT_ID)), /* idProduct (LSB) */
bogdanm 11:eeb3cbbaa996 970 (uint8_t)(MSB(PRODUCT_ID)), /* idProduct (MSB) */
bogdanm 11:eeb3cbbaa996 971 (uint8_t)(LSB(PRODUCT_RELEASE)), /* bcdDevice (LSB) */
bogdanm 11:eeb3cbbaa996 972 (uint8_t)(MSB(PRODUCT_RELEASE)), /* bcdDevice (MSB) */
samux 1:80ab0d068708 973 STRING_OFFSET_IMANUFACTURER, /* iManufacturer */
samux 1:80ab0d068708 974 STRING_OFFSET_IPRODUCT, /* iProduct */
samux 1:80ab0d068708 975 STRING_OFFSET_ISERIAL, /* iSerialNumber */
samux 1:80ab0d068708 976 0x01 /* bNumConfigurations */
samux 1:80ab0d068708 977 };
samux 1:80ab0d068708 978 return deviceDescriptor;
samux 1:80ab0d068708 979 }
samux 1:80ab0d068708 980
samux 1:80ab0d068708 981 uint8_t * USBDevice::stringLangidDesc() {
samux 1:80ab0d068708 982 static uint8_t stringLangidDescriptor[] = {
samux 1:80ab0d068708 983 0x04, /*bLength*/
samux 1:80ab0d068708 984 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
mbed_official 17:bbd6dac92961 985 0x09,0x04, /*bString Lang ID - 0x0409 - English*/
samux 1:80ab0d068708 986 };
samux 1:80ab0d068708 987 return stringLangidDescriptor;
samux 1:80ab0d068708 988 }
samux 1:80ab0d068708 989
samux 1:80ab0d068708 990 uint8_t * USBDevice::stringImanufacturerDesc() {
samux 1:80ab0d068708 991 static uint8_t stringImanufacturerDescriptor[] = {
samux 1:80ab0d068708 992 0x12, /*bLength*/
samux 1:80ab0d068708 993 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
samux 1:80ab0d068708 994 'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
samux 1:80ab0d068708 995 };
samux 1:80ab0d068708 996 return stringImanufacturerDescriptor;
samux 1:80ab0d068708 997 }
samux 1:80ab0d068708 998
samux 1:80ab0d068708 999 uint8_t * USBDevice::stringIserialDesc() {
samux 1:80ab0d068708 1000 static uint8_t stringIserialDescriptor[] = {
samux 1:80ab0d068708 1001 0x16, /*bLength*/
samux 1:80ab0d068708 1002 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
samux 1:80ab0d068708 1003 '0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/
samux 1:80ab0d068708 1004 };
samux 1:80ab0d068708 1005 return stringIserialDescriptor;
samux 1:80ab0d068708 1006 }
samux 1:80ab0d068708 1007
samux 1:80ab0d068708 1008 uint8_t * USBDevice::stringIConfigurationDesc() {
samux 1:80ab0d068708 1009 static uint8_t stringIconfigurationDescriptor[] = {
samux 1:80ab0d068708 1010 0x06, /*bLength*/
samux 1:80ab0d068708 1011 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
samux 1:80ab0d068708 1012 '0',0,'1',0, /*bString iConfiguration - 01*/
samux 1:80ab0d068708 1013 };
samux 1:80ab0d068708 1014 return stringIconfigurationDescriptor;
samux 1:80ab0d068708 1015 }
samux 1:80ab0d068708 1016
samux 1:80ab0d068708 1017 uint8_t * USBDevice::stringIinterfaceDesc() {
samux 1:80ab0d068708 1018 static uint8_t stringIinterfaceDescriptor[] = {
samux 1:80ab0d068708 1019 0x08, /*bLength*/
samux 1:80ab0d068708 1020 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
samux 1:80ab0d068708 1021 'U',0,'S',0,'B',0, /*bString iInterface - USB*/
samux 1:80ab0d068708 1022 };
samux 1:80ab0d068708 1023 return stringIinterfaceDescriptor;
samux 1:80ab0d068708 1024 }
samux 1:80ab0d068708 1025
samux 1:80ab0d068708 1026 uint8_t * USBDevice::stringIproductDesc() {
samux 1:80ab0d068708 1027 static uint8_t stringIproductDescriptor[] = {
samux 1:80ab0d068708 1028 0x16, /*bLength*/
samux 1:80ab0d068708 1029 STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
samux 1:80ab0d068708 1030 'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/
samux 1:80ab0d068708 1031 };
samux 1:80ab0d068708 1032 return stringIproductDescriptor;
samux 1:80ab0d068708 1033 }