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/USBEndpoint.cpp@9:2a7b7333245f, 2012-12-10 (annotated)
- Committer:
- donatien
- Date:
- Mon Dec 10 18:18:35 2012 +0000
- Revision:
- 9:2a7b7333245f
- Parent:
- 0:bfed5767d0a5
Merge
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 | 0:bfed5767d0a5 | 19 | |
donatien | 0:bfed5767d0a5 | 20 | #define __DEBUG__ 0 //Maximum verbosity |
donatien | 0:bfed5767d0a5 | 21 | #ifndef __MODULE__ |
donatien | 0:bfed5767d0a5 | 22 | #define __MODULE__ "USBEndpoint.cpp" |
donatien | 0:bfed5767d0a5 | 23 | #endif |
donatien | 0:bfed5767d0a5 | 24 | |
donatien | 0:bfed5767d0a5 | 25 | #include "core/dbg.h" |
donatien | 0:bfed5767d0a5 | 26 | #include <cstdint> |
donatien | 0:bfed5767d0a5 | 27 | |
donatien | 0:bfed5767d0a5 | 28 | #include "USBEndpoint.h" |
donatien | 0:bfed5767d0a5 | 29 | |
donatien | 0:bfed5767d0a5 | 30 | |
donatien | 0:bfed5767d0a5 | 31 | void USBEndpoint::init(HCED * hced, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t ep_number, HCTD* td_list[2]) { |
donatien | 0:bfed5767d0a5 | 32 | this->hced = hced; |
donatien | 0:bfed5767d0a5 | 33 | this->type = type; |
donatien | 0:bfed5767d0a5 | 34 | this->dir = /*(type == CONTROL_ENDPOINT) ? OUT :*/ dir; |
donatien | 0:bfed5767d0a5 | 35 | setup = (type == CONTROL_ENDPOINT) ? true : false; |
donatien | 0:bfed5767d0a5 | 36 | |
donatien | 0:bfed5767d0a5 | 37 | //TDs have been allocated by the host |
donatien | 0:bfed5767d0a5 | 38 | memcpy((HCTD**)this->td_list, td_list, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define |
donatien | 0:bfed5767d0a5 | 39 | memcpy(td_list[0], 0, sizeof(HCTD)); |
donatien | 0:bfed5767d0a5 | 40 | memcpy(td_list[1], 0, sizeof(HCTD)); |
donatien | 0:bfed5767d0a5 | 41 | |
donatien | 0:bfed5767d0a5 | 42 | this->hced->control = 0; |
donatien | 0:bfed5767d0a5 | 43 | //Empty queue |
donatien | 0:bfed5767d0a5 | 44 | this->hced->tailTD = (uint32_t)td_list[0]; |
donatien | 0:bfed5767d0a5 | 45 | this->hced->headTD = (uint32_t)td_list[0]; |
donatien | 0:bfed5767d0a5 | 46 | this->hced->nextED = 0; |
donatien | 0:bfed5767d0a5 | 47 | |
donatien | 0:bfed5767d0a5 | 48 | this->hced->control = ((ep_number & 0x7F) << 7) // Endpoint address |
donatien | 0:bfed5767d0a5 | 49 | | (type != CONTROL_ENDPOINT ? ( dir << 11) : 0 ) // direction : Out = 1, 2 = In |
donatien | 0:bfed5767d0a5 | 50 | | ((size & 0x3ff) << 16); // MaxPkt Size |
donatien | 0:bfed5767d0a5 | 51 | |
donatien | 0:bfed5767d0a5 | 52 | //carry = false; |
donatien | 0:bfed5767d0a5 | 53 | transfer_len = 0; |
donatien | 0:bfed5767d0a5 | 54 | transferred = 0; |
donatien | 0:bfed5767d0a5 | 55 | buf_start = 0; |
donatien | 0:bfed5767d0a5 | 56 | nextEp = NULL; |
donatien | 0:bfed5767d0a5 | 57 | |
donatien | 0:bfed5767d0a5 | 58 | td_current = td_list[0]; |
donatien | 0:bfed5767d0a5 | 59 | td_next = td_list[1]; |
donatien | 0:bfed5767d0a5 | 60 | |
donatien | 0:bfed5767d0a5 | 61 | state = USB_TYPE_IDLE; |
donatien | 0:bfed5767d0a5 | 62 | } |
donatien | 0:bfed5767d0a5 | 63 | |
donatien | 0:bfed5767d0a5 | 64 | void USBEndpoint::setSize(uint32_t size) { |
donatien | 0:bfed5767d0a5 | 65 | hced->control &= ~(0x3ff << 16); |
donatien | 0:bfed5767d0a5 | 66 | hced->control |= (size << 16); |
donatien | 0:bfed5767d0a5 | 67 | } |
donatien | 0:bfed5767d0a5 | 68 | |
donatien | 0:bfed5767d0a5 | 69 | |
donatien | 0:bfed5767d0a5 | 70 | uint32_t USBEndpoint::getSize() { |
donatien | 0:bfed5767d0a5 | 71 | return (hced->control >> 16) & 0x3ff; |
donatien | 0:bfed5767d0a5 | 72 | } |
donatien | 0:bfed5767d0a5 | 73 | |
donatien | 0:bfed5767d0a5 | 74 | void USBEndpoint::setDeviceAddress(uint8_t addr) { |
donatien | 0:bfed5767d0a5 | 75 | hced->control &= ~(0x7f); |
donatien | 0:bfed5767d0a5 | 76 | hced->control |= (addr & 0x7F); |
donatien | 0:bfed5767d0a5 | 77 | } |
donatien | 0:bfed5767d0a5 | 78 | |
donatien | 0:bfed5767d0a5 | 79 | uint8_t USBEndpoint::getDeviceAddress() { |
donatien | 0:bfed5767d0a5 | 80 | return hced->control & 0x7f; |
donatien | 0:bfed5767d0a5 | 81 | } |
donatien | 0:bfed5767d0a5 | 82 | |
donatien | 0:bfed5767d0a5 | 83 | void USBEndpoint::setSpeed(uint8_t speed) { |
donatien | 0:bfed5767d0a5 | 84 | if(speed) { |
donatien | 0:bfed5767d0a5 | 85 | DBG("SET LOW SPEED"); |
donatien | 0:bfed5767d0a5 | 86 | } |
donatien | 0:bfed5767d0a5 | 87 | hced->control &= ~(1 << 13); |
donatien | 0:bfed5767d0a5 | 88 | hced->control |= (speed << 13); |
donatien | 0:bfed5767d0a5 | 89 | } |
donatien | 0:bfed5767d0a5 | 90 | |
donatien | 0:bfed5767d0a5 | 91 | |
donatien | 0:bfed5767d0a5 | 92 | void USBEndpoint::setNextToken(uint32_t token) { //Only for control Eps |
donatien | 0:bfed5767d0a5 | 93 | switch (token) { |
donatien | 0:bfed5767d0a5 | 94 | case TD_SETUP: |
donatien | 0:bfed5767d0a5 | 95 | dir = OUT; |
donatien | 0:bfed5767d0a5 | 96 | setup = true; |
donatien | 0:bfed5767d0a5 | 97 | break; |
donatien | 0:bfed5767d0a5 | 98 | case TD_IN: |
donatien | 0:bfed5767d0a5 | 99 | dir = IN; |
donatien | 0:bfed5767d0a5 | 100 | setup = false; |
donatien | 0:bfed5767d0a5 | 101 | break; |
donatien | 0:bfed5767d0a5 | 102 | case TD_OUT: |
donatien | 0:bfed5767d0a5 | 103 | dir = OUT; |
donatien | 0:bfed5767d0a5 | 104 | setup = false; |
donatien | 0:bfed5767d0a5 | 105 | break; |
donatien | 0:bfed5767d0a5 | 106 | } |
donatien | 0:bfed5767d0a5 | 107 | } |
donatien | 0:bfed5767d0a5 | 108 | |
donatien | 0:bfed5767d0a5 | 109 | volatile HCTD* USBEndpoint::getNextTD() |
donatien | 0:bfed5767d0a5 | 110 | { |
donatien | 0:bfed5767d0a5 | 111 | return td_current/*(HCTD*) hced->tailTD*/; //It's the tailing one |
donatien | 0:bfed5767d0a5 | 112 | } |
donatien | 0:bfed5767d0a5 | 113 | |
donatien | 0:bfed5767d0a5 | 114 | void USBEndpoint::queueTransfer() { |
donatien | 0:bfed5767d0a5 | 115 | //Try with OHCI impl |
donatien | 0:bfed5767d0a5 | 116 | //Caller of getNextTD() has now populated the td |
donatien | 0:bfed5767d0a5 | 117 | //So insert it into queue |
donatien | 0:bfed5767d0a5 | 118 | |
donatien | 0:bfed5767d0a5 | 119 | //Find an OTHER free td |
donatien | 0:bfed5767d0a5 | 120 | //TODO: if we had more than 2 tds, this would have to be changed |
donatien | 0:bfed5767d0a5 | 121 | /*HCTD* toSendTD = (HCTD*) hced->tailTD;*/ |
donatien | 0:bfed5767d0a5 | 122 | //HCTD* freeTD; |
donatien | 0:bfed5767d0a5 | 123 | /* |
donatien | 0:bfed5767d0a5 | 124 | if( hced->tailTD == td_list[0] ) |
donatien | 0:bfed5767d0a5 | 125 | { |
donatien | 0:bfed5767d0a5 | 126 | freeTD = td_list[1]; |
donatien | 0:bfed5767d0a5 | 127 | } |
donatien | 0:bfed5767d0a5 | 128 | else *//*if( hced->tailTD == (uint32_t) td_list[1] )*/ |
donatien | 0:bfed5767d0a5 | 129 | /*{ |
donatien | 0:bfed5767d0a5 | 130 | freeTD = td_list[0]; |
donatien | 0:bfed5767d0a5 | 131 | } |
donatien | 0:bfed5767d0a5 | 132 | */ |
donatien | 0:bfed5767d0a5 | 133 | |
donatien | 0:bfed5767d0a5 | 134 | /* |
donatien | 0:bfed5767d0a5 | 135 | freeTD->control = 0; |
donatien | 0:bfed5767d0a5 | 136 | freeTD->currBufPtr = 0; |
donatien | 0:bfed5767d0a5 | 137 | freeTD->bufEnd = 0; |
donatien | 0:bfed5767d0a5 | 138 | freeTD->nextTD = 0; |
donatien | 0:bfed5767d0a5 | 139 | |
donatien | 0:bfed5767d0a5 | 140 | td_current = toSendTD; |
donatien | 0:bfed5767d0a5 | 141 | */ |
donatien | 0:bfed5767d0a5 | 142 | transfer_len = td_current->bufEnd - td_current->currBufPtr + 1; |
donatien | 0:bfed5767d0a5 | 143 | transferred = transfer_len; |
donatien | 0:bfed5767d0a5 | 144 | buf_start = td_current->currBufPtr; |
donatien | 0:bfed5767d0a5 | 145 | |
donatien | 0:bfed5767d0a5 | 146 | //No add this free TD at this end of the queue |
donatien | 0:bfed5767d0a5 | 147 | state = USB_TYPE_PROCESSING; |
donatien | 0:bfed5767d0a5 | 148 | td_current->nextTD = (volatile uint32_t)td_next; |
donatien | 0:bfed5767d0a5 | 149 | hced->tailTD = (volatile uint32_t)td_next; |
donatien | 0:bfed5767d0a5 | 150 | |
donatien | 0:bfed5767d0a5 | 151 | #if 0 |
donatien | 0:bfed5767d0a5 | 152 | // if TD list empty -> we put the head of the list |
donatien | 0:bfed5767d0a5 | 153 | if (!hced->headTD) { |
donatien | 0:bfed5767d0a5 | 154 | state = USB_TYPE_IDLE; |
donatien | 0:bfed5767d0a5 | 155 | hced->headTD = (uint32_t)(td); |
donatien | 0:bfed5767d0a5 | 156 | hced->tailTD = (uint32_t)(td); |
donatien | 0:bfed5767d0a5 | 157 | tailTD = (HCTD *) (hced->headTD); |
donatien | 0:bfed5767d0a5 | 158 | //DBG("queue null transfer: endpoint: %p, %08X\r\n", this, (uint32_t)(td)); |
donatien | 0:bfed5767d0a5 | 159 | } else { |
donatien | 0:bfed5767d0a5 | 160 | state = USB_TYPE_PROCESSING; |
donatien | 0:bfed5767d0a5 | 161 | td->nextTD = (uint32_t)headTD & ~(0x0f); |
donatien | 0:bfed5767d0a5 | 162 | hced->headTD = (uint32_t)(td) | ((carry) ? 0x2 : 0); |
donatien | 0:bfed5767d0a5 | 163 | } |
donatien | 0:bfed5767d0a5 | 164 | headTD = (HCTD *) ((hced->headTD) & ~(0x3)); |
donatien | 0:bfed5767d0a5 | 165 | transfer_len = td->bufEnd - td->currBufPtr + 1; |
donatien | 0:bfed5767d0a5 | 166 | transferred = transfer_len; |
donatien | 0:bfed5767d0a5 | 167 | buf_start = td->currBufPtr; |
donatien | 0:bfed5767d0a5 | 168 | #endif |
donatien | 0:bfed5767d0a5 | 169 | //printf("queue real transfer: endpoint: %p \t headTD: %p \t head: %08X \t tail: %08X \t td: %08X \t nexttd: %08X\r\n", this, hced->headTD, hced->headTD, ((HCTD *)((hced->headTD) & ~(0x0f)))->nextTD, toSendTD, toSendTD->nextTD); |
donatien | 0:bfed5767d0a5 | 170 | } |
donatien | 0:bfed5767d0a5 | 171 | |
donatien | 0:bfed5767d0a5 | 172 | volatile HCTD * USBEndpoint::getProcessedTD() |
donatien | 0:bfed5767d0a5 | 173 | { |
donatien | 0:bfed5767d0a5 | 174 | return td_current; |
donatien | 0:bfed5767d0a5 | 175 | } |
donatien | 0:bfed5767d0a5 | 176 | |
donatien | 0:bfed5767d0a5 | 177 | void USBEndpoint::setLengthTransferred(int len) { |
donatien | 0:bfed5767d0a5 | 178 | transferred = len; |
donatien | 0:bfed5767d0a5 | 179 | } |
donatien | 0:bfed5767d0a5 | 180 | |
donatien | 0:bfed5767d0a5 | 181 | uint32_t USBEndpoint::getBufStart() { |
donatien | 0:bfed5767d0a5 | 182 | return buf_start; |
donatien | 0:bfed5767d0a5 | 183 | } |
donatien | 0:bfed5767d0a5 | 184 | |
donatien | 0:bfed5767d0a5 | 185 | void USBEndpoint::unqueueTransfer(volatile HCTD * td) { |
donatien | 0:bfed5767d0a5 | 186 | //printf("unqueue transfer: %p on endpoint: %p\r\n", (void *)td, this); |
donatien | 0:bfed5767d0a5 | 187 | //headTD = tailTD; //FIXME FIXME |
donatien | 0:bfed5767d0a5 | 188 | // hced->headTD = hced->headTD | (td-> & 0x02); |
donatien | 0:bfed5767d0a5 | 189 | if(td != td_current) |
donatien | 0:bfed5767d0a5 | 190 | { |
donatien | 0:bfed5767d0a5 | 191 | ERR("MISMATCH"); |
donatien | 0:bfed5767d0a5 | 192 | ERR("this=%p, td_current = %p, td_next=%p, td=%p", this, td_current, td_next, td); |
donatien | 0:bfed5767d0a5 | 193 | error(""); |
donatien | 0:bfed5767d0a5 | 194 | } |
donatien | 0:bfed5767d0a5 | 195 | td->control=0; |
donatien | 0:bfed5767d0a5 | 196 | td->currBufPtr=0; |
donatien | 0:bfed5767d0a5 | 197 | td->bufEnd=0; |
donatien | 0:bfed5767d0a5 | 198 | td->nextTD=0; |
donatien | 0:bfed5767d0a5 | 199 | hced->headTD = hced->tailTD | (hced->headTD & 0x2); //Carry bit |
donatien | 0:bfed5767d0a5 | 200 | td_current = td_next; |
donatien | 0:bfed5767d0a5 | 201 | td_next = td; |
donatien | 0:bfed5767d0a5 | 202 | DBG("current:%p, next:%p", td_current, td_next); |
donatien | 0:bfed5767d0a5 | 203 | } |
donatien | 0:bfed5767d0a5 | 204 | |
donatien | 0:bfed5767d0a5 | 205 | ENDPOINT_TYPE USBEndpoint::getType() { |
donatien | 0:bfed5767d0a5 | 206 | return type; |
donatien | 0:bfed5767d0a5 | 207 | } |
donatien | 0:bfed5767d0a5 | 208 | |
donatien | 0:bfed5767d0a5 | 209 | |
donatien | 0:bfed5767d0a5 | 210 | USBEndpoint * USBEndpoint::nextEndpoint() { |
donatien | 0:bfed5767d0a5 | 211 | return (USBEndpoint*)nextEp; |
donatien | 0:bfed5767d0a5 | 212 | } |
donatien | 0:bfed5767d0a5 | 213 | |
donatien | 0:bfed5767d0a5 | 214 | |
donatien | 0:bfed5767d0a5 | 215 | void USBEndpoint::queueEndpoint(USBEndpoint * ed) { |
donatien | 0:bfed5767d0a5 | 216 | nextEp = ed; |
donatien | 0:bfed5767d0a5 | 217 | hced->nextED = (ed == NULL) ? 0 : (uint32_t)ed->getHCED(); |
donatien | 0:bfed5767d0a5 | 218 | } |
donatien | 0:bfed5767d0a5 | 219 | |
donatien | 0:bfed5767d0a5 | 220 | volatile HCED * USBEndpoint::getHCED() { |
donatien | 0:bfed5767d0a5 | 221 | return hced; |
donatien | 0:bfed5767d0a5 | 222 | } |
donatien | 0:bfed5767d0a5 | 223 | |
donatien | 0:bfed5767d0a5 | 224 | |
donatien | 0:bfed5767d0a5 | 225 | volatile HCTD * USBEndpoint::getHeadTD() { |
donatien | 0:bfed5767d0a5 | 226 | //return headTD; |
donatien | 0:bfed5767d0a5 | 227 | return (volatile HCTD*) (hced->headTD & ~0xF); |
donatien | 0:bfed5767d0a5 | 228 | } |
donatien | 0:bfed5767d0a5 | 229 | |
donatien | 0:bfed5767d0a5 | 230 | volatile HCTD ** USBEndpoint::getTDList() |
donatien | 0:bfed5767d0a5 | 231 | { |
donatien | 0:bfed5767d0a5 | 232 | return td_list; |
donatien | 0:bfed5767d0a5 | 233 | } |