//////////////////////////////////////////////////////////////////
//
// App:			Suppor functions
// Author:		Milan Korinek
// Version:		1.0
// Notice:		Logging and several auxiliary functions	
//////////////////////////////////////////////////////////////////

#ifndef __SUPPORT_H__
#define __SUPPORT_H__

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#include "libusbk.h"
#include "DigitalIOUSBCard.h"
#include "GlobalDevicesLists.h"


/* ============================================ */
/*			   	Debugs and logging			    */
/* ============================================ */

#ifdef NDEBUG
#	define	DIO_NDEBUG
#endif

#ifndef DIO_SEVERITY_MAX
#	define DIO_SEVERITY_MAX			10
#endif

#ifndef DIO_SEV_LEVEL_MIN
#	define DIO_SEVERITY_MIN			0
#endif

#define DIO_SEVERITY_CRITICAL		(DIO_SEVERITY_MAX - 1)
#define DIO_SEVERITY_IMPORTANT		(DIO_SEVERITY_MAX - 2)
#define DIO_SEVERITY_HIGH			(DIO_SEVERITY_MAX - 3)
#define DIO_SEVERITY_MEDIUM			(DIO_SEVERITY_MAX - 4)
#define DIO_SEVERITY_NORMAL			(DIO_SEVERITY_MAX - 5)
#define DIO_SEVERITY_LOW			(DIO_SEVERITY_MAX - 6)

#ifndef DIO_SEVERITY_LEVEL
#	define DIO_SEVERITY_LEVEL		DIO_SEVERITY_NORMAL
#endif

#ifdef  DIO_NDEBUG
#	define debug_printf(severity, FORMAT, ...)		((void)0)
#	define debug_puts(severity, MSG)				((void)0)
#	define debug_func_begin(severity, FORMAT, ...)	((void)0)
#	define debug_func_end(severity, FORMAT, ...)	((void)0)
#	define debug_error(severity, FORMAT, ...)		((void)0)
#	define debug_warning(severity, FORMAT, ...)		((void)0)
#	define debug_info(severity, FORMAT, ...)		((void)0)
#	define debug_event(severity, FORMAT, ...)		((void)0)
#else
#	define debug_iprintf(severity, HEADER, FORMAT, ...) \
				do { if ((severity) >= DIO_SEVERITY_LEVEL) fprintf(stderr, HEADER "(%d)::%s():: " FORMAT "\n", severity, __FUNCTION__, __VA_ARGS__); } while ( 0 )	
#	define debug_printf(severity, FORMAT, ...) \
				do { if ((severity) >= DIO_SEVERITY_LEVEL) fprintf(stderr, FORMAT, __VA_ARGS__); } while ( 0 )
#	define debug_func_begin(severity, FORMAT, ...)	debug_iprintf(severity,	"BEGIN", FORMAT, __VA_ARGS__)
#	define debug_func_end(severity, FORMAT, ...)	debug_iprintf(severity,	"END", FORMAT, __VA_ARGS__)
#	define debug_error(severity, FORMAT, ...)		debug_iprintf(severity,	"ERROR", FORMAT, __VA_ARGS__)
#	define debug_warning(severity, FORMAT, ...)		debug_iprintf(severity,	"WARN", FORMAT, __VA_ARGS__)
#	define debug_info(severity, FORMAT, ...)		debug_iprintf(severity,	"INFO", FORMAT, __VA_ARGS__)
#	define debug_event(severity, FORMAT, ...)		debug_iprintf(severity,	"EVENT", FORMAT, __VA_ARGS__)
#endif


/* ============================================ */
/*			   	Auxiliary functions			    */
/* ============================================ */

//! Maximum time to get access to mutex
#define MAX_SYNC_TIMEOUT	1000

/**
 * \brief Get USB device unique ID from libusbK struct.
 *
 * \param USBDeviceInfo LibusbK device information structure.
 *
 * \retval Unique string, terminated by \0.
 */
NOMANGLE char * GetUSBDeviceUniqueID(_In_ KLST_DEVINFO_HANDLE USBDeviceInfo);

/**
 * \brief Is this Digital I/O USB card?
 *
 * \param USBDeviceInfo LibusbK device information structure.
 *
 * \retval True - Digital I/O USB card.
 */
NOMANGLE BOOL IsDigitalIOUSBCard(_In_ KLST_DEVINFO_HANDLE USBDeviceInfo);

/**
 * \brief Configure USB interface of the USB device. Interface of the Digital I/O will be enabled (and endpoints).
 *
 * \param enable	True - Enable interface, False - disable interface
 * \param UsbHandle libusbK handle of USB.
 * \param UsbHandle libusbK Driver API function set .
 *
 * \retval True - success.
 */
