Lucas Lim / Mbed 2 deprecated HSP_Temperature_Barometer_CS3237

Dependencies:   mbed

Committer:
lucaslwl
Date:
Mon Aug 26 08:11:41 2019 +0000
Revision:
22:5c07298d3383
add library folder

Who changed what in which revision?

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