Base station firmware

Committer:
Perijah
Date:
Tue May 24 13:16:55 2016 +0000
Revision:
0:ecc3925d3f8c
Base station firmware

Who changed what in which revision?

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