#ifndef BIWAK_USB_CLASS_H
#define BIWAK_USB_CLASS_H
//----------------------------------------------------------------------------
///
/// \brief  USB device
///
///         See implementation files for further information.
//
/// \date   2018025
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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

#include <biwak/usb_device.h>
#include <biwak/iostream.h>
#include <biwak/exception.h>
#include <lepto/bufferRing.hpp>
#include <lepto/ring.h>
#include <inttypes.h>

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

#define HID_EPIN_ADDR                  0x81
//#define HID_EPIN_SIZE                  0x8
//#define HID_EPOUT_SIZE                 0x8

#define CDC_IN_EP                 0x81
#define CDC_OUT_EP                 0x01
#define CDC_CMD_EP                 0x82

#define CDC_CMD_PACKET_SIZE            8
//#define USB_HID_CONFIG_DESC_SIZ      34
//#define USB_HID_DESC_SIZ               9
//#define HID_MOUSE_REPORT_DESC_SIZE     74

#define HID_DESCRIPTOR_TYPE           0x21
#define HID_REPORT_DESC               0x22
#define DESCTYPE_CS_INTERFACE         0x24

#define HID_HS_BINTERVAL               0x07
#define HID_FS_BINTERVAL               0x0A
#define HID_POLLING_INTERVAL           0x0A

#define HID_REQ_SET_PROTOCOL          0x0B
#define HID_REQ_GET_PROTOCOL          0x03

#define HID_REQ_SET_IDLE              0x0A
#define HID_REQ_GET_IDLE              0x02

#define HID_REQ_SET_REPORT            0x09
#define HID_REQ_GET_REPORT            0x01


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

//#define USB_USE_BUFFER_RING
#undef USB_USE_BUFFER_RING

typedef uint8_t* TUsbClassDesc;

extern TUsbClassDesc usbClassCdc;
extern TUsbClassDesc usbClassHid;
    
class CUsbClass: public CIOStream
{
   private:
      #if defined USB_USE_BUFFER_RING
         CBufferRing m_rxBuffers;
         CBufferRing m_txBuffers;
      #else
         char m_inputData[0x10];
         char m_outputData[0x10];
      #endif

   public:
      //CRing<char> receiveBuffer;
      uint8_t protocol;
      uint8_t idleState;
      uint8_t altSetting;
      CUsb &usb;
      CUsbDevice &device;
      bool m_busy;
      bool m_receiving=false;
      TUsbClassDesc m_desc;

      CUsbClass(CUsb &_periphery, CUsbDevice &_device, TUsbClassDesc desc);

      virtual int write(const void *buf, int size) override;
      virtual void flushOutput() override;

      void EP0_TxSent();
      void EP0_RxReady();
      void startReceive();
      USBD_StatusTypeDef DataIn(int epnum, char *data, int len);
      USBD_StatusTypeDef DataOut(int epnum, char *data, int len);
      uint8_t  *getConfigurationDescription(uint16_t *length);
      void sof();
      int init(uint8_t cfgidx);
      void deInit(uint8_t cfgidx);
      USBD_StatusTypeDef setup(CUsbRequest &req);
      USBD_StatusTypeDef sendReport(uint8_t *data, int size);
      virtual void eventLoop() override;
      void checkStart();
};


//---fin----------------------------------------------------------------------
#endif // ? ! BIWAK_USB_CLASS_H
