/*!
 * @file        usbd_composite_winusb_itf.c
 *
 * @brief       usb device WINUSB class interface handler
 *
 * @version     V1.0.0
 *
 * @date        2025-02-15
 *
 * @attention
 *
 *  Copyright (C) 2025 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes ***************************************************************/
#include "usbd_composite_winusb_itf.h"

/* Private includes *******************************************************/
#include "usb_device_user.h"

/* Private macro **********************************************************/

/* Private typedef ********************************************************/

/* Private variables ******************************************************/
uint8_t winusbTxBuffer[USBD_WINUSB_TX_BUF_LEN];
uint8_t winusbRxBuffer[USBD_WINUSB_NUM][USBD_WINUSB_RX_BUF_LEN];

USBD_WINUSB_ITF_INFO_T gWinusbItf[USBD_WINUSB_NUM];

/* Private function prototypes ********************************************/

static USBD_STA_T USBD_HS_WINUSB_ItfInit(uint8_t winusbnum);
static USBD_STA_T USBD_HS_WINUSB_ItfDeInit(void);
static USBD_STA_T USBD_HS_WINUSB_ItfCtrl(uint8_t command, uint8_t *buffer, uint16_t length, uint8_t winusbnum);
static USBD_STA_T USBD_HS_WINUSB_ItfSendEnd(uint8_t epNum, uint8_t *buffer, uint32_t *length, uint8_t winusbnum);
static USBD_STA_T USBD_HS_WINUSB_ItfReceive(uint8_t *buffer, uint32_t *length, uint8_t winusbnum);

/* USB HS CDC interface handler */
USBD_WINUSB_INTERFACE_T USBD_WINUSB_INTERFACE_HS =
{
    "WINUSB Interface HS",
    USBD_HS_WINUSB_ItfInit,
    USBD_HS_WINUSB_ItfDeInit,
    USBD_HS_WINUSB_ItfCtrl,
    USBD_HS_WINUSB_ItfSend,
    USBD_HS_WINUSB_ItfSendEnd,
    USBD_HS_WINUSB_ItfReceive,
};

/* External variables *****************************************************/
extern USBD_INFO_T gUsbDeviceHS;

/* External functions *****************************************************/

/*!
 * @brief       USB device initializes WINUSB media handler
 *
 * @param       None
 *
 * @retval      USB device operation status
 */
static USBD_STA_T USBD_HS_WINUSB_ItfInit(uint8_t winusbnum)
{
    USBD_STA_T usbStatus = USBD_OK;
    
    USBD_Composite_WINUSB_ConfigRxBuffer(&gUsbDeviceHS, winusbRxBuffer[winusbnum], winusbnum);
    USBD_Composite_WINUSB_ConfigTxBuffer(&gUsbDeviceHS, winusbTxBuffer, 0, winusbnum);
    
    return usbStatus;
}

/*!
 * @brief       USB device deinitializes WINUSB media handler
 *
 * @param       None
 *
 * @retval      USB device operation status
 */
static USBD_STA_T USBD_HS_WINUSB_ItfDeInit(void)
{
    USBD_STA_T usbStatus = USBD_OK;

    return usbStatus;
}

/*!
 * @brief       USB device WINUSB interface control request handler
 *
 * @param       command: Command code
 *
 * @param       buffer: Command data buffer
 *
 * @param       length: Command data length
 *
 * @retval      USB device operation status
 */
static USBD_STA_T USBD_HS_WINUSB_ItfCtrl(uint8_t command, uint8_t *buffer, uint16_t length, uint8_t winusbnum)
{
    USBD_STA_T usbStatus = USBD_OK;

    UNUSED(command);
    UNUSED(buffer);
    UNUSED(length);
    UNUSED(winusbnum);

    return usbStatus;
}

/*!
 * @brief       USB device WINUSB interface send handler
 *
 * @param       buffer: Command data buffer
 *
 * @param       length: Command data length
 *
 * @retval      USB device operation status
 */
USBD_STA_T USBD_HS_WINUSB_ItfSend(uint8_t *buffer, uint16_t length, uint8_t winusbnum)
{
    USBD_STA_T usbStatus = USBD_OK;

    USBD_COMPOSITE_INFO_T* usbDevComposite = (USBD_COMPOSITE_INFO_T*)gUsbDeviceHS.devClass[gUsbDeviceHS.classID]->classData;
    
    if(usbDevComposite->winusbInfo[winusbnum].winusbTx.state != USBD_WINUSB_XFER_IDLE)
    {
        return USBD_BUSY;
    }
    
    USBD_Composite_WINUSB_ConfigTxBuffer(&gUsbDeviceHS, buffer, length, winusbnum);
    
    usbStatus = USBD_Composite_WINUSB_TxPacket(&gUsbDeviceHS, winusbnum);
    
    return usbStatus;
}

/*!
 * @brief       USB device WINUSB interface send end event handler
 *
 * @param       epNum: endpoint number
 *
 * @param       buffer: Command data buffer
 *
 * @param       length: Command data length
 *
 * @retval      USB device operation status
 */
USBD_STA_T USBD_HS_WINUSB_ItfSendEnd(uint8_t epNum, uint8_t *buffer, uint32_t *length, uint8_t winusbnum)
{
    USBD_STA_T usbStatus = USBD_OK;

    UNUSED(epNum);
    UNUSED(buffer);
    UNUSED(length);
    UNUSED(winusbnum);

    return usbStatus;
}

/*!
 * @brief       USB device WINUSB interface receive handler
 *
 * @param       buffer: Command data buffer
 *
 * @param       length: Command data length
 *
 * @retval      USB device operation status
 */
static USBD_STA_T USBD_HS_WINUSB_ItfReceive(uint8_t *buffer, uint32_t *length, uint8_t winusbnum)
{
    USBD_STA_T usbStatus = USBD_OK;
    
    USBD_Composite_WINUSB_ConfigRxBuffer(&gUsbDeviceHS, &buffer[0], winusbnum);
    
    USBD_Composite_WINUSB_RxPacket(&gUsbDeviceHS, winusbnum);
    
    gWinusbItf[winusbnum].state = USBD_WINUSB_ITF_REV_UPDATE;
    gWinusbItf[winusbnum].rxUpdateLen = *length;
    
    return usbStatus;
}
