Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
Diff: drv/usb/UsbEndpoint.cpp
- Revision:
- 4:fd826cad83c0
- Parent:
- 0:632c9925f013
- Child:
- 5:dd63a1e02b1b
diff -r 95e0bc00a1bb -r fd826cad83c0 drv/usb/UsbEndpoint.cpp
--- 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