library

Dependents:   USB_CDC_MSD_Hello

Committer:
sherckuith
Date:
Fri Aug 24 02:01:51 2012 +0000
Revision:
0:d5bb9a9c3e24
[mbed] converted /USB_CDC_MSD_Hello/USBDevice

Who changed what in which revision?

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