NOMANGLE BOOL ConfigureUSBDeviceInterface(_In_ BOOL enable,  _In_ DeviceInfoInternal_t * deviceInfo);

/**
 * \brief Lock/unlock Object by Mutex.
 *
 * \param hndlSyncObject Handle to mutex.
 * \param lock True for lock, false for unlock.
 *
 * \retval True if success.
 */
NOMANGLE BOOL LockObject(_In_ HANDLE hndlSyncObject, _In_ BOOL lock);

/**
 * \brief Write/read to/from control endpoint
 *
 * \param write true - write, false - read
 * \param deviceInfo Device information structure to fill.
 * \param value fied in contro packet
 * \param index fied in control packet
 * \param payloadLength payload length to send/buffer size
 * \param payload - send/receive buffer
 * \param transferred count of transferred bytes
 *
 * \retval True if success.
 */
NOMANGLE DIO_Errors_t USBControlEndpoint(_In_ BOOL write, 
										 _In_ DeviceInfoInternal_t * deviceInfo, 
										 _In_ USHORT value, 
										 _In_ USHORT index, 
										 _In_ UINT payloadLength, 
										 _Inout_ UCHAR * payload, 
										 _Out_ UINT * transferred);

/**
 * \brief Write/read to/from interrupt endpoint
 *
 * \param write true - write, false - read
 * \param deviceInfo Device information structure to fill.
 * \param payloadLength payload length to send/buffer size
 * \param payload - send/receive buffer
 * \param transferred count of transferred bytes
 *
 * \retval True if success.
 */
NOMANGLE BOOL USBInterruptEndpoint(_In_ BOOL write, 
								   _In_ DeviceInfoInternal_t * deviceInfo, 
								   _In_ UINT payloadLength, 
								   _Inout_ UCHAR * payload,
								   _Out_ UINT * transferred);

/**
 * \brief Write/read to/from bulk endpoint
 *
 * \param write true - write, false - read
 * \param deviceInfo Device information structure to fill.
 * \param value fied in contro packet
 * \param index fied in control packet
 * \param payloadLength payload length to send/buffer size
 * \param payload - send/receive buffer
 * \param transferred count of transferred bytes
 *
 * \retval True if success.
 */
NOMANGLE BOOL USBBulkEndpoint(_In_ BOOL write,
							  _In_ DeviceInfoInternal_t * deviceInfo, 
							  _In_ UINT payloadLength, 
							  _Inout_ UCHAR * payload, 
							  _Out_ UINT * transferred);

/* ============================================ */
/*	Shared Functions with Digital I/O USB card  */
/* ============================================ */

/* Serialize and Parsing function of configuration */

/**
 * \brief Get UINT8 data from buffer
 *
 * \param source
 * \param sourcePos ,auto incrementing
 * \param dest
 * \param size
 *
 */
NOMANGLE void Parse_Copy(_In_ UINT8 * source, _Inout_ UINT * sourcePos, _Out_ void * dest, _In_ size_t size);

NOMANGLE void Serialize_Copy(_In_ void * source, _In_ size_t size, _Out_ UINT8 * dest, _Inout_ UINT * destPos);

NOMANGLE void Parse_DIO_Behavior_t(_In_ UINT8 * buffer, _Inout_ UINT * buffPos, _Out_ DIO_Behavior_t * structure);

NOMANGLE void Serialize_DIO_Behavior_t(_In_ DIO_Behavior_t * structure, _Out_ UINT8 * buffer, _Inout_ UINT * buffPos);

NOMANGLE void Parse_DIO_PortConfig_t(_In_ UINT8 * buffer, _Inout_ UINT * buffPos, _Out_ DIO_PortConfig_t * structure);

NOMANGLE void Serialize_DIO_PortConfig_t(_In_ DIO_PortConfig_t * structure, _Out_ UINT8 * buffer, _Inout_ UINT * buffPos);

NOMANGLE BOOL ParseDeviceConfigurationPacket(_In_ UINT8 * payload,
_In_ UINT payload_length,
_Out_ E_DeviceState_t * DeviceState,
_Out_ DIO_Behavior_t * DeviceBehavior,
_Out_ DIO_PortConfig_t PortsConfiguration[DIO_MAX_PORTS]);

NOMANGLE BOOL CreateDeviceConfigurationPacket(_In_ E_DeviceState_t DeviceState,
_In_ DIO_Behavior_t * DeviceBehavior,
_In_ DIO_PortConfig_t PortsConfiguration[DIO_MAX_PORTS],
_Out_ UINT8 * payload,
_Out_ UINT * payload_length);

#endif /* __SUPPORT_H__ */