NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

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