/******************************************************************************
 *
 * Freescale Semiconductor Inc.
 * (c) Copyright 2004-2009 Freescale Semiconductor, Inc.
 * ALL RIGHTS RESERVED.
 *
 ******************************************************************************
 *
 * THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 **************************************************************************//*!
 *
 * @file usb_cdc_pstn.c
 *
 * @author
 *
 * @version
 *
 * @date May-28-2009
 *
 * @brief The file contains USB CDC_PSTN Sub Class implementation.
 *
 *****************************************************************************/

/******************************************************************************
 * Includes
 *****************************************************************************/
 #include "usb_cdc_pstn.h"  /* USB CDC PSTN Sub Class Header File */

 /*****************************************************************************
 * Constant and Macro's
 *****************************************************************************/

/*****************************************************************************
 * Global Functions Prototypes
 *****************************************************************************/

/****************************************************************************
 * Global Variables
 ****************************************************************************/

/*****************************************************************************
 * Local Types - None
 *****************************************************************************/

/*****************************************************************************
 * Local Functions Prototypes
 *****************************************************************************/

/*****************************************************************************
 * Local Variables
 *****************************************************************************/
/* PSTN subclass callback pointer */
static USB_CLASS_CALLBACK g_pstn_callback = NULL;
/* data terminal equipment present or not */
static boolean g_dte_present = FALSE;
static uint_8 g_dte_status = 0; /* Status of DATA TERMINAL EQUIPMENT */
static uint_16 g_break_duration = 0; /* Length of time in milliseconds of the
                                                              break signal */
static uint_8 g_current_interface = 0;
static UART_BITMAP g_uart_bitmap;

#if CIC_NOTIF_ELEM_SUPPORT
static uint_8 g_serial_state_buf[NOTIF_PACKET_SIZE+UART_BITMAP_SIZE] =
{
    NOTIF_REQUEST_TYPE,SERIAL_STATE_NOTIF,
    0x00,0x00,/*wValue*/
    0x00,0x00,/*interface - modifies*/
    UART_BITMAP_SIZE,0x00,/* wlength*/
    0x00,0x00 /*data initialized - modifies*/
};/*uart bitmap*/
#endif
 /*****************************************************************************
 * Local Functions
 *****************************************************************************/

/*****************************************************************************
 * Global Functions
 *****************************************************************************/

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_Pstn_Init
 *
 * @brief The function initializes the PSTN Module
 *
 * @param controller_ID     : Controller ID
 * @param callback          : PSTN Callback
 *
 * @return error
 *         USB_OK           : Always
 ******************************************************************************
 * PSTN Sub Class Initialization routine
 *****************************************************************************/
