Control the wondrous spinning-frog game of Zuma's Revenge with a rotating chair and an Airzooka. Maps compass rotation, flex sensor and push button input to USB actions to control Zuma's Revenge (http://www.popcap.com/games/zumas-revenge/online)

Dependencies:   LSM303DLHC mbed

Note that content for USB HID and USB Device is actually from the USBDevice mbed library. However, we made a couple of small changes to this library (allowing USB clicks at a particular location) that required us to break it off from the main project if we wanted to publish without pushing upstream.

Committer:
andrewhead
Date:
Mon Sep 29 01:12:20 2014 +0000
Revision:
0:4df415dde990
Initial Commit.

Who changed what in which revision?

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