- 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 --------------------------*/