uint_8 USB_Class_CDC_Pstn_Init (
    uint_8    controller_ID,        /* [IN] Controller ID */
    USB_CLASS_CALLBACK callback     /* [IN] PSTN Callback */
)
{
    uint_8 error = USB_OK;
    UNUSED (controller_ID);

    /* save input parameters */
    g_pstn_callback = callback;
    return error;
}
/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Get_Line_Coding
 *
 * @brief  This function is called in response to GetLineCoding request
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data to be send
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *          USB_OK : When Successfull
 *          USBERR_INVALID_REQ_TYPE: When  request for
 *                                   invalid Interface is presented
 ******************************************************************************
 * Calls application to receive Line Coding Information
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Get_Line_Coding (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data to be send */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{
    uint_8 status;
    UNUSED (size);
    g_current_interface = (uint_8)setup_packet->index ;
    status = USB_Desc_Get_Line_Coding(controller_ID, g_current_interface,
        data);

    return status;
}

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Set_Line_Coding
 *
 * @brief  This function is called in response to SetLineCoding request
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *      USB_OK                  : When Successfull
 *      USBERR_INVALID_REQ_TYPE : When  request for invalid
 *                                Interface is presented
 ******************************************************************************
 * Calls Applciation to update Line Coding Information
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Set_Line_Coding (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{
    uint_8 status;
    UNUSED(data);

    *size = 0;

    g_current_interface = (uint_8)setup_packet->index ;
    status = USB_Desc_Set_Line_Coding(controller_ID, g_current_interface,
        (uint_8_ptr *)&setup_packet);

    return status;
}

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Set_Ctrl_Line_State
 *
 * @brief  This function is called in response to Set Control Line State
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *                        USB_OK : Always
 ******************************************************************************
 * Updates Control Line State
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Set_Ctrl_Line_State (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data  */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{
    UNUSED(data);
    *size = 0;

    g_dte_status = (uint_8)setup_packet->value ;
    g_uart_bitmap._byte = 0x00; /* initialize */
    /* activate/deactivate Tx carrier */
    g_uart_bitmap.Bitmap_Uart.bTxCarrier = (g_dte_status &
        CARRIER_ACTIVATION_CHECK) ? 1 : 0 ;
     /* activate carrier and DTE */
    g_uart_bitmap.Bitmap_Uart.bRxCarrier = (g_dte_status &
        CARRIER_ACTIVATION_CHECK) ? 1 : 0 ;

    /* Indicates to DCE if DTE is present or not */
    g_dte_present = (boolean)((g_dte_status & DTE_PRESENCE_CHECK) ?
        TRUE : FALSE);
    UNUSED(g_dte_present);
#if CIC_NOTIF_ELEM_SUPPORT
    /* Send Notification to Host - Parameter on Device side has changed */
    USB_Class_CDC_PSTN_Send_Serial_State(controller_ID);
#endif
    if(g_pstn_callback != NULL)
    {
        if(g_dte_status & CARRIER_ACTIVATION_CHECK)
        {
            g_pstn_callback(controller_ID, USB_APP_CDC_CARRIER_ACTIVATED,
                NULL);
        }
        else
        {
            g_pstn_callback(controller_ID, USB_APP_CDC_CARRIER_DEACTIVATED,
                NULL);
        }
    }
    return USB_OK;
}

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Send_Break
 *
 * @brief  This function is called in response to Set Config request
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *                        USB_OK : Always
 ******************************************************************************
 * Updates Break Duration Information from Host
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Send_Break (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data  */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{
    UNUSED (controller_ID);
    UNUSED (data);
    *size = 0;

    g_break_duration = setup_packet->value;
    UNUSED(g_break_duration);

    return USB_OK;
}

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Get_Comm_Feature
 *
 * @brief  This function is called in response to GetCommFeature request
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data to be send
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *      USB_OK                  : When Successfull
 *      USBERR_INVALID_REQ_TYPE : When  request for invalid
 *                                Interface is presented
 ******************************************************************************
 * Returns the status of the get comm feature request
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Get_Comm_Feature (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data to send */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{   uint_8 status;

    status = USB_OK;
    *size = COMM_FEATURE_DATA_SIZE;
    g_current_interface = (uint_8)setup_packet->index ;
    if(setup_packet->value == ABSTRACT_STATE_FEATURE)
    {
        status = USB_Desc_Get_Abstract_State(controller_ID,
            g_current_interface, data);
    }
    else if(setup_packet->value == COUNTRY_SETTING_FEATURE)
    {
        status = USB_Desc_Get_Country_Setting(controller_ID,
            g_current_interface, data);
    }
    else
    {
        *size = 0; /* for Reserved/Invalid Feature Selector Value */
    }
    return status;
}

/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Set_Comm_Feature
 *
 * @brief  This function is called in response to SetCommFeature request
 *
 * @param controller_ID   : Controller ID
 * @param setup_packet    : Pointer to setup packet
 * @param data            : Pointer to Data
 * @param size            : Pointer to Size of Data
 *
 * @return status:
 *      USB_OK                  : When Successfull
 *      USBERR_INVALID_REQ_TYPE : When  request for invalid
 *                                Interface is presented
 ******************************************************************************
 * Sets the comm feature specified by Host
 *****************************************************************************/
uint_8 USB_Class_CDC_PSTN_Set_Comm_Feature (
    uint_8 controller_ID,               /* [IN] Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* [IN] Pointer to setup packet */
    uint_8_ptr *data,                   /* [OUT] Pointer to Data */
    USB_PACKET_SIZE *size               /* [OUT] Pointer to Size of Data */
)
{
    uint_8 status;
    status = USB_OK;
    *size = COMM_FEATURE_DATA_SIZE;
    g_current_interface = (uint_8)setup_packet->index ;
    if(setup_packet->value == ABSTRACT_STATE_FEATURE)
    {
        status = USB_Desc_Set_Abstract_State(controller_ID,
            g_current_interface, data);
    }
    else if(setup_packet->value == COUNTRY_SETTING_FEATURE)
    {
        status = USB_Desc_Set_Country_Setting(controller_ID,
            g_current_interface, data);
    }
    else
    {
        *size = 0; /* for Reserved/Invalid Feature Selector Value */
    }
    return status;
}

#if CIC_NOTIF_ELEM_SUPPORT
/**************************************************************************//*!
 *
 * @name  USB_Class_CDC_PSTN_Send_Serial_State
 *
 * @brief  This function is called to send serial state notification
 *
 * @param controller_ID : Controller ID
 *
 * @return NONE
 ******************************************************************************
 * Returns the Serial State
 *****************************************************************************/
void USB_Class_CDC_PSTN_Send_Serial_State (
    uint_8 controller_ID               /* [IN] Controller ID */
)
{
    /* update array for current interface */
    g_serial_state_buf[4] = g_current_interface;
    /* Lower byte of UART BITMAP */
    g_serial_state_buf[NOTIF_PACKET_SIZE+UART_BITMAP_SIZE-2] =
        g_uart_bitmap._byte;
    (void)USB_Class_CDC_Interface_CIC_Send_Data(controller_ID,
        g_serial_state_buf, (NOTIF_PACKET_SIZE + UART_BITMAP_SIZE));
}
#endif

