I changed one line of code in the file with path name: USBDeviceHT/targets/TARGET_Maxim

Fork of USBDeviceHT by Helmut Tschemernjak

Committer:
Helmut64
Date:
Mon Feb 05 10:22:57 2018 +0000
Revision:
0:a3ea811f80f2
Child:
2:195554780c9b
Inital checkin after copied from mbed.

Who changed what in which revision?

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