X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

Committer:
okini3939
Date:
Wed Jun 05 04:54:37 2019 +0000
Revision:
1:0dac72ab5910
sample

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 1:0dac72ab5910 1 /* mbed USBHost Library
okini3939 1:0dac72ab5910 2 * Copyright (c) 2006-2013 ARM Limited
okini3939 1:0dac72ab5910 3 *
okini3939 1:0dac72ab5910 4 * Licensed under the Apache License, Version 2.0 (the "License");
okini3939 1:0dac72ab5910 5 * you may not use this file except in compliance with the License.
okini3939 1:0dac72ab5910 6 * You may obtain a copy of the License at
okini3939 1:0dac72ab5910 7 *
okini3939 1:0dac72ab5910 8 * http://www.apache.org/licenses/LICENSE-2.0
okini3939 1:0dac72ab5910 9 *
okini3939 1:0dac72ab5910 10 * Unless required by applicable law or agreed to in writing, software
okini3939 1:0dac72ab5910 11 * distributed under the License is distributed on an "AS IS" BASIS,
okini3939 1:0dac72ab5910 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
okini3939 1:0dac72ab5910 13 * See the License for the specific language governing permissions and
okini3939 1:0dac72ab5910 14 * limitations under the License.
okini3939 1:0dac72ab5910 15 */
okini3939 1:0dac72ab5910 16
okini3939 1:0dac72ab5910 17
okini3939 1:0dac72ab5910 18 #include "USBHost.h"
okini3939 1:0dac72ab5910 19 #include "USBHostHub.h"
okini3939 1:0dac72ab5910 20
okini3939 1:0dac72ab5910 21 USBHost * USBHost::instHost = NULL;
okini3939 1:0dac72ab5910 22
okini3939 1:0dac72ab5910 23 #define DEVICE_CONNECTED_EVENT (1 << 0)
okini3939 1:0dac72ab5910 24 #define DEVICE_DISCONNECTED_EVENT (1 << 1)
okini3939 1:0dac72ab5910 25 #define TD_PROCESSED_EVENT (1 << 2)
okini3939 1:0dac72ab5910 26
okini3939 1:0dac72ab5910 27 #define MAX_TRY_ENUMERATE_HUB 3
okini3939 1:0dac72ab5910 28
okini3939 1:0dac72ab5910 29 #define MIN(a, b) ((a > b) ? b : a)
okini3939 1:0dac72ab5910 30
okini3939 1:0dac72ab5910 31 /**
okini3939 1:0dac72ab5910 32 * How interrupts are processed:
okini3939 1:0dac72ab5910 33 * - new device connected:
okini3939 1:0dac72ab5910 34 * - a message is queued in queue_usb_event with the id DEVICE_CONNECTED_EVENT
okini3939 1:0dac72ab5910 35 * - when the usb_thread receives the event, it:
okini3939 1:0dac72ab5910 36 * - resets the device
okini3939 1:0dac72ab5910 37 * - reads the device descriptor
okini3939 1:0dac72ab5910 38 * - sets the address of the device
okini3939 1:0dac72ab5910 39 * - if it is a hub, enumerates it
okini3939 1:0dac72ab5910 40 * - device disconnected:
okini3939 1:0dac72ab5910 41 * - a message is queued in queue_usb_event with the id DEVICE_DISCONNECTED_EVENT
okini3939 1:0dac72ab5910 42 * - when the usb_thread receives the event, it:
okini3939 1:0dac72ab5910 43 * - free the device and all its children (hub)
okini3939 1:0dac72ab5910 44 * - td processed
okini3939 1:0dac72ab5910 45 * - a message is queued in queue_usb_event with the id TD_PROCESSED_EVENT
okini3939 1:0dac72ab5910 46 * - when the usb_thread receives the event, it:
okini3939 1:0dac72ab5910 47 * - call the callback attached to the endpoint where the td is attached
okini3939 1:0dac72ab5910 48 */
okini3939 1:0dac72ab5910 49 void USBHost::usb_process()
okini3939 1:0dac72ab5910 50 {
okini3939 1:0dac72ab5910 51
okini3939 1:0dac72ab5910 52 bool controlListState;
okini3939 1:0dac72ab5910 53 bool bulkListState;
okini3939 1:0dac72ab5910 54 bool interruptListState;
okini3939 1:0dac72ab5910 55 USBEndpoint * ep;
okini3939 1:0dac72ab5910 56 uint8_t i, j, res, timeout_set_addr = 10;
okini3939 1:0dac72ab5910 57 uint8_t buf[8];
okini3939 1:0dac72ab5910 58 bool too_many_hub;
okini3939 1:0dac72ab5910 59 int idx;
okini3939 1:0dac72ab5910 60
okini3939 1:0dac72ab5910 61 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 62 uint8_t * buf_transfer;
okini3939 1:0dac72ab5910 63 #endif
okini3939 1:0dac72ab5910 64
okini3939 1:0dac72ab5910 65 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 66 uint8_t k;
okini3939 1:0dac72ab5910 67 #endif
okini3939 1:0dac72ab5910 68
okini3939 1:0dac72ab5910 69 while(1) {
okini3939 1:0dac72ab5910 70 osEvent evt = mail_usb_event.get();
okini3939 1:0dac72ab5910 71
okini3939 1:0dac72ab5910 72 if (evt.status == osEventMail) {
okini3939 1:0dac72ab5910 73
okini3939 1:0dac72ab5910 74 message_t * usb_msg = (message_t*)evt.value.p;
okini3939 1:0dac72ab5910 75
okini3939 1:0dac72ab5910 76 switch (usb_msg->event_id) {
okini3939 1:0dac72ab5910 77
okini3939 1:0dac72ab5910 78 // a new device has been connected
okini3939 1:0dac72ab5910 79 case DEVICE_CONNECTED_EVENT:
okini3939 1:0dac72ab5910 80 too_many_hub = false;
okini3939 1:0dac72ab5910 81 buf[4] = 0;
okini3939 1:0dac72ab5910 82
okini3939 1:0dac72ab5910 83 do {
okini3939 1:0dac72ab5910 84 Lock lock(this);
okini3939 1:0dac72ab5910 85 bool hub_unplugged = true;
okini3939 1:0dac72ab5910 86
okini3939 1:0dac72ab5910 87 int idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent));
okini3939 1:0dac72ab5910 88 /* check that hub is connected to root port */
okini3939 1:0dac72ab5910 89 if (usb_msg->hub_parent) {
okini3939 1:0dac72ab5910 90 /* a hub device must be present */
okini3939 1:0dac72ab5910 91 for (k = 0; k < MAX_HUB_NB; k++) {
okini3939 1:0dac72ab5910 92 if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) {
okini3939 1:0dac72ab5910 93 hub_unplugged=false;
okini3939 1:0dac72ab5910 94 }
okini3939 1:0dac72ab5910 95 }
okini3939 1:0dac72ab5910 96 } else {
okini3939 1:0dac72ab5910 97 hub_unplugged = false;
okini3939 1:0dac72ab5910 98 }
okini3939 1:0dac72ab5910 99
okini3939 1:0dac72ab5910 100 if (((idx!=-1) && deviceInUse[idx] ) || ((idx == -1) && hub_unplugged)) {
okini3939 1:0dac72ab5910 101 break;
okini3939 1:0dac72ab5910 102 }
okini3939 1:0dac72ab5910 103
okini3939 1:0dac72ab5910 104 for (i =0 ; i < MAX_DEVICE_CONNECTED; i++) {
okini3939 1:0dac72ab5910 105 if (!deviceInUse[i]) {
okini3939 1:0dac72ab5910 106 USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]);
okini3939 1:0dac72ab5910 107 devices[i].init(usb_msg->hub, usb_msg->port, usb_msg->lowSpeed);
okini3939 1:0dac72ab5910 108 deviceReset[i] = false;
okini3939 1:0dac72ab5910 109 deviceInited[i] = true;
okini3939 1:0dac72ab5910 110 break;
okini3939 1:0dac72ab5910 111 }
okini3939 1:0dac72ab5910 112 }
okini3939 1:0dac72ab5910 113
okini3939 1:0dac72ab5910 114 if (i == MAX_DEVICE_CONNECTED) {
okini3939 1:0dac72ab5910 115 USB_ERR("Too many device connected!!\r\n");
okini3939 1:0dac72ab5910 116 continue;
okini3939 1:0dac72ab5910 117 }
okini3939 1:0dac72ab5910 118
okini3939 1:0dac72ab5910 119 if (!controlEndpointAllocated) {
okini3939 1:0dac72ab5910 120 control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00);
okini3939 1:0dac72ab5910 121 addEndpoint(NULL, 0, (USBEndpoint*)control);
okini3939 1:0dac72ab5910 122 controlEndpointAllocated = true;
okini3939 1:0dac72ab5910 123 }
okini3939 1:0dac72ab5910 124
okini3939 1:0dac72ab5910 125 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 126 if (usb_msg->hub_parent) {
okini3939 1:0dac72ab5910 127 devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent));
okini3939 1:0dac72ab5910 128 }
okini3939 1:0dac72ab5910 129 #endif
okini3939 1:0dac72ab5910 130
okini3939 1:0dac72ab5910 131 for (j = 0; j < timeout_set_addr; j++) {
okini3939 1:0dac72ab5910 132
okini3939 1:0dac72ab5910 133 resetDevice(&devices[i]);
okini3939 1:0dac72ab5910 134
okini3939 1:0dac72ab5910 135 // set size of control endpoint
okini3939 1:0dac72ab5910 136 devices[i].setSizeControlEndpoint(8);
okini3939 1:0dac72ab5910 137
okini3939 1:0dac72ab5910 138 devices[i].activeAddress(false);
okini3939 1:0dac72ab5910 139
okini3939 1:0dac72ab5910 140 // get first 8 bit of device descriptor
okini3939 1:0dac72ab5910 141 // and check if we deal with a hub
okini3939 1:0dac72ab5910 142 USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]);
okini3939 1:0dac72ab5910 143 res = getDeviceDescriptor(&devices[i], buf, 8);
okini3939 1:0dac72ab5910 144
okini3939 1:0dac72ab5910 145 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 146 USB_ERR("usb_thread could not read dev descr");
okini3939 1:0dac72ab5910 147 continue;
okini3939 1:0dac72ab5910 148 }
okini3939 1:0dac72ab5910 149
okini3939 1:0dac72ab5910 150 // set size of control endpoint
okini3939 1:0dac72ab5910 151 devices[i].setSizeControlEndpoint(buf[7]);
okini3939 1:0dac72ab5910 152
okini3939 1:0dac72ab5910 153 // second step: set an address to the device
okini3939 1:0dac72ab5910 154 res = setAddress(&devices[i], devices[i].getAddress());
okini3939 1:0dac72ab5910 155
okini3939 1:0dac72ab5910 156 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 157 USB_ERR("SET ADDR FAILED");
okini3939 1:0dac72ab5910 158 continue;
okini3939 1:0dac72ab5910 159 }
okini3939 1:0dac72ab5910 160 devices[i].activeAddress(true);
okini3939 1:0dac72ab5910 161 USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress());
okini3939 1:0dac72ab5910 162
okini3939 1:0dac72ab5910 163 // try to read again the device descriptor to check if the device
okini3939 1:0dac72ab5910 164 // answers to its new address
okini3939 1:0dac72ab5910 165 res = getDeviceDescriptor(&devices[i], buf, 8);
okini3939 1:0dac72ab5910 166
okini3939 1:0dac72ab5910 167 if (res == USB_TYPE_OK) {
okini3939 1:0dac72ab5910 168 break;
okini3939 1:0dac72ab5910 169 }
okini3939 1:0dac72ab5910 170
okini3939 1:0dac72ab5910 171 Thread::wait(100);
okini3939 1:0dac72ab5910 172 }
okini3939 1:0dac72ab5910 173
okini3939 1:0dac72ab5910 174 USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port);
okini3939 1:0dac72ab5910 175
okini3939 1:0dac72ab5910 176 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 177 if (buf[4] == HUB_CLASS) {
okini3939 1:0dac72ab5910 178 for (k = 0; k < MAX_HUB_NB; k++) {
okini3939 1:0dac72ab5910 179 if (hub_in_use[k] == false) {
okini3939 1:0dac72ab5910 180 for (uint8_t j = 0; j < MAX_TRY_ENUMERATE_HUB; j++) {
okini3939 1:0dac72ab5910 181 if (hubs[k].connect(&devices[i])) {
okini3939 1:0dac72ab5910 182 devices[i].hub = &hubs[k];
okini3939 1:0dac72ab5910 183 hub_in_use[k] = true;
okini3939 1:0dac72ab5910 184 break;
okini3939 1:0dac72ab5910 185 }
okini3939 1:0dac72ab5910 186 }
okini3939 1:0dac72ab5910 187 if (hub_in_use[k] == true) {
okini3939 1:0dac72ab5910 188 break;
okini3939 1:0dac72ab5910 189 }
okini3939 1:0dac72ab5910 190 }
okini3939 1:0dac72ab5910 191 }
okini3939 1:0dac72ab5910 192
okini3939 1:0dac72ab5910 193 if (k == MAX_HUB_NB) {
okini3939 1:0dac72ab5910 194 USB_ERR("Too many hubs connected!!\r\n");
okini3939 1:0dac72ab5910 195 too_many_hub = true;
okini3939 1:0dac72ab5910 196 }
okini3939 1:0dac72ab5910 197 }
okini3939 1:0dac72ab5910 198
okini3939 1:0dac72ab5910 199 if (usb_msg->hub_parent) {
okini3939 1:0dac72ab5910 200 ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]);
okini3939 1:0dac72ab5910 201 }
okini3939 1:0dac72ab5910 202 #endif
okini3939 1:0dac72ab5910 203
okini3939 1:0dac72ab5910 204 if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) {
okini3939 1:0dac72ab5910 205 deviceInUse[i] = true;
okini3939 1:0dac72ab5910 206 }
okini3939 1:0dac72ab5910 207
okini3939 1:0dac72ab5910 208 } while(0);
okini3939 1:0dac72ab5910 209
okini3939 1:0dac72ab5910 210 break;
okini3939 1:0dac72ab5910 211
okini3939 1:0dac72ab5910 212 // a device has been disconnected
okini3939 1:0dac72ab5910 213 case DEVICE_DISCONNECTED_EVENT:
okini3939 1:0dac72ab5910 214
okini3939 1:0dac72ab5910 215 do {
okini3939 1:0dac72ab5910 216 Lock lock(this);
okini3939 1:0dac72ab5910 217
okini3939 1:0dac72ab5910 218 controlListState = disableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 219 bulkListState = disableList(BULK_ENDPOINT);
okini3939 1:0dac72ab5910 220 interruptListState = disableList(INTERRUPT_ENDPOINT);
okini3939 1:0dac72ab5910 221
okini3939 1:0dac72ab5910 222 idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent));
okini3939 1:0dac72ab5910 223 if (idx != -1) {
okini3939 1:0dac72ab5910 224 freeDevice((USBDeviceConnected*)&devices[idx]);
okini3939 1:0dac72ab5910 225 deviceInited[idx]=false;
okini3939 1:0dac72ab5910 226 }
okini3939 1:0dac72ab5910 227
okini3939 1:0dac72ab5910 228 if (controlListState) {
okini3939 1:0dac72ab5910 229 enableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 230 }
okini3939 1:0dac72ab5910 231 if (bulkListState) {
okini3939 1:0dac72ab5910 232 enableList(BULK_ENDPOINT);
okini3939 1:0dac72ab5910 233 }
okini3939 1:0dac72ab5910 234 if (interruptListState) {
okini3939 1:0dac72ab5910 235 enableList(INTERRUPT_ENDPOINT);
okini3939 1:0dac72ab5910 236 }
okini3939 1:0dac72ab5910 237
okini3939 1:0dac72ab5910 238 } while(0);
okini3939 1:0dac72ab5910 239
okini3939 1:0dac72ab5910 240 break;
okini3939 1:0dac72ab5910 241
okini3939 1:0dac72ab5910 242 // a td has been processed
okini3939 1:0dac72ab5910 243 // call callback on the ed associated to the td
okini3939 1:0dac72ab5910 244 // we are not in ISR -> users can use printf in their callback method
okini3939 1:0dac72ab5910 245 case TD_PROCESSED_EVENT:
okini3939 1:0dac72ab5910 246 ep = (USBEndpoint *) ((HCTD *)usb_msg->td_addr)->ep;
okini3939 1:0dac72ab5910 247 if (usb_msg->td_state == USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 248 USB_DBG_EVENT("call callback on td %p [ep: %p state: %s - dev: %p - %s]", usb_msg->td_addr, ep, ep->getStateString(), ep->dev, ep->dev->getName(ep->getIntfNb()));
okini3939 1:0dac72ab5910 249
okini3939 1:0dac72ab5910 250 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 251 if (ep->getDir() == IN) {
okini3939 1:0dac72ab5910 252 buf_transfer = ep->getBufStart();
okini3939 1:0dac72ab5910 253 printf("READ SUCCESS [%d bytes transferred - td: 0x%08X] on ep: [%p - addr: %02X]: ", ep->getLengthTransferred(), usb_msg->td_addr, ep, ep->getAddress());
okini3939 1:0dac72ab5910 254 for (int i = 0; i < ep->getLengthTransferred(); i++) {
okini3939 1:0dac72ab5910 255 printf("%02X ", buf_transfer[i]);
okini3939 1:0dac72ab5910 256 }
okini3939 1:0dac72ab5910 257 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 258 }
okini3939 1:0dac72ab5910 259 #endif
okini3939 1:0dac72ab5910 260 ep->call();
okini3939 1:0dac72ab5910 261 } else {
okini3939 1:0dac72ab5910 262 idx = findDevice(ep->dev);
okini3939 1:0dac72ab5910 263 if (idx != -1) {
okini3939 1:0dac72ab5910 264 if (deviceInUse[idx]) {
okini3939 1:0dac72ab5910 265 USB_WARN("td %p processed but not in idle state: %s [ep: %p - dev: %p - %s]", usb_msg->td_addr, ep->getStateString(), ep, ep->dev, ep->dev->getName(ep->getIntfNb()));
okini3939 1:0dac72ab5910 266 ep->setState(USB_TYPE_IDLE);
okini3939 1:0dac72ab5910 267 /* as error, on interrupt endpoint can be
okini3939 1:0dac72ab5910 268 * reported, call the call back registered ,
okini3939 1:0dac72ab5910 269 * if device still in use, this call back
okini3939 1:0dac72ab5910 270 * shall ask again an interrupt request.
okini3939 1:0dac72ab5910 271 */
okini3939 1:0dac72ab5910 272 ep->call();
okini3939 1:0dac72ab5910 273 }
okini3939 1:0dac72ab5910 274 }
okini3939 1:0dac72ab5910 275 }
okini3939 1:0dac72ab5910 276 break;
okini3939 1:0dac72ab5910 277 }
okini3939 1:0dac72ab5910 278
okini3939 1:0dac72ab5910 279 mail_usb_event.free(usb_msg);
okini3939 1:0dac72ab5910 280 }
okini3939 1:0dac72ab5910 281 }
okini3939 1:0dac72ab5910 282 }
okini3939 1:0dac72ab5910 283
okini3939 1:0dac72ab5910 284 USBHost::USBHost() : usbThread(osPriorityNormal, USB_THREAD_STACK)
okini3939 1:0dac72ab5910 285 {
okini3939 1:0dac72ab5910 286 #ifndef USBHOST_OTHER
okini3939 1:0dac72ab5910 287 headControlEndpoint = NULL;
okini3939 1:0dac72ab5910 288 headBulkEndpoint = NULL;
okini3939 1:0dac72ab5910 289 headInterruptEndpoint = NULL;
okini3939 1:0dac72ab5910 290 tailControlEndpoint = NULL;
okini3939 1:0dac72ab5910 291 tailBulkEndpoint = NULL;
okini3939 1:0dac72ab5910 292 tailInterruptEndpoint = NULL;
okini3939 1:0dac72ab5910 293 #endif
okini3939 1:0dac72ab5910 294 lenReportDescr = 0;
okini3939 1:0dac72ab5910 295
okini3939 1:0dac72ab5910 296 controlEndpointAllocated = false;
okini3939 1:0dac72ab5910 297
okini3939 1:0dac72ab5910 298 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
okini3939 1:0dac72ab5910 299 deviceInUse[i] = false;
okini3939 1:0dac72ab5910 300 devices[i].setAddress(i + 1);
okini3939 1:0dac72ab5910 301 deviceReset[i] = false;
okini3939 1:0dac72ab5910 302 deviceInited[i] = false;
okini3939 1:0dac72ab5910 303 for (uint8_t j = 0; j < MAX_INTF; j++) {
okini3939 1:0dac72ab5910 304 deviceAttachedDriver[i][j] = false;
okini3939 1:0dac72ab5910 305 }
okini3939 1:0dac72ab5910 306 }
okini3939 1:0dac72ab5910 307
okini3939 1:0dac72ab5910 308 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 309 for (uint8_t i = 0; i < MAX_HUB_NB; i++) {
okini3939 1:0dac72ab5910 310 hubs[i].setHost(this);
okini3939 1:0dac72ab5910 311 hub_in_use[i] = false;
okini3939 1:0dac72ab5910 312 }
okini3939 1:0dac72ab5910 313 #endif
okini3939 1:0dac72ab5910 314
okini3939 1:0dac72ab5910 315 usbThread.start(this, &USBHost::usb_process);
okini3939 1:0dac72ab5910 316 }
okini3939 1:0dac72ab5910 317
okini3939 1:0dac72ab5910 318 USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost)
okini3939 1:0dac72ab5910 319 {
okini3939 1:0dac72ab5910 320 m_pHost->usb_mutex.lock();
okini3939 1:0dac72ab5910 321 }
okini3939 1:0dac72ab5910 322
okini3939 1:0dac72ab5910 323 USBHost::Lock::~Lock()
okini3939 1:0dac72ab5910 324 {
okini3939 1:0dac72ab5910 325 m_pHost->usb_mutex.unlock();
okini3939 1:0dac72ab5910 326 }
okini3939 1:0dac72ab5910 327
okini3939 1:0dac72ab5910 328 void USBHost::transferCompleted(volatile uint32_t addr)
okini3939 1:0dac72ab5910 329 {
okini3939 1:0dac72ab5910 330 uint8_t state;
okini3939 1:0dac72ab5910 331
okini3939 1:0dac72ab5910 332 if(addr == 0) {
okini3939 1:0dac72ab5910 333 return;
okini3939 1:0dac72ab5910 334 }
okini3939 1:0dac72ab5910 335
okini3939 1:0dac72ab5910 336 volatile HCTD* tdList = NULL;
okini3939 1:0dac72ab5910 337
okini3939 1:0dac72ab5910 338 //First we must reverse the list order and dequeue each TD
okini3939 1:0dac72ab5910 339 do {
okini3939 1:0dac72ab5910 340 volatile HCTD* td = (volatile HCTD*)addr;
okini3939 1:0dac72ab5910 341 addr = (uint32_t)td->nextTD; //Dequeue from physical list
okini3939 1:0dac72ab5910 342 td->nextTD = (hcTd*)tdList; //Enqueue into reversed list
okini3939 1:0dac72ab5910 343 tdList = td;
okini3939 1:0dac72ab5910 344 } while(addr);
okini3939 1:0dac72ab5910 345
okini3939 1:0dac72ab5910 346 while(tdList != NULL) {
okini3939 1:0dac72ab5910 347 volatile HCTD* td = tdList;
okini3939 1:0dac72ab5910 348 tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below
okini3939 1:0dac72ab5910 349 if (td->ep != NULL) {
okini3939 1:0dac72ab5910 350 USBEndpoint * ep = (USBEndpoint *)(td->ep);
okini3939 1:0dac72ab5910 351
okini3939 1:0dac72ab5910 352 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 353 state = ((HCTD *)td)->state;
okini3939 1:0dac72ab5910 354 if (state == USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 355 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart());
okini3939 1:0dac72ab5910 356 }
okini3939 1:0dac72ab5910 357
okini3939 1:0dac72ab5910 358 #else
okini3939 1:0dac72ab5910 359 if (((HCTD *)td)->control >> 28) {
okini3939 1:0dac72ab5910 360 state = ((HCTD *)td)->control >> 28;
okini3939 1:0dac72ab5910 361 } else {
okini3939 1:0dac72ab5910 362 if (td->currBufPtr) {
okini3939 1:0dac72ab5910 363 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart());
okini3939 1:0dac72ab5910 364 }
okini3939 1:0dac72ab5910 365 state = 16 /*USB_TYPE_IDLE*/;
okini3939 1:0dac72ab5910 366 }
okini3939 1:0dac72ab5910 367 #endif
okini3939 1:0dac72ab5910 368 if (state == USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 369 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart());
okini3939 1:0dac72ab5910 370 }
okini3939 1:0dac72ab5910 371
okini3939 1:0dac72ab5910 372 ep->unqueueTransfer(td);
okini3939 1:0dac72ab5910 373
okini3939 1:0dac72ab5910 374 if (ep->getType() != CONTROL_ENDPOINT) {
okini3939 1:0dac72ab5910 375 // callback on the processed td will be called from the usb_thread (not in ISR)
okini3939 1:0dac72ab5910 376 message_t * usb_msg = mail_usb_event.alloc();
okini3939 1:0dac72ab5910 377 usb_msg->event_id = TD_PROCESSED_EVENT;
okini3939 1:0dac72ab5910 378 usb_msg->td_addr = (void *)td;
okini3939 1:0dac72ab5910 379 usb_msg->td_state = state;
okini3939 1:0dac72ab5910 380 mail_usb_event.put(usb_msg);
okini3939 1:0dac72ab5910 381 }
okini3939 1:0dac72ab5910 382 ep->setState((USB_TYPE)state);
okini3939 1:0dac72ab5910 383 ep->ep_queue.put((uint8_t*)1);
okini3939 1:0dac72ab5910 384 }
okini3939 1:0dac72ab5910 385 }
okini3939 1:0dac72ab5910 386 }
okini3939 1:0dac72ab5910 387
okini3939 1:0dac72ab5910 388 USBHost * USBHost::getHostInst()
okini3939 1:0dac72ab5910 389 {
okini3939 1:0dac72ab5910 390 if (instHost == NULL) {
okini3939 1:0dac72ab5910 391 instHost = new USBHost();
okini3939 1:0dac72ab5910 392 instHost->init();
okini3939 1:0dac72ab5910 393 }
okini3939 1:0dac72ab5910 394 return instHost;
okini3939 1:0dac72ab5910 395 }
okini3939 1:0dac72ab5910 396
okini3939 1:0dac72ab5910 397
okini3939 1:0dac72ab5910 398 /*
okini3939 1:0dac72ab5910 399 * Called when a device has been connected
okini3939 1:0dac72ab5910 400 * Called in ISR!!!! (no printf)
okini3939 1:0dac72ab5910 401 */
okini3939 1:0dac72ab5910 402 /* virtual */ void USBHost::deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent)
okini3939 1:0dac72ab5910 403 {
okini3939 1:0dac72ab5910 404 // be sure that the new device connected is not already connected...
okini3939 1:0dac72ab5910 405 int idx = findDevice(hub, port, hub_parent);
okini3939 1:0dac72ab5910 406 if (idx != -1) {
okini3939 1:0dac72ab5910 407 if (deviceInited[idx]) {
okini3939 1:0dac72ab5910 408 return;
okini3939 1:0dac72ab5910 409 }
okini3939 1:0dac72ab5910 410 }
okini3939 1:0dac72ab5910 411
okini3939 1:0dac72ab5910 412 message_t * usb_msg = mail_usb_event.alloc();
okini3939 1:0dac72ab5910 413 usb_msg->event_id = DEVICE_CONNECTED_EVENT;
okini3939 1:0dac72ab5910 414 usb_msg->hub = hub;
okini3939 1:0dac72ab5910 415 usb_msg->port = port;
okini3939 1:0dac72ab5910 416 usb_msg->lowSpeed = lowSpeed;
okini3939 1:0dac72ab5910 417 usb_msg->hub_parent = hub_parent;
okini3939 1:0dac72ab5910 418 mail_usb_event.put(usb_msg);
okini3939 1:0dac72ab5910 419 }
okini3939 1:0dac72ab5910 420
okini3939 1:0dac72ab5910 421 /*
okini3939 1:0dac72ab5910 422 * Called when a device has been disconnected
okini3939 1:0dac72ab5910 423 * Called in ISR!!!! (no printf)
okini3939 1:0dac72ab5910 424 */
okini3939 1:0dac72ab5910 425 /* virtual */ void USBHost::deviceDisconnected(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr)
okini3939 1:0dac72ab5910 426 {
okini3939 1:0dac72ab5910 427 // be sure that the device disconnected is connected...
okini3939 1:0dac72ab5910 428 int idx = findDevice(hub, port, hub_parent);
okini3939 1:0dac72ab5910 429 if (idx != -1) {
okini3939 1:0dac72ab5910 430 if (!deviceInUse[idx]) {
okini3939 1:0dac72ab5910 431 return;
okini3939 1:0dac72ab5910 432 }
okini3939 1:0dac72ab5910 433 } else {
okini3939 1:0dac72ab5910 434 return;
okini3939 1:0dac72ab5910 435 }
okini3939 1:0dac72ab5910 436
okini3939 1:0dac72ab5910 437 message_t * usb_msg = mail_usb_event.alloc();
okini3939 1:0dac72ab5910 438 usb_msg->event_id = DEVICE_DISCONNECTED_EVENT;
okini3939 1:0dac72ab5910 439 usb_msg->hub = hub;
okini3939 1:0dac72ab5910 440 usb_msg->port = port;
okini3939 1:0dac72ab5910 441 usb_msg->hub_parent = hub_parent;
okini3939 1:0dac72ab5910 442 mail_usb_event.put(usb_msg);
okini3939 1:0dac72ab5910 443 }
okini3939 1:0dac72ab5910 444
okini3939 1:0dac72ab5910 445 void USBHost::freeDevice(USBDeviceConnected * dev)
okini3939 1:0dac72ab5910 446 {
okini3939 1:0dac72ab5910 447 USBEndpoint * ep = NULL;
okini3939 1:0dac72ab5910 448 HCED * ed = NULL;
okini3939 1:0dac72ab5910 449
okini3939 1:0dac72ab5910 450 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 451 if (dev->getClass() == HUB_CLASS) {
okini3939 1:0dac72ab5910 452 if (dev->hub == NULL) {
okini3939 1:0dac72ab5910 453 USB_ERR("HUB NULL!!!!!\r\n");
okini3939 1:0dac72ab5910 454 } else {
okini3939 1:0dac72ab5910 455 dev->hub->hubDisconnected();
okini3939 1:0dac72ab5910 456 for (uint8_t i = 0; i < MAX_HUB_NB; i++) {
okini3939 1:0dac72ab5910 457 if (dev->hub == &hubs[i]) {
okini3939 1:0dac72ab5910 458 hub_in_use[i] = false;
okini3939 1:0dac72ab5910 459 break;
okini3939 1:0dac72ab5910 460 }
okini3939 1:0dac72ab5910 461 }
okini3939 1:0dac72ab5910 462 }
okini3939 1:0dac72ab5910 463 }
okini3939 1:0dac72ab5910 464
okini3939 1:0dac72ab5910 465 // notify hub parent that this device has been disconnected
okini3939 1:0dac72ab5910 466 if (dev->getHubParent()) {
okini3939 1:0dac72ab5910 467 dev->getHubParent()->deviceDisconnected(dev);
okini3939 1:0dac72ab5910 468 }
okini3939 1:0dac72ab5910 469
okini3939 1:0dac72ab5910 470 #endif
okini3939 1:0dac72ab5910 471
okini3939 1:0dac72ab5910 472 int idx = findDevice(dev);
okini3939 1:0dac72ab5910 473 if (idx != -1) {
okini3939 1:0dac72ab5910 474 deviceInUse[idx] = false;
okini3939 1:0dac72ab5910 475 deviceReset[idx] = false;
okini3939 1:0dac72ab5910 476
okini3939 1:0dac72ab5910 477 for (uint8_t j = 0; j < MAX_INTF; j++) {
okini3939 1:0dac72ab5910 478 deviceAttachedDriver[idx][j] = false;
okini3939 1:0dac72ab5910 479 if (dev->getInterface(j) != NULL) {
okini3939 1:0dac72ab5910 480 USB_DBG("FREE INTF %d on dev: %p, %p, nb_endpot: %d, %s", j, (void *)dev->getInterface(j), dev, dev->getInterface(j)->nb_endpoint, dev->getName(j));
okini3939 1:0dac72ab5910 481 for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) {
okini3939 1:0dac72ab5910 482 if ((ep = dev->getEndpoint(j, i)) != NULL) {
okini3939 1:0dac72ab5910 483 #ifndef USBHOST_OTHER
okini3939 1:0dac72ab5910 484 ed = (HCED *)ep->getHCED();
okini3939 1:0dac72ab5910 485 ed->control |= (1 << 14); //sKip bit
okini3939 1:0dac72ab5910 486 #endif
okini3939 1:0dac72ab5910 487 unqueueEndpoint(ep);
okini3939 1:0dac72ab5910 488
okini3939 1:0dac72ab5910 489 freeTD((volatile uint8_t*)ep->getTDList()[0]);
okini3939 1:0dac72ab5910 490 freeTD((volatile uint8_t*)ep->getTDList()[1]);
okini3939 1:0dac72ab5910 491
okini3939 1:0dac72ab5910 492 freeED((uint8_t *)ep->getHCED());
okini3939 1:0dac72ab5910 493 }
okini3939 1:0dac72ab5910 494 printList(BULK_ENDPOINT);
okini3939 1:0dac72ab5910 495 printList(INTERRUPT_ENDPOINT);
okini3939 1:0dac72ab5910 496 }
okini3939 1:0dac72ab5910 497 USB_INFO("Device disconnected [%p - %s - hub: %d - port: %d]", dev, dev->getName(j), dev->getHub(), dev->getPort());
okini3939 1:0dac72ab5910 498 }
okini3939 1:0dac72ab5910 499 }
okini3939 1:0dac72ab5910 500 dev->disconnect();
okini3939 1:0dac72ab5910 501 }
okini3939 1:0dac72ab5910 502 }
okini3939 1:0dac72ab5910 503
okini3939 1:0dac72ab5910 504
okini3939 1:0dac72ab5910 505 void USBHost::unqueueEndpoint(USBEndpoint * ep)
okini3939 1:0dac72ab5910 506 {
okini3939 1:0dac72ab5910 507 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 508 ep->setState(USB_TYPE_FREE);
okini3939 1:0dac72ab5910 509 #else
okini3939 1:0dac72ab5910 510 USBEndpoint * prec = NULL;
okini3939 1:0dac72ab5910 511 USBEndpoint * current = NULL;
okini3939 1:0dac72ab5910 512
okini3939 1:0dac72ab5910 513 for (int i = 0; i < 2; i++) {
okini3939 1:0dac72ab5910 514 current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)headInterruptEndpoint;
okini3939 1:0dac72ab5910 515 prec = current;
okini3939 1:0dac72ab5910 516 while (current != NULL) {
okini3939 1:0dac72ab5910 517 if (current == ep) {
okini3939 1:0dac72ab5910 518 if (current->nextEndpoint() != NULL) {
okini3939 1:0dac72ab5910 519 prec->queueEndpoint(current->nextEndpoint());
okini3939 1:0dac72ab5910 520 if (current == headBulkEndpoint) {
okini3939 1:0dac72ab5910 521 updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED());
okini3939 1:0dac72ab5910 522 headBulkEndpoint = current->nextEndpoint();
okini3939 1:0dac72ab5910 523 } else if (current == headInterruptEndpoint) {
okini3939 1:0dac72ab5910 524 updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED());
okini3939 1:0dac72ab5910 525 headInterruptEndpoint = current->nextEndpoint();
okini3939 1:0dac72ab5910 526 }
okini3939 1:0dac72ab5910 527 }
okini3939 1:0dac72ab5910 528 // here we are dequeuing the queue of ed
okini3939 1:0dac72ab5910 529 // we need to update the tail pointer
okini3939 1:0dac72ab5910 530 else {
okini3939 1:0dac72ab5910 531 prec->queueEndpoint(NULL);
okini3939 1:0dac72ab5910 532 if (current == headBulkEndpoint) {
okini3939 1:0dac72ab5910 533 updateBulkHeadED(0);
okini3939 1:0dac72ab5910 534 headBulkEndpoint = current->nextEndpoint();
okini3939 1:0dac72ab5910 535 } else if (current == headInterruptEndpoint) {
okini3939 1:0dac72ab5910 536 updateInterruptHeadED(0);
okini3939 1:0dac72ab5910 537 headInterruptEndpoint = current->nextEndpoint();
okini3939 1:0dac72ab5910 538 }
okini3939 1:0dac72ab5910 539
okini3939 1:0dac72ab5910 540 // modify tail
okini3939 1:0dac72ab5910 541 switch (current->getType()) {
okini3939 1:0dac72ab5910 542 case BULK_ENDPOINT:
okini3939 1:0dac72ab5910 543 tailBulkEndpoint = prec;
okini3939 1:0dac72ab5910 544 break;
okini3939 1:0dac72ab5910 545 case INTERRUPT_ENDPOINT:
okini3939 1:0dac72ab5910 546 tailInterruptEndpoint = prec;
okini3939 1:0dac72ab5910 547 break;
okini3939 1:0dac72ab5910 548 default:
okini3939 1:0dac72ab5910 549 break;
okini3939 1:0dac72ab5910 550 }
okini3939 1:0dac72ab5910 551 }
okini3939 1:0dac72ab5910 552 current->setState(USB_TYPE_FREE);
okini3939 1:0dac72ab5910 553 return;
okini3939 1:0dac72ab5910 554 }
okini3939 1:0dac72ab5910 555 prec = current;
okini3939 1:0dac72ab5910 556 current = current->nextEndpoint();
okini3939 1:0dac72ab5910 557 }
okini3939 1:0dac72ab5910 558 }
okini3939 1:0dac72ab5910 559 #endif
okini3939 1:0dac72ab5910 560 }
okini3939 1:0dac72ab5910 561
okini3939 1:0dac72ab5910 562
okini3939 1:0dac72ab5910 563 USBDeviceConnected * USBHost::getDevice(uint8_t index)
okini3939 1:0dac72ab5910 564 {
okini3939 1:0dac72ab5910 565 if ((index >= MAX_DEVICE_CONNECTED) || (!deviceInUse[index])) {
okini3939 1:0dac72ab5910 566 return NULL;
okini3939 1:0dac72ab5910 567 }
okini3939 1:0dac72ab5910 568 return (USBDeviceConnected*)&devices[index];
okini3939 1:0dac72ab5910 569 }
okini3939 1:0dac72ab5910 570
okini3939 1:0dac72ab5910 571 // create an USBEndpoint descriptor. the USBEndpoint is not linked
okini3939 1:0dac72ab5910 572 USBEndpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr)
okini3939 1:0dac72ab5910 573 {
okini3939 1:0dac72ab5910 574 int i = 0;
okini3939 1:0dac72ab5910 575 HCED * ed = (HCED *)getED();
okini3939 1:0dac72ab5910 576 HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() };
okini3939 1:0dac72ab5910 577
okini3939 1:0dac72ab5910 578 memset((void *)td_list[0], 0x00, sizeof(HCTD));
okini3939 1:0dac72ab5910 579 memset((void *)td_list[1], 0x00, sizeof(HCTD));
okini3939 1:0dac72ab5910 580
okini3939 1:0dac72ab5910 581 // search a free USBEndpoint
okini3939 1:0dac72ab5910 582 for (i = 0; i < MAX_ENDPOINT; i++) {
okini3939 1:0dac72ab5910 583 if (endpoints[i].getState() == USB_TYPE_FREE) {
okini3939 1:0dac72ab5910 584 endpoints[i].init(ed, type, dir, size, addr, td_list);
okini3939 1:0dac72ab5910 585 USB_DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d, state: %s", &endpoints[i], type, dir, size, addr, endpoints[i].getStateString());
okini3939 1:0dac72ab5910 586 return &endpoints[i];
okini3939 1:0dac72ab5910 587 }
okini3939 1:0dac72ab5910 588 }
okini3939 1:0dac72ab5910 589 USB_ERR("could not allocate more endpoints!!!!");
okini3939 1:0dac72ab5910 590 return NULL;
okini3939 1:0dac72ab5910 591 }
okini3939 1:0dac72ab5910 592
okini3939 1:0dac72ab5910 593
okini3939 1:0dac72ab5910 594 USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev)
okini3939 1:0dac72ab5910 595 {
okini3939 1:0dac72ab5910 596 int index = findDevice(dev);
okini3939 1:0dac72ab5910 597 if (index != -1) {
okini3939 1:0dac72ab5910 598 USB_DBG("Resetting hub %d, port %d\n", dev->getHub(), dev->getPort());
okini3939 1:0dac72ab5910 599 Thread::wait(100);
okini3939 1:0dac72ab5910 600 if (dev->getHub() == 0) {
okini3939 1:0dac72ab5910 601 resetRootHub();
okini3939 1:0dac72ab5910 602 }
okini3939 1:0dac72ab5910 603 #if MAX_HUB_NB
okini3939 1:0dac72ab5910 604 else {
okini3939 1:0dac72ab5910 605 dev->getHubParent()->portReset(dev->getPort());
okini3939 1:0dac72ab5910 606 }
okini3939 1:0dac72ab5910 607 #endif
okini3939 1:0dac72ab5910 608 Thread::wait(100);
okini3939 1:0dac72ab5910 609 deviceReset[index] = true;
okini3939 1:0dac72ab5910 610 return USB_TYPE_OK;
okini3939 1:0dac72ab5910 611 }
okini3939 1:0dac72ab5910 612
okini3939 1:0dac72ab5910 613 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 614 }
okini3939 1:0dac72ab5910 615
okini3939 1:0dac72ab5910 616 // link the USBEndpoint to the linked list and attach an USBEndpoint to a device
okini3939 1:0dac72ab5910 617 bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep)
okini3939 1:0dac72ab5910 618 {
okini3939 1:0dac72ab5910 619
okini3939 1:0dac72ab5910 620 if (ep == NULL) {
okini3939 1:0dac72ab5910 621 return false;
okini3939 1:0dac72ab5910 622 }
okini3939 1:0dac72ab5910 623
okini3939 1:0dac72ab5910 624 #ifndef USBHOST_OTHER
okini3939 1:0dac72ab5910 625 HCED * prevEd;
okini3939 1:0dac72ab5910 626
okini3939 1:0dac72ab5910 627 #endif
okini3939 1:0dac72ab5910 628 // set device address in the USBEndpoint descriptor
okini3939 1:0dac72ab5910 629 if (dev == NULL) {
okini3939 1:0dac72ab5910 630 ep->setDeviceAddress(0);
okini3939 1:0dac72ab5910 631 } else {
okini3939 1:0dac72ab5910 632 ep->setDeviceAddress(dev->getAddress());
okini3939 1:0dac72ab5910 633 }
okini3939 1:0dac72ab5910 634
okini3939 1:0dac72ab5910 635 if ((dev != NULL) && dev->getSpeed()) {
okini3939 1:0dac72ab5910 636 ep->setSpeed(dev->getSpeed());
okini3939 1:0dac72ab5910 637 }
okini3939 1:0dac72ab5910 638
okini3939 1:0dac72ab5910 639 ep->setIntfNb(intf_nb);
okini3939 1:0dac72ab5910 640
okini3939 1:0dac72ab5910 641 #ifndef USBHOST_OTHER
okini3939 1:0dac72ab5910 642 // queue the new USBEndpoint on the ED list
okini3939 1:0dac72ab5910 643 switch (ep->getType()) {
okini3939 1:0dac72ab5910 644
okini3939 1:0dac72ab5910 645 case CONTROL_ENDPOINT:
okini3939 1:0dac72ab5910 646 prevEd = ( HCED*) controlHeadED();
okini3939 1:0dac72ab5910 647 if (!prevEd) {
okini3939 1:0dac72ab5910 648 updateControlHeadED((uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 649 USB_DBG_TRANSFER("First control USBEndpoint: %08X", (uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 650 headControlEndpoint = ep;
okini3939 1:0dac72ab5910 651 tailControlEndpoint = ep;
okini3939 1:0dac72ab5910 652 return true;
okini3939 1:0dac72ab5910 653 }
okini3939 1:0dac72ab5910 654 tailControlEndpoint->queueEndpoint(ep);
okini3939 1:0dac72ab5910 655 tailControlEndpoint = ep;
okini3939 1:0dac72ab5910 656 return true;
okini3939 1:0dac72ab5910 657
okini3939 1:0dac72ab5910 658 case BULK_ENDPOINT:
okini3939 1:0dac72ab5910 659 prevEd = ( HCED*) bulkHeadED();
okini3939 1:0dac72ab5910 660 if (!prevEd) {
okini3939 1:0dac72ab5910 661 updateBulkHeadED((uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 662 USB_DBG_TRANSFER("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 663 headBulkEndpoint = ep;
okini3939 1:0dac72ab5910 664 tailBulkEndpoint = ep;
okini3939 1:0dac72ab5910 665 break;
okini3939 1:0dac72ab5910 666 }
okini3939 1:0dac72ab5910 667 USB_DBG_TRANSFER("Queue BULK Ed %p after %p\r\n",ep->getHCED(), prevEd);
okini3939 1:0dac72ab5910 668 tailBulkEndpoint->queueEndpoint(ep);
okini3939 1:0dac72ab5910 669 tailBulkEndpoint = ep;
okini3939 1:0dac72ab5910 670 break;
okini3939 1:0dac72ab5910 671
okini3939 1:0dac72ab5910 672 case INTERRUPT_ENDPOINT:
okini3939 1:0dac72ab5910 673 prevEd = ( HCED*) interruptHeadED();
okini3939 1:0dac72ab5910 674 if (!prevEd) {
okini3939 1:0dac72ab5910 675 updateInterruptHeadED((uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 676 USB_DBG_TRANSFER("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
okini3939 1:0dac72ab5910 677 headInterruptEndpoint = ep;
okini3939 1:0dac72ab5910 678 tailInterruptEndpoint = ep;
okini3939 1:0dac72ab5910 679 break;
okini3939 1:0dac72ab5910 680 }
okini3939 1:0dac72ab5910 681 USB_DBG_TRANSFER("Queue INTERRUPT Ed %p after %p\r\n",ep->getHCED(), prevEd);
okini3939 1:0dac72ab5910 682 tailInterruptEndpoint->queueEndpoint(ep);
okini3939 1:0dac72ab5910 683 tailInterruptEndpoint = ep;
okini3939 1:0dac72ab5910 684 break;
okini3939 1:0dac72ab5910 685 default:
okini3939 1:0dac72ab5910 686 return false;
okini3939 1:0dac72ab5910 687 }
okini3939 1:0dac72ab5910 688
okini3939 1:0dac72ab5910 689 #endif
okini3939 1:0dac72ab5910 690 ep->dev = dev;
okini3939 1:0dac72ab5910 691 dev->addEndpoint(intf_nb, ep);
okini3939 1:0dac72ab5910 692
okini3939 1:0dac72ab5910 693 return true;
okini3939 1:0dac72ab5910 694 }
okini3939 1:0dac72ab5910 695
okini3939 1:0dac72ab5910 696
okini3939 1:0dac72ab5910 697 int USBHost::findDevice(USBDeviceConnected * dev)
okini3939 1:0dac72ab5910 698 {
okini3939 1:0dac72ab5910 699 for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) {
okini3939 1:0dac72ab5910 700 if (dev == &devices[i]) {
okini3939 1:0dac72ab5910 701 return i;
okini3939 1:0dac72ab5910 702 }
okini3939 1:0dac72ab5910 703 }
okini3939 1:0dac72ab5910 704 return -1;
okini3939 1:0dac72ab5910 705 }
okini3939 1:0dac72ab5910 706
okini3939 1:0dac72ab5910 707 int USBHost::findDevice(uint8_t hub, uint8_t port, USBHostHub * hub_parent)
okini3939 1:0dac72ab5910 708 {
okini3939 1:0dac72ab5910 709 for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) {
okini3939 1:0dac72ab5910 710 if (devices[i].getHub() == hub && devices[i].getPort() == port) {
okini3939 1:0dac72ab5910 711 if (hub_parent != NULL) {
okini3939 1:0dac72ab5910 712 if (hub_parent == devices[i].getHubParent()) {
okini3939 1:0dac72ab5910 713 return i;
okini3939 1:0dac72ab5910 714 }
okini3939 1:0dac72ab5910 715 } else {
okini3939 1:0dac72ab5910 716 return i;
okini3939 1:0dac72ab5910 717 }
okini3939 1:0dac72ab5910 718 }
okini3939 1:0dac72ab5910 719 }
okini3939 1:0dac72ab5910 720 return -1;
okini3939 1:0dac72ab5910 721 }
okini3939 1:0dac72ab5910 722
okini3939 1:0dac72ab5910 723 void USBHost::printList(ENDPOINT_TYPE type)
okini3939 1:0dac72ab5910 724 {
okini3939 1:0dac72ab5910 725 #if DEBUG_EP_STATE && !defined(USBHOST_OTHER)
okini3939 1:0dac72ab5910 726 volatile HCED * hced;
okini3939 1:0dac72ab5910 727 switch(type) {
okini3939 1:0dac72ab5910 728 case CONTROL_ENDPOINT:
okini3939 1:0dac72ab5910 729 hced = (HCED *)controlHeadED();
okini3939 1:0dac72ab5910 730 break;
okini3939 1:0dac72ab5910 731 case BULK_ENDPOINT:
okini3939 1:0dac72ab5910 732 hced = (HCED *)bulkHeadED();
okini3939 1:0dac72ab5910 733 break;
okini3939 1:0dac72ab5910 734 case INTERRUPT_ENDPOINT:
okini3939 1:0dac72ab5910 735 hced = (HCED *)interruptHeadED();
okini3939 1:0dac72ab5910 736 break;
okini3939 1:0dac72ab5910 737 }
okini3939 1:0dac72ab5910 738 volatile HCTD * hctd = NULL;
okini3939 1:0dac72ab5910 739 const char * type_str = (type == BULK_ENDPOINT) ? "BULK" :
okini3939 1:0dac72ab5910 740 ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" :
okini3939 1:0dac72ab5910 741 ((type == CONTROL_ENDPOINT) ? "CONTROL" : "ISOCHRONOUS"));
okini3939 1:0dac72ab5910 742 printf("State of %s:\r\n", type_str);
okini3939 1:0dac72ab5910 743 while (hced != NULL) {
okini3939 1:0dac72ab5910 744 uint8_t dir = ((hced->control & (3 << 11)) >> 11);
okini3939 1:0dac72ab5910 745 printf("hced: %p [ADDR: %d, DIR: %s, EP_NB: 0x%X]\r\n", hced,
okini3939 1:0dac72ab5910 746 hced->control & 0x7f,
okini3939 1:0dac72ab5910 747 (dir == 1) ? "OUT" : ((dir == 0) ? "FROM_TD":"IN"),
okini3939 1:0dac72ab5910 748 (hced->control & (0xf << 7)) >> 7);
okini3939 1:0dac72ab5910 749 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0xf));
okini3939 1:0dac72ab5910 750 while (hctd != hced->tailTD) {
okini3939 1:0dac72ab5910 751 printf("\thctd: %p [DIR: %s]\r\n", hctd, ((hctd->control & (3 << 19)) >> 19) == 1 ? "OUT" : "IN");
okini3939 1:0dac72ab5910 752 hctd = hctd->nextTD;
okini3939 1:0dac72ab5910 753 }
okini3939 1:0dac72ab5910 754 printf("\thctd: %p\r\n", hctd);
okini3939 1:0dac72ab5910 755 hced = hced->nextED;
okini3939 1:0dac72ab5910 756 }
okini3939 1:0dac72ab5910 757 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 758 #endif
okini3939 1:0dac72ab5910 759 }
okini3939 1:0dac72ab5910 760
okini3939 1:0dac72ab5910 761
okini3939 1:0dac72ab5910 762 // add a transfer on the TD linked list
okini3939 1:0dac72ab5910 763 USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len)
okini3939 1:0dac72ab5910 764 {
okini3939 1:0dac72ab5910 765 USB_TYPE ret=USB_TYPE_PROCESSING;
okini3939 1:0dac72ab5910 766 td_mutex.lock();
okini3939 1:0dac72ab5910 767
okini3939 1:0dac72ab5910 768 // allocate a TD which will be freed in TDcompletion
okini3939 1:0dac72ab5910 769 volatile HCTD * td = ed->getNextTD();
okini3939 1:0dac72ab5910 770 if (td == NULL) {
okini3939 1:0dac72ab5910 771 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 772 }
okini3939 1:0dac72ab5910 773
okini3939 1:0dac72ab5910 774 #ifndef USBHOST_OTHER
okini3939 1:0dac72ab5910 775 uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT ));
okini3939 1:0dac72ab5910 776
okini3939 1:0dac72ab5910 777 uint32_t td_toggle;
okini3939 1:0dac72ab5910 778
okini3939 1:0dac72ab5910 779 if (ed->getType() == CONTROL_ENDPOINT) {
okini3939 1:0dac72ab5910 780 if (ed->isSetup()) {
okini3939 1:0dac72ab5910 781 td_toggle = TD_TOGGLE_0;
okini3939 1:0dac72ab5910 782 } else {
okini3939 1:0dac72ab5910 783 td_toggle = TD_TOGGLE_1;
okini3939 1:0dac72ab5910 784 }
okini3939 1:0dac72ab5910 785 } else {
okini3939 1:0dac72ab5910 786 td_toggle = 0;
okini3939 1:0dac72ab5910 787 }
okini3939 1:0dac72ab5910 788
okini3939 1:0dac72ab5910 789 td->control = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC);
okini3939 1:0dac72ab5910 790 td->currBufPtr = buf;
okini3939 1:0dac72ab5910 791 td->bufEnd = (buf + (len - 1));
okini3939 1:0dac72ab5910 792
okini3939 1:0dac72ab5910 793 ENDPOINT_TYPE type = ed->getType();
okini3939 1:0dac72ab5910 794
okini3939 1:0dac72ab5910 795 disableList(type);
okini3939 1:0dac72ab5910 796 ed->queueTransfer();
okini3939 1:0dac72ab5910 797 printList(type);
okini3939 1:0dac72ab5910 798 enableList(type);
okini3939 1:0dac72ab5910 799 #else
okini3939 1:0dac72ab5910 800 /* call method specific for endpoint */
okini3939 1:0dac72ab5910 801 td->currBufPtr = buf;
okini3939 1:0dac72ab5910 802 td->size = len;
okini3939 1:0dac72ab5910 803 ret = ed->queueTransfer();
okini3939 1:0dac72ab5910 804 #endif
okini3939 1:0dac72ab5910 805
okini3939 1:0dac72ab5910 806 td_mutex.unlock();
okini3939 1:0dac72ab5910 807
okini3939 1:0dac72ab5910 808 return ret;
okini3939 1:0dac72ab5910 809 }
okini3939 1:0dac72ab5910 810
okini3939 1:0dac72ab5910 811
okini3939 1:0dac72ab5910 812
okini3939 1:0dac72ab5910 813 USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_dev_descr)
okini3939 1:0dac72ab5910 814 {
okini3939 1:0dac72ab5910 815 USB_TYPE t = controlRead( dev,
okini3939 1:0dac72ab5910 816 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
okini3939 1:0dac72ab5910 817 GET_DESCRIPTOR,
okini3939 1:0dac72ab5910 818 (DEVICE_DESCRIPTOR << 8) | (0),
okini3939 1:0dac72ab5910 819 0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf));
okini3939 1:0dac72ab5910 820 if (len_dev_descr) {
okini3939 1:0dac72ab5910 821 *len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf);
okini3939 1:0dac72ab5910 822 }
okini3939 1:0dac72ab5910 823
okini3939 1:0dac72ab5910 824 return t;
okini3939 1:0dac72ab5910 825 }
okini3939 1:0dac72ab5910 826
okini3939 1:0dac72ab5910 827 USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr)
okini3939 1:0dac72ab5910 828 {
okini3939 1:0dac72ab5910 829 USB_TYPE res;
okini3939 1:0dac72ab5910 830 uint16_t total_conf_descr_length = 0;
okini3939 1:0dac72ab5910 831
okini3939 1:0dac72ab5910 832 // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr
okini3939 1:0dac72ab5910 833 res = controlRead( dev,
okini3939 1:0dac72ab5910 834 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
okini3939 1:0dac72ab5910 835 GET_DESCRIPTOR,
okini3939 1:0dac72ab5910 836 (CONFIGURATION_DESCRIPTOR << 8) | (0),
okini3939 1:0dac72ab5910 837 0, buf, CONFIGURATION_DESCRIPTOR_LENGTH);
okini3939 1:0dac72ab5910 838
okini3939 1:0dac72ab5910 839 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 840 USB_ERR("GET CONF 1 DESCR FAILED");
okini3939 1:0dac72ab5910 841 return res;
okini3939 1:0dac72ab5910 842 }
okini3939 1:0dac72ab5910 843 total_conf_descr_length = buf[2] | (buf[3] << 8);
okini3939 1:0dac72ab5910 844 total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length);
okini3939 1:0dac72ab5910 845
okini3939 1:0dac72ab5910 846 if (len_conf_descr) {
okini3939 1:0dac72ab5910 847 *len_conf_descr = total_conf_descr_length;
okini3939 1:0dac72ab5910 848 }
okini3939 1:0dac72ab5910 849
okini3939 1:0dac72ab5910 850 USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]);
okini3939 1:0dac72ab5910 851
okini3939 1:0dac72ab5910 852 return controlRead( dev,
okini3939 1:0dac72ab5910 853 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
okini3939 1:0dac72ab5910 854 GET_DESCRIPTOR,
okini3939 1:0dac72ab5910 855 (CONFIGURATION_DESCRIPTOR << 8) | (0),
okini3939 1:0dac72ab5910 856 0, buf, total_conf_descr_length);
okini3939 1:0dac72ab5910 857 }
okini3939 1:0dac72ab5910 858
okini3939 1:0dac72ab5910 859
okini3939 1:0dac72ab5910 860 USB_TYPE USBHost::setAddress(USBDeviceConnected * dev, uint8_t address)
okini3939 1:0dac72ab5910 861 {
okini3939 1:0dac72ab5910 862 return controlWrite( dev,
okini3939 1:0dac72ab5910 863 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
okini3939 1:0dac72ab5910 864 SET_ADDRESS,
okini3939 1:0dac72ab5910 865 address,
okini3939 1:0dac72ab5910 866 0, NULL, 0);
okini3939 1:0dac72ab5910 867
okini3939 1:0dac72ab5910 868 }
okini3939 1:0dac72ab5910 869
okini3939 1:0dac72ab5910 870 USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf)
okini3939 1:0dac72ab5910 871 {
okini3939 1:0dac72ab5910 872 return controlWrite( dev,
okini3939 1:0dac72ab5910 873 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
okini3939 1:0dac72ab5910 874 SET_CONFIGURATION,
okini3939 1:0dac72ab5910 875 conf,
okini3939 1:0dac72ab5910 876 0, NULL, 0);
okini3939 1:0dac72ab5910 877 }
okini3939 1:0dac72ab5910 878
okini3939 1:0dac72ab5910 879 uint8_t USBHost::numberDriverAttached(USBDeviceConnected * dev)
okini3939 1:0dac72ab5910 880 {
okini3939 1:0dac72ab5910 881 int index = findDevice(dev);
okini3939 1:0dac72ab5910 882 uint8_t cnt = 0;
okini3939 1:0dac72ab5910 883 if (index == -1) {
okini3939 1:0dac72ab5910 884 return 0;
okini3939 1:0dac72ab5910 885 }
okini3939 1:0dac72ab5910 886 for (uint8_t i = 0; i < MAX_INTF; i++) {
okini3939 1:0dac72ab5910 887 if (deviceAttachedDriver[index][i]) {
okini3939 1:0dac72ab5910 888 cnt++;
okini3939 1:0dac72ab5910 889 }
okini3939 1:0dac72ab5910 890 }
okini3939 1:0dac72ab5910 891 return cnt;
okini3939 1:0dac72ab5910 892 }
okini3939 1:0dac72ab5910 893
okini3939 1:0dac72ab5910 894 // enumerate a device with the control USBEndpoint
okini3939 1:0dac72ab5910 895 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
okini3939 1:0dac72ab5910 896 {
okini3939 1:0dac72ab5910 897 uint16_t total_conf_descr_length = 0;
okini3939 1:0dac72ab5910 898 USB_TYPE res;
okini3939 1:0dac72ab5910 899
okini3939 1:0dac72ab5910 900 do {
okini3939 1:0dac72ab5910 901 Lock lock(this);
okini3939 1:0dac72ab5910 902
okini3939 1:0dac72ab5910 903 // don't enumerate a device which all interfaces are registered to a specific driver
okini3939 1:0dac72ab5910 904 int index = findDevice(dev);
okini3939 1:0dac72ab5910 905
okini3939 1:0dac72ab5910 906 if (index == -1) {
okini3939 1:0dac72ab5910 907 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 908 }
okini3939 1:0dac72ab5910 909
okini3939 1:0dac72ab5910 910 uint8_t nb_intf_attached = numberDriverAttached(dev);
okini3939 1:0dac72ab5910 911 USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf());
okini3939 1:0dac72ab5910 912 USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached);
okini3939 1:0dac72ab5910 913 if ((nb_intf_attached != 0) && (dev->getNbIntf() == nb_intf_attached)) {
okini3939 1:0dac72ab5910 914 USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev);
okini3939 1:0dac72ab5910 915 return USB_TYPE_OK;
okini3939 1:0dac72ab5910 916 }
okini3939 1:0dac72ab5910 917
okini3939 1:0dac72ab5910 918 USB_DBG("Enumerate dev: %p", dev);
okini3939 1:0dac72ab5910 919
okini3939 1:0dac72ab5910 920 // third step: get the whole device descriptor to see vid, pid
okini3939 1:0dac72ab5910 921 res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH);
okini3939 1:0dac72ab5910 922
okini3939 1:0dac72ab5910 923 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 924 USB_DBG("GET DEV DESCR FAILED");
okini3939 1:0dac72ab5910 925 return res;
okini3939 1:0dac72ab5910 926 }
okini3939 1:0dac72ab5910 927
okini3939 1:0dac72ab5910 928 dev->setClass(data[4]);
okini3939 1:0dac72ab5910 929 dev->setSubClass(data[5]);
okini3939 1:0dac72ab5910 930 dev->setProtocol(data[6]);
okini3939 1:0dac72ab5910 931 dev->setVid(data[8] | (data[9] << 8));
okini3939 1:0dac72ab5910 932 dev->setPid(data[10] | (data[11] << 8));
okini3939 1:0dac72ab5910 933 USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8));
okini3939 1:0dac72ab5910 934
okini3939 1:0dac72ab5910 935 pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) );
okini3939 1:0dac72ab5910 936
okini3939 1:0dac72ab5910 937 res = getConfigurationDescriptor(dev, data, sizeof(data), &total_conf_descr_length);
okini3939 1:0dac72ab5910 938 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 939 return res;
okini3939 1:0dac72ab5910 940 }
okini3939 1:0dac72ab5910 941
okini3939 1:0dac72ab5910 942 #if (DEBUG > 3)
okini3939 1:0dac72ab5910 943 USB_DBG("CONFIGURATION DESCRIPTOR:\r\n");
okini3939 1:0dac72ab5910 944 for (int i = 0; i < total_conf_descr_length; i++) {
okini3939 1:0dac72ab5910 945 printf("%02X ", data[i]);
okini3939 1:0dac72ab5910 946 }
okini3939 1:0dac72ab5910 947 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 948 #endif
okini3939 1:0dac72ab5910 949
okini3939 1:0dac72ab5910 950 // Parse the configuration descriptor
okini3939 1:0dac72ab5910 951 parseConfDescr(dev, data, total_conf_descr_length, pEnumerator);
okini3939 1:0dac72ab5910 952
okini3939 1:0dac72ab5910 953 // only set configuration if not enumerated before
okini3939 1:0dac72ab5910 954 if (!dev->isEnumerated()) {
okini3939 1:0dac72ab5910 955
okini3939 1:0dac72ab5910 956 USB_DBG("Set configuration 1 on dev: %p", dev);
okini3939 1:0dac72ab5910 957 // sixth step: set configuration (only 1 supported)
okini3939 1:0dac72ab5910 958 res = setConfiguration(dev, 1);
okini3939 1:0dac72ab5910 959
okini3939 1:0dac72ab5910 960 if (res != USB_TYPE_OK) {
okini3939 1:0dac72ab5910 961 USB_DBG("SET CONF FAILED");
okini3939 1:0dac72ab5910 962 return res;
okini3939 1:0dac72ab5910 963 }
okini3939 1:0dac72ab5910 964 }
okini3939 1:0dac72ab5910 965
okini3939 1:0dac72ab5910 966 dev->setEnumerated();
okini3939 1:0dac72ab5910 967
okini3939 1:0dac72ab5910 968 // Now the device is enumerated!
okini3939 1:0dac72ab5910 969 USB_DBG("dev %p is enumerated\r\n", dev);
okini3939 1:0dac72ab5910 970
okini3939 1:0dac72ab5910 971 } while(0);
okini3939 1:0dac72ab5910 972
okini3939 1:0dac72ab5910 973 // Some devices may require this delay
okini3939 1:0dac72ab5910 974 Thread::wait(100);
okini3939 1:0dac72ab5910 975
okini3939 1:0dac72ab5910 976 return USB_TYPE_OK;
okini3939 1:0dac72ab5910 977 }
okini3939 1:0dac72ab5910 978 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
okini3939 1:0dac72ab5910 979 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
okini3939 1:0dac72ab5910 980 {
okini3939 1:0dac72ab5910 981 uint32_t index = 0;
okini3939 1:0dac72ab5910 982 uint32_t len_desc = 0;
okini3939 1:0dac72ab5910 983 uint8_t id = 0;
okini3939 1:0dac72ab5910 984 int nb_endpoints_used = 0;
okini3939 1:0dac72ab5910 985 USBEndpoint * ep = NULL;
okini3939 1:0dac72ab5910 986 uint8_t intf_nb = 0;
okini3939 1:0dac72ab5910 987 bool parsing_intf = false;
okini3939 1:0dac72ab5910 988 uint8_t current_intf = 0;
okini3939 1:0dac72ab5910 989
okini3939 1:0dac72ab5910 990 while (index < len) {
okini3939 1:0dac72ab5910 991 len_desc = conf_descr[index];
okini3939 1:0dac72ab5910 992 id = conf_descr[index+1];
okini3939 1:0dac72ab5910 993 switch (id) {
okini3939 1:0dac72ab5910 994 case CONFIGURATION_DESCRIPTOR:
okini3939 1:0dac72ab5910 995 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
okini3939 1:0dac72ab5910 996 dev->setNbIntf(conf_descr[4]);
okini3939 1:0dac72ab5910 997 break;
okini3939 1:0dac72ab5910 998 case INTERFACE_DESCRIPTOR:
okini3939 1:0dac72ab5910 999 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
okini3939 1:0dac72ab5910 1000 if (intf_nb++ <= MAX_INTF) {
okini3939 1:0dac72ab5910 1001 current_intf = conf_descr[index + 2];
okini3939 1:0dac72ab5910 1002 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
okini3939 1:0dac72ab5910 1003 nb_endpoints_used = 0;
okini3939 1:0dac72ab5910 1004 USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
okini3939 1:0dac72ab5910 1005 } else {
okini3939 1:0dac72ab5910 1006 USB_DBG("Drop intf...");
okini3939 1:0dac72ab5910 1007 }
okini3939 1:0dac72ab5910 1008 parsing_intf = true;
okini3939 1:0dac72ab5910 1009 } else {
okini3939 1:0dac72ab5910 1010 parsing_intf = false;
okini3939 1:0dac72ab5910 1011 }
okini3939 1:0dac72ab5910 1012 break;
okini3939 1:0dac72ab5910 1013 case ENDPOINT_DESCRIPTOR:
okini3939 1:0dac72ab5910 1014 if (parsing_intf && (intf_nb <= MAX_INTF) ) {
okini3939 1:0dac72ab5910 1015 if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) {
okini3939 1:0dac72ab5910 1016 if( pEnumerator->useEndpoint(current_intf, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) {
okini3939 1:0dac72ab5910 1017 // if the USBEndpoint is isochronous -> skip it (TODO: fix this)
okini3939 1:0dac72ab5910 1018 if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) {
okini3939 1:0dac72ab5910 1019 ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03),
okini3939 1:0dac72ab5910 1020 (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1),
okini3939 1:0dac72ab5910 1021 conf_descr[index + 4] | (conf_descr[index + 5] << 8),
okini3939 1:0dac72ab5910 1022 conf_descr[index + 2] & 0x0f);
okini3939 1:0dac72ab5910 1023 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
okini3939 1:0dac72ab5910 1024 if (ep != NULL && dev != NULL) {
okini3939 1:0dac72ab5910 1025 addEndpoint(dev, current_intf, ep);
okini3939 1:0dac72ab5910 1026 } else {
okini3939 1:0dac72ab5910 1027 USB_DBG("EP NULL");
okini3939 1:0dac72ab5910 1028 }
okini3939 1:0dac72ab5910 1029 nb_endpoints_used++;
okini3939 1:0dac72ab5910 1030 } else {
okini3939 1:0dac72ab5910 1031 USB_DBG("ISO USBEndpoint NOT SUPPORTED");
okini3939 1:0dac72ab5910 1032 }
okini3939 1:0dac72ab5910 1033 }
okini3939 1:0dac72ab5910 1034 }
okini3939 1:0dac72ab5910 1035 }
okini3939 1:0dac72ab5910 1036 break;
okini3939 1:0dac72ab5910 1037 case HID_DESCRIPTOR:
okini3939 1:0dac72ab5910 1038 lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
okini3939 1:0dac72ab5910 1039 break;
okini3939 1:0dac72ab5910 1040 default:
okini3939 1:0dac72ab5910 1041 break;
okini3939 1:0dac72ab5910 1042 }
okini3939 1:0dac72ab5910 1043 index += len_desc;
okini3939 1:0dac72ab5910 1044 }
okini3939 1:0dac72ab5910 1045 }
okini3939 1:0dac72ab5910 1046
okini3939 1:0dac72ab5910 1047
okini3939 1:0dac72ab5910 1048 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
okini3939 1:0dac72ab5910 1049 {
okini3939 1:0dac72ab5910 1050 return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, true);
okini3939 1:0dac72ab5910 1051 }
okini3939 1:0dac72ab5910 1052
okini3939 1:0dac72ab5910 1053 USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
okini3939 1:0dac72ab5910 1054 {
okini3939 1:0dac72ab5910 1055 return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, false);
okini3939 1:0dac72ab5910 1056 }
okini3939 1:0dac72ab5910 1057
okini3939 1:0dac72ab5910 1058 USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
okini3939 1:0dac72ab5910 1059 {
okini3939 1:0dac72ab5910 1060 return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, true);
okini3939 1:0dac72ab5910 1061 }
okini3939 1:0dac72ab5910 1062
okini3939 1:0dac72ab5910 1063 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
okini3939 1:0dac72ab5910 1064 {
okini3939 1:0dac72ab5910 1065 return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, false);
okini3939 1:0dac72ab5910 1066 }
okini3939 1:0dac72ab5910 1067
okini3939 1:0dac72ab5910 1068 USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write)
okini3939 1:0dac72ab5910 1069 {
okini3939 1:0dac72ab5910 1070
okini3939 1:0dac72ab5910 1071 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 1072 const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS");
okini3939 1:0dac72ab5910 1073 USB_DBG_TRANSFER("----- %s %s [dev: %p - %s - hub: %d - port: %d - addr: %d - ep: %02X]------", type_str, (write) ? "WRITE" : "READ", dev, dev->getName(ep->getIntfNb()), dev->getHub(), dev->getPort(), dev->getAddress(), ep->getAddress());
okini3939 1:0dac72ab5910 1074 #endif
okini3939 1:0dac72ab5910 1075
okini3939 1:0dac72ab5910 1076 Lock lock(this);
okini3939 1:0dac72ab5910 1077
okini3939 1:0dac72ab5910 1078 USB_TYPE res;
okini3939 1:0dac72ab5910 1079 ENDPOINT_DIRECTION dir = (write) ? OUT : IN;
okini3939 1:0dac72ab5910 1080
okini3939 1:0dac72ab5910 1081 if (dev == NULL) {
okini3939 1:0dac72ab5910 1082 USB_ERR("dev NULL");
okini3939 1:0dac72ab5910 1083 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 1084 }
okini3939 1:0dac72ab5910 1085
okini3939 1:0dac72ab5910 1086 if (ep == NULL) {
okini3939 1:0dac72ab5910 1087 USB_ERR("ep NULL");
okini3939 1:0dac72ab5910 1088 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 1089 }
okini3939 1:0dac72ab5910 1090
okini3939 1:0dac72ab5910 1091 if (ep->getState() != USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 1092 USB_WARN("[ep: %p - dev: %p - %s] NOT IDLE: %s", ep, ep->dev, ep->dev->getName(ep->getIntfNb()), ep->getStateString());
okini3939 1:0dac72ab5910 1093 return ep->getState();
okini3939 1:0dac72ab5910 1094 }
okini3939 1:0dac72ab5910 1095
okini3939 1:0dac72ab5910 1096 if ((ep->getDir() != dir) || (ep->getType() != type)) {
okini3939 1:0dac72ab5910 1097 USB_ERR("[ep: %p - dev: %p] wrong dir or bad USBEndpoint type", ep, ep->dev);
okini3939 1:0dac72ab5910 1098 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 1099 }
okini3939 1:0dac72ab5910 1100
okini3939 1:0dac72ab5910 1101 if (dev->getAddress() != ep->getDeviceAddress()) {
okini3939 1:0dac72ab5910 1102 USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep, ep->dev);
okini3939 1:0dac72ab5910 1103 return USB_TYPE_ERROR;
okini3939 1:0dac72ab5910 1104 }
okini3939 1:0dac72ab5910 1105
okini3939 1:0dac72ab5910 1106 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 1107 if (write) {
okini3939 1:0dac72ab5910 1108 USB_DBG_TRANSFER("%s WRITE buffer", type_str);
okini3939 1:0dac72ab5910 1109 for (int i = 0; i < ep->getLengthTransferred(); i++) {
okini3939 1:0dac72ab5910 1110 printf("%02X ", buf[i]);
okini3939 1:0dac72ab5910 1111 }
okini3939 1:0dac72ab5910 1112 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 1113 }
okini3939 1:0dac72ab5910 1114 #endif
okini3939 1:0dac72ab5910 1115 res = addTransfer(ep, buf, len);
okini3939 1:0dac72ab5910 1116
okini3939 1:0dac72ab5910 1117 if ((blocking)&& (res == USB_TYPE_PROCESSING)) {
okini3939 1:0dac72ab5910 1118 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 1119 osEvent event = ep->ep_queue.get(TD_TIMEOUT);
okini3939 1:0dac72ab5910 1120 if (event.status == osEventTimeout) {
okini3939 1:0dac72ab5910 1121 /* control endpoint is confusing for merge on b */
okini3939 1:0dac72ab5910 1122 disableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1123 ep->setState(USB_TYPE_ERROR);
okini3939 1:0dac72ab5910 1124 ep->ep_queue.get(0);
okini3939 1:0dac72ab5910 1125 ep->unqueueTransfer(ep->getProcessedTD());
okini3939 1:0dac72ab5910 1126 enableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1127 }
okini3939 1:0dac72ab5910 1128 #else
okini3939 1:0dac72ab5910 1129 ep->ep_queue.get();
okini3939 1:0dac72ab5910 1130 #endif
okini3939 1:0dac72ab5910 1131 res = ep->getState();
okini3939 1:0dac72ab5910 1132
okini3939 1:0dac72ab5910 1133 USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str, ep->getStateString(), ep);
okini3939 1:0dac72ab5910 1134
okini3939 1:0dac72ab5910 1135 if (res != USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 1136 return res;
okini3939 1:0dac72ab5910 1137 }
okini3939 1:0dac72ab5910 1138
okini3939 1:0dac72ab5910 1139 return USB_TYPE_OK;
okini3939 1:0dac72ab5910 1140 }
okini3939 1:0dac72ab5910 1141
okini3939 1:0dac72ab5910 1142 return res;
okini3939 1:0dac72ab5910 1143
okini3939 1:0dac72ab5910 1144 }
okini3939 1:0dac72ab5910 1145
okini3939 1:0dac72ab5910 1146
okini3939 1:0dac72ab5910 1147 USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len)
okini3939 1:0dac72ab5910 1148 {
okini3939 1:0dac72ab5910 1149 return controlTransfer(dev, requestType, request, value, index, buf, len, false);
okini3939 1:0dac72ab5910 1150 }
okini3939 1:0dac72ab5910 1151
okini3939 1:0dac72ab5910 1152 USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len)
okini3939 1:0dac72ab5910 1153 {
okini3939 1:0dac72ab5910 1154 return controlTransfer(dev, requestType, request, value, index, buf, len, true);
okini3939 1:0dac72ab5910 1155 }
okini3939 1:0dac72ab5910 1156
okini3939 1:0dac72ab5910 1157 USB_TYPE USBHost::controlTransfer(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len, bool write)
okini3939 1:0dac72ab5910 1158 {
okini3939 1:0dac72ab5910 1159 Lock lock(this);
okini3939 1:0dac72ab5910 1160 USB_DBG_TRANSFER("----- CONTROL %s [dev: %p - hub: %d - port: %d] ------", (write) ? "WRITE" : "READ", dev, dev->getHub(), dev->getPort());
okini3939 1:0dac72ab5910 1161
okini3939 1:0dac72ab5910 1162 int length_transfer = len;
okini3939 1:0dac72ab5910 1163 USB_TYPE res;
okini3939 1:0dac72ab5910 1164 uint32_t token;
okini3939 1:0dac72ab5910 1165
okini3939 1:0dac72ab5910 1166 control->setSpeed(dev->getSpeed());
okini3939 1:0dac72ab5910 1167 control->setSize(dev->getSizeControlEndpoint());
okini3939 1:0dac72ab5910 1168 if (dev->isActiveAddress()) {
okini3939 1:0dac72ab5910 1169 control->setDeviceAddress(dev->getAddress());
okini3939 1:0dac72ab5910 1170 } else {
okini3939 1:0dac72ab5910 1171 control->setDeviceAddress(0);
okini3939 1:0dac72ab5910 1172 }
okini3939 1:0dac72ab5910 1173
okini3939 1:0dac72ab5910 1174 USB_DBG_TRANSFER("Control transfer on device: %d\r\n", control->getDeviceAddress());
okini3939 1:0dac72ab5910 1175 fillControlBuf(requestType, request, value, index, len);
okini3939 1:0dac72ab5910 1176
okini3939 1:0dac72ab5910 1177 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 1178 USB_DBG_TRANSFER("SETUP PACKET: ");
okini3939 1:0dac72ab5910 1179 for (int i = 0; i < 8; i++) {
okini3939 1:0dac72ab5910 1180 printf("%01X ", setupPacket[i]);
okini3939 1:0dac72ab5910 1181 }
okini3939 1:0dac72ab5910 1182 printf("\r\n");
okini3939 1:0dac72ab5910 1183 #endif
okini3939 1:0dac72ab5910 1184
okini3939 1:0dac72ab5910 1185 control->setNextToken(TD_SETUP);
okini3939 1:0dac72ab5910 1186 res = addTransfer(control, (uint8_t*)setupPacket, 8);
okini3939 1:0dac72ab5910 1187
okini3939 1:0dac72ab5910 1188 if (res == USB_TYPE_PROCESSING)
okini3939 1:0dac72ab5910 1189 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 1190 {
okini3939 1:0dac72ab5910 1191 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL);
okini3939 1:0dac72ab5910 1192 if (event.status == osEventTimeout) {
okini3939 1:0dac72ab5910 1193 disableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1194 control->setState(USB_TYPE_ERROR);
okini3939 1:0dac72ab5910 1195 control->ep_queue.get(0);
okini3939 1:0dac72ab5910 1196 control->unqueueTransfer(control->getProcessedTD());
okini3939 1:0dac72ab5910 1197 enableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1198 }
okini3939 1:0dac72ab5910 1199 }
okini3939 1:0dac72ab5910 1200 #else
okini3939 1:0dac72ab5910 1201 control->ep_queue.get();
okini3939 1:0dac72ab5910 1202 #endif
okini3939 1:0dac72ab5910 1203 res = control->getState();
okini3939 1:0dac72ab5910 1204
okini3939 1:0dac72ab5910 1205 USB_DBG_TRANSFER("CONTROL setup stage %s", control->getStateString());
okini3939 1:0dac72ab5910 1206
okini3939 1:0dac72ab5910 1207 if (res != USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 1208 return res;
okini3939 1:0dac72ab5910 1209 }
okini3939 1:0dac72ab5910 1210
okini3939 1:0dac72ab5910 1211 if (length_transfer) {
okini3939 1:0dac72ab5910 1212 token = (write) ? TD_OUT : TD_IN;
okini3939 1:0dac72ab5910 1213 control->setNextToken(token);
okini3939 1:0dac72ab5910 1214 res = addTransfer(control, (uint8_t *)buf, length_transfer);
okini3939 1:0dac72ab5910 1215
okini3939 1:0dac72ab5910 1216 if (res == USB_TYPE_PROCESSING)
okini3939 1:0dac72ab5910 1217 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 1218 {
okini3939 1:0dac72ab5910 1219 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL);
okini3939 1:0dac72ab5910 1220 if (event.status == osEventTimeout) {
okini3939 1:0dac72ab5910 1221 disableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1222 control->setState(USB_TYPE_ERROR);
okini3939 1:0dac72ab5910 1223 control->ep_queue.get(0);
okini3939 1:0dac72ab5910 1224 control->unqueueTransfer(control->getProcessedTD());
okini3939 1:0dac72ab5910 1225 enableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1226 }
okini3939 1:0dac72ab5910 1227 }
okini3939 1:0dac72ab5910 1228 #else
okini3939 1:0dac72ab5910 1229 control->ep_queue.get();
okini3939 1:0dac72ab5910 1230 #endif
okini3939 1:0dac72ab5910 1231 res = control->getState();
okini3939 1:0dac72ab5910 1232
okini3939 1:0dac72ab5910 1233 #if DEBUG_TRANSFER
okini3939 1:0dac72ab5910 1234 USB_DBG_TRANSFER("CONTROL %s stage %s", (write) ? "WRITE" : "READ", control->getStateString());
okini3939 1:0dac72ab5910 1235 if (write) {
okini3939 1:0dac72ab5910 1236 USB_DBG_TRANSFER("CONTROL WRITE buffer");
okini3939 1:0dac72ab5910 1237 for (int i = 0; i < control->getLengthTransferred(); i++) {
okini3939 1:0dac72ab5910 1238 printf("%02X ", buf[i]);
okini3939 1:0dac72ab5910 1239 }
okini3939 1:0dac72ab5910 1240 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 1241 } else {
okini3939 1:0dac72ab5910 1242 USB_DBG_TRANSFER("CONTROL READ SUCCESS [%d bytes transferred]", control->getLengthTransferred());
okini3939 1:0dac72ab5910 1243 for (int i = 0; i < control->getLengthTransferred(); i++) {
okini3939 1:0dac72ab5910 1244 printf("%02X ", buf[i]);
okini3939 1:0dac72ab5910 1245 }
okini3939 1:0dac72ab5910 1246 printf("\r\n\r\n");
okini3939 1:0dac72ab5910 1247 }
okini3939 1:0dac72ab5910 1248 #endif
okini3939 1:0dac72ab5910 1249
okini3939 1:0dac72ab5910 1250 if (res != USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 1251 return res;
okini3939 1:0dac72ab5910 1252 }
okini3939 1:0dac72ab5910 1253 }
okini3939 1:0dac72ab5910 1254
okini3939 1:0dac72ab5910 1255 token = (write) ? TD_IN : TD_OUT;
okini3939 1:0dac72ab5910 1256 control->setNextToken(token);
okini3939 1:0dac72ab5910 1257 res = addTransfer(control, NULL, 0);
okini3939 1:0dac72ab5910 1258 if (res == USB_TYPE_PROCESSING)
okini3939 1:0dac72ab5910 1259 #ifdef USBHOST_OTHER
okini3939 1:0dac72ab5910 1260 {
okini3939 1:0dac72ab5910 1261 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL);
okini3939 1:0dac72ab5910 1262 if (event.status == osEventTimeout) {
okini3939 1:0dac72ab5910 1263 disableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1264 control->setState(USB_TYPE_ERROR);
okini3939 1:0dac72ab5910 1265 control->ep_queue.get(0);
okini3939 1:0dac72ab5910 1266 control->unqueueTransfer(control->getProcessedTD());
okini3939 1:0dac72ab5910 1267 enableList(CONTROL_ENDPOINT);
okini3939 1:0dac72ab5910 1268 }
okini3939 1:0dac72ab5910 1269 }
okini3939 1:0dac72ab5910 1270 #else
okini3939 1:0dac72ab5910 1271 control->ep_queue.get();
okini3939 1:0dac72ab5910 1272 #endif
okini3939 1:0dac72ab5910 1273 res = control->getState();
okini3939 1:0dac72ab5910 1274
okini3939 1:0dac72ab5910 1275 USB_DBG_TRANSFER("CONTROL ack stage %s", control->getStateString());
okini3939 1:0dac72ab5910 1276
okini3939 1:0dac72ab5910 1277 if (res != USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 1278 return res;
okini3939 1:0dac72ab5910 1279 }
okini3939 1:0dac72ab5910 1280
okini3939 1:0dac72ab5910 1281 return USB_TYPE_OK;
okini3939 1:0dac72ab5910 1282 }
okini3939 1:0dac72ab5910 1283
okini3939 1:0dac72ab5910 1284
okini3939 1:0dac72ab5910 1285 void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index, int len)
okini3939 1:0dac72ab5910 1286 {
okini3939 1:0dac72ab5910 1287 setupPacket[0] = requestType;
okini3939 1:0dac72ab5910 1288 setupPacket[1] = request;
okini3939 1:0dac72ab5910 1289 setupPacket[2] = (uint8_t) value;
okini3939 1:0dac72ab5910 1290 setupPacket[3] = (uint8_t) (value >> 8);
okini3939 1:0dac72ab5910 1291 setupPacket[4] = (uint8_t) index;
okini3939 1:0dac72ab5910 1292 setupPacket[5] = (uint8_t) (index >> 8);
okini3939 1:0dac72ab5910 1293 setupPacket[6] = (uint8_t) len;
okini3939 1:0dac72ab5910 1294 setupPacket[7] = (uint8_t) (len >> 8);
okini3939 1:0dac72ab5910 1295 }