/*
 * RT-Thread UsbCdcTransport for eRPC
 *
 * Uses RT-Thread rt_device ("cdc0") character device as backend.
 * No NXP SerialManager.
 * Still keeps the class name UsbCdcTransport and init/rx_cb/tx_cb APIs.
 */

#ifndef _EMBEDDED_RPC__USB_CDC_TRANSPORT_H_
#define _EMBEDDED_RPC__USB_CDC_TRANSPORT_H_

#include "erpc_config_internal.h"
#include "erpc_framed_transport.hpp"

extern "C" {
#include <rtthread.h>
#include <rtdevice.h>
}

#ifdef __cplusplus

/* 复用原 NXP 类型名：保持 transport_setup_usb_cdc.cpp 签名不变 */
typedef struct serial_port_usb_cdc_config
{
    const char *dev_name;   /* e.g. "cdc0" */
    rt_int32_t  rx_wait_ms; /* receive 等待超时(ms)，<=0 表示永久等待 */
    rt_int32_t  tx_wait_ms; /* send 等待超时(ms)，<=0 表示永久等待（通常不用，写已阻塞） */
} serial_port_usb_cdc_config_t;

/* 保持签名兼容，但 RT-Thread 适配不使用这些参数 */
typedef void *serial_handle_t;
typedef struct serial_manager_config serial_manager_config_t;

namespace erpc {

class UsbCdcTransport : public FramedTransport
{
public:
    UsbCdcTransport(serial_handle_t serialHandle,
                    serial_manager_config_t *serialConfig,
                    serial_port_usb_cdc_config_t *usbCdcConfig,
                    uint8_t *usbRingBuffer,
                    uint32_t usbRingBufferLength);

    virtual ~UsbCdcTransport(void);

    /* 打开 cdc0，注册 rx_indicate/tx_complete，创建信号量 */
    virtual erpc_status_t init(void);

    /* 被 rx_indicate/tx_complete 调用，用信号量唤醒 */
    void rx_cb(void);
    void tx_cb(void);

protected:
    /* ✅ 不用 erpc::Semaphore，直接用 RT-Thread 信号量 */
    rt_sem_t m_rxSem;
    rt_sem_t m_txSem;

private:
    using FramedTransport::underlyingReceive;
    using FramedTransport::underlyingSend;

    virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size) override;
    virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size) override;

private:
    static rt_err_t rx_indicate_stub(rt_device_t dev, rt_size_t size);
    static rt_err_t tx_complete_stub(rt_device_t dev, void *buffer);

    bool is_configured(void);

    /* 等待 configured，避免“先启动再插线” */
    bool wait_configured(rt_int32_t wait_ms);

private:
    const char *m_devName;
    rt_int32_t  m_rxWaitMs;
    rt_int32_t  m_txWaitMs;

    rt_device_t m_dev;

    /* keep original members for signature compatibility */
    serial_handle_t m_serialHandle;
    serial_manager_config_t *m_serialConfig;
    serial_port_usb_cdc_config_t *m_usbCdcConfig;
    uint8_t *m_usbRingBuffer;
    uint32_t m_usbRingBufferLength;
};

} // namespace erpc

#endif /* __cplusplus */

#endif /* _EMBEDDED_RPC__USB_CDC_TRANSPORT_H_ */
