max4146x_comp

Dependencies:   MAX14690

Committer:
sdivarci
Date:
Sun Oct 25 20:10:02 2020 +0000
Revision:
0:0061165683ee
sdivarci

Who changed what in which revision?

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