only for STM32F769NI-DISCOVERY, porting from mbed OS5 unsupport functions

Committer:
kenjiArai
Date:
Wed Aug 07 05:33:53 2019 +0000
Revision:
0:dae1ac0c0a7b
only for STM32F769NI-DISCOVERY, porting from mbed OS5 unsupport functions

Who changed what in which revision?

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