Changes to support Vodafone K4606
Fork of USBHostWANDongle by
USBHost/USBHost.cpp@9:c9e9817c398c, 2012-07-31 (annotated)
- Committer:
- donatien
- Date:
- Tue Jul 31 10:37:16 2012 +0000
- Revision:
- 9:c9e9817c398c
- Parent:
- 8:0d1ec493842c
- Child:
- 10:08bce4cd973a
- Child:
- 12:a712bad7a979
Renamed Endpoint->USBEndpoint because it conflicted with the Socket API! Made some weird symbols mixups happen that made everything explode when the first USB endpoint was allocated.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
donatien | 0:ae46a0638b2c | 1 | /* Copyright (c) 2010-2011 mbed.org, MIT License |
donatien | 0:ae46a0638b2c | 2 | * |
donatien | 0:ae46a0638b2c | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
donatien | 0:ae46a0638b2c | 4 | * and associated documentation files (the "Software"), to deal in the Software without |
donatien | 0:ae46a0638b2c | 5 | * restriction, including without limitation the rights to use, copy, modify, merge, publish, |
donatien | 0:ae46a0638b2c | 6 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the |
donatien | 0:ae46a0638b2c | 7 | * Software is furnished to do so, subject to the following conditions: |
donatien | 0:ae46a0638b2c | 8 | * |
donatien | 0:ae46a0638b2c | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
donatien | 0:ae46a0638b2c | 10 | * substantial portions of the Software. |
donatien | 0:ae46a0638b2c | 11 | * |
donatien | 0:ae46a0638b2c | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
donatien | 0:ae46a0638b2c | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
donatien | 0:ae46a0638b2c | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
donatien | 0:ae46a0638b2c | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
donatien | 0:ae46a0638b2c | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
donatien | 0:ae46a0638b2c | 17 | */ |
donatien | 0:ae46a0638b2c | 18 | |
donatien | 0:ae46a0638b2c | 19 | |
donatien | 0:ae46a0638b2c | 20 | #define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT... |
donatien | 0:ae46a0638b2c | 21 | #ifndef __MODULE__ |
donatien | 0:ae46a0638b2c | 22 | #define __MODULE__ "USBHost.cpp" |
donatien | 0:ae46a0638b2c | 23 | #endif |
donatien | 0:ae46a0638b2c | 24 | |
donatien | 0:ae46a0638b2c | 25 | #include "dbg.h" |
donatien | 0:ae46a0638b2c | 26 | #include <cstdint> |
donatien | 0:ae46a0638b2c | 27 | |
donatien | 0:ae46a0638b2c | 28 | #include "USBHost.h" |
donatien | 0:ae46a0638b2c | 29 | #include "rtos.h" |
donatien | 0:ae46a0638b2c | 30 | |
donatien | 0:ae46a0638b2c | 31 | |
donatien | 6:075e36a3463e | 32 | #define NB_MAX_INTF 2 |
donatien | 0:ae46a0638b2c | 33 | |
donatien | 0:ae46a0638b2c | 34 | USBHost * USBHost::instHost = NULL; |
donatien | 0:ae46a0638b2c | 35 | |
donatien | 0:ae46a0638b2c | 36 | USBHost::USBHost() |
donatien | 0:ae46a0638b2c | 37 | #if 0 //try not to use this |
donatien | 0:ae46a0638b2c | 38 | : m_usbQueue(), m_usbThread(3, this, &USBHost::usbProcess) |
donatien | 0:ae46a0638b2c | 39 | #endif |
donatien | 0:ae46a0638b2c | 40 | { |
donatien | 0:ae46a0638b2c | 41 | headControlEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 42 | headBulkEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 43 | headInterruptEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 44 | tailControlEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 45 | tailBulkEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 46 | tailInterruptEndpoint = NULL; |
donatien | 0:ae46a0638b2c | 47 | |
donatien | 0:ae46a0638b2c | 48 | nb_devices = 0; |
donatien | 0:ae46a0638b2c | 49 | lenReportDescr = 0; |
donatien | 0:ae46a0638b2c | 50 | |
donatien | 0:ae46a0638b2c | 51 | controlEndpointAllocated = false; |
donatien | 0:ae46a0638b2c | 52 | |
donatien | 0:ae46a0638b2c | 53 | for (int i = 0; i < MAX_DEVICE_NB; i++) { |
donatien | 0:ae46a0638b2c | 54 | deviceInUse[i] = false; |
donatien | 0:ae46a0638b2c | 55 | devices[i].setAddress(i + 1); |
donatien | 0:ae46a0638b2c | 56 | deviceReset[i] = false; |
donatien | 0:ae46a0638b2c | 57 | } |
donatien | 0:ae46a0638b2c | 58 | } |
donatien | 0:ae46a0638b2c | 59 | |
donatien | 0:ae46a0638b2c | 60 | |
donatien | 0:ae46a0638b2c | 61 | void USBHost::transferCompleted(volatile uint32_t addr) { |
donatien | 0:ae46a0638b2c | 62 | #if 0 //try not to use this |
donatien | 0:ae46a0638b2c | 63 | Interrupt::enter(); |
donatien | 0:ae46a0638b2c | 64 | m_usbQueue.post(addr); |
donatien | 0:ae46a0638b2c | 65 | Interrupt::leave(); |
donatien | 0:ae46a0638b2c | 66 | #else |
donatien | 0:ae46a0638b2c | 67 | |
donatien | 0:ae46a0638b2c | 68 | if(addr == NULL) //Nothing to process? |
donatien | 0:ae46a0638b2c | 69 | { |
donatien | 0:ae46a0638b2c | 70 | return; |
donatien | 0:ae46a0638b2c | 71 | } |
donatien | 0:ae46a0638b2c | 72 | |
donatien | 0:ae46a0638b2c | 73 | volatile HCTD* tdList = NULL; |
donatien | 0:ae46a0638b2c | 74 | |
donatien | 0:ae46a0638b2c | 75 | //First we must reverse the list order and dequeue each TD |
donatien | 0:ae46a0638b2c | 76 | do |
donatien | 0:ae46a0638b2c | 77 | { |
donatien | 0:ae46a0638b2c | 78 | volatile HCTD* td = (volatile HCTD*)addr; |
donatien | 0:ae46a0638b2c | 79 | |
donatien | 0:ae46a0638b2c | 80 | if(td->control & 0xF0000000 != 0) |
donatien | 0:ae46a0638b2c | 81 | { |
donatien | 0:ae46a0638b2c | 82 | WARN("Condition code %02x", td->control >> 28); |
donatien | 0:ae46a0638b2c | 83 | } |
donatien | 0:ae46a0638b2c | 84 | |
donatien | 0:ae46a0638b2c | 85 | addr = td->nextTD; //Dequeue from physical list |
donatien | 0:ae46a0638b2c | 86 | td->nextTD = (uint32_t)tdList; //Enqueue into reversed list |
donatien | 0:ae46a0638b2c | 87 | tdList = td; |
donatien | 0:ae46a0638b2c | 88 | } while(addr); |
donatien | 0:ae46a0638b2c | 89 | |
donatien | 0:ae46a0638b2c | 90 | //Now we can process the list |
donatien | 9:c9e9817c398c | 91 | USBEndpoint * volatile iter = NULL; |
donatien | 0:ae46a0638b2c | 92 | |
donatien | 0:ae46a0638b2c | 93 | while(tdList != NULL) |
donatien | 0:ae46a0638b2c | 94 | { |
donatien | 0:ae46a0638b2c | 95 | bool found = false; |
donatien | 0:ae46a0638b2c | 96 | volatile HCTD* td = tdList; |
donatien | 0:ae46a0638b2c | 97 | tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below |
donatien | 0:ae46a0638b2c | 98 | for (int i = 0; i < 3; i++) { |
donatien | 0:ae46a0638b2c | 99 | if (found) { |
donatien | 0:ae46a0638b2c | 100 | break; |
donatien | 0:ae46a0638b2c | 101 | } |
donatien | 0:ae46a0638b2c | 102 | iter = (i == 0) ? headControlEndpoint : ( (i == 1) ? headBulkEndpoint : headInterruptEndpoint); |
donatien | 0:ae46a0638b2c | 103 | while (iter != NULL) { |
donatien | 0:ae46a0638b2c | 104 | if (iter->getProcessedTD() == td) { |
donatien | 0:ae46a0638b2c | 105 | DBG("td=%p FOUND ed: %08X", td, (void *)iter->getHCED()); |
donatien | 0:ae46a0638b2c | 106 | if (((HCTD *)td)->control >> 28) { |
donatien | 0:ae46a0638b2c | 107 | DBG("TD Error: %d", td->control >> 28); |
donatien | 0:ae46a0638b2c | 108 | iter->setState(USB_TYPE_TDFAIL); |
donatien | 0:ae46a0638b2c | 109 | } else if ((uint32_t)iter->getHCED() & 0x1) { |
donatien | 0:ae46a0638b2c | 110 | DBG("HALTED"); |
donatien | 0:ae46a0638b2c | 111 | iter->setState(USB_TYPE_HALTED); |
donatien | 0:ae46a0638b2c | 112 | } else if (!td->currBufPtr) { |
donatien | 0:ae46a0638b2c | 113 | DBG("!%p", iter); |
donatien | 0:ae46a0638b2c | 114 | iter->setState(USB_TYPE_IDLE); |
donatien | 0:ae46a0638b2c | 115 | found=true; |
donatien | 0:ae46a0638b2c | 116 | } else { |
donatien | 0:ae46a0638b2c | 117 | DBG("!%p", iter); |
donatien | 0:ae46a0638b2c | 118 | iter->setState(USB_TYPE_IDLE); |
donatien | 0:ae46a0638b2c | 119 | iter->setLengthTransferred(td->currBufPtr - iter->getBufStart()); |
donatien | 0:ae46a0638b2c | 120 | found=true; |
donatien | 0:ae46a0638b2c | 121 | } |
donatien | 0:ae46a0638b2c | 122 | break; |
donatien | 0:ae46a0638b2c | 123 | } |
donatien | 0:ae46a0638b2c | 124 | iter = iter->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 125 | } |
donatien | 0:ae46a0638b2c | 126 | } |
donatien | 0:ae46a0638b2c | 127 | |
donatien | 0:ae46a0638b2c | 128 | |
donatien | 0:ae46a0638b2c | 129 | if (found) { |
donatien | 0:ae46a0638b2c | 130 | iter->unqueueTransfer(td); |
donatien | 0:ae46a0638b2c | 131 | |
donatien | 0:ae46a0638b2c | 132 | if (iter->getType() != CONTROL_ENDPOINT) { |
donatien | 0:ae46a0638b2c | 133 | iter->call(); |
donatien | 0:ae46a0638b2c | 134 | } |
donatien | 0:ae46a0638b2c | 135 | } |
donatien | 0:ae46a0638b2c | 136 | else |
donatien | 0:ae46a0638b2c | 137 | { |
donatien | 0:ae46a0638b2c | 138 | WARN("TD not found!!!"); |
donatien | 0:ae46a0638b2c | 139 | freeTD((uint8_t *)td); //Device must have been disconnected meanwhile |
donatien | 0:ae46a0638b2c | 140 | } |
donatien | 0:ae46a0638b2c | 141 | |
donatien | 0:ae46a0638b2c | 142 | } |
donatien | 0:ae46a0638b2c | 143 | #endif |
donatien | 0:ae46a0638b2c | 144 | } |
donatien | 0:ae46a0638b2c | 145 | |
donatien | 0:ae46a0638b2c | 146 | USBHost * USBHost::getHostInst() { |
donatien | 0:ae46a0638b2c | 147 | if (instHost == NULL) { |
donatien | 0:ae46a0638b2c | 148 | instHost = new USBHost(); |
donatien | 0:ae46a0638b2c | 149 | instHost->init(); |
donatien | 0:ae46a0638b2c | 150 | } |
donatien | 0:ae46a0638b2c | 151 | return instHost; |
donatien | 0:ae46a0638b2c | 152 | } |
donatien | 0:ae46a0638b2c | 153 | |
donatien | 0:ae46a0638b2c | 154 | |
donatien | 0:ae46a0638b2c | 155 | /* |
donatien | 0:ae46a0638b2c | 156 | * Call in ISR when a device has been connected |
donatien | 0:ae46a0638b2c | 157 | */ |
donatien | 0:ae46a0638b2c | 158 | void USBHost::deviceConnected(int hub, int port, bool lowSpeed) { |
donatien | 0:ae46a0638b2c | 159 | |
donatien | 0:ae46a0638b2c | 160 | for (int i = 0; i < MAX_DEVICE_NB; i++) { |
donatien | 0:ae46a0638b2c | 161 | if (!deviceInUse[i]) { |
donatien | 0:ae46a0638b2c | 162 | deviceInUse[i] = true; |
donatien | 0:ae46a0638b2c | 163 | WARN("will call init on device %p: speed: %d", (void *)&devices[i], lowSpeed); |
donatien | 0:ae46a0638b2c | 164 | devices[i].init(hub, port, lowSpeed); |
donatien | 0:ae46a0638b2c | 165 | deviceReset[i] = false; |
donatien | 0:ae46a0638b2c | 166 | break; |
donatien | 0:ae46a0638b2c | 167 | } |
donatien | 0:ae46a0638b2c | 168 | } |
donatien | 0:ae46a0638b2c | 169 | |
donatien | 0:ae46a0638b2c | 170 | if (!controlEndpointAllocated) { |
donatien | 0:ae46a0638b2c | 171 | control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); |
donatien | 9:c9e9817c398c | 172 | addEndpoint(NULL, 0, (USBEndpoint*)control); |
donatien | 0:ae46a0638b2c | 173 | controlEndpointAllocated = true; |
donatien | 0:ae46a0638b2c | 174 | } |
donatien | 0:ae46a0638b2c | 175 | } |
donatien | 0:ae46a0638b2c | 176 | |
donatien | 0:ae46a0638b2c | 177 | /* |
donatien | 0:ae46a0638b2c | 178 | * Call in ISR when a device has been disconnected |
donatien | 0:ae46a0638b2c | 179 | */ |
donatien | 0:ae46a0638b2c | 180 | void USBHost::deviceDisconnected(int hub, int port, volatile uint32_t addr) { |
donatien | 0:ae46a0638b2c | 181 | |
donatien | 0:ae46a0638b2c | 182 | bool controlListState = disableControlList(); |
donatien | 0:ae46a0638b2c | 183 | bool bulkListState = disableBulkList(); |
donatien | 0:ae46a0638b2c | 184 | bool interruptListState = disableInterruptList(); |
donatien | 0:ae46a0638b2c | 185 | |
donatien | 0:ae46a0638b2c | 186 | transferCompleted(addr); //Finish processing any pending completed TD |
donatien | 0:ae46a0638b2c | 187 | |
donatien | 0:ae46a0638b2c | 188 | for (int i = 0; i < MAX_DEVICE_NB; i++) { |
donatien | 0:ae46a0638b2c | 189 | if ((devices[i].getHub() == hub) && (devices[i].getPort() == port)) { |
donatien | 0:ae46a0638b2c | 190 | WARN("device disconnected: %p", (void *)&devices[i]); |
donatien | 0:ae46a0638b2c | 191 | deviceInUse[i] = false; |
donatien | 0:ae46a0638b2c | 192 | deviceReset[i] = false; |
donatien | 0:ae46a0638b2c | 193 | freeDevice((USBDeviceConnected*)&devices[i]); |
donatien | 0:ae46a0638b2c | 194 | break; |
donatien | 0:ae46a0638b2c | 195 | } |
donatien | 0:ae46a0638b2c | 196 | } |
donatien | 0:ae46a0638b2c | 197 | nb_devices--; |
donatien | 0:ae46a0638b2c | 198 | |
donatien | 0:ae46a0638b2c | 199 | if (controlListState) enableControlList(); |
donatien | 0:ae46a0638b2c | 200 | if (bulkListState) enableBulkList(); |
donatien | 0:ae46a0638b2c | 201 | if (interruptListState) enableInterruptList(); |
donatien | 0:ae46a0638b2c | 202 | } |
donatien | 0:ae46a0638b2c | 203 | |
donatien | 0:ae46a0638b2c | 204 | void USBHost::freeDevice(USBDeviceConnected * dev) { |
donatien | 9:c9e9817c398c | 205 | USBEndpoint * ep = NULL; |
donatien | 0:ae46a0638b2c | 206 | // HCTD * td = NULL; |
donatien | 0:ae46a0638b2c | 207 | HCED * ed = NULL; |
donatien | 0:ae46a0638b2c | 208 | |
donatien | 0:ae46a0638b2c | 209 | for (int j = 0; j < dev->getNbInterface(); j++) { |
donatien | 0:ae46a0638b2c | 210 | DBG("FREE INTF %d, %p, nb_endpot: %d", j, (void *)dev->getInterface(j), dev->getInterface(j)->nb_endpoint); |
donatien | 0:ae46a0638b2c | 211 | for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) { |
donatien | 0:ae46a0638b2c | 212 | if ((ep = dev->getEndpoint(j, i)) != NULL) { |
donatien | 9:c9e9817c398c | 213 | DBG("Freeing USBEndpoint"); |
donatien | 0:ae46a0638b2c | 214 | ed = (HCED *)ep->getHCED(); |
donatien | 0:ae46a0638b2c | 215 | ed->control |= (1 << 13); //sKip bit |
donatien | 9:c9e9817c398c | 216 | DBG("Dequeueing USBEndpoint"); |
donatien | 0:ae46a0638b2c | 217 | unqueueEndpoint(ep); |
donatien | 0:ae46a0638b2c | 218 | |
donatien | 7:c4483d48fe96 | 219 | DBG("Freeing first transfer descriptor"); |
donatien | 7:c4483d48fe96 | 220 | freeTD((volatile uint8_t*)ep->getTDList()[0]); |
donatien | 7:c4483d48fe96 | 221 | DBG("Freeing second transfer descriptor"); |
donatien | 7:c4483d48fe96 | 222 | freeTD((volatile uint8_t*)ep->getTDList()[1]); |
donatien | 0:ae46a0638b2c | 223 | |
donatien | 9:c9e9817c398c | 224 | DBG("Freeing USBEndpoint descriptor"); |
donatien | 0:ae46a0638b2c | 225 | freeED((uint8_t *)ep->getHCED()); |
donatien | 0:ae46a0638b2c | 226 | } |
donatien | 0:ae46a0638b2c | 227 | //printBulk(); |
donatien | 0:ae46a0638b2c | 228 | //printInt(); |
donatien | 0:ae46a0638b2c | 229 | } |
donatien | 0:ae46a0638b2c | 230 | } |
donatien | 0:ae46a0638b2c | 231 | DBG("Disconnecting device"); |
donatien | 0:ae46a0638b2c | 232 | dev->disconnect(); |
donatien | 0:ae46a0638b2c | 233 | DBG("Device disconnected"); |
donatien | 0:ae46a0638b2c | 234 | } |
donatien | 0:ae46a0638b2c | 235 | |
donatien | 0:ae46a0638b2c | 236 | |
donatien | 9:c9e9817c398c | 237 | void USBHost::unqueueEndpoint(USBEndpoint * ep) { |
donatien | 9:c9e9817c398c | 238 | USBEndpoint * prec = NULL; |
donatien | 9:c9e9817c398c | 239 | USBEndpoint * current = NULL; |
donatien | 0:ae46a0638b2c | 240 | bool found = false; |
donatien | 0:ae46a0638b2c | 241 | |
donatien | 0:ae46a0638b2c | 242 | DBG("want to unqueue ep: %p", (void *)ep->getHCED()); |
donatien | 0:ae46a0638b2c | 243 | |
donatien | 0:ae46a0638b2c | 244 | for (int i = 0; i < 2; i++) { |
donatien | 0:ae46a0638b2c | 245 | if (found) { |
donatien | 9:c9e9817c398c | 246 | DBG("USBEndpoint unqueued: %p", (void *)ep->getHCED()); |
donatien | 0:ae46a0638b2c | 247 | break; |
donatien | 0:ae46a0638b2c | 248 | } |
donatien | 9:c9e9817c398c | 249 | current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)headInterruptEndpoint; |
donatien | 0:ae46a0638b2c | 250 | prec = current; |
donatien | 0:ae46a0638b2c | 251 | while (current != NULL) { |
donatien | 0:ae46a0638b2c | 252 | if (current == ep) { |
donatien | 0:ae46a0638b2c | 253 | if (current->nextEndpoint() != NULL) { |
donatien | 0:ae46a0638b2c | 254 | prec->queueEndpoint(current->nextEndpoint()); |
donatien | 0:ae46a0638b2c | 255 | if (current == headBulkEndpoint) { |
donatien | 0:ae46a0638b2c | 256 | updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED()); |
donatien | 0:ae46a0638b2c | 257 | headBulkEndpoint = current->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 258 | } |
donatien | 0:ae46a0638b2c | 259 | if (current == headInterruptEndpoint) { |
donatien | 0:ae46a0638b2c | 260 | updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED()); |
donatien | 0:ae46a0638b2c | 261 | headInterruptEndpoint = current->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 262 | } |
donatien | 0:ae46a0638b2c | 263 | } else { |
donatien | 0:ae46a0638b2c | 264 | prec->queueEndpoint(NULL); |
donatien | 0:ae46a0638b2c | 265 | if (current == headBulkEndpoint) { |
donatien | 0:ae46a0638b2c | 266 | updateBulkHeadED(0); |
donatien | 0:ae46a0638b2c | 267 | headBulkEndpoint = current->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 268 | } |
donatien | 0:ae46a0638b2c | 269 | if (current == headInterruptEndpoint) { |
donatien | 0:ae46a0638b2c | 270 | updateInterruptHeadED(0); |
donatien | 0:ae46a0638b2c | 271 | headInterruptEndpoint = current->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 272 | } |
donatien | 0:ae46a0638b2c | 273 | } |
donatien | 0:ae46a0638b2c | 274 | found = true; |
donatien | 0:ae46a0638b2c | 275 | current->setState(USB_TYPE_FREE); |
donatien | 0:ae46a0638b2c | 276 | break; |
donatien | 0:ae46a0638b2c | 277 | } |
donatien | 0:ae46a0638b2c | 278 | prec = current; |
donatien | 0:ae46a0638b2c | 279 | current = current->nextEndpoint(); |
donatien | 0:ae46a0638b2c | 280 | } |
donatien | 0:ae46a0638b2c | 281 | } |
donatien | 0:ae46a0638b2c | 282 | //printBulk(); |
donatien | 0:ae46a0638b2c | 283 | //printInt(); |
donatien | 0:ae46a0638b2c | 284 | } |
donatien | 0:ae46a0638b2c | 285 | |
donatien | 0:ae46a0638b2c | 286 | |
donatien | 0:ae46a0638b2c | 287 | USBDeviceConnected * USBHost::getDevice(uint8_t index) { |
donatien | 0:ae46a0638b2c | 288 | if ((index >= MAX_DEVICE_NB) || (!deviceInUse[index])) { |
donatien | 0:ae46a0638b2c | 289 | return NULL; |
donatien | 0:ae46a0638b2c | 290 | } |
donatien | 0:ae46a0638b2c | 291 | return (USBDeviceConnected*)&devices[index]; |
donatien | 0:ae46a0638b2c | 292 | } |
donatien | 0:ae46a0638b2c | 293 | |
donatien | 0:ae46a0638b2c | 294 | |
donatien | 0:ae46a0638b2c | 295 | |
donatien | 9:c9e9817c398c | 296 | // create an USBEndpoint descriptor. the USBEndpoint is not linked |
donatien | 9:c9e9817c398c | 297 | USBEndpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) { |
donatien | 0:ae46a0638b2c | 298 | int i = 0; |
donatien | 0:ae46a0638b2c | 299 | HCED * ed = (HCED *)getED(); |
donatien | 0:ae46a0638b2c | 300 | HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() }; |
donatien | 0:ae46a0638b2c | 301 | |
donatien | 0:ae46a0638b2c | 302 | memset((void *)td_list[0], 0x00, sizeof(HCTD)); |
donatien | 0:ae46a0638b2c | 303 | memset((void *)td_list[1], 0x00, sizeof(HCTD)); |
donatien | 0:ae46a0638b2c | 304 | |
donatien | 9:c9e9817c398c | 305 | // search a free USBEndpoint |
donatien | 0:ae46a0638b2c | 306 | for (i = 0; i < MAX_ENDPOINT; i++) { |
donatien | 0:ae46a0638b2c | 307 | if (endpoints[i].getState() == USB_TYPE_FREE) { |
donatien | 0:ae46a0638b2c | 308 | DBG("Trying to create ep"); |
donatien | 0:ae46a0638b2c | 309 | endpoints[i].init(ed, type, dir, size, addr, td_list); |
donatien | 0:ae46a0638b2c | 310 | //endpoints[i].queueTransfer(nullTd); |
donatien | 9:c9e9817c398c | 311 | DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d", &endpoints[i], type, dir, size, addr); |
donatien | 0:ae46a0638b2c | 312 | return &endpoints[i]; |
donatien | 0:ae46a0638b2c | 313 | } |
donatien | 0:ae46a0638b2c | 314 | } |
donatien | 0:ae46a0638b2c | 315 | DBG("could not allocate more endpoints!!!!"); |
donatien | 0:ae46a0638b2c | 316 | return NULL; |
donatien | 0:ae46a0638b2c | 317 | } |
donatien | 0:ae46a0638b2c | 318 | |
donatien | 0:ae46a0638b2c | 319 | |
donatien | 0:ae46a0638b2c | 320 | void USBHost::resetDevice(USBDeviceConnected * dev) { |
donatien | 0:ae46a0638b2c | 321 | int index = findDevice(dev); |
donatien | 0:ae46a0638b2c | 322 | if ((index != -1) && (!deviceReset[index])) { |
donatien | 0:ae46a0638b2c | 323 | resetPort(dev->getHub(), dev->getPort()); |
donatien | 0:ae46a0638b2c | 324 | deviceReset[index] = true; |
donatien | 0:ae46a0638b2c | 325 | } |
donatien | 0:ae46a0638b2c | 326 | } |
donatien | 0:ae46a0638b2c | 327 | |
donatien | 9:c9e9817c398c | 328 | // link the USBEndpoint to the linked list and attach an USBEndpoint to a device |
donatien | 9:c9e9817c398c | 329 | bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep) { |
donatien | 0:ae46a0638b2c | 330 | |
donatien | 0:ae46a0638b2c | 331 | if (ep == NULL) { |
donatien | 0:ae46a0638b2c | 332 | return false; |
donatien | 0:ae46a0638b2c | 333 | } |
donatien | 0:ae46a0638b2c | 334 | |
donatien | 0:ae46a0638b2c | 335 | DBG("New ep %p", ep); |
donatien | 0:ae46a0638b2c | 336 | |
donatien | 0:ae46a0638b2c | 337 | HCED * prevEd; |
donatien | 0:ae46a0638b2c | 338 | |
donatien | 9:c9e9817c398c | 339 | // set device address in the USBEndpoint descriptor |
donatien | 0:ae46a0638b2c | 340 | if (dev == NULL) { |
donatien | 0:ae46a0638b2c | 341 | ep->setDeviceAddress(0); |
donatien | 0:ae46a0638b2c | 342 | } else { |
donatien | 0:ae46a0638b2c | 343 | ep->setDeviceAddress(dev->getAddress()); |
donatien | 0:ae46a0638b2c | 344 | } |
donatien | 0:ae46a0638b2c | 345 | |
donatien | 0:ae46a0638b2c | 346 | if (dev != NULL && dev->getSpeed()) { |
donatien | 9:c9e9817c398c | 347 | DBG("add USBEndpoint: set speed"); |
donatien | 0:ae46a0638b2c | 348 | ep->setSpeed(dev->getSpeed()); |
donatien | 0:ae46a0638b2c | 349 | } |
donatien | 0:ae46a0638b2c | 350 | |
donatien | 9:c9e9817c398c | 351 | // queue the new USBEndpoint on the ED list |
donatien | 0:ae46a0638b2c | 352 | switch (ep->getType()) { |
donatien | 0:ae46a0638b2c | 353 | |
donatien | 0:ae46a0638b2c | 354 | case CONTROL_ENDPOINT: |
donatien | 0:ae46a0638b2c | 355 | prevEd = ( HCED*) controlHeadED(); |
donatien | 0:ae46a0638b2c | 356 | if (!prevEd) { |
donatien | 0:ae46a0638b2c | 357 | updateControlHeadED((uint32_t) ep->getHCED()); |
donatien | 9:c9e9817c398c | 358 | DBG("First control USBEndpoint: %08X", (uint32_t) ep->getHCED()); |
donatien | 0:ae46a0638b2c | 359 | headControlEndpoint = ep; |
donatien | 0:ae46a0638b2c | 360 | tailControlEndpoint = ep; |
donatien | 0:ae46a0638b2c | 361 | return true; |
donatien | 0:ae46a0638b2c | 362 | } |
donatien | 0:ae46a0638b2c | 363 | tailControlEndpoint->queueEndpoint(ep); |
donatien | 0:ae46a0638b2c | 364 | tailControlEndpoint = ep; |
donatien | 0:ae46a0638b2c | 365 | return true; |
donatien | 0:ae46a0638b2c | 366 | |
donatien | 0:ae46a0638b2c | 367 | case BULK_ENDPOINT: |
donatien | 0:ae46a0638b2c | 368 | prevEd = ( HCED*) bulkHeadED(); |
donatien | 0:ae46a0638b2c | 369 | if (!prevEd) { |
donatien | 0:ae46a0638b2c | 370 | updateBulkHeadED((uint32_t) ep->getHCED()); |
donatien | 9:c9e9817c398c | 371 | //DBG("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); |
donatien | 0:ae46a0638b2c | 372 | headBulkEndpoint = ep; |
donatien | 0:ae46a0638b2c | 373 | tailBulkEndpoint = ep; |
donatien | 0:ae46a0638b2c | 374 | break; |
donatien | 0:ae46a0638b2c | 375 | } |
donatien | 0:ae46a0638b2c | 376 | tailBulkEndpoint->queueEndpoint(ep); |
donatien | 0:ae46a0638b2c | 377 | tailBulkEndpoint = ep; |
donatien | 0:ae46a0638b2c | 378 | break; |
donatien | 0:ae46a0638b2c | 379 | |
donatien | 0:ae46a0638b2c | 380 | case INTERRUPT_ENDPOINT: |
donatien | 0:ae46a0638b2c | 381 | prevEd = ( HCED*) interruptHeadED(); |
donatien | 0:ae46a0638b2c | 382 | if (!prevEd) { |
donatien | 0:ae46a0638b2c | 383 | updateInterruptHeadED((uint32_t) ep->getHCED()); |
donatien | 9:c9e9817c398c | 384 | //DBG("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); |
donatien | 0:ae46a0638b2c | 385 | headInterruptEndpoint = ep; |
donatien | 0:ae46a0638b2c | 386 | tailInterruptEndpoint = ep; |
donatien | 0:ae46a0638b2c | 387 | break; |
donatien | 0:ae46a0638b2c | 388 | } |
donatien | 0:ae46a0638b2c | 389 | tailInterruptEndpoint->queueEndpoint(ep); |
donatien | 0:ae46a0638b2c | 390 | tailInterruptEndpoint = ep; |
donatien | 0:ae46a0638b2c | 391 | break; |
donatien | 0:ae46a0638b2c | 392 | default: |
donatien | 0:ae46a0638b2c | 393 | return false; |
donatien | 0:ae46a0638b2c | 394 | } |
donatien | 0:ae46a0638b2c | 395 | |
donatien | 0:ae46a0638b2c | 396 | dev->addEndpoint(intf_nb, ep); |
donatien | 0:ae46a0638b2c | 397 | //printBulk(); |
donatien | 0:ae46a0638b2c | 398 | //printInt(); |
donatien | 0:ae46a0638b2c | 399 | |
donatien | 0:ae46a0638b2c | 400 | return true; |
donatien | 0:ae46a0638b2c | 401 | } |
donatien | 0:ae46a0638b2c | 402 | |
donatien | 0:ae46a0638b2c | 403 | |
donatien | 0:ae46a0638b2c | 404 | int USBHost::findDevice(USBDeviceConnected * dev) { |
donatien | 0:ae46a0638b2c | 405 | for (int i = 0; i < MAX_DEVICE_NB; i++) { |
donatien | 0:ae46a0638b2c | 406 | if (dev == &devices[i]) { |
donatien | 0:ae46a0638b2c | 407 | return i; |
donatien | 0:ae46a0638b2c | 408 | } |
donatien | 0:ae46a0638b2c | 409 | } |
donatien | 0:ae46a0638b2c | 410 | return -1; |
donatien | 0:ae46a0638b2c | 411 | } |
donatien | 0:ae46a0638b2c | 412 | |
donatien | 0:ae46a0638b2c | 413 | void USBHost::printBulk() { |
donatien | 0:ae46a0638b2c | 414 | HCED * hced = (HCED *)bulkHeadED(); |
donatien | 0:ae46a0638b2c | 415 | HCTD * hctd = NULL; |
donatien | 0:ae46a0638b2c | 416 | printf("---------State of Bulk:--------\r\n"); |
donatien | 0:ae46a0638b2c | 417 | while (hced != NULL) { |
donatien | 0:ae46a0638b2c | 418 | printf("hced: %p\r\n", hced); |
donatien | 0:ae46a0638b2c | 419 | hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 420 | while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) { |
donatien | 0:ae46a0638b2c | 421 | printf("\thctd: %p\r\n", hctd); |
donatien | 0:ae46a0638b2c | 422 | hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 423 | } |
donatien | 0:ae46a0638b2c | 424 | printf("\thctd: %p\r\n", hctd); |
donatien | 0:ae46a0638b2c | 425 | hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 426 | } |
donatien | 0:ae46a0638b2c | 427 | printf("--------------------\r\n"); |
donatien | 0:ae46a0638b2c | 428 | } |
donatien | 0:ae46a0638b2c | 429 | |
donatien | 0:ae46a0638b2c | 430 | void USBHost::printInt() { |
donatien | 0:ae46a0638b2c | 431 | HCED * hced = (HCED *)interruptHeadED(); |
donatien | 0:ae46a0638b2c | 432 | HCTD * hctd = NULL; |
donatien | 0:ae46a0638b2c | 433 | printf("---------State of Int:--------\r\n"); |
donatien | 0:ae46a0638b2c | 434 | while (hced != NULL) { |
donatien | 0:ae46a0638b2c | 435 | printf("hced: %p\r\n", hced); |
donatien | 0:ae46a0638b2c | 436 | hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 437 | while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) { |
donatien | 0:ae46a0638b2c | 438 | printf("\thctd: %p\r\n", hctd); |
donatien | 0:ae46a0638b2c | 439 | hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 440 | } |
donatien | 0:ae46a0638b2c | 441 | printf("\thctd: %p\r\n", hctd); |
donatien | 0:ae46a0638b2c | 442 | hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f)); |
donatien | 0:ae46a0638b2c | 443 | } |
donatien | 0:ae46a0638b2c | 444 | printf("--------------------\r\n"); |
donatien | 0:ae46a0638b2c | 445 | } |
donatien | 0:ae46a0638b2c | 446 | |
donatien | 0:ae46a0638b2c | 447 | |
donatien | 0:ae46a0638b2c | 448 | // add a transfer on the TD linked list |
donatien | 9:c9e9817c398c | 449 | USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) { |
donatien | 0:ae46a0638b2c | 450 | |
donatien | 0:ae46a0638b2c | 451 | // allocate a TD which will be freed in TDcompletion |
donatien | 0:ae46a0638b2c | 452 | volatile HCTD * td = ed->getNextTD(); |
donatien | 0:ae46a0638b2c | 453 | if (td == NULL) { |
donatien | 0:ae46a0638b2c | 454 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 455 | } |
donatien | 0:ae46a0638b2c | 456 | |
donatien | 0:ae46a0638b2c | 457 | DBG("Next td = %p",td); |
donatien | 0:ae46a0638b2c | 458 | |
donatien | 0:ae46a0638b2c | 459 | uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT )); |
donatien | 0:ae46a0638b2c | 460 | |
donatien | 0:ae46a0638b2c | 461 | uint32_t td_toggle; |
donatien | 0:ae46a0638b2c | 462 | |
donatien | 0:ae46a0638b2c | 463 | if (ed->getType() == CONTROL_ENDPOINT) { |
donatien | 0:ae46a0638b2c | 464 | if (ed->isSetup()) { |
donatien | 0:ae46a0638b2c | 465 | td_toggle = TD_TOGGLE_0; |
donatien | 0:ae46a0638b2c | 466 | } else { |
donatien | 0:ae46a0638b2c | 467 | td_toggle = TD_TOGGLE_1; |
donatien | 0:ae46a0638b2c | 468 | } |
donatien | 0:ae46a0638b2c | 469 | } else { |
donatien | 0:ae46a0638b2c | 470 | td_toggle = 0; |
donatien | 0:ae46a0638b2c | 471 | } |
donatien | 0:ae46a0638b2c | 472 | |
donatien | 0:ae46a0638b2c | 473 | DBG("Buf=%d, len=%d", buf, len); |
donatien | 0:ae46a0638b2c | 474 | td->control = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC); |
donatien | 0:ae46a0638b2c | 475 | td->currBufPtr = (uint32_t) buf; |
donatien | 0:ae46a0638b2c | 476 | td->bufEnd = (uint32_t)(buf + (len - 1)); |
donatien | 0:ae46a0638b2c | 477 | |
donatien | 0:ae46a0638b2c | 478 | DBG("Now do queue transfer on ep %p", ed); |
donatien | 0:ae46a0638b2c | 479 | |
donatien | 0:ae46a0638b2c | 480 | ed->queueTransfer(); |
donatien | 0:ae46a0638b2c | 481 | |
donatien | 0:ae46a0638b2c | 482 | DBG("Enable list if needed"); |
donatien | 0:ae46a0638b2c | 483 | |
donatien | 0:ae46a0638b2c | 484 | switch (ed->getType()) { |
donatien | 0:ae46a0638b2c | 485 | case CONTROL_ENDPOINT: |
donatien | 0:ae46a0638b2c | 486 | enableControlList(); |
donatien | 0:ae46a0638b2c | 487 | break; |
donatien | 0:ae46a0638b2c | 488 | case BULK_ENDPOINT: |
donatien | 0:ae46a0638b2c | 489 | enableBulkList(); |
donatien | 0:ae46a0638b2c | 490 | break; |
donatien | 0:ae46a0638b2c | 491 | case INTERRUPT_ENDPOINT: |
donatien | 0:ae46a0638b2c | 492 | //printInt(); |
donatien | 0:ae46a0638b2c | 493 | enableInterruptList(); |
donatien | 0:ae46a0638b2c | 494 | break; |
donatien | 0:ae46a0638b2c | 495 | } |
donatien | 0:ae46a0638b2c | 496 | |
donatien | 0:ae46a0638b2c | 497 | DBG("Wait for HC to process TD"); |
donatien | 0:ae46a0638b2c | 498 | |
donatien | 0:ae46a0638b2c | 499 | |
donatien | 0:ae46a0638b2c | 500 | return USB_TYPE_PROCESSING; |
donatien | 0:ae46a0638b2c | 501 | } |
donatien | 0:ae46a0638b2c | 502 | |
donatien | 0:ae46a0638b2c | 503 | |
donatien | 0:ae46a0638b2c | 504 | |
donatien | 0:ae46a0638b2c | 505 | USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf) { |
donatien | 0:ae46a0638b2c | 506 | return controlRead( dev, |
donatien | 0:ae46a0638b2c | 507 | USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 508 | GET_DESCRIPTOR, |
donatien | 0:ae46a0638b2c | 509 | (DEVICE_DESCRIPTOR << 8) | (0), |
donatien | 0:ae46a0638b2c | 510 | 0, |
donatien | 0:ae46a0638b2c | 511 | buf, |
donatien | 0:ae46a0638b2c | 512 | DEVICE_DESCRIPTOR_LENGTH); |
donatien | 0:ae46a0638b2c | 513 | } |
donatien | 0:ae46a0638b2c | 514 | |
donatien | 8:0d1ec493842c | 515 | USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t * len_conf_descr) { |
donatien | 0:ae46a0638b2c | 516 | USB_TYPE res; |
donatien | 8:0d1ec493842c | 517 | uint16_t total_conf_descr_length = 0; |
donatien | 0:ae46a0638b2c | 518 | |
donatien | 0:ae46a0638b2c | 519 | // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr |
donatien | 0:ae46a0638b2c | 520 | res = controlRead( dev, |
donatien | 0:ae46a0638b2c | 521 | USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 522 | GET_DESCRIPTOR, |
donatien | 0:ae46a0638b2c | 523 | (CONFIGURATION_DESCRIPTOR << 8) | (0), |
donatien | 0:ae46a0638b2c | 524 | 0, |
donatien | 0:ae46a0638b2c | 525 | buf, |
donatien | 0:ae46a0638b2c | 526 | CONFIGURATION_DESCRIPTOR_LENGTH); |
donatien | 0:ae46a0638b2c | 527 | |
donatien | 0:ae46a0638b2c | 528 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 529 | ERR("GET CONF 1 DESCR FAILED"); |
donatien | 0:ae46a0638b2c | 530 | return res; |
donatien | 0:ae46a0638b2c | 531 | } |
donatien | 0:ae46a0638b2c | 532 | total_conf_descr_length = buf[2] | (buf[3] << 8); |
donatien | 0:ae46a0638b2c | 533 | if (len_conf_descr != NULL) { |
donatien | 0:ae46a0638b2c | 534 | *len_conf_descr = total_conf_descr_length; |
donatien | 0:ae46a0638b2c | 535 | } |
donatien | 0:ae46a0638b2c | 536 | DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]); |
donatien | 0:ae46a0638b2c | 537 | |
donatien | 0:ae46a0638b2c | 538 | return controlRead( dev, |
donatien | 0:ae46a0638b2c | 539 | USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 540 | GET_DESCRIPTOR, |
donatien | 0:ae46a0638b2c | 541 | (CONFIGURATION_DESCRIPTOR << 8) | (0), |
donatien | 0:ae46a0638b2c | 542 | 0, |
donatien | 0:ae46a0638b2c | 543 | buf, |
donatien | 0:ae46a0638b2c | 544 | total_conf_descr_length); |
donatien | 0:ae46a0638b2c | 545 | |
donatien | 0:ae46a0638b2c | 546 | } |
donatien | 0:ae46a0638b2c | 547 | |
donatien | 0:ae46a0638b2c | 548 | USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf) { |
donatien | 0:ae46a0638b2c | 549 | return controlWrite( dev, |
donatien | 0:ae46a0638b2c | 550 | USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 551 | SET_CONFIGURATION, |
donatien | 0:ae46a0638b2c | 552 | conf, |
donatien | 0:ae46a0638b2c | 553 | 0, |
donatien | 0:ae46a0638b2c | 554 | NULL, |
donatien | 0:ae46a0638b2c | 555 | 0); |
donatien | 0:ae46a0638b2c | 556 | |
donatien | 0:ae46a0638b2c | 557 | } |
donatien | 0:ae46a0638b2c | 558 | |
donatien | 0:ae46a0638b2c | 559 | |
donatien | 9:c9e9817c398c | 560 | // enumerate a device with the control USBEndpoint |
donatien | 6:075e36a3463e | 561 | USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) { |
donatien | 8:0d1ec493842c | 562 | uint8_t data[384]; |
donatien | 8:0d1ec493842c | 563 | uint16_t total_conf_descr_length = 0; |
donatien | 0:ae46a0638b2c | 564 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 565 | |
donatien | 0:ae46a0638b2c | 566 | DBG("data = %p", data); |
donatien | 0:ae46a0638b2c | 567 | |
donatien | 0:ae46a0638b2c | 568 | if (dev->isEnumerated()) { |
donatien | 0:ae46a0638b2c | 569 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 570 | } |
donatien | 0:ae46a0638b2c | 571 | |
donatien | 9:c9e9817c398c | 572 | // first step: get the size of USBEndpoint 0 |
donatien | 0:ae46a0638b2c | 573 | DBG("Get size of EP 0"); |
donatien | 0:ae46a0638b2c | 574 | res = controlRead( dev, |
donatien | 0:ae46a0638b2c | 575 | USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 576 | GET_DESCRIPTOR, |
donatien | 0:ae46a0638b2c | 577 | (DEVICE_DESCRIPTOR << 8) | (0), |
donatien | 0:ae46a0638b2c | 578 | 0, |
donatien | 0:ae46a0638b2c | 579 | data, |
donatien | 0:ae46a0638b2c | 580 | 8); |
donatien | 0:ae46a0638b2c | 581 | |
donatien | 0:ae46a0638b2c | 582 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 583 | ERR("Control read failed!!"); |
donatien | 0:ae46a0638b2c | 584 | return res; |
donatien | 0:ae46a0638b2c | 585 | } |
donatien | 0:ae46a0638b2c | 586 | dev->setSizeControlEndpoint(data[7]); |
donatien | 9:c9e9817c398c | 587 | DBG("size control USBEndpoint: %d", dev->getSizeControlEndpoint()); |
donatien | 6:075e36a3463e | 588 | |
donatien | 0:ae46a0638b2c | 589 | DBG("Now set addr"); |
donatien | 0:ae46a0638b2c | 590 | // second step: set an address to the device |
donatien | 0:ae46a0638b2c | 591 | res = controlWrite( dev, |
donatien | 0:ae46a0638b2c | 592 | USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, |
donatien | 0:ae46a0638b2c | 593 | SET_ADDRESS, |
donatien | 0:ae46a0638b2c | 594 | dev->getAddress(), |
donatien | 0:ae46a0638b2c | 595 | 0, |
donatien | 0:ae46a0638b2c | 596 | NULL, |
donatien | 0:ae46a0638b2c | 597 | 0); |
donatien | 0:ae46a0638b2c | 598 | |
donatien | 0:ae46a0638b2c | 599 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 600 | DBG("SET ADDR FAILED"); |
donatien | 0:ae46a0638b2c | 601 | freeDevice(dev); |
donatien | 0:ae46a0638b2c | 602 | return res; |
donatien | 0:ae46a0638b2c | 603 | } |
donatien | 0:ae46a0638b2c | 604 | dev->activeAddress(); |
donatien | 0:ae46a0638b2c | 605 | |
donatien | 0:ae46a0638b2c | 606 | |
donatien | 0:ae46a0638b2c | 607 | // third step: get the whole device descriptor to see vid, pid |
donatien | 0:ae46a0638b2c | 608 | res = getDeviceDescriptor(dev, data); |
donatien | 0:ae46a0638b2c | 609 | |
donatien | 0:ae46a0638b2c | 610 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 611 | DBG("GET DEV DESCR FAILED"); |
donatien | 0:ae46a0638b2c | 612 | return res; |
donatien | 0:ae46a0638b2c | 613 | } |
donatien | 0:ae46a0638b2c | 614 | dev->setClass(data[4]); |
donatien | 0:ae46a0638b2c | 615 | dev->setSubClass(data[5]); |
donatien | 0:ae46a0638b2c | 616 | dev->setProtocol(data[6]); |
donatien | 0:ae46a0638b2c | 617 | dev->setVid(data[8] | (data[9] << 8)); |
donatien | 0:ae46a0638b2c | 618 | dev->setPid(data[10] | (data[11] << 8)); |
donatien | 0:ae46a0638b2c | 619 | DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); |
donatien | 6:075e36a3463e | 620 | |
donatien | 6:075e36a3463e | 621 | pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); |
donatien | 0:ae46a0638b2c | 622 | |
donatien | 0:ae46a0638b2c | 623 | res = getConfigurationDescriptor(dev, data, &total_conf_descr_length); |
donatien | 0:ae46a0638b2c | 624 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 625 | return res; |
donatien | 0:ae46a0638b2c | 626 | } |
donatien | 0:ae46a0638b2c | 627 | |
donatien | 0:ae46a0638b2c | 628 | // Parse the configuration descriptor |
donatien | 6:075e36a3463e | 629 | parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); |
donatien | 0:ae46a0638b2c | 630 | |
donatien | 0:ae46a0638b2c | 631 | |
donatien | 0:ae46a0638b2c | 632 | // sixth step: set configuration (only 1 supported) |
donatien | 0:ae46a0638b2c | 633 | res = setConfiguration(dev, 1); |
donatien | 0:ae46a0638b2c | 634 | |
donatien | 0:ae46a0638b2c | 635 | if (res != USB_TYPE_OK) { |
donatien | 0:ae46a0638b2c | 636 | DBG("SET CONF FAILED"); |
donatien | 0:ae46a0638b2c | 637 | freeDevice(dev); |
donatien | 0:ae46a0638b2c | 638 | return res; |
donatien | 0:ae46a0638b2c | 639 | } |
donatien | 0:ae46a0638b2c | 640 | |
donatien | 0:ae46a0638b2c | 641 | // Now the device is enumerated! |
donatien | 0:ae46a0638b2c | 642 | dev->setEnumerated(); |
donatien | 0:ae46a0638b2c | 643 | DBG("device enumerated!!!!"); |
donatien | 0:ae46a0638b2c | 644 | |
donatien | 0:ae46a0638b2c | 645 | // Some devices may require this delay |
donatien | 0:ae46a0638b2c | 646 | Thread::wait(100); |
donatien | 0:ae46a0638b2c | 647 | |
donatien | 0:ae46a0638b2c | 648 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 649 | } |
donatien | 0:ae46a0638b2c | 650 | |
donatien | 0:ae46a0638b2c | 651 | // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. |
donatien | 6:075e36a3463e | 652 | void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) { |
donatien | 0:ae46a0638b2c | 653 | uint32_t index = 0; |
donatien | 0:ae46a0638b2c | 654 | uint32_t len_desc = 0; |
donatien | 0:ae46a0638b2c | 655 | uint8_t id = 0; |
donatien | 0:ae46a0638b2c | 656 | int nb_endpoints_used = 0; |
donatien | 9:c9e9817c398c | 657 | USBEndpoint * ep = NULL; |
donatien | 0:ae46a0638b2c | 658 | uint8_t intf_nb = 0; |
donatien | 6:075e36a3463e | 659 | bool parsing_intf = false; |
donatien | 0:ae46a0638b2c | 660 | |
donatien | 0:ae46a0638b2c | 661 | while (index < len) { |
donatien | 0:ae46a0638b2c | 662 | len_desc = conf_descr[index]; |
donatien | 0:ae46a0638b2c | 663 | id = conf_descr[index+1]; |
donatien | 0:ae46a0638b2c | 664 | switch (id) { |
donatien | 0:ae46a0638b2c | 665 | case CONFIGURATION_DESCRIPTOR: |
donatien | 0:ae46a0638b2c | 666 | break; |
donatien | 0:ae46a0638b2c | 667 | case INTERFACE_DESCRIPTOR: |
donatien | 6:075e36a3463e | 668 | if(pEnumerator->parseInterface(intf_nb, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) |
donatien | 6:075e36a3463e | 669 | { |
donatien | 6:075e36a3463e | 670 | if (intf_nb++ <= NB_MAX_INTF) { |
donatien | 6:075e36a3463e | 671 | dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); |
donatien | 6:075e36a3463e | 672 | nb_endpoints_used = 0; |
donatien | 6:075e36a3463e | 673 | DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); |
donatien | 6:075e36a3463e | 674 | } else { |
donatien | 6:075e36a3463e | 675 | DBG("Drop intf..."); |
donatien | 6:075e36a3463e | 676 | } |
donatien | 6:075e36a3463e | 677 | parsing_intf = true; |
donatien | 6:075e36a3463e | 678 | } |
donatien | 6:075e36a3463e | 679 | else |
donatien | 6:075e36a3463e | 680 | { |
donatien | 6:075e36a3463e | 681 | parsing_intf = false; |
donatien | 0:ae46a0638b2c | 682 | } |
donatien | 0:ae46a0638b2c | 683 | break; |
donatien | 0:ae46a0638b2c | 684 | case ENDPOINT_DESCRIPTOR: |
donatien | 3:4394986752db | 685 | DBG("Ep DESC"); |
donatien | 6:075e36a3463e | 686 | if (parsing_intf && (intf_nb <= NB_MAX_INTF) ) { |
donatien | 0:ae46a0638b2c | 687 | if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { |
donatien | 6:075e36a3463e | 688 | if( pEnumerator->useEndpoint(intf_nb - 1, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) |
donatien | 6:075e36a3463e | 689 | { |
donatien | 9:c9e9817c398c | 690 | // if the USBEndpoint is isochronous -> skip it (TODO: fix this) |
donatien | 6:075e36a3463e | 691 | if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) { |
donatien | 6:075e36a3463e | 692 | ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03), |
donatien | 6:075e36a3463e | 693 | (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1), |
donatien | 6:075e36a3463e | 694 | conf_descr[index + 4] | (conf_descr[index + 5] << 8), |
donatien | 6:075e36a3463e | 695 | conf_descr[index + 2] & 0x0f); |
donatien | 9:c9e9817c398c | 696 | DBG("ADD USBEndpoint %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev); |
donatien | 6:075e36a3463e | 697 | if (ep != NULL && dev != NULL) { |
donatien | 6:075e36a3463e | 698 | addEndpoint(dev, intf_nb - 1, ep); |
donatien | 6:075e36a3463e | 699 | } else { |
donatien | 6:075e36a3463e | 700 | DBG("EP NULL"); |
donatien | 6:075e36a3463e | 701 | } |
donatien | 6:075e36a3463e | 702 | nb_endpoints_used++; |
donatien | 0:ae46a0638b2c | 703 | } else { |
donatien | 9:c9e9817c398c | 704 | DBG("ISO USBEndpoint NOT SUPPORTED"); |
donatien | 0:ae46a0638b2c | 705 | } |
donatien | 0:ae46a0638b2c | 706 | } |
donatien | 0:ae46a0638b2c | 707 | } |
donatien | 0:ae46a0638b2c | 708 | } |
donatien | 9:c9e9817c398c | 709 | //DBG("USBEndpoint DESCR"); |
donatien | 0:ae46a0638b2c | 710 | break; |
donatien | 0:ae46a0638b2c | 711 | case HID_DESCRIPTOR: |
donatien | 0:ae46a0638b2c | 712 | lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); |
donatien | 0:ae46a0638b2c | 713 | break; |
donatien | 0:ae46a0638b2c | 714 | default: |
donatien | 0:ae46a0638b2c | 715 | break; |
donatien | 0:ae46a0638b2c | 716 | } |
donatien | 0:ae46a0638b2c | 717 | index += len_desc; |
donatien | 0:ae46a0638b2c | 718 | } |
donatien | 0:ae46a0638b2c | 719 | } |
donatien | 0:ae46a0638b2c | 720 | |
donatien | 0:ae46a0638b2c | 721 | |
donatien | 9:c9e9817c398c | 722 | USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
donatien | 0:ae46a0638b2c | 723 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 724 | |
donatien | 0:ae46a0638b2c | 725 | if (dev == NULL || ep == NULL) { |
donatien | 0:ae46a0638b2c | 726 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 727 | } |
donatien | 0:ae46a0638b2c | 728 | |
donatien | 0:ae46a0638b2c | 729 | if ((ep->getDir() != IN) || (ep->getType() != BULK_ENDPOINT)) { |
donatien | 9:c9e9817c398c | 730 | DBG("wrong dir or bad USBEndpoint type"); |
donatien | 0:ae46a0638b2c | 731 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 732 | } |
donatien | 0:ae46a0638b2c | 733 | if (dev->getAddress() != ep->getDeviceAddress()) { |
donatien | 9:c9e9817c398c | 734 | DBG("USBEndpoint addr and device addr don't match"); |
donatien | 0:ae46a0638b2c | 735 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 736 | } |
donatien | 0:ae46a0638b2c | 737 | addTransfer(ep, buf, len); |
donatien | 0:ae46a0638b2c | 738 | if (blocking) { |
donatien | 0:ae46a0638b2c | 739 | unlock(); |
donatien | 0:ae46a0638b2c | 740 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 741 | lock(); |
donatien | 0:ae46a0638b2c | 742 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 743 | return res; |
donatien | 0:ae46a0638b2c | 744 | } |
donatien | 0:ae46a0638b2c | 745 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 746 | } |
donatien | 0:ae46a0638b2c | 747 | return USB_TYPE_PROCESSING; |
donatien | 0:ae46a0638b2c | 748 | } |
donatien | 0:ae46a0638b2c | 749 | |
donatien | 9:c9e9817c398c | 750 | USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
donatien | 0:ae46a0638b2c | 751 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 752 | |
donatien | 0:ae46a0638b2c | 753 | if (dev == NULL || ep == NULL) { |
donatien | 0:ae46a0638b2c | 754 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 755 | } |
donatien | 0:ae46a0638b2c | 756 | |
donatien | 0:ae46a0638b2c | 757 | if ((ep->getDir() != OUT) || (ep->getType() != BULK_ENDPOINT)) { |
donatien | 9:c9e9817c398c | 758 | DBG("wrong dir or bad USBEndpoint type"); |
donatien | 0:ae46a0638b2c | 759 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 760 | } |
donatien | 0:ae46a0638b2c | 761 | if (dev->getAddress() != ep->getDeviceAddress()) { |
donatien | 9:c9e9817c398c | 762 | DBG("USBEndpoint addr and device addr don't match"); |
donatien | 0:ae46a0638b2c | 763 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 764 | } |
donatien | 0:ae46a0638b2c | 765 | addTransfer(ep, buf, len); |
donatien | 0:ae46a0638b2c | 766 | if (blocking) { |
donatien | 0:ae46a0638b2c | 767 | unlock(); |
donatien | 0:ae46a0638b2c | 768 | while ((res = control->getState()) == USB_TYPE_PROCESSING) |
donatien | 0:ae46a0638b2c | 769 | { |
donatien | 0:ae46a0638b2c | 770 | DBG("!!!!!!!!!!!!!wait bulkwrite"); |
donatien | 0:ae46a0638b2c | 771 | Thread::wait(100); |
donatien | 0:ae46a0638b2c | 772 | } |
donatien | 0:ae46a0638b2c | 773 | lock(); |
donatien | 0:ae46a0638b2c | 774 | DBG("!!!!!!!!!!!!! bulkwrite finished"); |
donatien | 0:ae46a0638b2c | 775 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 776 | return res; |
donatien | 0:ae46a0638b2c | 777 | } |
donatien | 0:ae46a0638b2c | 778 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 779 | } |
donatien | 0:ae46a0638b2c | 780 | return USB_TYPE_PROCESSING; |
donatien | 0:ae46a0638b2c | 781 | } |
donatien | 0:ae46a0638b2c | 782 | |
donatien | 9:c9e9817c398c | 783 | USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
donatien | 0:ae46a0638b2c | 784 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 785 | |
donatien | 0:ae46a0638b2c | 786 | if (dev == NULL || ep == NULL) { |
donatien | 0:ae46a0638b2c | 787 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 788 | } |
donatien | 0:ae46a0638b2c | 789 | |
donatien | 0:ae46a0638b2c | 790 | if (ep->getState() != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 791 | return ep->getState(); |
donatien | 0:ae46a0638b2c | 792 | } |
donatien | 0:ae46a0638b2c | 793 | |
donatien | 0:ae46a0638b2c | 794 | if ((ep->getDir() != OUT) || (ep->getType() != INTERRUPT_ENDPOINT)) { |
donatien | 9:c9e9817c398c | 795 | ERR("wrong dir or bad USBEndpoint type: %d, %d", ep->getDir(), ep->getType()); |
donatien | 0:ae46a0638b2c | 796 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 797 | } |
donatien | 0:ae46a0638b2c | 798 | if (dev->getAddress() != ep->getDeviceAddress()) { |
donatien | 9:c9e9817c398c | 799 | ERR("USBEndpoint addr and device addr don't match"); |
donatien | 0:ae46a0638b2c | 800 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 801 | } |
donatien | 0:ae46a0638b2c | 802 | addTransfer(ep, buf, len); |
donatien | 0:ae46a0638b2c | 803 | if (blocking) { |
donatien | 0:ae46a0638b2c | 804 | while ((res = ep->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 805 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 806 | return res; |
donatien | 0:ae46a0638b2c | 807 | } |
donatien | 0:ae46a0638b2c | 808 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 809 | } |
donatien | 0:ae46a0638b2c | 810 | return USB_TYPE_PROCESSING; |
donatien | 0:ae46a0638b2c | 811 | } |
donatien | 0:ae46a0638b2c | 812 | |
donatien | 9:c9e9817c398c | 813 | USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
donatien | 0:ae46a0638b2c | 814 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 815 | |
donatien | 0:ae46a0638b2c | 816 | if (dev == NULL || ep == NULL) { |
donatien | 0:ae46a0638b2c | 817 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 818 | } |
donatien | 0:ae46a0638b2c | 819 | |
donatien | 0:ae46a0638b2c | 820 | if (ep->getState() != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 821 | return ep->getState(); |
donatien | 0:ae46a0638b2c | 822 | } |
donatien | 0:ae46a0638b2c | 823 | |
donatien | 0:ae46a0638b2c | 824 | if ((ep->getDir() != IN) || (ep->getType() != INTERRUPT_ENDPOINT)) { |
donatien | 9:c9e9817c398c | 825 | ERR("wrong dir or bad USBEndpoint type"); |
donatien | 0:ae46a0638b2c | 826 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 827 | } |
donatien | 0:ae46a0638b2c | 828 | |
donatien | 0:ae46a0638b2c | 829 | if (dev->getAddress() != ep->getDeviceAddress()) { |
donatien | 9:c9e9817c398c | 830 | ERR("USBEndpoint addr and device addr don't match"); |
donatien | 0:ae46a0638b2c | 831 | return USB_TYPE_ERROR; |
donatien | 0:ae46a0638b2c | 832 | } |
donatien | 0:ae46a0638b2c | 833 | addTransfer(ep, buf, len); |
donatien | 0:ae46a0638b2c | 834 | if (blocking) { |
donatien | 0:ae46a0638b2c | 835 | while ((res = ep->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 836 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 837 | return res; |
donatien | 0:ae46a0638b2c | 838 | } |
donatien | 0:ae46a0638b2c | 839 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 840 | } |
donatien | 0:ae46a0638b2c | 841 | return USB_TYPE_PROCESSING; |
donatien | 0:ae46a0638b2c | 842 | } |
donatien | 0:ae46a0638b2c | 843 | |
donatien | 0:ae46a0638b2c | 844 | |
donatien | 0:ae46a0638b2c | 845 | USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { |
donatien | 0:ae46a0638b2c | 846 | int length_transfer = len; |
donatien | 0:ae46a0638b2c | 847 | //DBG("want to transfer: %d bytes\r\n", length_transfer); |
donatien | 0:ae46a0638b2c | 848 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 849 | control->setSpeed(dev->getSpeed()); |
donatien | 0:ae46a0638b2c | 850 | control->setSize(dev->getSizeControlEndpoint()); |
donatien | 0:ae46a0638b2c | 851 | if (dev->isActiveAddress()) { |
donatien | 0:ae46a0638b2c | 852 | control->setDeviceAddress(dev->getAddress()); |
donatien | 0:ae46a0638b2c | 853 | } else { |
donatien | 0:ae46a0638b2c | 854 | control->setDeviceAddress(0); |
donatien | 0:ae46a0638b2c | 855 | } |
donatien | 0:ae46a0638b2c | 856 | fillControlBuf(requestType, request, value, index, len); |
donatien | 0:ae46a0638b2c | 857 | /* DBG("will call transfer: "); |
donatien | 0:ae46a0638b2c | 858 | for (int i = 0; i < 8; i++) { |
donatien | 0:ae46a0638b2c | 859 | DBG("%02X ", setupPacket[i]); |
donatien | 0:ae46a0638b2c | 860 | }*/ |
donatien | 0:ae46a0638b2c | 861 | control->setNextToken(TD_SETUP); |
donatien | 0:ae46a0638b2c | 862 | addTransfer(control, (uint8_t*)setupPacket, 8); |
donatien | 0:ae46a0638b2c | 863 | DBG("Now wait for TD to be processed"); |
donatien | 0:ae46a0638b2c | 864 | unlock(); |
donatien | 0:ae46a0638b2c | 865 | DBG("Unlocked"); |
donatien | 0:ae46a0638b2c | 866 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 867 | lock(); |
donatien | 0:ae46a0638b2c | 868 | DBG("TD processed with result %d", res); |
donatien | 0:ae46a0638b2c | 869 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 870 | return res; |
donatien | 0:ae46a0638b2c | 871 | } |
donatien | 0:ae46a0638b2c | 872 | |
donatien | 0:ae46a0638b2c | 873 | if (length_transfer) { |
donatien | 0:ae46a0638b2c | 874 | DBG("In data to be transfered..."); |
donatien | 0:ae46a0638b2c | 875 | control->setNextToken(TD_IN); |
donatien | 0:ae46a0638b2c | 876 | addTransfer(control, (uint8_t *)buf, length_transfer); |
donatien | 0:ae46a0638b2c | 877 | unlock(); |
donatien | 0:ae46a0638b2c | 878 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 879 | lock(); |
donatien | 0:ae46a0638b2c | 880 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 881 | return res; |
donatien | 0:ae46a0638b2c | 882 | } |
donatien | 0:ae46a0638b2c | 883 | } |
donatien | 0:ae46a0638b2c | 884 | |
donatien | 0:ae46a0638b2c | 885 | DBG("Transfer NULL packet (OUT)"); |
donatien | 0:ae46a0638b2c | 886 | control->setNextToken(TD_OUT); |
donatien | 0:ae46a0638b2c | 887 | addTransfer(control, NULL, 0); |
donatien | 0:ae46a0638b2c | 888 | unlock(); |
donatien | 0:ae46a0638b2c | 889 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 890 | lock(); |
donatien | 0:ae46a0638b2c | 891 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 892 | return res; |
donatien | 0:ae46a0638b2c | 893 | } |
donatien | 0:ae46a0638b2c | 894 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 895 | } |
donatien | 0:ae46a0638b2c | 896 | |
donatien | 0:ae46a0638b2c | 897 | |
donatien | 0:ae46a0638b2c | 898 | USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { |
donatien | 0:ae46a0638b2c | 899 | control->setSpeed(dev->getSpeed()); |
donatien | 0:ae46a0638b2c | 900 | |
donatien | 0:ae46a0638b2c | 901 | int length_transfer = len; |
donatien | 0:ae46a0638b2c | 902 | USB_TYPE res; |
donatien | 0:ae46a0638b2c | 903 | |
donatien | 0:ae46a0638b2c | 904 | control->setSize(dev->getSizeControlEndpoint()); |
donatien | 0:ae46a0638b2c | 905 | if (dev->isActiveAddress()) { |
donatien | 0:ae46a0638b2c | 906 | control->setDeviceAddress(dev->getAddress()); |
donatien | 0:ae46a0638b2c | 907 | } else { |
donatien | 0:ae46a0638b2c | 908 | control->setDeviceAddress(0); |
donatien | 0:ae46a0638b2c | 909 | } |
donatien | 0:ae46a0638b2c | 910 | fillControlBuf(requestType, request, value, index, len); |
donatien | 0:ae46a0638b2c | 911 | /*DBG("will call transfer: "); |
donatien | 0:ae46a0638b2c | 912 | for (int i = 0; i < 8; i++) { |
donatien | 0:ae46a0638b2c | 913 | printf("%01X ", setupPacket[i]); |
donatien | 0:ae46a0638b2c | 914 | } |
donatien | 0:ae46a0638b2c | 915 | printf("\r\n");*/ |
donatien | 0:ae46a0638b2c | 916 | control->setNextToken(TD_SETUP); |
donatien | 0:ae46a0638b2c | 917 | addTransfer(control, (uint8_t*)setupPacket, 8); |
donatien | 0:ae46a0638b2c | 918 | unlock(); |
donatien | 0:ae46a0638b2c | 919 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 920 | lock(); |
donatien | 0:ae46a0638b2c | 921 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 922 | return res; |
donatien | 0:ae46a0638b2c | 923 | } |
donatien | 0:ae46a0638b2c | 924 | |
donatien | 0:ae46a0638b2c | 925 | if (length_transfer) { |
donatien | 0:ae46a0638b2c | 926 | control->setNextToken(TD_OUT); |
donatien | 0:ae46a0638b2c | 927 | addTransfer(control, (uint8_t *)buf, length_transfer); |
donatien | 0:ae46a0638b2c | 928 | unlock(); |
donatien | 0:ae46a0638b2c | 929 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 930 | lock(); |
donatien | 0:ae46a0638b2c | 931 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 932 | return res; |
donatien | 0:ae46a0638b2c | 933 | } |
donatien | 0:ae46a0638b2c | 934 | } |
donatien | 0:ae46a0638b2c | 935 | |
donatien | 0:ae46a0638b2c | 936 | control->setNextToken(TD_IN); |
donatien | 0:ae46a0638b2c | 937 | addTransfer(control, NULL, 0); |
donatien | 0:ae46a0638b2c | 938 | unlock(); |
donatien | 0:ae46a0638b2c | 939 | while ((res = control->getState()) == USB_TYPE_PROCESSING); |
donatien | 0:ae46a0638b2c | 940 | lock(); |
donatien | 0:ae46a0638b2c | 941 | if (res != USB_TYPE_IDLE) { |
donatien | 0:ae46a0638b2c | 942 | return res; |
donatien | 0:ae46a0638b2c | 943 | } |
donatien | 0:ae46a0638b2c | 944 | return USB_TYPE_OK; |
donatien | 0:ae46a0638b2c | 945 | } |
donatien | 0:ae46a0638b2c | 946 | |
donatien | 0:ae46a0638b2c | 947 | |
donatien | 0:ae46a0638b2c | 948 | void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len) { |
donatien | 0:ae46a0638b2c | 949 | #ifdef __BIG_ENDIAN |
donatien | 0:ae46a0638b2c | 950 | #error "Must implement BE to LE conv here" |
donatien | 0:ae46a0638b2c | 951 | #endif |
donatien | 0:ae46a0638b2c | 952 | setupPacket[0] = requestType; |
donatien | 0:ae46a0638b2c | 953 | setupPacket[1] = request; |
donatien | 0:ae46a0638b2c | 954 | //We are in LE so it's fine |
donatien | 0:ae46a0638b2c | 955 | *((uint32_t*)&setupPacket[2]) = value; |
donatien | 0:ae46a0638b2c | 956 | *((uint32_t*)&setupPacket[4]) = index; |
donatien | 0:ae46a0638b2c | 957 | *((uint32_t*)&setupPacket[6]) = (uint32_t) len; |
donatien | 0:ae46a0638b2c | 958 | } |
donatien | 0:ae46a0638b2c | 959 | |
donatien | 0:ae46a0638b2c | 960 |