A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Sun Feb 24 14:52:33 2019 +0100
Revision:
8:961423d1da74
Parent:
5:fb690c44c0b1
Added sleep manager support to avoids sleeps while a USB CDC
connection is active

Who changed what in which revision?

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