local fork (temporary)

Dependents:   VodafoneUSBModem_bleedingedge2

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBEndpoint.cpp Source File

USBEndpoint.cpp

00001 /* Copyright (c) 2010-2012 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 
00020 #define __DEBUG__ 0 //Maximum verbosity
00021 #ifndef __MODULE__
00022 #define __MODULE__ "USBEndpoint.cpp"
00023 #endif
00024 
00025 #include "core/dbg.h"
00026 #include <cstdint>
00027 #include "capi/error.h"
00028 
00029 #include "USBEndpoint.h"
00030 
00031 
00032 void USBEndpoint::init(HCED * hced, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t ep_number, HCTD* td_list[2]) {
00033     this->hced = hced;
00034     this->type = type;
00035     this->dir = /*(type == CONTROL_ENDPOINT) ? OUT :*/ dir;
00036     setup = (type == CONTROL_ENDPOINT) ? true : false;
00037 
00038     //TDs have been allocated by the host
00039     memcpy((HCTD**)this->td_list, td_list, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define
00040     memcpy(td_list[0], 0, sizeof(HCTD));
00041     memcpy(td_list[1], 0, sizeof(HCTD));
00042 
00043     this->hced->control = 0;
00044     //Empty queue
00045     this->hced->tailTD = (uint32_t)td_list[0];
00046     this->hced->headTD = (uint32_t)td_list[0];
00047     this->hced->nextED = 0;
00048 
00049     this->hced->control = ((ep_number & 0x7F) << 7)                         // Endpoint address
00050                           | (type != CONTROL_ENDPOINT ? ( dir << 11) : 0 )  // direction : Out = 1, 2 = In
00051                           | ((size & 0x3ff) << 16);                         // MaxPkt Size
00052                           
00053     //carry = false;
00054     transfer_len = 0;
00055     transferred = 0;
00056     buf_start = 0;
00057     nextEp = NULL;
00058 
00059     td_current = td_list[0];
00060     td_next = td_list[1];
00061 
00062     state = USB_TYPE_IDLE;
00063 }
00064 
00065 void USBEndpoint::setSize(uint32_t size) {
00066     hced->control &= ~(0x3ff << 16);
00067     hced->control |= (size << 16);
00068 }
00069 
00070 
00071 uint32_t USBEndpoint::getSize() {
00072     return (hced->control >> 16) & 0x3ff;
00073 }
00074 
00075 void USBEndpoint::setDeviceAddress(uint8_t addr) {
00076     hced->control &= ~(0x7f);
00077     hced->control |= (addr & 0x7F);
00078 }
00079 
00080 uint8_t USBEndpoint::getDeviceAddress() {
00081     return hced->control & 0x7f;
00082 }
00083 
00084 void USBEndpoint::setSpeed(uint8_t speed) {
00085     if(speed) {
00086         DBG("SET LOW SPEED");
00087     }
00088     hced->control &= ~(1 << 13);
00089     hced->control |= (speed << 13);
00090 }
00091 
00092 
00093 void USBEndpoint::setNextToken(uint32_t token) { //Only for control Eps
00094     switch (token) {
00095         case TD_SETUP:
00096             dir = OUT;
00097             setup = true;
00098             break;
00099         case TD_IN:
00100             dir = IN;
00101             setup = false;
00102             break;
00103         case TD_OUT:
00104             dir = OUT;
00105             setup = false;
00106             break;
00107     }
00108 }
00109 
00110 volatile HCTD* USBEndpoint::getNextTD()
00111 {
00112   return td_current/*(HCTD*) hced->tailTD*/; //It's the tailing one
00113 }
00114 
00115 void USBEndpoint::queueTransfer() {
00116   //Try with OHCI impl
00117   //Caller of getNextTD() has now populated the td
00118   //So insert it into queue
00119 
00120   //Find an OTHER free td
00121   //TODO: if we had more than 2 tds, this would have to be changed
00122   /*HCTD* toSendTD = (HCTD*) hced->tailTD;*/
00123   //HCTD* freeTD;
00124 /*
00125   if( hced->tailTD == td_list[0] )
00126   {
00127     freeTD = td_list[1];
00128   }
00129   else *//*if( hced->tailTD == (uint32_t) td_list[1] )*/
00130   /*{
00131     freeTD = td_list[0];
00132   }
00133   */
00134 
00135   /*
00136   freeTD->control = 0;
00137   freeTD->currBufPtr = 0;
00138   freeTD->bufEnd = 0;
00139   freeTD->nextTD = 0;
00140 
00141   td_current = toSendTD;
00142 */
00143   transfer_len = td_current->bufEnd - td_current->currBufPtr + 1;
00144   transferred = transfer_len;
00145   buf_start = td_current->currBufPtr;
00146 
00147   //No add this free TD at this end of the queue
00148   state = USB_TYPE_PROCESSING;
00149   td_current->nextTD = (volatile uint32_t)td_next;
00150   hced->tailTD = (volatile uint32_t)td_next;
00151 
00152   #if 0
00153     // if TD list empty -> we put the head of the list
00154     if (!hced->headTD) {
00155         state = USB_TYPE_IDLE;
00156         hced->headTD = (uint32_t)(td);
00157         hced->tailTD = (uint32_t)(td);
00158         tailTD = (HCTD *) (hced->headTD);
00159         //DBG("queue null transfer: endpoint: %p,  %08X\r\n", this, (uint32_t)(td));
00160     } else {
00161         state = USB_TYPE_PROCESSING;
00162         td->nextTD = (uint32_t)headTD & ~(0x0f);
00163         hced->headTD = (uint32_t)(td) | ((carry) ? 0x2 : 0);
00164     }
00165     headTD = (HCTD *) ((hced->headTD) & ~(0x3));
00166     transfer_len = td->bufEnd - td->currBufPtr + 1;
00167     transferred = transfer_len;
00168     buf_start = td->currBufPtr;
00169 #endif
00170     //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);
00171 }
00172 
00173 volatile HCTD * USBEndpoint::getProcessedTD()
00174 {
00175   return td_current;
00176 }
00177 
00178 void USBEndpoint::setLengthTransferred(int len) {
00179     transferred = len;
00180 }
00181 
00182 uint32_t USBEndpoint::getBufStart() {
00183     return buf_start;
00184 }
00185 
00186 void USBEndpoint::unqueueTransfer(volatile HCTD * td) {
00187     //printf("unqueue transfer: %p on endpoint: %p\r\n", (void *)td, this);
00188     //headTD = tailTD; //FIXME FIXME
00189 //  hced->headTD = hced->headTD | (td->  & 0x02);
00190   if(td != td_current)
00191   {
00192     ERR("MISMATCH");
00193     ERR("this=%p, td_current = %p, td_next=%p, td=%p", this, td_current, td_next, td);
00194     error("");
00195   }
00196   td->control=0;
00197   td->currBufPtr=0;
00198   td->bufEnd=0;
00199   td->nextTD=0;
00200   hced->headTD = hced->tailTD | (hced->headTD & 0x2); //Carry bit
00201   td_current = td_next;
00202   td_next = td;
00203   DBG("current:%p, next:%p", td_current, td_next);
00204 }
00205 
00206 ENDPOINT_TYPE USBEndpoint::getType() {
00207     return type;
00208 }
00209 
00210 
00211 USBEndpoint * USBEndpoint::nextEndpoint() {
00212     return (USBEndpoint*)nextEp;
00213 }
00214 
00215 
00216 void USBEndpoint::queueEndpoint(USBEndpoint * ed) {
00217     nextEp = ed;
00218     hced->nextED = (ed == NULL) ? 0 : (uint32_t)ed->getHCED();
00219 }
00220 
00221 volatile HCED * USBEndpoint::getHCED() {
00222     return hced;
00223 }
00224 
00225 
00226 volatile HCTD * USBEndpoint::getHeadTD() {
00227     //return headTD;
00228   return (volatile HCTD*) (hced->headTD & ~0xF);
00229 }
00230 
00231 volatile HCTD ** USBEndpoint::getTDList()
00232 {
00233   return td_list;
00234 }