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