Fork of the official USBDevice library

Fork of USBDevice by mbed official

Committer:
screamer
Date:
Fri Apr 28 17:01:10 2017 +0000
Branch:
device-files
Revision:
76:f0fd8d911b24
Parent:
73:8d28a0cb7b43
Changed the layout of USBDevice implementation for various targets to match mbed-os/targets. This also reduces the amount of files being compiled as USBDevice code for other targets is not compiled.

Who changed what in which revision?

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