#ifndef _INTERFACE_H_
#define _INTERFACE_H_

#include "commdef.h"

// the error code the INTERFACE returned, 
// if no error occurred, return the bytes sent or read
//
#define IF_OK				(0)
#define IF_MORE_DATA		(-1)
#define	IF_FAIL_READ		(-2)
#define	IF_FAIL_WRITE		(-3)
#define	IF_NEED_RETRY		(-4)
#define	IF_OVER_MTU_SIZE	(-5)
#define IF_FAIL_PARAMETER   (-6)
#define IF_READ_TIMEOUT		(-7)
#define IF_WRITE_TIMEOUT    (-8)
#define IF_CTLR_FAILED      (-9)


// rwflag
#define	IF_WRITE_ONLY		0x01	// just do the operation of send
#define	IF_READ_ONLY		0x02	// just do the operation of read
#define IF_RAW_READ			0x04
#define IF_RAW_WRITE		0x08
#define IF_SAS				0x10


//	THE BELOW BLOCK IS ONLY FOR INTERNAL USE
/************************************************************************************/
enum
{
GUI_SET_SERIAL = 0x10,
GUI_SET_VENDOR,
GUI_SET_MODEL,
GUI_IDENTIFY,
GUI_CHECK_PASSWORD,
GUI_LOGOUT,
GUI_HTTP,
GUI_SET_ETHERNET_ADDR,
GUI_SET_LOGO,
GUI_POLL_EVENT,
GUI_GET_EVENT,
GUI_GET_HW_MONITOR,
GUI_SMART_TEST,
GUI_SET_TIME,
GUI_SNMP,
GUI_MISC,		// 0x1F

GUI_GET_INFO_R = 0x20,
GUI_GET_INFO_V,
GUI_GET_INFO_P,
GUI_GET_INFO_S,
GUI_CLEAR_EVENT,

GUI_MUTE_BEEPER = 0x30,
GUI_BEEPER_SETTING,
GUI_SET_PASSWORD,
GUI_HOST_INTERFACE_MODE,
GUI_REBUILD_PRIORITY,
GUI_MAX_ATA_MODE,
GUI_RESET_CONTROLLER,
GUI_COM_PORT_SETTING,
GUI_NO_OPERATION,
GUI_DHCP_IP,

GUI_CREATE_PASS_THROUGH = 0x40,
GUI_MODIFY_PASS_THROUGH,
GUI_DELETE_PASS_THROUGH,
GUI_IDENTIFY_DEVICE,

GUI_CREATE_RAIDSET = 0x50,
GUI_DELETE_RAIDSET,
GUI_EXPAND_RAIDSET,
GUI_ACTIVATE_RAIDSET,
GUI_CREATE_HOT_SPARE,
GUI_DELETE_HOT_SPARE,

GUI_CREATE_VOLUME = 0x60,
GUI_MODIFY_VOLUME,
GUI_DELETE_VOLUME,
GUI_START_CHECK_VOLUME,
GUI_STOP_CHECK_VOLUME
};

// Application specific
enum 
{
GUI_RAW_READ_WRITE   = 0xEC,
GUI_RAW_READ   = 0xED,
GUI_RAW_WRITE  = 0xEE,
GUI_SET_ENCLOSURE_UNIT_SERIAL,
GUI_GET_TCPPORT,
GUI_GET_COMATTR,

// status code
GUI_WOULDBLOCK,
GUI_TIMEOUT
};
/****************************************************************************************/

//
// Library returned status
//
#define ARC_STATUS					int
#define ARC_SUCCESS					0x00	// Operation succeeded 
#define ARC_FAILURE					0x01	// Operation failed
#define ARC_RETURN_FRAME_ERROR 		0x02	// The library does not recognize the returned data
                                            // (including invalid data header, length or checksum, etc...)
#define ARC_INVALID_COM_HANDLE		0x03	// Invalid RS-232 handle
#define ARC_DATA_TRANSMIT_ERROR		0x04	// Failed to write to media
#define ARC_DATA_RECEIVE_ERROR		0x05	// Failed to read from media( no response from raid subsystem)
#define ARC_PARAMETER_ERROR			0x06	// The wrong parameter(s)
#define ARC_OPENFILE_ERROR			0x07	// Failed to open file
#define ARC_PASSWORD_REQUIRED       0x08	// Password required
#define ARC_INVALID_PASSWORD        0x09	// Wrong password
#define ARC_INSUFFICIENT_MEM		0x0A	// Memory too small
#define ARC_CANT_ALLOC_MEM			0x0B	// Failed to allocate necessary memory
#define ARC_BUFFER_TOO_SMALL		0x0C	// The buffer is too small to put the returned data
#define	ARC_SOCKET_ERROR			0x0D	// Socket error
#define ARC_INVALID_SOCKET			0x0E	// Invalid socket
#define ARC_INIT_COM_ERROR			0x0F	// Failed to open COM port
#define ARC_SOCKET_STARTUP_ERROR	0x10	// Failed to init socket
#define ARC_INVALID_INTERFACE		0x11	// Invalid interface
#define ARC_NO_SUCH_DEVICE			0x12	// Device not found( including raidset, volumeset, physical drive )
#define ARC_DATA_TRANSMIT_TIMEOUT   0x13	// Failed to write to media in a given time
#define ARC_DATA_RECEIVE_TIMEOUT    0x14	// Failed to read from media in a given time
#define ARC_CTLR_FAILURE			0x15	// Controller failure or inactive
#define ARC_UNKNOWN_ERROR			0x3F	// Unknown error

