#ifndef _USB_H_
#define _USB_H_
//----------------------------------------------------------------------------
///
/// \brief  Usb
///
///         See implementation files for further information.
//
/// \date   20160305
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


//---Includes-----------------------------------------------------------------


//---Own------------------------------

#include <biwak/gpio.hpp>


//---Defines------------------------------------------------------------------


#if defined (STM32)
   #ifdef __STM32F0xx_HAL_PCD_H
      #define USB_HANDLE_TYPE    PCD_HandleTypeDef
   #else
      //#define USB_HANDLE_TYPE    void
   #endif
   #include <HALWrapper/stm32_usb.h>
   //#include <biwak/usb_device.h>
   #include <biwak/usb_defines.h>
#else
   #define UART_HANDLE_TYPE    void
   //typedef int USBD_StatusTypeDef;
   typedef int PCD_HandleTypeDef;
   #include <biwak/usb_defines.h>
#endif

#if defined(STM32L151xx)
#define GPIO_AFx_USB 0
#endif


//---Declaration--------------------------------------------------------------


extern int usbKeeper;
//class CUsbRequest;

#if 1

class IUsbCallbacks
{
   public:
      virtual USBD_StatusTypeDef dataOutStage(uint8_t epnum, uint8_t *pdata, int len) = 0;
      virtual USBD_StatusTypeDef dataInStage(uint8_t epnum, uint8_t *pdata, int len) = 0;
      virtual USBD_StatusTypeDef setupStage(uint8_t *pdata) = 0;
      virtual USBD_StatusTypeDef SOF() = 0;
      virtual USBD_StatusTypeDef reset() = 0;
      virtual USBD_StatusTypeDef suspend() = 0;
      virtual USBD_StatusTypeDef resume() = 0;
      virtual USBD_StatusTypeDef ISOOUTIncomplete() = 0;
      virtual USBD_StatusTypeDef ISOINIncomplete() = 0;
      virtual USBD_StatusTypeDef connect() = 0;
      virtual USBD_StatusTypeDef disconnect() = 0;
};

#endif

class CUsbDimpl;
//typedef struct PCD_HandleTypeDef;
//struct PCD_HandleTypeDef;
class CUsb
{
    private:
         //USB_HANDLE_TYPE *m_pHandle;
        CUsbDimpl *dimpl;
        //void *m_pHandle;
        CGpio gpioDm;
        CGpio gpioDp;

    public:
        IUsbCallbacks *interface;

        CUsb(EGpioPeripheral _eGpioPeripheralTx, EGpioPin _eGpioPinTx,
             EGpioPeripheral _eGpioPeripheralRx, EGpioPin _eGpioPinRx
             , int altFunc);
        ~CUsb();
        void start(IUsbCallbacks *_interface);
        void stallEP( uint8_t ep_addr);
        void clearStallEP( uint8_t ep_addr);
        int isStallEP(uint8_t ep_addr);
        USBD_StatusTypeDef transmit(uint8_t ep_addr, uint8_t *pbuf, uint16_t size);
        USBD_StatusTypeDef receive(uint8_t ep_addr, uint8_t *pbuf, uint16_t size);
        void openEP(uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps);
        void closeEP(uint8_t ep_addr);
        void setUsbAddress(int dev_addr);
        #if ! ( defined (STM32F303x8) || defined (STM32L431xx) || defined (STM32L0) || defined (STM32G0) )
        PCD_HandleTypeDef *getPcdHandle();
        #endif
};



//---fin----------------------------------------------------------------------
#endif // ? ! _USB_H_
