• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

UsbCdc.c

Go to the documentation of this file.
00001 //******************************************************************************
00002 //THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
00003 //REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
00004 //INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
00005 //FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
00006 //COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
00007 //TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
00008 //POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
00009 //INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
00010 //YOUR USE OF THE PROGRAM.
00011 //
00012 //IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
00013 //CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
00014 //THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
00015 //OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
00016 //OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
00017 //EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
00018 //REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
00019 //OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
00020 //USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
00021 //AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
00022 //YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
00023 //(U.S.$500).
00024 //
00025 //Unless otherwise stated, the Program written and copyrighted
00026 //by Texas Instruments is distributed as "freeware".  You may,
00027 //only under TI's copyright in the Program, use and modify the
00028 //Program without any charge or restriction.  You may
00029 //distribute to third parties, provided that you transfer a
00030 //copy of this license to the third party and the third party
00031 //agrees to these terms by its first use of the Program. You
00032 //must reproduce the copyright notice and any other legend of
00033 //ownership on each copy or partial copy, of the Program.
00034 //
00035 //You acknowledge and agree that the Program contains
00036 //copyrighted material, trade secrets and other TI proprietary
00037 //information and is protected by copyright laws,
00038 //international copyright treaties, and trade secret laws, as
00039 //well as other intellectual property laws.  To protect TI's
00040 //rights in the Program, you agree not to decompile, reverse
00041 //engineer, disassemble or otherwise translate any object code
00042 //versions of the Program to a human-readable form.  You agree
00043 //that in no event will you alter, remove or destroy any
00044 //copyright notice included in the Program.  TI reserves all
00045 //rights not specifically granted under this license. Except
00046 //as specifically provided herein, nothing in this agreement
00047 //shall be construed as conferring by implication, estoppel,
00048 //or otherwise, upon you, any license or other right under any
00049 //TI patents, copyrights or trade secrets.
00050 // 
00051 //You may not use the Program in non-TI devices.
00052 //
00053 //This software has been submitted to export control regulations
00054 //The ECCN is EAR99 
00066 // (c)2009 by Texas Instruments Incorporated, All Rights Reserved.
00067 /*----------------------------------------------------------------------------+
00068 |                                                                             |
00069 |                              Texas Instruments                              |
00070 |                                                                             |
00071 |                          MSP430 USB-Example (CDC Driver)                    |
00072 |                                                                             |
00073 +-----------------------------------------------------------------------------+
00074 |  Source: UsbCdc.c, v1.18 2009/06/11                                         |
00075 |  Author: RSTO                                                               |
00076 |                                                                             |
00077 |  WHO          WHEN         WHAT                                             |
00078 |  ---          ----------   ------------------------------------------------ |
00079 |  RSTO         2008/09/03   born                                             |
00080 |  RSTO         2008/09/19   Changed USBCDC_sendData to send more then 64bytes|
00081 |  RSTO         2008/12/23   enhancements of CDC API                          |
00082 |  RSTO         2008/05/19   updated USBCDC_intfStatus()                      |
00083 |  RSTO         2009/05/26   added USBCDC_bytesInUSBBuffer()                  |
00084 |  RSTO         2009/05/28   changed USBCDC_sendData()                        |
00085 |  RSTO         2009/07/17   updated USBCDC_bytesInUSBBuffer()                |
00086 |  RSTO         2009/10/21   move __disable_interrupt() before                |
00087 |                            checking for suspend                             |
00088 +----------------------------------------------------------------------------*/
00089 
00090 #include "..\USB_Common\descriptors.h"
00091 
00092 #ifdef _CDC_
00093 
00094 
00095 #include "MSP430.h"
00096 #include "..\Common\types.h"              // Basic Type declarations
00097 #include "..\USB_Common\defMSP430USB.h"
00098 #include "..\USB_Common\usb.h"            // USB-specific Data Structures
00099 #include "..\USB_CDC_API\UsbCdc.h"
00100 #include <string.h>
00101 
00102 
00103 static ULONG lBaudrate = 0;
00104 static BYTE bDataBits = 8;
00105 static BYTE bStopBits = 0;
00106 static BYTE bParity = 0;
00107 
00108 static struct _CdcWrite
00109 {
00110     WORD nCdcBytesToSend;        // holds counter of bytes to be sent
00111     WORD nCdcBytesToSendLeft;    // holds counter how many bytes is still to be sent
00112     const BYTE* pBufferToSend;   // holds the buffer with data to be sent
00113     BYTE bCurrentBufferXY;       // is 0 if current buffer to write data is X, or 1 if current buffer is Y
00114 } CdcWriteCtrl;
00115 
00116 static struct _CdcRead
00117 {
00118     BYTE *pUserBuffer;     // holds the current position of user's receiving buffer. If NULL- no receiving operation started
00119     BYTE *pCurrentEpPos;   // current positon to read of received data from curent EP
00120     WORD nBytesToReceive;  // holds how many bytes was requested by receiveData() to receive
00121     WORD nBytesToReceiveLeft;        // holds how many bytes is still requested by receiveData() to receive
00122     BYTE * pCT1;           // holds current EPBCTxx register
00123     BYTE * pCT2;           // holds next EPBCTxx register
00124     BYTE * pEP2;           // holds addr of the next EP buffer
00125     BYTE nBytesInEp;       // how many received bytes still available in current EP
00126     BYTE bCurrentBufferXY; // indicates which buffer is used by host to transmit data via OUT endpoint3
00127 } CdcReadCtrl;
00128 
00129 
00130 extern WORD wUsbEventMask;
00131 
00132 //function pointers
00133 extern VOID *(*USB_TX_memcpy)(VOID * dest, const VOID * source, size_t count);
00134 extern VOID *(*USB_RX_memcpy)(VOID * dest, const VOID * source, size_t count);
00135 
00136 
00137 /*----------------------------------------------------------------------------+
00138 | Global Variables                                                            |
00139 +----------------------------------------------------------------------------*/
00140 
00141 extern __no_init tEDB __data16 tInputEndPointDescriptorBlock[];
00142 extern __no_init tEDB __data16 tOutputEndPointDescriptorBlock[];
00143 
00144 
00145 VOID CdcResetData()
00146 {
00147     // indicates which buffer is used by host to transmit data via OUT endpoint3 - X buffer is first
00148     //CdcReadCtrl.bCurrentBufferXY = X_BUFFER;
00149 
00150     memset(&CdcWriteCtrl, 0, sizeof(CdcWriteCtrl));
00151     memset(&CdcReadCtrl, 0, sizeof(CdcReadCtrl));
00152 }
00153 
00154 /*
00155 Sends data over interface intfNum, of size size and starting at address data.
00156 Returns: kUSBCDC_sendStarted
00157          kUSBCDC_sendComplete
00158          kUSBCDC_intfBusyError
00159 */
00160 BYTE USBCDC_sendData(const BYTE* data, WORD size, BYTE intfNum)
00161 {
00162     if (size == 0)
00163     {
00164         return kUSBCDC_generalError;
00165     }
00166 
00167     // atomic operation - disable interrupts
00168     __disable_interrupt();                   // Disable global interrupts
00169     
00170     // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR
00171     if ((bFunctionSuspended) ||
00172         (bEnumerationStatus != ENUMERATION_COMPLETE))
00173     {
00174         // data can not be read because of USB suspended
00175         __enable_interrupt();                // enable global interrupts
00176         return kUSBCDC_busNotAvailable;
00177     }
00178 
00179     if (CdcWriteCtrl.nCdcBytesToSendLeft != 0)
00180     {
00181         // the USB still sends previous data, we have to wait
00182         __enable_interrupt();                // enable global interrupts
00183         return kUSBCDC_intfBusyError;
00184     }
00185 
00186     //This function generate the USB interrupt. The data will be sent out from interrupt
00187 
00188     CdcWriteCtrl.nCdcBytesToSend = size;
00189     CdcWriteCtrl.nCdcBytesToSendLeft = size;
00190     CdcWriteCtrl.pBufferToSend = data;
00191 
00192     //trigger Endpoint Interrupt - to start send operation
00193     USBIEPIFG |= 1<<(EDB(CDC_INEP_ADDR)+1);  //IEPIFGx;
00194 
00195     __enable_interrupt();                // enable global interrupts
00196 
00197     return kUSBCDC_sendStarted;
00198 }
00199 
00200 //workaround for CDC windows driver: it doesn't give data to Application if was sent 64 byte
00201 #define EP_MAX_PACKET_SIZE_CDC      0x3F
00202 
00203 //this function is used only by USB interrupt
00204 BOOL CdcToHostFromBuffer()
00205 {
00206     BYTE byte_count, nTmp2;
00207     BYTE * pEP1;
00208     BYTE * pEP2;
00209     BYTE * pCT1;
00210     BYTE * pCT2;
00211     BYTE bWakeUp = FALSE; //TRUE for wake up after interrupt
00212     static BYTE bZeroPacketSent; // = FALSE;
00213 
00214     if (CdcWriteCtrl.nCdcBytesToSendLeft == 0)           // do we have somtething to send?
00215     {
00216         if (!bZeroPacketSent)               // zero packet was not yet sent
00217         {
00218             bZeroPacketSent = TRUE;
00219 
00220             CdcWriteCtrl.nCdcBytesToSend = 0;   // nothing to send
00221 
00222             //call event callback function
00223             if (wUsbEventMask & kUSB_sendCompletedEvent)
00224             {
00225                 bWakeUp = USBCDC_handleSendCompleted(1);
00226             }
00227 
00228         } // if (!bSentZeroPacket)
00229 
00230         return bWakeUp;
00231     }
00232 
00233     bZeroPacketSent = FALSE;    // zero packet will be not sent: we have data
00234 
00235     if (CdcWriteCtrl.bCurrentBufferXY == X_BUFFER)
00236     {
00237         //this is the active EP buffer
00238         pEP1 = (BYTE*)IEP3_X_BUFFER_ADDRESS;
00239         pCT1 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTX;
00240 
00241         //second EP buffer
00242         pEP2 = (BYTE*)IEP3_Y_BUFFER_ADDRESS;
00243         pCT2 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTY;
00244     }
00245     else
00246     {
00247         //this is the active EP buffer
00248         pEP1 = (BYTE*)IEP3_Y_BUFFER_ADDRESS;
00249         pCT1 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTY;
00250 
00251         //second EP buffer
00252         pEP2 = (BYTE*)IEP3_X_BUFFER_ADDRESS;
00253         pCT2 = &tInputEndPointDescriptorBlock[EDB(CDC_INEP_ADDR)].bEPBCTX;
00254     }
00255 
00256     // how many byte we can send over one endpoint buffer
00257     byte_count = (CdcWriteCtrl.nCdcBytesToSendLeft > EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl.nCdcBytesToSendLeft;
00258     nTmp2 = *pCT1;
00259 
00260     if(nTmp2 & EPBCNT_NAK)
00261     {
00262         USB_TX_memcpy(pEP1, CdcWriteCtrl.pBufferToSend, byte_count); // copy data into IEP3 X or Y buffer
00263         *pCT1 = byte_count;                      // Set counter for usb In-Transaction
00264         CdcWriteCtrl.bCurrentBufferXY = (CdcWriteCtrl.bCurrentBufferXY+1)&0x01; //switch buffer
00265         CdcWriteCtrl.nCdcBytesToSendLeft -= byte_count;
00266         CdcWriteCtrl.pBufferToSend += byte_count;             // move buffer pointer
00267 
00268         //try to send data over second buffer
00269         nTmp2 = *pCT2;
00270         if ((CdcWriteCtrl.nCdcBytesToSendLeft > 0) &&                                  // do we have more data to send?
00271             (nTmp2 & EPBCNT_NAK)) // if the second buffer is free?
00272         {
00273             // how many byte we can send over one endpoint buffer
00274             byte_count = (CdcWriteCtrl.nCdcBytesToSendLeft > EP_MAX_PACKET_SIZE_CDC) ? EP_MAX_PACKET_SIZE_CDC : CdcWriteCtrl.nCdcBytesToSendLeft;
00275 
00276             USB_TX_memcpy(pEP2, CdcWriteCtrl.pBufferToSend, byte_count); // copy data into IEP3 X or Y buffer
00277             *pCT2 = byte_count;                      // Set counter for usb In-Transaction
00278             CdcWriteCtrl.bCurrentBufferXY = (CdcWriteCtrl.bCurrentBufferXY+1)&0x01; //switch buffer
00279             CdcWriteCtrl.nCdcBytesToSendLeft -= byte_count;
00280             CdcWriteCtrl.pBufferToSend += byte_count;            //move buffer pointer
00281         }
00282     }
00283     return bWakeUp;
00284 }
00285 
00286 /*
00287 Aborts an active send operation on interface intfNum.
00288 Returns the number of bytes that were sent prior to the abort, in size.
00289 */
00290 BYTE USBCDC_abortSend(WORD* size, BYTE intfNum)
00291 {
00292     __disable_interrupt(); //disable interrupts - atomic operation
00293 
00294     *size = (CdcWriteCtrl.nCdcBytesToSend - CdcWriteCtrl.nCdcBytesToSendLeft);
00295     CdcWriteCtrl.nCdcBytesToSend = 0;
00296     CdcWriteCtrl.nCdcBytesToSendLeft = 0;
00297 
00298     __enable_interrupt();   //enable interrupts
00299     return kUSB_succeed;
00300 }
00301 
00302 // This function copies data from OUT endpoint into user's buffer
00303 // Arguments:
00304 //    pEP - pointer to EP to copy from
00305 //    pCT - pointer to pCT control reg
00306 //
00307 VOID CopyUsbToBuff(BYTE* pEP, BYTE* pCT)
00308 {
00309     BYTE nCount;
00310 
00311     // how many byte we can get from one endpoint buffer
00312     nCount = (CdcReadCtrl.nBytesToReceiveLeft > CdcReadCtrl.nBytesInEp) ? CdcReadCtrl.nBytesInEp : CdcReadCtrl.nBytesToReceiveLeft;
00313 
00314     USB_RX_memcpy(CdcReadCtrl.pUserBuffer, pEP, nCount); // copy data from OEP3 X or Y buffer
00315     CdcReadCtrl.nBytesToReceiveLeft -= nCount;
00316     CdcReadCtrl.pUserBuffer += nCount;          // move buffer pointer
00317                                                 // to read rest of data next time from this place
00318 
00319     if (nCount == CdcReadCtrl.nBytesInEp)       // all bytes are copied from receive buffer?
00320     {
00321         //switch current buffer
00322         CdcReadCtrl.bCurrentBufferXY = (CdcReadCtrl.bCurrentBufferXY+1) &0x01;
00323 
00324         CdcReadCtrl.nBytesInEp = 0;
00325 
00326         //clear NAK, EP ready to receive data
00327         *pCT = 0x00;
00328     }
00329     else
00330     {
00331         // set correct rest_data available in EP buffer
00332         if (CdcReadCtrl.nBytesInEp > nCount)
00333         {
00334             CdcReadCtrl.nBytesInEp -= nCount;
00335             CdcReadCtrl.pCurrentEpPos = pEP + nCount;
00336         }
00337         else
00338         {
00339             CdcReadCtrl.nBytesInEp = 0;
00340         }
00341     }
00342 }
00343 
00344 /*
00345 Receives data over interface intfNum, of size size, into memory starting at address data.
00346 Returns:
00347     kUSBCDC_receiveStarted  if the receiving process started.
00348     kUSBCDC_receiveCompleted  all requested date are received.
00349     kUSBCDC_receiveInProgress  previous receive opereation is in progress. The requested receive operation can be not started.
00350     kUSBCDC_generalError  error occurred.
00351 */
00352 BYTE USBCDC_receiveData(BYTE* data, WORD size, BYTE intfNum)
00353 {
00354     BYTE nTmp1;
00355 
00356     if ((size == 0) ||                          // read size is 0
00357         (data == NULL))
00358     {
00359         return kUSBCDC_generalError;
00360     }
00361 
00362     // atomic operation - disable interrupts
00363     __disable_interrupt();               // Disable global interrupts
00364 
00365     // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR
00366     if ((bFunctionSuspended) ||
00367         (bEnumerationStatus != ENUMERATION_COMPLETE))
00368     {
00369         // data can not be read because of USB suspended
00370         __enable_interrupt();                   // enable global interrupts
00371         return kUSBCDC_busNotAvailable;
00372     }
00373 
00374     if (CdcReadCtrl.pUserBuffer != NULL)        // receive process already started
00375     {
00376         __enable_interrupt();                   // enable global interrupts
00377         return kUSBCDC_intfBusyError;
00378     }
00379 
00380     CdcReadCtrl.nBytesToReceive = size;         // bytes to receive
00381     CdcReadCtrl.nBytesToReceiveLeft = size;     // left bytes to receive
00382     CdcReadCtrl.pUserBuffer = data;             // set user receive buffer
00383 
00384     //read rest of data from buffer, if any
00385     if (CdcReadCtrl.nBytesInEp > 0)
00386     {
00387         // copy data from pEP-endpoint into User's buffer
00388         CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1);
00389 
00390         if (CdcReadCtrl.nBytesToReceiveLeft == 0)     // the Receive opereation is completed
00391         {
00392             CdcReadCtrl.pUserBuffer = NULL;     // no more receiving pending
00393             USBCDC_handleReceiveCompleted(1);   // call event handler in interrupt context
00394             __enable_interrupt();               // interrupts enable
00395             return kUSBCDC_receiveCompleted;    // receive completed
00396         }
00397 
00398         // check other EP buffer for data - exchange pCT1 with pCT2
00399         if (CdcReadCtrl.pCT1 == &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX)
00400         {
00401             CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY;
00402             CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_Y_BUFFER_ADDRESS;
00403         }
00404         else
00405         {
00406             CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX;
00407             CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_X_BUFFER_ADDRESS;
00408         }
00409 
00410         nTmp1 = *CdcReadCtrl.pCT1;
00411         //try read data from second buffer
00412         if (nTmp1 & EPBCNT_NAK)                 // if the second buffer has received data?
00413         {
00414             nTmp1 = nTmp1 &0x7f;                // clear NAK bit
00415             CdcReadCtrl.nBytesInEp = nTmp1;     // holds how many valid bytes in the EP buffer
00416             CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1);
00417         }
00418 
00419         if (CdcReadCtrl.nBytesToReceiveLeft == 0)     // the Receive opereation is completed
00420         {
00421             CdcReadCtrl.pUserBuffer = NULL;     // no more receiving pending
00422             __enable_interrupt();               // interrupts enable
00423             return kUSBCDC_receiveCompleted;    // receive completed
00424         }
00425     } //read rest of data from buffer, if any
00426 
00427     //read 'fresh' data, if available
00428     nTmp1 = 0;
00429     if (CdcReadCtrl.bCurrentBufferXY == X_BUFFER)  //this is current buffer
00430     {
00431         if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK) //this buffer has a valid data packet
00432         {
00433             //this is the active EP buffer
00434             //pEP1
00435             CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_X_BUFFER_ADDRESS;
00436             CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX;
00437 
00438             //second EP buffer
00439             CdcReadCtrl.pEP2 = (BYTE*)OEP3_Y_BUFFER_ADDRESS;
00440             CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY;
00441             nTmp1 = 1;    //indicate that data is available
00442         }
00443     }
00444     else // Y_BUFFER
00445     if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK)
00446     {
00447         //this is the active EP buffer
00448         CdcReadCtrl.pCurrentEpPos = (BYTE*)OEP3_Y_BUFFER_ADDRESS;
00449         CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY;
00450 
00451         //second EP buffer
00452         CdcReadCtrl.pEP2 = (BYTE*)OEP3_X_BUFFER_ADDRESS;
00453         CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX;
00454         nTmp1 = 1;    //indicate that data is available
00455     }
00456 
00457     if (nTmp1)
00458     {
00459         // how many byte we can get from one endpoint buffer
00460         nTmp1 = *CdcReadCtrl.pCT1;
00461         while(nTmp1 == 0)
00462         {
00463             nTmp1 = *CdcReadCtrl.pCT1;
00464         }
00465 
00466         if(nTmp1 & EPBCNT_NAK)
00467         {
00468             nTmp1 = nTmp1 &0x7f;            // clear NAK bit
00469             CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valid bytes in the EP buffer
00470 
00471             CopyUsbToBuff(CdcReadCtrl.pCurrentEpPos, CdcReadCtrl.pCT1);
00472 
00473             nTmp1 = *CdcReadCtrl.pCT2;
00474             //try read data from second buffer
00475             if ((CdcReadCtrl.nBytesToReceiveLeft > 0) &&       // do we have more data to send?
00476                 (nTmp1 & EPBCNT_NAK))                 // if the second buffer has received data?
00477             {
00478                 nTmp1 = nTmp1 &0x7f;                  // clear NAK bit
00479                 CdcReadCtrl.nBytesInEp = nTmp1;       // holds how many valid bytes in the EP buffer
00480                 CopyUsbToBuff(CdcReadCtrl.pEP2, CdcReadCtrl.pCT2);
00481                 CdcReadCtrl.pCT1 = CdcReadCtrl.pCT2;
00482             }
00483         }
00484     }
00485 
00486     if (CdcReadCtrl.nBytesToReceiveLeft == 0)     // the Receive opereation is completed
00487     {
00488         CdcReadCtrl.pUserBuffer = NULL;           // no more receiving pending
00489         USBCDC_handleReceiveCompleted(1);         // call event handler in interrupt context
00490         __enable_interrupt();                     // interrupts enable
00491         return kUSBCDC_receiveCompleted;
00492     }
00493 
00494     //interrupts enable
00495     __enable_interrupt();
00496     return kUSBCDC_receiveStarted;
00497 }
00498 
00499 
00500 //this function is used only by USB interrupt.
00501 //It fills user receiving buffer with received data
00502 BOOL CdcToBufferFromHost()
00503 {
00504     BYTE * pEP1;
00505     BYTE nTmp1;
00506     BYTE bWakeUp = FALSE; // per default we do not wake up after interrupt
00507 
00508     if (CdcReadCtrl.nBytesToReceiveLeft == 0)       // do we have somtething to receive?
00509     {
00510         CdcReadCtrl.pUserBuffer = NULL;             // no more receiving pending
00511         return bWakeUp;
00512     }
00513 
00514     // No data to receive...
00515     if (!((tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX |
00516            tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY)
00517            & 0x80))
00518     {
00519         return bWakeUp;
00520     }
00521 
00522     if (CdcReadCtrl.bCurrentBufferXY == X_BUFFER)   //X is current buffer
00523     {
00524         //this is the active EP buffer
00525         pEP1 = (BYTE*)OEP3_X_BUFFER_ADDRESS;
00526         CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX;
00527 
00528         //second EP buffer
00529         CdcReadCtrl.pEP2 = (BYTE*)OEP3_Y_BUFFER_ADDRESS;
00530         CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY;
00531     }
00532     else
00533     {
00534         //this is the active EP buffer
00535         pEP1 = (BYTE*)OEP3_Y_BUFFER_ADDRESS;
00536         CdcReadCtrl.pCT1 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY;
00537 
00538         //second EP buffer
00539         CdcReadCtrl.pEP2 = (BYTE*)OEP3_X_BUFFER_ADDRESS;
00540         CdcReadCtrl.pCT2 = &tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX;
00541     }
00542 
00543     // how many byte we can get from one endpoint buffer
00544     nTmp1 = *CdcReadCtrl.pCT1;
00545     while(nTmp1 == 0)
00546     {
00547         nTmp1 = *CdcReadCtrl.pCT1;
00548     }
00549 
00550     if(nTmp1 & EPBCNT_NAK)
00551     {
00552         nTmp1 = nTmp1 &0x7f;            // clear NAK bit
00553         CdcReadCtrl.nBytesInEp = nTmp1; // holds how many valid bytes in the EP buffer
00554 
00555         CopyUsbToBuff(pEP1, CdcReadCtrl.pCT1);
00556 
00557         nTmp1 = *CdcReadCtrl.pCT2;
00558         //try read data from second buffer
00559         if ((CdcReadCtrl.nBytesToReceiveLeft > 0) &&       // do we have more data to send?
00560             (nTmp1 & EPBCNT_NAK))                 // if the second buffer has received data?
00561         {
00562             nTmp1 = nTmp1 &0x7f;                  // clear NAK bit
00563             CdcReadCtrl.nBytesInEp = nTmp1;       // holds how many valid bytes in the EP buffer
00564             CopyUsbToBuff(CdcReadCtrl.pEP2, CdcReadCtrl.pCT2);
00565             CdcReadCtrl.pCT1 = CdcReadCtrl.pCT2;
00566         }
00567     }
00568 
00569     if (CdcReadCtrl.nBytesToReceiveLeft == 0)     // the Receive opereation is completed
00570     {
00571         CdcReadCtrl.pUserBuffer = NULL;   // no more receiving pending
00572         if (wUsbEventMask & kUSB_receiveCompletedEvent)
00573         {
00574             bWakeUp = USBCDC_handleReceiveCompleted(1);
00575         }
00576 
00577         if (CdcReadCtrl.nBytesInEp)       // Is not read data still available in the EP?
00578         {
00579             if (wUsbEventMask & kUSB_dataReceivedEvent)
00580             {
00581                 bWakeUp = USBCDC_handleDataReceived(1);
00582             }
00583         }
00584     }
00585     return bWakeUp;
00586 }
00587 
00588 // helper for USB interrupt handler
00589 BOOL CdcIsReceiveInProgress()
00590 {
00591     return (CdcReadCtrl.pUserBuffer != NULL);
00592 }
00593 
00594 
00595 /*
00596 Aborts an active receive operation on interface intfNum.
00597   Returns the number of bytes that were received and transferred
00598   to the data location established for this receive operation.
00599 */
00600 BYTE USBCDC_abortReceive(WORD* size, BYTE intfNum)
00601 {
00602     //interrupts disable
00603     __disable_interrupt();
00604 
00605     *size = 0; //set received bytes count to 0
00606 
00607     //is receive operation underway?
00608     if (CdcReadCtrl.pUserBuffer)
00609     {
00610         //how many bytes are already received?
00611         *size = CdcReadCtrl.nBytesToReceive - CdcReadCtrl.nBytesToReceiveLeft;
00612 
00613         CdcReadCtrl.nBytesInEp = 0;
00614         CdcReadCtrl.pUserBuffer = NULL;
00615         CdcReadCtrl.nBytesToReceiveLeft = 0;
00616     }
00617 
00618      //interrupts enable
00619     __enable_interrupt();
00620     return kUSB_succeed;
00621 }
00622 
00623 /*
00624 This function rejects payload data that has been received from the host.
00625 */
00626 BYTE USBCDC_rejectData(BYTE intfNum)
00627 {
00628     // atomic operation - disable interrupts
00629     __disable_interrupt();               // Disable global interrupts
00630 
00631     // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR
00632     if (bFunctionSuspended)
00633     {
00634         __enable_interrupt();            // enable global interrupts
00635         return kUSBCDC_busNotAvailable;
00636     }
00637 
00638     //Is receive operation underway?
00639     // - do not flush buffers if any operation still active.
00640     if (!CdcReadCtrl.pUserBuffer)
00641     {
00642         BYTE tmp1 = tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK;
00643         BYTE tmp2 = tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK;
00644 
00645         if (tmp1 ^ tmp2) // switch current buffer if any and only ONE of buffers is full
00646         {
00647             //switch current buffer
00648             CdcReadCtrl.bCurrentBufferXY = (CdcReadCtrl.bCurrentBufferXY+1) &0x01;
00649         }
00650 
00651         tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX = 0;  //flush buffer X
00652         tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY = 0;  //flush buffer Y
00653         CdcReadCtrl.nBytesInEp = 0;                     // indicates that no more data available in the EP
00654     }
00655 
00656     __enable_interrupt();       //interrupts enable
00657     return kUSB_succeed;
00658 }
00659 
00660 /*
00661 This function indicates the status of the itnerface intfNum.
00662   If a send operation is active for this interface,
00663   the function also returns the number of bytes that have been transmitted to the host.
00664   If a receiver operation is active for this interface, the function also returns
00665   the number of bytes that have been received from the host and are waiting at the assigned address.
00666 
00667 returns kUSBCDC_waitingForSend (indicates that a call to USBCDC_SendData()
00668   has been made, for which data transfer has not been completed)
00669 
00670 returns kUSBCDC_waitingForReceive (indicates that a receive operation
00671   has been initiated, but not all data has yet been received)
00672 
00673 returns kUSBCDC_dataWaiting (indicates that data has been received
00674   from the host, waiting in the USB receive buffers)
00675 */
00676 BYTE USBCDC_intfStatus(BYTE intfNum, WORD* bytesSent, WORD* bytesReceived)
00677 {
00678     BYTE ret = 0;
00679     *bytesSent = 0;
00680     *bytesReceived = 0;
00681 
00682     //interrupts disable
00683     __disable_interrupt();
00684 
00685     // Is send operation underway?
00686     if (CdcWriteCtrl.nCdcBytesToSendLeft != 0)
00687     {
00688         ret |= kUSBCDC_waitingForSend;
00689         *bytesSent = CdcWriteCtrl.nCdcBytesToSend - CdcWriteCtrl.nCdcBytesToSendLeft;
00690     }
00691 
00692     //Is receive operation underway?
00693     if (CdcReadCtrl.pUserBuffer != NULL)
00694     {
00695         ret |= kUSBCDC_waitingForReceive;
00696         *bytesReceived = CdcReadCtrl.nBytesToReceive - CdcReadCtrl.nBytesToReceiveLeft;
00697     }
00698     else // receive operation not started
00699     {
00700         // do not access USB memory if suspended (PLL off). It may produce BUS_ERROR
00701         if (!bFunctionSuspended)
00702         {
00703             if((tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK)  | //any of buffers has a valid data packet
00704                (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK))
00705             {
00706                 ret |= kUSBCDC_dataWaiting;
00707             }
00708         }
00709     }
00710 
00711     if ((bFunctionSuspended) ||
00712         (bEnumerationStatus != ENUMERATION_COMPLETE))
00713     {
00714         // if suspended or not enumerated - report no other tasks pending
00715         ret = kUSBCDC_busNotAvailable;
00716     }
00717 
00718     //interrupts enable
00719     __enable_interrupt();
00720 
00721     __no_operation();
00722     return ret;
00723 }
00724 
00725 /*
00726 Returns how many bytes are in the buffer are received and ready to be read.
00727 */
00728 BYTE USBCDC_bytesInUSBBuffer(BYTE intfNum)
00729 {
00730     BYTE bTmp1 = 0;
00731 
00732     // atomic operation - disable interrupts
00733     __disable_interrupt();               // Disable global interrupts
00734 
00735     if ((bFunctionSuspended) ||
00736         (bEnumerationStatus != ENUMERATION_COMPLETE))
00737     {
00738         __enable_interrupt();               // enable global interrupts
00739         // if suspended or not enumerated - report 0 bytes available
00740         return 0;
00741     }
00742 
00743     if (CdcReadCtrl.nBytesInEp > 0)         // If a RX operation is underway, part of data may was read of the OEP buffer
00744     {
00745         bTmp1 = CdcReadCtrl.nBytesInEp;
00746         if (*CdcReadCtrl.pCT2 & EPBCNT_NAK) // the next buffer has a valid data packet
00747         {
00748             bTmp1 += *CdcReadCtrl.pCT2 & 0x7F;
00749         }
00750     }
00751     else
00752     {
00753         if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & EPBCNT_NAK) //this buffer has a valid data packet
00754         {
00755             bTmp1 = tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTX & 0x7F;
00756         }
00757         if (tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & EPBCNT_NAK) //this buffer has a valid data packet
00758         {
00759             bTmp1 += tOutputEndPointDescriptorBlock[EDB(CDC_OUTEP_ADDR)].bEPBCTY & 0x7F;
00760         }
00761     }
00762 
00763     //interrupts enable
00764     __enable_interrupt();
00765     return bTmp1;
00766 }
00767 
00768 
00769 //----------------------------------------------------------------------------
00770 //  Line Coding Structure
00771 //  dwDTERate     | 4 | Data terminal rate, in bits per second
00772 //  bCharFormat   | 1 | Stop bits, 0 = 1 Stop bit, 1 = 1,5 Stop bits, 2 = 2 Stop bits
00773 //  bParityType   | 1 | Parity, 0 = None, 1 = Odd, 2 = Even, 3= Mark, 4 = Space
00774 //  bDataBits     | 1 | Data bits (5,6,7,8,16)
00775 //----------------------------------------------------------------------------
00776 VOID usbGetLineCoding(VOID)
00777 {
00778     abUsbRequestReturnData[6] = bDataBits;               // Data bits = 8
00779     abUsbRequestReturnData[5] = bParity;                 // No Parity
00780     abUsbRequestReturnData[4] = bStopBits;               // Stop bits = 1
00781 
00782     abUsbRequestReturnData[3] = lBaudrate >> 24;
00783     abUsbRequestReturnData[2] = lBaudrate >> 16;
00784     abUsbRequestReturnData[1] = lBaudrate >> 8;
00785     abUsbRequestReturnData[0] = lBaudrate;
00786 
00787     wBytesRemainingOnIEP0 = 0x07;                   // amount of data to be send over EP0 to host
00788     usbSendDataPacketOnEP0((PBYTE)&abUsbRequestReturnData[0]);  // send data to host
00789 }
00790 
00791 //----------------------------------------------------------------------------
00792 
00793 VOID usbSetLineCoding(VOID)
00794 {
00795     usbReceiveDataPacketOnEP0((PBYTE) &abUsbRequestIncomingData);     // receive data over EP0 from Host
00796 }
00797 
00798 //----------------------------------------------------------------------------
00799 
00800 VOID usbSetControlLineState(VOID)
00801 {
00802     usbSendZeroLengthPacketOnIEP0();    // Send ZLP for status stage
00803 }
00804 
00805 //----------------------------------------------------------------------------
00806 
00807 VOID Handler_SetLineCoding(VOID)
00808 {
00809     // Baudrate Settings
00810 
00811     lBaudrate = (ULONG)abUsbRequestIncomingData[3] << 24 | (ULONG)abUsbRequestIncomingData[2]<<16 |
00812       (ULONG)abUsbRequestIncomingData[1]<<8 | abUsbRequestIncomingData[0];
00813 }
00814 
00815 #endif //ifdef _CDC_
00816 
00817 /*----------------------------------------------------------------------------+
00818 | End of source file                                                          |
00819 +----------------------------------------------------------------------------*/
00820 /*------------------------ Nothing Below This Line --------------------------*/

Generated on Fri Dec 17 2010 12:09:22 for Multi-cell Lithium-Ion Battery Manager System using MSP430 and BQ76PL536 by  doxygen 1.7.1