//******************************************************************************
//THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
//REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
//INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
//COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
//TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
//POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
//INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
//YOUR USE OF THE PROGRAM.
//
//IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
//CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
//THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
//OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
//OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
//EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
//REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
//OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
//USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
//AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
//YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
//(U.S.$500).
//
//Unless otherwise stated, the Program written and copyrighted
//by Texas Instruments is distributed as "freeware".  You may,
//only under TI's copyright in the Program, use and modify the
//Program without any charge or restriction.  You may
//distribute to third parties, provided that you transfer a
//copy of this license to the third party and the third party
//agrees to these terms by its first use of the Program. You
//must reproduce the copyright notice and any other legend of
//ownership on each copy or partial copy, of the Program.
//
//You acknowledge and agree that the Program contains
//copyrighted material, trade secrets and other TI proprietary
//information and is protected by copyright laws,
//international copyright treaties, and trade secret laws, as
//well as other intellectual property laws.  To protect TI's
//rights in the Program, you agree not to decompile, reverse
//engineer, disassemble or otherwise translate any object code
//versions of the Program to a human-readable form.  You agree
//that in no event will you alter, remove or destroy any
//copyright notice included in the Program.  TI reserves all
//rights not specifically granted under this license. Except
//as specifically provided herein, nothing in this agreement
//shall be construed as conferring by implication, estoppel,
//or otherwise, upon you, any license or other right under any
//TI patents, copyrights or trade secrets.
// 
//You may not use the Program in non-TI devices.
//
//This software has been submitted to export control regulations
//The ECCN is EAR99 
/**
*  \file USBCDC_constructs.c
*  \brief For more information on this file please refer to 
*   Programmer’s Guide: MSP430 USB API Stack for CDC/HID
*  http://focus.ti.com/docs/prod/folders/print/msp430f5529.html#toolssoftware. 
*  \author Texas Instruments, Inc
*  \date November 2010
*  \version 1.0 Initial Release
*  \note Built with IAR Embedded Workbench for MSP430 Version: 5.10.1
*/

#include "MSP430.h"
#include "Common\types.h"          // Basic Type declarations

#include "USB_Common\descriptors.h"
#include "USB_Common\usb.h"        // USB-specific functions

#include "main.h"
#ifdef _CDC_
    #include "USB_CDC_API\UsbCdc.h"
#endif

#include <intrinsics.h>
#include "USBCDC_constructs.h"




//*********************************************************************************************
// Please see the MSP430 USB CDC API Programmer's Guide Sec. 9 for a full description of these 
// functions, how they work, and how to use them.  
//*********************************************************************************************




// This call assumes no previous send operation is underway; also assumes size is non-zero.  
// Returns zero if send completed; non-zero if it failed, with 1 = timeout and 2 = bus is gone.  
BYTE sendData_waitTilDone(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
{
  ULONG sendCounter = 0;
  WORD bytesSent, bytesReceived;
  BYTE ret;

  ret = USBCDC_sendData(dataBuf,size,intfNum);  // ret is either sendStarted or busNotAvailable
  if(ret == kUSBCDC_busNotAvailable)
    return 2;
  
  while(1)                                      // ret was sendStarted
  {
    ret = USBCDC_intfStatus(intfNum,&bytesSent,&bytesReceived);
    if(ret & kUSBCDC_busNotAvailable)           // This may happen at any time
      return 2;
    else if(ret & kUSBCDC_waitingForSend)
    {
      if(ulTimeout && (sendCounter++ >= ulTimeout))  // Incr counter & try again
        return(1);                                   // Timed out
    }
    else return 0;                              // If neither busNotAvailable nor waitingForSend, it succeeded
  }
}



// This call assumes a previous send operation might be underway; also assumes size is non-zero.  
// Returns zero if send completed; non-zero if it failed, with 1 = timeout and 2 = bus is gone.  
BYTE sendData_inBackground(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
{
  ULONG sendCounter = 0; 
  WORD bytesSent, bytesReceived;
  
  while(USBCDC_intfStatus(intfNum,&bytesSent,&bytesReceived) & kUSBCDC_waitingForSend)
  {
    if(ulTimeout && ((sendCounter++)>ulTimeout))  // A send operation is underway; incr counter & try again
      return 1;                                   // Timed out               
  }
  
  // At this point, a return from sendData() has to be either busNotAvailable or sendStarted
  if(USBCDC_sendData(dataBuf,size,intfNum) == kUSBCDC_busNotAvailable)    // This may happen at any time
    return 2;
  else return 0;                                  // Indicate success            
}                                  



// This call assumes a previous receive operation is NOT underway; also assumes size is non-zero.  
// Returns zero if receive completed; non-zero if it failed, with 1 = timeout and 2 = bus is gone
BYTE receiveData_waitTilDone(BYTE* dataBuf, WORD size, BYTE intfNum, ULONG ulTimeout)
{
  ULONG rcvCounter = 0;
  BYTE ret;
  WORD bytesSent, bytesReceived;
  
  ret = USBCDC_receiveData(dataBuf,size,intfNum); 
  if(ret == kUSBCDC_busNotAvailable)
    return 2;       // Indicate bus is gone
  if(ret == kUSBCDC_receiveCompleted)
    return 0;       // Indicate success
  
  while(1)
  {
    ret = USBCDC_intfStatus(intfNum,&bytesSent,&bytesReceived);
    if(ret & kUSBCDC_busNotAvailable)
      return 2;
    else if(ret & kUSBCDC_waitingForReceive)
    {
      if(ulTimeout && (rcvCounter++ >= ulTimeout))
         return 1;   // Indicate timed out 
    }
    else return 0;   // Indicate success
  }
}
                         
                         
// This call assumes a prevoius receive operation is NOT underway.  It only retrieves what data is waiting in the buffer
// It doesn't check for kUSBCDC_busNotAvailable, b/c it doesn't matter if it's not.  size is the maximum that
// is allowed to be received before exiting; i.e., it is the size allotted to dataBuf.  
// Returns the number of bytes received.  
WORD receiveDataInBuffer(BYTE* dataBuf, WORD size, BYTE intfNum)
{
  WORD bytesInBuf;
  BYTE* currentPos=dataBuf;
 
  while(bytesInBuf = USBCDC_bytesInUSBBuffer(intfNum))
  {
    if((WORD)(currentPos-dataBuf+bytesInBuf) > size) 
      break;
 
    USBCDC_receiveData(currentPos,bytesInBuf,intfNum); 
    currentPos += bytesInBuf;
  } 
  return (currentPos-dataBuf);
}


