NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
UsbEndpoint.cpp
00001 00002 /* 00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 THE SOFTWARE. 00022 */ 00023 00024 #include "UsbEndpoint.h" 00025 00026 #include "UsbDevice.h" 00027 00028 #include "usb_mem.h" 00029 00030 #include "netCfg.h" 00031 #if NET_USB 00032 00033 //#define __DEBUG 00034 #include "dbg/dbg.h" 00035 00036 UsbEndpoint::UsbEndpoint( UsbDevice* pDevice, uint8_t ep, bool dir, UsbEndpointType type, uint16_t size, int addr /*= -1*/ ) : m_pDevice(pDevice), m_result(true), m_status((int)USBERR_OK), m_len(0), m_pBufStartPtr(NULL), 00037 m_pCbItem(NULL), m_pCbMeth(NULL), m_pNextEp(NULL) 00038 { 00039 //Insert into Eps list 00040 //FIXME: Assert that no USB interrupt is triggered meanwhile 00041 if(m_pHeadEp) 00042 { 00043 m_pNextEp = m_pHeadEp; 00044 m_pHeadEp = this; 00045 } 00046 else 00047 { 00048 m_pNextEp = NULL; 00049 m_pHeadEp = this; 00050 } 00051 00052 m_pEd = (volatile HCED*)usb_get_ed(); 00053 00054 m_pTdHead = (volatile HCTD*)usb_get_td(); 00055 m_pTdTail = (volatile HCTD*)usb_get_td(); 00056 00057 //printf("\r\n--m_pEd = %p--\r\n", m_pEd); 00058 DBG("m_pEd = %p\n", m_pEd); 00059 DBG("m_pTdHead = %p\n", m_pTdHead); 00060 DBG("m_pTdTail = %p\n", m_pTdTail); 00061 00062 //Init Ed & Td 00063 //printf("\r\n--Ep Init--\r\n"); 00064 memset((void*)m_pEd, 0, sizeof(HCED)); 00065 //printf("\r\n--Td Init--\r\n"); 00066 00067 memset((void*)m_pTdHead, 0, sizeof(HCTD)); 00068 memset((void*)m_pTdTail, 0, sizeof(HCTD)); 00069 00070 if(addr == -1) 00071 addr = pDevice->m_addr; 00072 00073 //Setup Ed 00074 //printf("\r\n--Ep Setup--\r\n"); 00075 m_pEd->Control = addr | /* USB address */ 00076 ((ep & 0x7F) << 7) | /* Endpoint address */ 00077 (type!=USB_CONTROL?((dir?2:1) << 11):0) | /* direction : Out = 1, 2 = In */ 00078 (size << 16); /* MaxPkt Size */ 00079 00080 m_dir = dir; 00081 m_setup = false; 00082 m_type = type; 00083 00084 m_pEd->TailTd = m_pEd->HeadTd = (uint32_t) m_pTdTail; //Empty TD list 00085 00086 DBG("Before link\n"); 00087 00088 //printf("\r\n--Ep Reg--\r\n"); 00089 //Append Ed to Ed list 00090 volatile HCED* prevEd; 00091 switch( m_type ) 00092 { 00093 case USB_CONTROL: 00094 prevEd = (volatile HCED*) LPC_USB->HcControlHeadED; 00095 break; 00096 case USB_BULK: 00097 default: 00098 prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; 00099 break; 00100 } 00101 00102 DBG("prevEd is %p\n", prevEd); 00103 00104 if(prevEd) 00105 { 00106 DBG("prevEd set\n") 00107 00108 while(prevEd->Next) 00109 { 00110 DBG("prevEd->Next = %08x\n", prevEd->Next); 00111 prevEd = (volatile HCED*) prevEd->Next; 00112 } 00113 prevEd->Next = (uint32_t) m_pEd; 00114 00115 } 00116 else 00117 { 00118 switch( m_type ) 00119 { 00120 case USB_CONTROL: 00121 LPC_USB->HcControlHeadED = (uint32_t) m_pEd; 00122 break; 00123 case USB_BULK: 00124 default: 00125 LPC_USB->HcBulkHeadED = (uint32_t) m_pEd; 00126 break; 00127 } 00128 } 00129 00130 DBG("Ep init\n"); 00131 } 00132 00133 UsbEndpoint::~UsbEndpoint() 00134 { 00135 //Remove from Eps list 00136 //FIXME: Assert that no USB interrupt is triggered meanwhile 00137 if(m_pHeadEp != this) 00138 { 00139 UsbEndpoint* prevEp = m_pHeadEp; 00140 while(prevEp->m_pNextEp != this) 00141 prevEp = prevEp->m_pNextEp; 00142 prevEp->m_pNextEp = m_pNextEp; 00143 } 00144 else 00145 { 00146 m_pHeadEp = m_pNextEp; 00147 } 00148 00149 m_pEd->Control |= ED_SKIP; //Skip this Ep in queue 00150 00151 //Remove from queue 00152 volatile HCED* prevEd; 00153 switch( m_type ) 00154 { 00155 case USB_CONTROL: 00156 prevEd = (volatile HCED*) LPC_USB->HcControlHeadED; 00157 break; 00158 case USB_BULK: 00159 default: 00160 prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; 00161 break; 00162 } 00163 if( m_pEd == prevEd ) 00164 { 00165 switch( m_type ) 00166 { 00167 case USB_CONTROL: 00168 LPC_USB->HcControlHeadED = m_pEd->Next; 00169 break; 00170 case USB_BULK: 00171 default: 00172 LPC_USB->HcBulkHeadED = m_pEd->Next; 00173 break; 00174 } 00175 LPC_USB->HcBulkHeadED = m_pEd->Next; 00176 } 00177 else 00178 { 00179 while( prevEd->Next != (uint32_t) m_pEd ) 00180 { 00181 prevEd = (volatile HCED*) prevEd->Next; 00182 } 00183 prevEd->Next = m_pEd->Next; 00184 } 00185 00186 // 00187 usb_free_ed((volatile byte*)m_pEd); 00188 00189 usb_free_td((volatile byte*)m_pTdHead); 00190 usb_free_td((volatile byte*)m_pTdTail); 00191 } 00192 00193 void UsbEndpoint::setNextToken(uint32_t token) //Only for control Eps 00194 { 00195 switch(token) 00196 { 00197 case TD_SETUP: 00198 m_dir = false; 00199 m_setup = true; 00200 break; 00201 case TD_IN: 00202 m_dir = true; 00203 m_setup = false; 00204 break; 00205 case TD_OUT: 00206 m_dir = false; 00207 m_setup = false; 00208 break; 00209 } 00210 } 00211 00212 UsbErr UsbEndpoint::transfer(volatile uint8_t* buf, uint32_t len) 00213 { 00214 if(!m_result) 00215 return USBERR_BUSY; //The previous trasnfer is not completed 00216 //FIXME: We should be able to queue the next transfer, still needs to be implemented 00217 00218 if( !m_pDevice->connected() ) 00219 return USBERR_DISCONNECTED; 00220 00221 m_result = false; 00222 00223 volatile uint32_t token = (m_setup?TD_SETUP:(m_dir?TD_IN:TD_OUT)); 00224 00225 volatile uint32_t td_toggle; 00226 if (m_type == USB_CONTROL) 00227 { 00228 if (m_setup) 00229 { 00230 td_toggle = TD_TOGGLE_0; 00231 } 00232 else 00233 { 00234 td_toggle = TD_TOGGLE_1; 00235 } 00236 } 00237 else 00238 { 00239 td_toggle = 0; 00240 } 00241 00242 //Swap Tds 00243 volatile HCTD* pTdSwap; 00244 pTdSwap = m_pTdTail; 00245 m_pTdTail = m_pTdHead; 00246 m_pTdHead = pTdSwap; 00247 00248 m_pTdHead->Control = (TD_ROUNDING | 00249 token | 00250 TD_DELAY_INT(0) |//7 00251 td_toggle | 00252 TD_CC); 00253 00254 m_pTdTail->Control = 0; 00255 m_pTdHead->CurrBufPtr = (uint32_t) buf; 00256 m_pBufStartPtr = buf; 00257 m_pTdTail->CurrBufPtr = 0; 00258 m_pTdHead->Next = (uint32_t) m_pTdTail; 00259 m_pTdTail->Next = 0; 00260 m_pTdHead->BufEnd = (uint32_t)(buf + (len - 1)); 00261 m_pTdTail->BufEnd = 0; 00262 00263 m_pEd->HeadTd = (uint32_t)m_pTdHead | ((m_pEd->HeadTd) & 0x00000002); //Carry bit 00264 m_pEd->TailTd = (uint32_t)m_pTdTail; 00265 00266 //DBG("m_pEd->HeadTd = %08x\n", m_pEd->HeadTd); 00267 00268 if(m_type == USB_CONTROL) 00269 { 00270 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_CLF; 00271 LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_CLE; //Enable control list 00272 } 00273 else //USB_BULK 00274 { 00275 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; 00276 LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; //Enable bulk list 00277 } 00278 00279 //m_done = false; 00280 m_len = len; 00281 00282 return USBERR_PROCESSING; 00283 00284 } 00285 00286 int UsbEndpoint::status() 00287 { 00288 if( !m_pDevice->connected() ) 00289 { 00290 if(!m_result) 00291 onCompletion(); 00292 m_result = true; 00293 return (int)USBERR_DISCONNECTED; 00294 } 00295 else if( !m_result ) 00296 { 00297 return (int)USBERR_PROCESSING; 00298 } 00299 /*else if( m_done ) 00300 { 00301 return (int)USBERR_OK; 00302 }*/ 00303 else 00304 { 00305 return m_status; 00306 } 00307 } 00308 00309 void UsbEndpoint::updateAddr(int addr) 00310 { 00311 DBG("m_pEd->Control = %08x\n", m_pEd->Control); 00312 m_pEd->Control &= ~0x7F; 00313 m_pEd->Control |= addr; 00314 DBG("m_pEd->Control = %08x\n", m_pEd->Control); 00315 } 00316 00317 void UsbEndpoint::updateSize(uint16_t size) 00318 { 00319 DBG("m_pEd->Control = %08x\n", m_pEd->Control); 00320 m_pEd->Control &= ~0x3FF0000; 00321 m_pEd->Control |= (size << 16); 00322 DBG("m_pEd->Control = %08x\n", m_pEd->Control); 00323 } 00324 00325 #if 0 //For doc only 00326 template <class T> 00327 void UsbEndpoint::setOnCompletion( T* pCbItem, void (T::*pCbMeth)() ) 00328 { 00329 m_pCbItem = (CDummy*) pCbItem; 00330 m_pCbMeth = (void (CDummy::*)()) pCbMeth; 00331 } 00332 #endif 00333 00334 void UsbEndpoint::onCompletion() 00335 { 00336 //DBG("Transfer completed\n"); 00337 if( m_pTdHead->Control >> 28 ) 00338 { 00339 DBG("TD Failed with condition code %01x\n", m_pTdHead->Control >> 28 ); 00340 m_status = (int)USBERR_TDFAIL; 00341 } 00342 else if( m_pEd->HeadTd & 0x1 ) 00343 { 00344 m_pEd->HeadTd = m_pEd->HeadTd & ~0x1; 00345 DBG("\r\nHALTED!!\r\n"); 00346 m_status = (int)USBERR_HALTED; 00347 } 00348 else if( (m_pEd->HeadTd & ~0xF) == (uint32_t) m_pTdTail ) 00349 { 00350 //Done 00351 int len; 00352 //DBG("m_pTdHead->CurrBufPtr = %08x, m_pBufStartPtr=%08x\n", m_pTdHead->CurrBufPtr, (uint32_t) m_pBufStartPtr); 00353 if(m_pTdHead->CurrBufPtr) 00354 len = m_pTdHead->CurrBufPtr - (uint32_t) m_pBufStartPtr; 00355 else 00356 len = m_len; 00357 /*if(len == 0) //Packet transfered completely 00358 len = m_len;*/ 00359 //m_done = true; 00360 DBG("Transfered %d bytes\n", len); 00361 m_status = len; 00362 } 00363 else 00364 { 00365 DBG("Unknown error...\n"); 00366 m_status = (int)USBERR_ERROR; 00367 } 00368 m_result = true; 00369 if(m_pCbItem && m_pCbMeth) 00370 (m_pCbItem->*m_pCbMeth)(); 00371 } 00372 00373 void UsbEndpoint::sOnCompletion(uint32_t pTd) 00374 { 00375 if(!m_pHeadEp) 00376 return; 00377 do 00378 { 00379 //DBG("sOnCompletion (pTd = %08x)\n", pTd); 00380 UsbEndpoint* pEp = m_pHeadEp; 00381 do 00382 { 00383 if((uint32_t)pEp->m_pTdHead == pTd) 00384 { 00385 pEp->onCompletion(); 00386 break; 00387 } 00388 } while(pEp = pEp->m_pNextEp); 00389 } while( pTd = (uint32_t)( ((HCTD*)pTd)->Next ) ); //Go around the Done queue 00390 } 00391 00392 UsbEndpoint* UsbEndpoint::m_pHeadEp = NULL; 00393 00394 #endif
Generated on Tue Jul 12 2022 11:52:58 by
![doxygen](doxygen.png)