/*
 * usb_handlers
 *
 * Copyright (C) 2022 Texas Instruments Incorporated
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS 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 THE COPYRIGHT
 *  OWNER OR 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 description here.
 *
 */

/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

/* Kernel includes. */
#include "FreeRTOS.h"
#include "semphr.h"

/* Hardware includes. */
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_uart.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "driverlib/usb.h"
#include "usblib/usblib.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdbulk.h"
#include "utils/ustdlib.h"
#include "usb_bulk_structs.h"
/*-----------------------------------------------------------*/

/*
 * Flag indicating whether or not we are currently sending a Break condition.
 */
bool g_bSendingBreak = false;

/*
 * Counting semaphore used to inform the bulk layer another interrupt has been
 * received.
 */
extern SemaphoreHandle_t xCountSemaphore;
/*-----------------------------------------------------------*/

/*
 * Handles CDC driver notifications related to the transmit channel (data to
 * the USB host).
 *
 * \param ui32CBData is the client-supplied callback pointer for this channel.
 * \param ui32Event identifies the event we are being notified about.
 * \param ui32MsgValue is an event-specific value.
 * \param pvMsgData is an event-specific pointer.
 *
 * This function is called by the CDC driver to notify us of any events
 * related to operation of the transmit data channel (the IN channel carrying
 * data to the USB host).
 *
 * \return The return value is event-specific.
 */
uint32_t
TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
          void *pvMsgData)
{
    //
    // Which event have we been sent?
    //
    switch(ui32Event)
    {
        case USB_EVENT_TX_COMPLETE:
            //
            // Since we are using the USBBuffer, we don't need to do anything
            // here.
            //
            break;

        //
        // We don't expect to receive any other events.  Ignore any that show
        // up in a release build or hang in a debug build.
        //
        default:
            break;
    }
    return(0);
}
/*-----------------------------------------------------------*/

/*
 * Handles CDC driver notifications related to the receive channel (data from
 * the USB host).
 *
 * \param ui32CBData is the client-supplied callback data value for this
 *        channel.
 * \param ui32Event identifies the event we are being notified about.
 * \param ui32MsgValue is an event-specific value.
 * \param pvMsgData is an event-specific pointer.
 *
 * This function is called by the CDC driver to notify us of any events
 * related to operation of the receive data channel (the OUT channel carrying
 * data from the USB host).
 *
 * \return The return value is event-specific.
 */
uint32_t
RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
          void *pvMsgData)
{
    BaseType_t xHigherPriorityTaskWoken;

    //
    // Which event are we being sent?
    //
    switch(ui32Event)
    {
        //
        // We are connected to a host and communication is now possible.
        //
        case USB_EVENT_CONNECTED:
        {
            //
            // Flush our buffers.
            //
            USBBufferFlush(&g_sTxBuffer);
            USBBufferFlush(&g_sRxBuffer);

            break;
        }

        //
        // The host has disconnected.
        //
        case USB_EVENT_DISCONNECTED:
        {
            break;
        }

        //
        // A new packet has been received.
        //
        case USB_EVENT_RX_AVAILABLE:
        {
            /* While this interrupt Handler has hooks to get information about
             * the received USB data, the deferred data processing of the RTOS
             * approach means that information may be out of date by the time
             * the task processes it.  Therefore, the USB stack will be checked
             * during the task execution for the latest details on what USB
             * data has been received. */

            /* The xHigherPriorityTaskWoken parameter must be initialized to
             * pdFALSE as it will get set to pdTRUE inside the interrupt safe
             * API function if a context switch is required. */
            xHigherPriorityTaskWoken = pdFALSE;

            /* Give the counting semaphore to the USB task so it can process
             * the received USB data. */
            xSemaphoreGiveFromISR( xCountSemaphore, &xHigherPriorityTaskWoken );

            /* This FreeRTOS API call will handle the context switch if it is
             * required or have no effect if that is not needed. */
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }

        //
        // Ignore SUSPEND and RESUME for now.
        //
        case USB_EVENT_SUSPEND:
        case USB_EVENT_RESUME:
        {
            break;
        }

        //
        // Ignore all other events and return 0.
        //
        default:
        {
            break;
        }
    }

    return(0);
}

