EthernetNetIf Compatibility.

Dependents:   XBeeWiFi_SPI_example

Fork of NetServicesSource by Donatien Garnier

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