// RAID controller returned status
#define GUI_OK						0x41	// Operation successed
#define GUI_RAIDSET_NOT_NORMAL		0x42
#define GUI_VOLUMESET_NOT_NORMAL	0x43
#define GUI_NO_RAIDSET				0x44
#define GUI_NO_VOLUMESET			0x45
#define GUI_NO_PHYSICAL_DRIVE		0x46
#define GUI_PARAMETER_ERROR			0x47
#define GUI_UNSUPPORTED_COMMAND		0x48
#define GUI_DISK_CONFIG_CHANGED		0x49
#define GUI_INVALID_PASSWORD		0x4a
#define GUI_NO_DISK_SPACE			0x4b
#define GUI_CHECKSUM_ERROR			0x4c
#define GUI_PASSWORD_REQUIRED		0x4d
#define GUI_NO_MORE_DATA   			0x4e	// Internal use only
#define GUI_INTERNAL_ERROR   		0x4f
#define GUI_FIRMWARE_CRC_ERROR  	0x50
#define GUI_FIRMWARE_INVALID  		0x51
#define GUI_FIRMWARE_UPDATE_FAILED 	0x52
#define GUI_FIRMWARE_NO_HDD   		0x53
#define GUI_END_OF_DATA    			0x54

typedef int (*fn_decode_frame)(unsigned char *buf, int len);
typedef unsigned char (*fn_decode_cs)(unsigned char *buf, int len);

////////////////////////////////////////////////////////////
// for internal use only
//
typedef struct _IF_CMD_BLOCK
{	
	unsigned long timeout;	// [in]in milliseconds
	unsigned long rwflag;	// [in]the flag which control the behavior of read/write	
	const char *outBuf;		// [in] the output data buffer to be sent
	unsigned long outLen;	// [in] the output data buffer size
	char *inBuf;			// [out] the input data buffer to put the firmware returned data
	unsigned long inLen;	// [out] the input data buffer size
	unsigned long io_status;// [out] the status of i/o
	fn_decode_frame df;		// [in] 
	fn_decode_cs    dc;		// [in]
}sIF_CMD_BLOCK, *pIF_CMD_BLOCK;
////////////////////////////////////////////////////////////


#ifdef _WIN32
class ARCLIB_API ArcInterface
#else
class ArcInterface
#endif
{	
public:	
	virtual ~ArcInterface()
	{
	}
	virtual int send(sIF_CMD_BLOCK *ifData) = 0;	
	virtual int recv(sIF_CMD_BLOCK *ifData) = 0;
	virtual int syncSend(sIF_CMD_BLOCK *ifData) = 0;

    //
	//	MTU: Maximum transmission unit
	//  the size (in bytes) of the largest packet that this layer can carry out.	
	//	
	virtual int	 getMTU() = 0;
	virtual void *getDeviceHandle() = 0;

	// These two member functions will be called by the syncSend() member function
	// to ensure the synchronization of send() and recv() to the single controller.
	// The requirelock() will be called before the send(), 
	// and releaselock() will be called after the recv().
	virtual void requirelock(){}
	virtual void releaselock(){}

	virtual int getFirmSpec()
	{
		return 1;
	}

	// set the timeout for interface read operation
	void setTimeOut(int nSec)
	{
		if(nSec > 0)
		{
			nTimeOut = nSec;
		}
	}

	int getTimeOut()
	{
		return nTimeOut;
	}

private:
	int nTimeOut;	
};


typedef void (*CMD_CALLBACK)(void *data);


typedef enum _SRC_SOURCE
{
	SRC_UNKNOWN = -1,
	SRC_COMM = 0,
	SRC_DRIVER,
	SRC_INBAND,
	SRC_ETHERNET,
	SRC_DRIVER_ODIN,
	SRC_TOTAL
};


#ifdef _WIN32
class ARCLIB_API CArclibObj
#else
class CArclibObj
#endif
{	
public:
	CArclibObj()
	{
		m_Source = SRC_UNKNOWN;
	}
	
	virtual ~CArclibObj() {}
public:
	unsigned long m_Source;
};


#ifdef _WIN32
class ARCLIB_API CArclibBase : public CArclibObj
#else
class CArclibBase : public CArclibObj
#endif
{	
public:	
	CArclibBase()
	{
		m_Interface = NULL;
		m_CallBackFunc = NULL;
	}
	
	virtual ~CArclibBase()
	{
		if(m_Interface)
		{
			delete m_Interface;
			m_Interface = NULL;
		}
	}

	virtual void ArcSetCallBack(CMD_CALLBACK pFunc)
	{
		m_CallBackFunc = pFunc;
	}

	/************************************************************************************
	Function Name:	ArcInitSession
	Function:		Startup areca library by assigning an interface to it
	Input:			1. ArcInterface
	Output:			None.
	Return Values:	1. ARC_STATUS					
	Note:			This function should be called before any member functions be called
	************************************************************************************/	
	virtual ARC_STATUS ArcInitSession(ArcInterface *Interface)
	{
		m_Interface = Interface;
		return ARC_SUCCESS;
	}

protected:
	ArcInterface *m_Interface;	// The communication path to the raid-subsystem
	CMD_CALLBACK m_CallBackFunc;

};



#endif
