This program operates a pH meter and requires an Excel spreadsheet template available at www.kissinstrments.com

Dependencies:   mbed

Committer:
KISScientific
Date:
Fri Jul 22 00:03:25 2016 +0000
Revision:
0:f6b418db17d2
pH-V12 version 1

Who changed what in which revision?

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