EthernetNetIf Compatibility.
Dependents: XBeeWiFi_SPI_example
Fork of NetServicesSource by
Diff: drv/usb/UsbEndpoint.cpp
- Revision:
- 4:fd826cad83c0
- Parent:
- 0:632c9925f013
- Child:
- 5:dd63a1e02b1b
--- a/drv/usb/UsbEndpoint.cpp Fri Jun 18 10:38:57 2010 +0000 +++ b/drv/usb/UsbEndpoint.cpp Fri Jul 09 14:46:47 2010 +0000 @@ -23,272 +23,369 @@ #include "UsbEndpoint.h" +#include "UsbDevice.h" + +#include "usb_mem.h" + #include "netCfg.h" #if NET_USB -EdPool::EdPool(int size) : m_pos(0) -{ - m_pool = new uint8_t[2*size*0x10]; - printf("\r\n--HCED* m_pool= %p of size %d--\r\n", m_pool, 2*size*0x10); -} - -EdPool::~EdPool() -{ - printf("\r\n--~EdPool()--\r\n"); - delete[] m_pool; -} +//#define __DEBUG +#include "dbg/dbg.h" -HCED* EdPool::get() -{ - printf("\r\n--HCED* &m_pool[m_pos]= %p--\r\n", &m_pool[m_pos]); - while( ( ((uint32_t)&m_pool[m_pos]) & 0xF ) != 0 ) - { - m_pos++; - } - HCED* pEd = (HCED*) &m_pool[m_pos]; - m_pos += sizeof(HCED); - printf("\r\n--HCED* pEd = %p--\r\n", pEd); - return pEd; -} - -TdPool::TdPool(int size) : m_pos(0) -{ - m_pool = new uint8_t[2*size*0x10]; - printf("\r\n--HCTD* m_pool= %p of size %d--\r\n", m_pool, 2*size*0x10); -} - -TdPool::~TdPool() -{ - printf("\r\n--~EdPool()--\r\n"); - delete[] m_pool; -} - -HCTD* TdPool::get() +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), +m_pCbItem(NULL), m_pCbMeth(NULL), m_pNextEp(NULL) { - printf("\r\n--HCTD* &m_pool[m_pos]= %p--\r\n", &m_pool[m_pos]); - while( ( ((uint32_t)&m_pool[m_pos]) & 0xF ) != 0 ) + //Insert into Eps list + //FIXME: Assert that no USB interrupt is triggered meanwhile + if(m_pHeadEp) { - m_pos++; - } - HCTD* pTd = (HCTD*) &m_pool[m_pos]; - m_pos += sizeof(HCTD); - printf("\r\n--HCTD* pTd = %p--\r\n", pTd); - return pTd; -} -//uint8_t TdPool::pool[16*0x10]={0};//Ok for 2 Eps (2*(2Tds/Ep*2Eps)) -//int TdPool::pos = 0; + m_pNextEp = m_pHeadEp; + m_pHeadEp = this; + } + else + { + m_pNextEp = NULL; + m_pHeadEp = this; + } -extern volatile HCED* EDBulkHead; -//volatile HCED* UsbEndpoint::m_pNextEd = NULL; - -UsbEndpoint::UsbEndpoint( /* UsbDevice*, */ uint8_t ep, bool dir, uint16_t size ) : m_edPool(1), m_tdPool(2), m_done(true), m_len(0), m_pBufStartPtr(NULL) -{ - #if 1 + m_pEd = (volatile HCED*)usb_get_ed(); - m_pEd = m_edPool.get(); - - #else - if(m_pNextEd == NULL) - { - m_pNextEd = EDBulkHead; - //printf("\r\n--m_pEd = %p < EDBulkHead = %p --\r\n", m_pEd, EDBulkHead); - } + m_pTdHead = (volatile HCTD*)usb_get_td(); + m_pTdTail = (volatile HCTD*)usb_get_td(); - printf("\r\n--Ep Inst--\r\n"); - m_pEd = /*new HCED(); // */m_pNextEd; - - //printf("\r\n--m_pNextEd = %p--\r\n", m_pNextEd); - m_pNextEd += 1; //TODO: Avail mem check - //printf("\r\n--m_pNextEd = %p--\r\n", m_pNextEd); - #endif - - m_pTdHead = m_tdPool.get();//new HCTD(); - m_pTdTail = m_tdPool.get();//new HCTD(); - - printf("\r\n--m_pEd = %p--\r\n", m_pEd); + //printf("\r\n--m_pEd = %p--\r\n", m_pEd); //Init Ed & Td - printf("\r\n--Ep Init--\r\n"); - Host_EDInit(m_pEd); - printf("\r\n--Td Init--\r\n"); - Host_TDInit(m_pTdHead); - Host_TDInit(m_pTdTail); + //printf("\r\n--Ep Init--\r\n"); + memset((void*)m_pEd, 0, sizeof(HCED)); + //printf("\r\n--Td Init--\r\n"); + + memset((void*)m_pTdHead, 0, sizeof(HCTD)); + memset((void*)m_pTdTail, 0, sizeof(HCTD)); + + if(addr == -1) + addr = pDevice->m_addr; //Setup Ed - printf("\r\n--Ep Setup--\r\n"); - m_pEd->Control = 1 | /* USB address */ //FIXME: Device Id + //printf("\r\n--Ep Setup--\r\n"); + m_pEd->Control = addr | /* USB address */ ((ep & 0x7F) << 7) | /* Endpoint address */ - ((dir?2:1) << 11) | /* direction : Out = 1, 2 = In */ + (type!=USB_CONTROL?((dir?2:1) << 11):0) | /* direction : Out = 1, 2 = In */ (size << 16); /* MaxPkt Size */ m_dir = dir; + m_setup = false; + m_type = type; - m_pEd->TailTd = m_pEd->HeadTd = (USB_INT32U) m_pTdTail; //Empty TD list + m_pEd->TailTd = m_pEd->HeadTd = (uint32_t) m_pTdTail; //Empty TD list + + DBG("Before link\n"); - printf("\r\n--Ep Reg--\r\n"); - //Append Ed to bulk Ep list - #if 1 - volatile HCED* prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; - m_pEd->Next = (USB_INT32U) prevEd; - LPC_USB->HcBulkHeadED = (USB_INT32U) m_pEd; - #else - if( LPC_USB->HcBulkHeadED == 0 ) + //printf("\r\n--Ep Reg--\r\n"); + //Append Ed to Ed list + volatile HCED* prevEd; + switch( m_type ) { - LPC_USB->HcBulkHeadED = (USB_INT32U)m_pEd; - printf("\r\n--Bulk head--\r\n"); + case USB_CONTROL: + prevEd = (volatile HCED*) LPC_USB->HcControlHeadED; + break; + case USB_BULK: + default: + prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; + break; + } + + DBG("prevEd is %p\n", prevEd); + + if(prevEd) + { + DBG("prevEd set\n") + + while(prevEd->Next) + { + DBG("prevEd->Next = %08x\n", prevEd->Next); + prevEd = (volatile HCED*) prevEd->Next; + } + prevEd->Next = (uint32_t) m_pEd; + } else { - volatile HCED* prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; - while(prevEd->Next) + switch( m_type ) { - prevEd = (volatile HCED*) prevEd->Next; + case USB_CONTROL: + LPC_USB->HcControlHeadED = (uint32_t) m_pEd; + break; + case USB_BULK: + default: + LPC_USB->HcBulkHeadED = (uint32_t) m_pEd; + break; } - printf("\r\n--Appended to ep list (prevEd = %p)--\r\n", prevEd); - prevEd->Next = (USB_INT32U) m_pEd; } - #endif - /* - printf("\r\n--Writing config reg--\r\n"); - LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; - LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; - */ + + DBG("Ep init\n"); } UsbEndpoint::~UsbEndpoint() { + //Remove from Eps list + //FIXME: Assert that no USB interrupt is triggered meanwhile + if(m_pHeadEp != this) + { + UsbEndpoint* prevEp = m_pHeadEp; + while(prevEp->m_pNextEp != this) + prevEp = prevEp->m_pNextEp; + prevEp->m_pNextEp = m_pNextEp; + } + else + { + m_pHeadEp = m_pNextEp; + } + m_pEd->Control |= ED_SKIP; //Skip this Ep in queue //Remove from queue - if( LPC_USB->HcBulkHeadED == (USB_INT32U) m_pEd ) + volatile HCED* prevEd; + switch( m_type ) { + case USB_CONTROL: + prevEd = (volatile HCED*) LPC_USB->HcControlHeadED; + break; + case USB_BULK: + default: + prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; + break; + } + if( m_pEd == prevEd ) + { + switch( m_type ) + { + case USB_CONTROL: + LPC_USB->HcControlHeadED = m_pEd->Next; + break; + case USB_BULK: + default: + LPC_USB->HcBulkHeadED = m_pEd->Next; + break; + } LPC_USB->HcBulkHeadED = m_pEd->Next; } else { - volatile HCED* prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; - while( prevEd->Next != (USB_INT32U) m_pEd ) + while( prevEd->Next != (uint32_t) m_pEd ) { prevEd = (volatile HCED*) prevEd->Next; } prevEd->Next = m_pEd->Next; } - if( LPC_USB->HcBulkCurrentED == (USB_INT32U) m_pEd ) - { - LPC_USB->HcBulkCurrentED = 0; - } - + // + usb_free_ed((volatile byte*)m_pEd); - #if 0 //NO WAY! Owned by pool!!! - delete m_pEd; - delete m_pTdHead; - delete m_pTdTail; - #endif + usb_free_td((volatile byte*)m_pTdHead); + usb_free_td((volatile byte*)m_pTdTail); +} + +void UsbEndpoint::setNextToken(uint32_t token) //Only for control Eps +{ + switch(token) + { + case TD_SETUP: + m_dir = false; + m_setup = true; + break; + case TD_IN: + m_dir = true; + m_setup = false; + break; + case TD_OUT: + m_dir = false; + m_setup = false; + break; + } } -RC UsbEndpoint::transfer(volatile uint8_t* buf, uint32_t len) +UsbErr UsbEndpoint::transfer(volatile uint8_t* buf, uint32_t len) { - if(!m_done) - return ERR_TD_FAIL; - volatile USB_INT32U token = (m_dir?TD_IN:TD_OUT); - //printf("\r\n--m_pEd->HeadTd = %16x, m_pTdHead = %16x, m_pEd->TailTd = %16x, m_pTdTail = %16x--\r\n",m_pEd->HeadTd,(USB_INT32U)m_pTdHead,m_pEd->TailTd,(USB_INT32U)m_pTdTail); + if(!m_result) + return USBERR_BUSY; //The previous trasnfer is not completed + //FIXME: We should be able to queue the next transfer, still needs to be implemented + + if( !m_pDevice->connected() ) + return USBERR_DISCONNECTED; + + m_result = false; + + volatile uint32_t token = (m_setup?TD_SETUP:(m_dir?TD_IN:TD_OUT)); + + volatile uint32_t td_toggle; + if (m_type == USB_CONTROL) + { + if (m_setup) + { + td_toggle = TD_TOGGLE_0; + } + else + { + td_toggle = TD_TOGGLE_1; + } + } + else + { + td_toggle = 0; + } //Swap Tds - //printf("\r\n--Swap Tds--\r\n"); - volatile HCTD* pTdSwap; - pTdSwap = m_pTdTail; - m_pTdTail = m_pTdHead; - m_pTdHead = pTdSwap; - - - // printf("\r\n--m_pEd->HeadTd = %16x, m_pTdHead = %16x, m_pEd->TailTd = %16x, m_pTdTail = %16x--\r\n",m_pEd->HeadTd,(USB_INT32U)m_pTdHead,m_pEd->TailTd,(USB_INT32U)m_pTdTail); - - // printf("\r\n--Tds setup--\r\n"); - m_pTdHead->Control = (TD_ROUNDING | - token | - // TD_DELAY_INT(0) | - TD_DELAY_INT(7) | - TD_CC); - m_pTdTail->Control = 0; - m_pTdHead->CurrBufPtr = (USB_INT32U) buf; - m_pBufStartPtr = buf; - m_pTdTail->CurrBufPtr = 0; - m_pTdHead->Next = (USB_INT32U) m_pTdTail; - m_pTdTail->Next = 0; - m_pTdHead->BufEnd = (USB_INT32U)(buf + (len - 1)); - m_pTdTail->BufEnd = 0; - -// printf("\r\n--Ed setup--\r\n"); -// m_pEd->HeadTd = (USB_INT32U)m_pTdHead | ((m_pEd->HeadTd) & 0x00000002); - m_pEd->HeadTd = (USB_INT32U)m_pTdHead | ((m_pEd->HeadTd) & 0x00000002); //Carry bit - m_pEd->TailTd = (USB_INT32U)m_pTdTail; -/* - printf("\r\n--Swap Tds--\r\n"); volatile HCTD* pTdSwap; pTdSwap = m_pTdTail; m_pTdTail = m_pTdHead; m_pTdHead = pTdSwap; - */ -// ed->Next = 0; + + m_pTdHead->Control = (TD_ROUNDING | + token | + TD_DELAY_INT(0) |//7 + td_toggle | + TD_CC); - //printf("\r\n--m_pEd->HeadTd = %16x, m_pTdHead = %16x, m_pEd->TailTd = %16x, m_pTdTail = %16x--\r\n",m_pEd->HeadTd,(USB_INT32U)m_pTdHead,m_pEd->TailTd,(USB_INT32U)m_pTdTail); + m_pTdTail->Control = 0; + m_pTdHead->CurrBufPtr = (uint32_t) buf; + m_pBufStartPtr = buf; + m_pTdTail->CurrBufPtr = 0; + m_pTdHead->Next = (uint32_t) m_pTdTail; + m_pTdTail->Next = 0; + m_pTdHead->BufEnd = (uint32_t)(buf + (len - 1)); + m_pTdTail->BufEnd = 0; - // printf("\r\n--Writing config reg--\r\n"); - LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; - LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; + m_pEd->HeadTd = (uint32_t)m_pTdHead | ((m_pEd->HeadTd) & 0x00000002); //Carry bit + m_pEd->TailTd = (uint32_t)m_pTdTail; - // printf("\r\n--Processing queue--\r\n"); - // __WFI(); - m_done = false; + //DBG("m_pEd->HeadTd = %08x\n", m_pEd->HeadTd); + + if(m_type == USB_CONTROL) + { + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_CLF; + LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_CLE; //Enable control list + } + else //USB_BULK + { + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; + LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; //Enable bulk list + } + + //m_done = false; m_len = len; - return PROCESSING; + + return USBERR_PROCESSING; } -RC UsbEndpoint::status() +int UsbEndpoint::status() { - if( m_done ) + if( !m_pDevice->connected() ) { - return OK; + if(!m_result) + onCompletion(); + m_result = true; + return (int)USBERR_DISCONNECTED; } - //volatile HCTD* pTd = (volatile HCTD*) m_pEd->HeadTd; - //printf("\r\nm_pTdHead->CurrBufPtr = %16x", m_pTdHead->CurrBufPtr); - //printf("\r\n--m_pEd->HeadTd = %16x, m_pTdHead = %16x, m_pEd->TailTd = %16x, m_pTdTail = %16x--\r\n",m_pEd->HeadTd,(USB_INT32U)m_pTdHead,m_pEd->TailTd,(USB_INT32U)m_pTdTail); - //if( pTd->CurrBufPtr == 0 /*m_pEd->HeadTd != (USB_INT32U)m_pTdHead*//*m_pEd->HeadTd == (USB_INT32U)m_pTdTail*/) //Empty queue - else if( (m_pEd->HeadTd & ~0xF) == (USB_INT32U) m_pTdTail ) + else if( !m_result ) + { + return (int)USBERR_PROCESSING; + } + /*else if( m_done ) + { + return (int)USBERR_OK; + }*/ + else { - //Done - //printf("\r\n--m_pEd->HeadTd = %16x, m_pTdHead = %16x, m_pEd->TailTd = %16x, m_pTdTail = %16x--\r\n",m_pEd->HeadTd,(USB_INT32U)m_pTdHead,m_pEd->TailTd,(USB_INT32U)m_pTdTail); - int len; - if(m_pTdHead->CurrBufPtr) - len = m_pTdHead->CurrBufPtr - (USB_INT32U)m_pBufStartPtr; //Does not work properly, packet might have been discarded - else - len = m_len; -// printf("\r\nDone w/ len = %d (m_pTdHead->CurrBufPtr=%16x)\r\n", len, m_pTdHead->CurrBufPtr); - if(len == 0) //Packet transfered completely - len = m_len; - //Host_TDInit(m_pTdTail); - //m_pEd->TailTd = m_pEd->HeadTd = (USB_INT32U) m_pTdTail; //Empty TD list - - // printf("\r\n--Writing config reg--\r\n"); - //LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; - //LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; - - m_done = true; - return len; - //return OK; + return m_status; + } +} + +void UsbEndpoint::updateAddr(int addr) +{ + DBG("m_pEd->Control = %08x\n", m_pEd->Control); + m_pEd->Control &= ~0x7F; + m_pEd->Control |= addr; + DBG("m_pEd->Control = %08x\n", m_pEd->Control); +} + +void UsbEndpoint::updateSize(uint16_t size) +{ + DBG("m_pEd->Control = %08x\n", m_pEd->Control); + m_pEd->Control &= ~0x3FF0000; + m_pEd->Control |= (size << 16); + DBG("m_pEd->Control = %08x\n", m_pEd->Control); +} + +#if 0 //For doc only +template <class T> +void UsbEndpoint::setOnCompletion( T* pCbItem, void (T::*pCbMeth)() ) +{ + m_pCbItem = (CDummy*) pCbItem; + m_pCbMeth = (void (CDummy::*)()) pCbMeth; +} +#endif + +void UsbEndpoint::onCompletion() +{ + DBG("Transfer completed\n"); + if( m_pTdHead->Control >> 28 ) + { + DBG("\r\nTD Failed with condition code %01x\r\n", m_pTdHead->Control >> 28 ); + m_status = (int)USBERR_TDFAIL; } else if( m_pEd->HeadTd & 0x1 ) { - printf("\r\nHALTED!!\r\n"); - return ERR_TD_FAIL; + m_pEd->HeadTd = m_pEd->HeadTd & ~0x1; + DBG("\r\nHALTED!!\r\n"); + m_status = (int)USBERR_HALTED; + } + else if( (m_pEd->HeadTd & ~0xF) == (uint32_t) m_pTdTail ) + { + //Done + int len; + DBG("m_pTdHead->CurrBufPtr = %08x, m_pBufStartPtr=%08x\n", m_pTdHead->CurrBufPtr, (uint32_t) m_pBufStartPtr); + if(m_pTdHead->CurrBufPtr) + len = m_pTdHead->CurrBufPtr - (uint32_t) m_pBufStartPtr; + else + len = m_len; + /*if(len == 0) //Packet transfered completely + len = m_len;*/ + //m_done = true; + DBG("Transfered %d bytes\n", len); + m_status = len; } else - { - // wait(1); - return PROCESSING; + { + DBG("\r\nUnknown error...\r\n"); + m_status = (int)USBERR_ERROR; } + m_result = true; + if(m_pCbItem && m_pCbMeth) + (m_pCbItem->*m_pCbMeth)(); } +void UsbEndpoint::sOnCompletion(uint32_t pTd) +{ + if(!m_pHeadEp) + return; + do + { + DBG("sOnCompletion (pTd = %08x)\n", pTd); + UsbEndpoint* pEp = m_pHeadEp; + do + { + if((uint32_t)pEp->m_pTdHead == pTd) + { + pEp->onCompletion(); + break; + } + } while(pEp = pEp->m_pNextEp); + } while( pTd = (uint32_t)( ((HCTD*)pTd)->Next ) ); //Go around the Done queue +} + +UsbEndpoint* UsbEndpoint::m_pHeadEp = NULL; + #endif