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