/*---------------------------------------------------------------
	FILE: CInterfaceFTDI.h

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es
  ---------------------------------------------------------------*/

#ifndef CInterfaceFTDI_H
#define CInterfaceFTDI_H

#include <MRPT/config.h>
#include <MRPT/UTILS/CStream.h>

namespace HWDRIVERS
{

	/** A definition of a CStream actually representing a USB connection to a FTDI chip.
	 *
	 *  This class implements the communication with FT245BM / FT245RL chips.
	 *   Using this class will generate a dependency on "FT2XX.DLL" and device drivers (see FTDI website)
	 *
	 *  If there is any error loading this DLL, or during the communications, a std::exception will be raised.
	 *
	 *  Please refer to FTDI documentation for the "FTD2XX" interface.
	 *
	 * Warning: Avoid defining an object of this class in a global scope if you want to catch all potential
	 *      exceptions during the constructors (like DLL not found, etc...)
	 *
	 * VERSIONS:
	 *		- 11/ABR/2005: Initial development. JLBC
	 *		- 16/FEB/2007: Integration into the MRPT framework. Support for device serial numbers. JLBC
	 *
	 */
	class CInterfaceFTDI : public UTILS::CStream
	{
	public:
		/** Constructor, which loads driver interface (the DLL under Windows)
		  */
		CInterfaceFTDI();

		/** Destructor, which closes the connection with the chip and unloads the driver
		  */
		virtual ~CInterfaceFTDI();

		/** Checks whether the chip has been successfully open.
		  */
		bool  isOpen();

		/** Open by device serial number
		  */
		void  OpenBySerialNumber( const std::string &serialNumber );

		/** Open by device description
		  */
		void  OpenByDescription( const std::string &description );


		void  Open(void* pvDevice);
		void  OpenEx(void* pArg1, unsigned long dwFlags);
		void  ListDevices(void*pArg1, void*pArg2, unsigned long dwFlags);
		void  Close();
		void  Read(void  *lpvBuffer, unsigned long dwBuffSize, unsigned long  *lpdwBytesRead);
		void  Write(const void  *lpvBuffer, unsigned long dwBuffSize, unsigned long  *lpdwBytes);
		void  ResetDevice();
		void  Purge(unsigned long dwMask);
		void  SetTimeouts(unsigned long dwReadTimeout_ms, unsigned long dwWriteTimeout_ms);
		void  GetQueueStatus(unsigned long  *lpdwAmountInRxQueue);
		void  SetLatencyTimer (unsigned char latency_ms);

	protected:
		/** Introduces a pure virtual method responsible for reading from the stream.
		 */
		size_t  Read(void *Buffer, size_t Count);

		/** Introduces a pure virtual method responsible for writing to the stream.
		 *  Write attempts to write up to Count bytes to Buffer, and returns the number of bytes actually written.
		 */
		size_t  Write(const void *Buffer, size_t Count);

		/** Introduces a pure virtual method for moving to a specified position in the streamed resource.
		 *   he Origin parameter indicates how to interpret the Offset parameter. Origin should be one of the following values:
		 *	- sFromBeginning	(Default) Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
		 *	- sFromCurrent		Offset is from the current position in the resource. Seek moves to Position + Offset.
		 *	- sFromEnd			Offset is from the end of the resource. Offset must be <= 0 to indicate a number of bytes before the end of the file.
		 * \return Seek returns the new value of the Position property.
		 */
		unsigned long  Seek(long Offset, CStream::TSeekOrigin Origin = sFromBeginning);

		/** Returns the total amount of bytes in the stream.
		 */
		unsigned long  getTotalBytesCount();

		/** Method for getting the current cursor position, where 0 is the first byte and TotalBytesCount-1 the last one.
		 */
		unsigned long  getPosition();


		void 		checkErrorAndRaise(int errorCode);

#if defined(MRPT_OS_WINDOWS)
		void				*m_hmodule;
		unsigned long		m_ftHandle;

		void 		loadDriver();

		enum FT_STATUS
		{
			dummy
		};

		typedef FT_STATUS (__stdcall *PtrToOpen)(void*, unsigned long  *);
		PtrToOpen m_pOpen;

		typedef FT_STATUS (__stdcall *PtrToOpenEx)(void*, unsigned long, unsigned long  *);
		PtrToOpenEx m_pOpenEx;

		typedef FT_STATUS (__stdcall *PtrToListDevices)(void*, void*, unsigned long);
		PtrToListDevices m_pListDevices;

		typedef FT_STATUS (__stdcall *PtrToClose)(unsigned long );
		PtrToClose m_pClose;

		typedef FT_STATUS (__stdcall *PtrToRead)(unsigned long , void  *, unsigned long, unsigned long  *);
		PtrToRead m_pRead;

		typedef FT_STATUS (__stdcall *PtrToWrite)(unsigned long , const void  *, unsigned long, unsigned long  *);
		PtrToWrite m_pWrite;

		typedef FT_STATUS (__stdcall *PtrToResetDevice)(unsigned long );
		PtrToResetDevice m_pResetDevice;

		typedef FT_STATUS (__stdcall *PtrToPurge)(unsigned long , unsigned long);
		PtrToPurge m_pPurge;

		typedef FT_STATUS (__stdcall *PtrToSetTimeouts)(unsigned long , unsigned long, unsigned long);
		PtrToSetTimeouts m_pSetTimeouts;

		typedef FT_STATUS (__stdcall *PtrToGetQueueStatus)(unsigned long , unsigned long  *);
		PtrToGetQueueStatus m_pGetQueueStatus;

		typedef FT_STATUS (__stdcall *PtrToSetLatencyTimer )(unsigned long , unsigned char);
		PtrToSetLatencyTimer m_pSetLatencyTimer;

#else
    // Declarations for Linux:



#endif


	}; // end of class

} // end of namespace


#endif
