works!

Dependencies:   mbed

Committer:
kchhouk
Date:
Fri Feb 21 21:03:41 2020 +0000
Revision:
2:5e5cdc3504fe
Parent:
1:6e512faaa17c
Added the functionality of scanf

Who changed what in which revision?

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