BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS

Dependencies:   FatFileSystem mbed

Fork of BTstack by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UsbEndpoint.cpp Source File

UsbEndpoint.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "UsbEndpoint.h"
00025 #include "UsbDevice.h"
00026 #include "usb_mem.h"
00027 #include "Usb_td.h"
00028 #include "netCfg.h"
00029 #if NET_USB
00030 
00031 //#define __DEBUG
00032 //#define __DEBUG3
00033 //#include "dbg/dbg.h"
00034 #include "mydbg.h"
00035 
00036 UsbEndpoint::UsbEndpoint( UsbDevice* pDevice, uint8_t ep, bool dir, UsbEndpointType type, uint16_t size, int addr /*= -1*/ ) 
00037 : m_pDevice(pDevice), m_result(true), m_status((int)USBERR_OK), m_len(0), m_pBufStartPtr(NULL),
00038   m_pCbItem(NULL), m_pCbMeth(NULL)
00039 {
00040   if (type == USB_ISO) {
00041       UsbEndpoint_iso(pDevice, ep, dir, type, size, addr);
00042       return;
00043   }
00044 
00045   m_pEd = (volatile HCED*)usb_get_ed();
00046   DBG_ASSERT(m_pEd);
00047   memset((void*)m_pEd, 0, sizeof(HCED));
00048   
00049   m_pTdHead = (volatile HCTD*)usb_get_td((uint32_t)this);
00050   DBG_ASSERT(m_pTdHead);
00051   m_pTdTail = (volatile HCTD*)usb_get_td((uint32_t)this);
00052   DBG_ASSERT(m_pTdTail);
00053   DBG("m_pEd    =%p\n", m_pEd);
00054   DBG("m_pTdHead=%p\n", m_pTdHead);
00055   DBG("m_pTdTail=%p\n", m_pTdTail);
00056   
00057   if(addr == -1)
00058     addr = pDevice->m_addr;
00059   
00060   //Setup Ed
00061   //printf("\r\n--Ep Setup--\r\n");
00062   m_pEd->Control =  addr        |      /* USB address           */
00063   ((ep & 0x7F) << 7)            |      /* Endpoint address      */
00064   (type!=USB_CONTROL?((dir?2:1) << 11):0)             |      /* direction : Out = 1, 2 = In */
00065   (size << 16);     /* MaxPkt Size           */
00066   DBG3("m_pEd->Control=%08X\n", m_pEd->Control);
00067   m_dir = dir;
00068   m_setup = false;
00069   m_type = type;
00070   
00071   m_pEd->TailTd = m_pEd->HeadTd = (uint32_t) m_pTdTail; //Empty TD list
00072   
00073   DBG("Before link\n");
00074   
00075   //printf("\r\n--Ep Reg--\r\n");
00076   //Append Ed to Ed list
00077   HCCA* hcca;
00078   //volatile HCED* nextEd;
00079   DBG("m_type=%d\n", m_type);
00080   switch( m_type )
00081   {
00082   case USB_CONTROL:
00083     m_pEd->Next = LPC_USB->HcControlHeadED;
00084     LPC_USB->HcControlHeadED = (uint32_t)m_pEd;
00085     return;
00086 
00087   case USB_BULK:
00088     m_pEd->Next = LPC_USB->HcBulkHeadED;
00089     LPC_USB->HcBulkHeadED = (uint32_t)m_pEd;
00090     return;
00091 
00092   case USB_INT:
00093     hcca = (HCCA*)usb_get_hcca();
00094     m_pEd->Next = hcca->IntTable[0];
00095     hcca->IntTable[0] = (uint32_t)m_pEd;
00096     return;
00097   
00098   default:
00099     DBG_ASSERT(0);
00100   }
00101 }
00102 
00103 
00104 UsbEndpoint::~UsbEndpoint()
00105 {
00106   DBG_ASSERT(0);
00107 
00108   m_pEd->Control |= ED_SKIP; //Skip this Ep in queue
00109 
00110   //Remove from queue
00111   volatile HCED* prevEd;
00112   HCCA* hcca;
00113   switch( m_type )
00114   {
00115   case USB_CONTROL:
00116     prevEd = (volatile HCED*) LPC_USB->HcControlHeadED;
00117     break;
00118   case USB_BULK:
00119     prevEd = (volatile HCED*) LPC_USB->HcBulkHeadED;
00120     break;
00121   case USB_INT:
00122     hcca = (HCCA*)usb_get_hcca();
00123     prevEd = (volatile HCED*)hcca->IntTable[0];
00124     break;
00125   default:
00126     DBG_ASSERT(0);
00127   }
00128   if( m_pEd == prevEd )
00129   {
00130     switch( m_type )
00131     {
00132     case USB_CONTROL:
00133       LPC_USB->HcControlHeadED = m_pEd->Next;
00134       break;
00135     case USB_BULK:
00136       LPC_USB->HcBulkHeadED = m_pEd->Next;
00137       break;
00138     case USB_INT:
00139       hcca = (HCCA*)usb_get_hcca();
00140       hcca->IntTable[0] = m_pEd->Next;
00141       break;
00142     default:
00143       DBG_ASSERT(0);
00144     }
00145     LPC_USB->HcBulkHeadED = m_pEd->Next;
00146   }
00147   else
00148   {
00149     while( prevEd->Next != (uint32_t) m_pEd )
00150     {
00151       prevEd = (volatile HCED*) prevEd->Next;
00152     }
00153     prevEd->Next = m_pEd->Next;
00154   }
00155   
00156   //
00157   usb_free_ed((volatile byte*)m_pEd);
00158   
00159   usb_free_td((volatile byte*)m_pTdHead);
00160   usb_free_td((volatile byte*)m_pTdTail);
00161 }
00162 
00163 void UsbEndpoint::setNextToken(uint32_t token) //Only for control Eps
00164 {
00165   switch(token)
00166   {
00167     case TD_SETUP:
00168       m_dir = false;
00169       m_setup = true;
00170       break;
00171     case TD_IN:
00172       m_dir = true;
00173       m_setup = false;
00174       break;
00175     case TD_OUT:
00176       m_dir = false;
00177       m_setup = false;
00178       break;
00179   }
00180 }
00181 
00182 UsbErr UsbEndpoint::transfer(volatile uint8_t* buf, uint32_t len)
00183 {
00184   DBG("buf=%p\n", buf);
00185   if(!m_result)
00186     return USBERR_BUSY; //The previous trasnfer is not completed 
00187     //FIXME: We should be able to queue the next transfer, still needs to be implemented
00188   
00189   if( !m_pDevice->connected() )
00190     return USBERR_DISCONNECTED;
00191   
00192   m_result = false;
00193   
00194   volatile uint32_t token = (m_setup?TD_SETUP:(m_dir?TD_IN:TD_OUT));
00195 
00196   volatile uint32_t td_toggle;
00197   if (m_type == USB_CONTROL)
00198   {
00199     if (m_setup)
00200     {
00201       td_toggle = TD_TOGGLE_0;
00202     }
00203     else
00204     {
00205       td_toggle = TD_TOGGLE_1;
00206     }
00207   }
00208   else
00209   {
00210     td_toggle = 0;
00211   }
00212 
00213   //Swap Tds
00214   volatile HCTD* pTdSwap;
00215   pTdSwap = m_pTdTail;
00216   m_pTdTail = m_pTdHead;
00217   m_pTdHead = pTdSwap;
00218 
00219   m_pTdHead->Control = (TD_ROUNDING    |
00220                        token           |
00221                        TD_DELAY_INT(0) |//7
00222                        td_toggle       |
00223                        TD_CC);
00224 
00225   m_pTdTail->Control = 0;
00226   m_pTdHead->CurrBufPtr   = (uint32_t) buf;
00227   m_pBufStartPtr = buf;
00228   m_pTdTail->CurrBufPtr   = 0;
00229   m_pTdHead->Next         = (uint32_t) m_pTdTail;
00230   m_pTdTail->Next         = 0;
00231   m_pTdHead->BufEnd       = (uint32_t)(buf + (len - 1));
00232   m_pTdTail->BufEnd       = 0;
00233   
00234   m_pEd->HeadTd  = (uint32_t)m_pTdHead | ((m_pEd->HeadTd) & 0x00000002); //Carry bit
00235   m_pEd->TailTd  = (uint32_t)m_pTdTail;
00236   
00237   //DBG("m_pEd->HeadTd = %08x\n", m_pEd->HeadTd);
00238 
00239   if(m_type == USB_CONTROL) {
00240     LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_CLF;
00241     LPC_USB->HcControl       = LPC_USB->HcControl       | OR_CONTROL_CLE; //Enable control list
00242   } else if (m_type == USB_BULK) { //USB_BULK
00243     LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF;
00244     LPC_USB->HcControl       = LPC_USB->HcControl       | OR_CONTROL_BLE; //Enable bulk list
00245   } else if (m_type == USB_INT) { // USB_INT
00246     LPC_USB->HcControl       = LPC_USB->HcControl       | OR_CONTROL_PLE; //Enable Periodic
00247   } else { // USB_ISO
00248     DBG_ASSERT(0);
00249   }
00250   
00251   //m_done = false;
00252   m_len = len;
00253 
00254   return USBERR_PROCESSING;
00255  
00256 }
00257 
00258 int UsbEndpoint::status()
00259 {
00260   if( !m_pDevice->connected() )
00261   {
00262     if(!m_result)
00263       onCompletion();
00264     m_result = true;
00265     return (int)USBERR_DISCONNECTED;
00266   }
00267   else if( !m_result )
00268   { 
00269     return (int)USBERR_PROCESSING;
00270   }
00271   /*else if( m_done )
00272   {
00273     return (int)USBERR_OK;
00274   }*/
00275   else
00276   {
00277     return m_status;
00278   }
00279 }
00280 
00281 void UsbEndpoint::updateAddr(int addr)
00282 {
00283   DBG("m_pEd->Control = %08x\n", m_pEd->Control);
00284   m_pEd->Control &= ~0x7F;
00285   m_pEd->Control |= addr;
00286   DBG("m_pEd->Control = %08x\n", m_pEd->Control);
00287 }
00288 
00289 void UsbEndpoint::updateSize(uint16_t size)
00290 {
00291   DBG("m_pEd->Control = %08x\n", m_pEd->Control);
00292   m_pEd->Control &= ~0x3FF0000;
00293   m_pEd->Control |= (size << 16);
00294   DBG("m_pEd->Control = %08x\n", m_pEd->Control);
00295 }
00296 
00297 #if 0 //For doc only
00298 template <class T>
00299 void UsbEndpoint::setOnCompletion( T* pCbItem, void (T::*pCbMeth)() )
00300 {
00301   m_pCbItem = (CDummy*) pCbItem;
00302   m_pCbMeth = (void (CDummy::*)()) pCbMeth;
00303 }
00304 #endif
00305 
00306 void UsbEndpoint::onCompletion()
00307 {
00308   DBG_ASSERT(m_type != USB_ISO);
00309   DBG_ASSERT(m_pTdHead);
00310   //DBG("Transfer completed\n");
00311   if( m_pTdHead->Control >> 28  )
00312   {
00313     DBG("TD Failed with condition code %01x\n", m_pTdHead->Control >> 28 );
00314     m_status = (int)USBERR_TDFAIL;
00315   }
00316   else if( m_pEd->HeadTd & 0x1 )
00317   {
00318     m_pEd->HeadTd = m_pEd->HeadTd & ~0x1;
00319     DBG("\r\nHALTED!!\r\n");
00320     m_status = (int)USBERR_HALTED;
00321   }
00322   else if( (m_pEd->HeadTd & ~0xF) == (uint32_t) m_pTdTail )
00323   {
00324     //Done
00325     int len;
00326     DBG("m_pEp=%p\n", m_pEd);
00327     DBG("m_pTdHead->CurrBufPtr=%08x\n", (uint32_t)m_pTdHead->CurrBufPtr);
00328     DBG("m_pBufStartPtr=%08x\n", (uint32_t) m_pBufStartPtr);
00329     if(m_pTdHead->CurrBufPtr)
00330       len = m_pTdHead->CurrBufPtr - (uint32_t) m_pBufStartPtr;
00331     else
00332       len = m_len;
00333     /*if(len == 0) //Packet transfered completely
00334       len = m_len;*/
00335     //m_done = true;
00336     DBG("Transfered %d bytes\n", len);
00337     m_status = len; 
00338   }
00339   else
00340   {
00341     DBG("Unknown error...\n");
00342     m_status = (int)USBERR_ERROR;
00343   }
00344   m_result = true;
00345   if(m_pCbItem && m_pCbMeth)
00346     (m_pCbItem->*m_pCbMeth)();
00347 }
00348 
00349 
00350  
00351 void UsbEndpoint::sOnCompletion(uint32_t pTd)
00352 {
00353     HCTD* td = td_reverse((HCTD*)pTd);
00354     while(td) {
00355         HCTD* next = (HCTD*)td->Next;
00356         HCUTD* utd = (HCUTD*)td;
00357         UsbEndpoint* pEp = (UsbEndpoint*)utd->UsbEndpoint;
00358         DBG_ASSERT(pEp);
00359         if (usb_is_itd((byte*)td)) {
00360             HCITD* itd = (HCITD*)td;
00361             DBG_ASSERT(pEp->m_type == USB_ISO);
00362             pEp->queue_done_itd.push(itd);
00363         } else {
00364             DBG_ASSERT(pEp->m_pTdHead == td);
00365             if(pEp->m_pTdHead == td) { // found?
00366                 pEp->onCompletion();
00367             }
00368         }
00369         td = next;
00370     }
00371 }
00372 
00373 #endif