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