EthernetNetIf Compatibility.
Dependents: XBeeWiFi_SPI_example
Fork of NetServicesSource by
Diff: drv/usb/UsbEndpoint.cpp
- Revision:
- 0:632c9925f013
- Child:
- 4:fd826cad83c0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drv/usb/UsbEndpoint.cpp Fri Jun 11 16:05:15 2010 +0000 @@ -0,0 +1,294 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "UsbEndpoint.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; +} + +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() +{ + printf("\r\n--HCTD* &m_pool[m_pos]= %p--\r\n", &m_pool[m_pos]); + while( ( ((uint32_t)&m_pool[m_pos]) & 0xF ) != 0 ) + { + 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; + +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 = m_edPool.get(); + + #else + if(m_pNextEd == NULL) + { + m_pNextEd = EDBulkHead; + //printf("\r\n--m_pEd = %p < EDBulkHead = %p --\r\n", m_pEd, EDBulkHead); + } + + 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); + + //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); + + //Setup Ed + printf("\r\n--Ep Setup--\r\n"); + m_pEd->Control = 1 | /* USB address */ //FIXME: Device Id + ((ep & 0x7F) << 7) | /* Endpoint address */ + ((dir?2:1) << 11) | /* direction : Out = 1, 2 = In */ + (size << 16); /* MaxPkt Size */ + + m_dir = dir; + + m_pEd->TailTd = m_pEd->HeadTd = (USB_INT32U) m_pTdTail; //Empty TD list + + 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 ) + { + LPC_USB->HcBulkHeadED = (USB_INT32U)m_pEd; + printf("\r\n--Bulk head--\r\n"); + } + else + { + volatile HCED* prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; + while(prevEd->Next) + { + prevEd = (volatile HCED*) prevEd->Next; + } + 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; + */ +} + +UsbEndpoint::~UsbEndpoint() +{ + m_pEd->Control |= ED_SKIP; //Skip this Ep in queue + + //Remove from queue + if( LPC_USB->HcBulkHeadED == (USB_INT32U) m_pEd ) + { + LPC_USB->HcBulkHeadED = m_pEd->Next; + } + else + { + volatile HCED* prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED; + while( prevEd->Next != (USB_INT32U) m_pEd ) + { + prevEd = (volatile HCED*) prevEd->Next; + } + prevEd->Next = m_pEd->Next; + } + + if( LPC_USB->HcBulkCurrentED == (USB_INT32U) m_pEd ) + { + LPC_USB->HcBulkCurrentED = 0; + } + + + #if 0 //NO WAY! Owned by pool!!! + delete m_pEd; + delete m_pTdHead; + delete m_pTdTail; + #endif +} + +RC 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); + + //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; + + //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--Writing config reg--\r\n"); + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; + LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; + + // printf("\r\n--Processing queue--\r\n"); + // __WFI(); + m_done = false; + m_len = len; + return PROCESSING; + +} + +RC UsbEndpoint::status() +{ + if( m_done ) + { + return OK; + } + //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 ) + { + //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; + } + else if( m_pEd->HeadTd & 0x1 ) + { + printf("\r\nHALTED!!\r\n"); + return ERR_TD_FAIL; + } + else + { + // wait(1); + return PROCESSING; + } +} + +#endif