USBMSD test for GR-PEACH

Dependencies:   USBDevice USBMSD_SD mbed

Fork of USBMSD_SD_HelloWorld_Mbed by Samuel Mokrani

Committer:
samux
Date:
Wed Nov 16 17:17:42 2011 +0000
Revision:
11:a26e7b7a1221
GOOD COMMIT: msd and hid work even on MAC...

Who changed what in which revision?

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