#include <pthread.h>

#ifdef __cplusplus
extern "C" {
#endif

#if defined (_DEBUG_PRINT) || defined (_DEBUG_PRINT_CANTX) || defined (_DEBUG_PRINT_CANRX)
extern char TempStr[200];
#endif

/* This define the currently version of library 
 * The format is 1.0.0 => 1 00 00  in decimal
 * Ex: 1.0.13 => 1 00  13
 */
#define LIBRARY_VERSION	10001			//1.0.1

#define CANFD_DEFAULT_COMM_TIMEOUT 1000	//msec

#define CANFD_HEADER_LENGTH	6
#define CANFD_MAX_PACKET_LENGTH 512

#define CANFD_MAX_CANSTDID_FILTER_NUM	128	//maximum CAN std id filter num
#define CANFD_MAX_CANEXTID_FILTER_NUM	64	//maximum CAN ext id filter num

#define TXBUF_MAX_SIZE	8
#define TXBUF_MASK	TXBUF_MAX_SIZE-1

/* USB protocol for normal packet definition (Byte index) */
#define NOR_PKT_OPERATION_CODE  0
#define NOR_PKT_RESERVED_BYTE1  1
#define NOR_PKT_FUNCTION_CODE   2
#define NOR_PKT_PACKET_LENGTH   4
#define NOR_PKT_DATA_REGION     6

/* I-7565-FD Operation Code */
#define DEVOP_Get	'$'
#define DEVOP_Set	'#'
#define DEVOP_Bulk	':'
#define DEVOP_RspErr	'?'
#define DEVOP_RspOK	'!'


/* I-7565-FD Function Code */
// Get/Test FC (request/response)
#define DEVFC_Get_FW_Ver		0x0000		//Module FW version
#define DEVFC_Get_INIT_Dip_Status	0x0001		//Module INIT pin state

//CAN1 read parameters
#define DEVFC_Get_CAN1_OPMode		0x0100		//Enable/Disable and Bus monitoring mode
#define DEVFC_Get_CAN1_STATUS		0x0101		//CAN status
#define DEVFC_Get_CAN1_ADBaud		0x0102		//CAN Arbitration/Data phase in bps	
#define DEVFC_Get_CAN1_Filter		0x0103		//CAN filter configuration (GFC + STD/EXT Msg ID Filter List Size)
#define DEVFC_Get_CAN1_STDFID_0		0x0104		//CAN STD Msg ID Filter (0~63) 
#define DEVFC_Get_CAN1_STDFID_1		0x0105		//CAN STD Msg ID Filter (64~127)
#define DEVFC_Get_CAN1_EXDFID_0		0x0106		//CAN EXD Msg ID Filter (0~31) 
#define DEVFC_Get_CAN1_EXDFID_1		0x0107		//CAN EXD Msg ID Filter (32~64)
#define DEVFC_Get_CAN1_RxFPS		0x0108		//CAN Rx FPS
#define DEVFC_Get_CAN1_HWSendMode	0x0109		//CAN Hardware send mode

//CAN2 read parameters
#define DEVFC_Get_CAN2_OPMode		0x0200
#define DEVFC_Get_CAN2_STATUS		0x0201
#define DEVFC_Get_CAN2_ADBaud		0x0202
#define DEVFC_Get_CAN2_Filter		0x0203
#define DEVFC_Get_CAN2_STDFID_0		0x0204
#define DEVFC_Get_CAN2_STDFID_1		0x0205
#define DEVFC_Get_CAN2_EXDFID_0		0x0206
#define DEVFC_Get_CAN2_EXDFID_1		0x0207
#define DEVFC_Get_CAN2_RxFPS		0x0208
#define DEVFC_Get_CAN2_HWSendMode	0x0209

// Set FC (request/response)
#define DEVFC_Set_SN			0x0000		//USB device SN
#define DEVFC_Set_LED_Mode		0x0001		//QC LED - set LED mode
#define DEVFC_Set_LED_State		0x0002		//QC LED - set LED state

//CAN1 write parameters
#define DEVFC_Set_CAN1_ReInitialize	0x0100		//Re-initiaize CAN1
#define DEVFC_Set_CAN1_OPMode		0x0101		//Enable/Disable and Bus monitoring mode
#define DEVFC_Set_CAN1_ADBaud		0x0102		//CAN Arbitration/Data phase in bps	
#define DEVFC_Set_CAN1_Filter		0x0103		//CAN filter configuration (GFC)
#define DEVFC_Set_CAN1_STDFListSize	0x0104		//CAN filter configuration (STD Msg ID Filter List Size)
#define DEVFC_Set_CAN1_EXTFListSize	0x0105		//CAN filter configuration (EXT Msg ID Filter List Size)
#define DEVFC_Set_CAN1_STDFID_0		0x0106		//CAN STD Msg ID Filter (0~63) 
#define DEVFC_Set_CAN1_STDFID_1		0x0107		//CAN STD Msg ID Filter (64~127)
#define DEVFC_Set_CAN1_EXTFID_0		0x0108		//CAN EXD Msg ID Filter (0~31) 
#define DEVFC_Set_CAN1_EXTFID_1		0x0109		//CAN EXD Msg ID Filter (32~64)
#define DEVFC_Set_CAN1_HWSendMode	0x010A		//CAN Hardware send mode
#define DEVFC_Set_CAN1_HWSendMsg	0x010B		//CAN Hardware send message

//CAN2 write parameters
#define DEVFC_Set_CAN2_ReInitialize	0x0200		//Re-initiaize CAN2
#define DEVFC_Set_CAN2_OPMode		0x0201
#define DEVFC_Set_CAN2_ADBaud		0x0202
#define DEVFC_Set_CAN2_Filter		0x0203
#define DEVFC_Set_CAN2_STDFListSize	0x0204
#define DEVFC_Set_CAN2_EXTFListSize	0x0205
#define DEVFC_Set_CAN2_STDFID_0		0x0206
#define DEVFC_Set_CAN2_STDFID_1		0x0207
#define DEVFC_Set_CAN2_EXTFID_0		0x0208
#define DEVFC_Set_CAN2_EXTFID_1		0x0209
#define DEVFC_Set_CAN2_HWSendMode	0x020A
#define DEVFC_Set_CAN2_HWSendMsg	0x020B

// Host to Device/Device to Host FC (no response)
#define DEVFC_H2D_CAN1Msg		0x0000
#define DEVFC_H2D_CAN2Msg		0x0001
#define DEVFC_D2H_CAN1Msg		0x0010
#define DEVFC_D2H_CAN2Msg		0x0011

#define DEVFC_H2D_ResetModule		0x00E0
#define DEVFC_H2D_ResetModuleWDT	0x00E1

typedef struct USBDEV_TxBuf_St
{
	BYTE data[HID_MAX_BYTE];
	int size;
}USBDEV_TxBuf_St ;

typedef struct CANRxPacketStruct
{	
  struct{
    DWORD id : 29;	// CAN Frame Identifier.
    DWORD rtr : 1;	// CAN Frame Type(DATA or REMOTE).
    DWORD xtd : 1;	// CAN Frame Type(STD or EXT).
    DWORD esi : 1;	// CAN Frame Error State Indicator.
  };
  struct{
    WORD dlc : 4;	  // Data Length Code      9 10 11 12 13 14 15
                    //  Number of data bytes 12 16 20 24 32 48 64
    WORD brs : 1;   // Bit Rate Switch.
    WORD fdf : 1;   // CAN FD format.
	  WORD eve : 2;	  // CAN Rx Event. 0: Rx data, 1: error warning/passive, bus off event, other: reserved
    WORD : 8;	      // Reserved.
  };
  WORD size;		    // classical CAN is 8(bytes), FD is 12/64 such.
  BYTE  data[64];
  DWORD second;	    //second
  DWORD usecond;	  //micro-sec
} CANRxPacketStruct;

typedef struct CANTxPacketStruct
{	
  struct{
    DWORD id : 29;	// CAN Frame Identifier.		0~28
    DWORD rtr : 1;	// CAN Frame Type(DATA or REMOTE).	29
    DWORD xtd : 1;	// CAN Frame Type(STD or EXT).		30
    DWORD esi : 1;	// CAN Frame Error State Indicator.	31
  };
  struct{
    WORD dlc : 4;	  // Data Length Code      9 10 11 12 13 14 15	0~3
                    //  Number of data bytes 12 16 20 24 32 48 64	
    WORD brs : 1;   // Bit Rate Switch.			 4
    WORD fdf : 1;   // CAN FD format.				 5
    WORD : 10;      // Reserved.					   6~15
  };
  WORD size;		    // classical CAN is 8(bytes), FD is 12/64 such.
  BYTE  data[64];
} CANTxPacketStruct;

typedef struct CANTxHWSendPacketStruct
{	
  struct{
    DWORD id : 29;	// CAN Frame Identifier.
    DWORD rtr : 1;	// CAN Frame Type(DATA or REMOTE).
    DWORD xtd : 1;	// CAN Frame Type(STD or EXT).
    DWORD esi : 1;	// CAN Frame Error State Indicator.
  };
  struct{
    WORD dlc : 4;	  // Data Length Code      9 10 11 12 13 14 15
                    //  Number of data bytes 12 16 20 24 32 48 64
    WORD brs : 1;   // Bit Rate Switch.
    WORD fdf : 1;   // CAN FD format.
    WORD : 10;      // Reserved.
  };
  WORD size;		    // classical CAN is 8(bytes), FD is 12/64 such.
  BYTE  data[64];
  DWORD period;	    //send period (unit: 0.1 ms)
  DWORD counter;	  //send conuter
} CANTxHWSendPacketStruct;

/* I-7565-FD Rx buffer of CAN1/2 Normal/Large package */
#define CANFD_NORMAL_PACKET_LENGTH	512	//HID maximum Package
#define CANFD_LARGE_RX_PACKET_LENGTH sizeof(CANRxPacketStruct) * 10240UL	//CAN Rx Data (80 * 10240)
#define CANFD_LARGE_RX_PACKET_LENGTH_MAX_CNT	CANFD_LARGE_RX_PACKET_LENGTH - sizeof(CANRxPacketStruct)
#define CANFD_LARGE_MAX_RX_DATA_NUM	6	//max rx data number per package

/* buffer of CAN1/2 tx package */
#define CANFD_LARGE_TX_PACKET_LENGTH sizeof(CANTxPacketStruct) * 128UL		//CAN Tx Data (72 * 128)
#define CANFD_LARGE_TX_PACKET_LENGTH_MAX_CNT	CANFD_LARGE_TX_PACKET_LENGTH - sizeof(CANTxPacketStruct)
#define CANFD_LARGE_MAX_TX_DATA_NUM		7	//max tx data number per package

typedef struct ICPDAS_CANFD_CAN_Buf_St
{
	int fd;
  BYTE hidNum;        //hidraw number
  WORD PID;
  DWORD BID;          //board of ID, means serial number
	BYTE IsDeviceOpen;
	int event_fd;       // Event file descriptor for notifications
	unsigned long LastError;

	struct USBDEV_TxBuf_St TxBuf[TXBUF_MAX_SIZE];
	int TxIn;
	int TxOut;
	int TxCnt;

	pthread_mutex_t mutex_USBDevTx;
	pthread_mutex_t mutex_CANTx_P1;
	pthread_mutex_t mutex_CANTx_P2;
	pthread_mutex_t mutex_CANRx_P1;
	pthread_mutex_t mutex_CANRx_P2;
	pthread_mutex_t mutex_NormPkt;

	//USB Rx CAN buffer flag
	DWORD BUFF_RX_Larg_C1_Start;
	DWORD BUFF_RX_Larg_C1_End;
	DWORD BUFF_RX_Larg_C1_Count;
	DWORD BUFF_RX_Larg_C2_Start;
	DWORD BUFF_RX_Larg_C2_End;
	DWORD BUFF_RX_Larg_C2_Count;
	
	//USB Tx CAN buffer flag
	DWORD BUFF_TX_Larg_C1_Start;
	DWORD BUFF_TX_Larg_C1_End;
	DWORD BUFF_TX_Larg_C1_Count;
	DWORD BUFF_TX_Larg_C2_Start;
	DWORD BUFF_TX_Larg_C2_End;
	DWORD BUFF_TX_Larg_C2_Count;

	//USB Rx CAN buffer
	BYTE BUFF_RX_NormPkt[CANFD_NORMAL_PACKET_LENGTH];
	BYTE BUFF_RX_LargPkt_C1[CANFD_LARGE_RX_PACKET_LENGTH];	
	BYTE BUFF_RX_LargPkt_C2[CANFD_LARGE_RX_PACKET_LENGTH];
	
	//USB Tx CAN buffer
	BYTE BUFF_TX_LargPkt_C1[CANFD_LARGE_TX_PACKET_LENGTH];	
	BYTE BUFF_TX_LargPkt_C2[CANFD_LARGE_TX_PACKET_LENGTH];

	BYTE m_byNormalPktArrive;

}ICPDAS_CANFD_CAN_Buf_St, *PICPDAS_CANFD_CAN_Buf_St;

extern int PackReadPacket(WORD wFCCode, WORD wDataLen, BYTE *byData, BYTE* byPkt);
extern int PackWritePacket(WORD wFCCode, WORD wDataLen, BYTE *byData, BYTE* byPkt);
extern int PackLargeDataPacket(WORD wFCCode, WORD wDataLen, BYTE *byData, BYTE* byPkt);

extern void CANBufStructInit(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL);
extern int CANRxBufIsFull(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANTxBufIsFull(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANRxBufIsEmpty(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANTxBufIsEmpty(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANRxBufClear(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANTxBufClear(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort);
extern int CANRxBufDataCount(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, DWORD *o_wCount);
extern int CANTxBufDataCount(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, DWORD *o_wCount);
extern int CANRxBufWriteN(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, BYTE *i_byElem, DWORD i_wLen);
extern int CANTxBufWriteN(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, BYTE *i_byElem, DWORD i_wLen);
extern int CANRxBufReadN(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, BYTE *i_byElem, DWORD i_wLen);
extern int CANTxBufReadN(ICPDAS_CANFD_CAN_Buf_St *pCAN_DL, BYTE i_byCANPort, BYTE *i_byElem, DWORD i_wLen);

#ifdef __cplusplus
}
#endif
