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