CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 13:16:14 2013 +0000
Revision:
2:540f6e142d59
Moved to single package

Who changed what in which revision?

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