//////////////////////////////////////////////////////////////////
//
// App:			Global device list
// Author:		Milan Korinek
// Version:		1.0
// Notice:		Share memory list, internal device info list
//				USB Hot Plug monitor 
//////////////////////////////////////////////////////////////////

#ifndef __GLOBAL_DEVICES_LISTS_H__
#define __GLOBAL_DEVICES_LISTS_H__

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


/* ============================================ */
/*				Constants and enums				*/
/* ============================================ */

//! Ownership of the some Object
typedef enum _E_ProcessOwnership {

	//! Object is avaiable
	E_PROCESS_OWNERSHIP_FREE =	0,

	//! Owner of the object is current process
	E_PROCESS_OWNERSHIP_OWNER = 1,

	//! Owner of the object is other process
	E_PROCESS_OWNERSHIP_USED =	2,

} E_ProcessOwnership_t;



/* ============================================ */
/*			     	Structures				    */
/* ============================================ */

typedef struct _DeviceOwnership {
	
	//! Is device used with some proccess?
	BOOL IsUsed;

	//! Process ID
	DWORD ProcessID;

	//! Serial number of device
	char ProcessName[DIO_STRING_MAX_LEN];

	//! Device unique ID (by libusbK)
	char DeviceID[KLST_STRING_MAX_LEN];

} DeviceOwnership_t;

//! Device info internal
typedef struct _DeviceInfoInternal {

	//! Mutex lock of this structure
	HANDLE					hndlLock;

	E_ProcessOwnership_t	ProcessOwnership;

	//! Device unique ID (by linusbK)
	char					DeviceID[KLST_STRING_MAX_LEN];

	//! Basic device info
	DIO_DeviceInfo_t		DeviceInfo;

	//! Device connecton state
	E_DeviceConnectionState_t	DeviceConnectionState;

	//! Device state
	E_DeviceState_t			DeviceState;

	//! USB device info
	KLST_DEVINFO_HANDLE		USBDeviceInfo;

	//! USB handle
	KUSB_HANDLE				hndlUSB;

	//! USB Driver API provided by usblibK
	KUSB_DRIVER_API			USB_Driver;

} DeviceInfoInternal_t;

/* ============================================ */
/*				Share device list				*/
/* ============================================ */

// Share Device List in Shared Memory
// -----------------------------------------------

//! Name of Share Device List
#define SHARE_DEVICE_LIST_MEM_NAME (TEXT("Digital_IO_USB_Card/File_Mapping_Object/ShareDeviceList"))

//! Size of Share Device List
#define SHARE_DEVICE_LIST_MEM_SIZE (sizeof(DeviceOwnership_t) * DIO_MAX_DEVICES_SUPPORT)


// Share Device List Sync - Mutex
// -----------------------------------------------

//! Name of Share Device List Sync
#define SHARE_DEVICE_LIST_SYNC_NAME (TEXT("Digital_IO_USB_Card/Mutex/ShareDeviceListSync"))


//! Default settings of struct DIO_DeviceInfo_t
extern const DIO_DeviceInfo_t DIO_DEVICE_INFO_DEFAULT;

//! Default settings of struct DeviceOwnership_t
extern const DeviceOwnership_t DEVICE_OWNERSHIP_DEFAULT;

//! Default settings of struct DeviceInfoInternal_t
extern const DeviceInfoInternal_t DEVICE_INFO_INTERNAL_DEFAULT;

/* ============================================ */
/*				General functions				*/
/* ============================================ */

NOMANGLE DIO_Errors_t InitiateLists(void);

NOMANGLE DIO_Errors_t FreeLists(void);

NOMANGLE DIO_Errors_t OpenDevice(_In_ DeviceInfoInternal_t * device);

NOMANGLE DIO_Errors_t CloseDevice(_In_ DeviceInfoInternal_t * device);

NOMANGLE DIO_Errors_t CloseDevices(void);

/* ============================================ */
/*		   USB Hot Plug Monitor   				*/
/* ============================================ */
NOMANGLE static VOID KUSB_API  USBHotPlugMonitor(
	KHOT_HANDLE Handle, 
	KLST_DEVINFO_HANDLE DeviceInfo, 
	KLST_SYNC_FLAG NotificationType);

NOMANGLE static BOOL USBHotPlugMonitor_Start();

NOMANGLE static BOOL USBHotPlugMonitor_Stop();

/* ============================================ */
/*		Share device list functions				*/
/* ============================================ */

// Global functions
// -----------------------------------------------

/**
 * \brief Debug print of Share device list
 *
 * \param all True for print all, False skip empty objects
 *
 * \retval True if success.
 */
NOMANGLE void PrintShareDeviceList(_In_ BOOL all);

// Local functions
// -----------------------------------------------

/**
 * \brief Create new Share Device List (between processes)
 *
 * \retval DIO_ERROR_SUCCESS		New Share Device List was created.
 * \retval DIO_ERROR_ALREADY_EXIST	Succes, Share Device List already exists.
 * \retval DIO_ERROR_FAIL_CREATE	Can not create Share dvice List.
 */
NOMANGLE static DIO_Errors_t CreateShareDeviceList(void);

/**
 * \brief Free all Share device list resources.
 *
 * \retval True if success.
 */
NOMANGLE static BOOL FreeShareDeviceList(void);

/**
 * \brief Set default values of Share Device List
 *
 * \retval True if success.
 */
NOMANGLE static BOOL SetDefaultShareDeviceList(void);

/* ============================================ */
/*		Device info list functions				*/
/* ============================================ */

// Global functions
// -----------------------------------------------

/**
 * \brief	Finf device info for specific address of the module
 *
 * \param	module Address of the module.
 * \param	dest	Destination to copy Device Info.
 *
 * \retval	>=0 Index of Device Info in list
 * \retval	-1  Device not found
 * \retval	-2	Serious error
 */
NOMANGLE int FindDeviceInfoByModule(_In_ UINT32 module, _Out_ DeviceInfoInternal_t ** dest);

/**
 * \brief  Get number of USB devies in Device Info list. Skip disconnected devices.
 *
 * \retval True if some new USB device was added to List.
 */
NOMANGLE UINT32 GetDeviceInfoListCount(void);

/**
 * \brief Debug print of Device Info Internal List
 *
 * \param all True for print all, False skip empty objects
 *
 * \retval True if success.
 */
NOMANGLE void PrintDeviceInfoInternalList(_In_ BOOL all);

// Local functions
// -----------------------------------------------

/**
 * \brief  Create new Device Info Internal List.
 *
 * \retval True - success.
 */
NOMANGLE static BOOL CreateInternalDeviceList(void);

/**
 * \brief  Clear Device Info Internal List.
 *
 * \retval True - success.
 */
NOMANGLE static BOOL FreeInternalDeviceList(void);

/**
 * \brief  Try to find new USB devices (using libusbK) and add to to device list.
 *
 * \retval True if some new USB device was added to List.
 */
NOMANGLE static BOOL GenInternalListFromUSBDevices(void);

NOMANGLE static BOOL FreeAllInternalDeviceItems();

NOMANGLE static BOOL FreeInternalDeviceItem(unsigned int index);

/**
 * \brief Get information about device such as nam, serial number etc.
 *
 * \param deviceInfo LibusbK device information structure.
 *
 * \retval >=  0 Success, index of added device in list.
 * \retval == -1 Device is already in the list.
 * \retval <  -1 Error.
 */
NOMANGLE static int AddUSBDevicesToList(_In_ KLST_DEVINFO_HANDLE deviceInfo);

/**
 * \brief  Set default values to Device Info Internal List
 */
NOMANGLE static void SetDefaultDeviceInfoList(void);

/**
 * \brief	Finf device info for specific address of the module
 *
 * \param	deviceInfo LibusbK device information structure.
 * \param	dest	Destination to copy Device Info.
 *
 * \retval	>=0 Index of Device Info in list
 * \retval	-1  Device not found
 * \retval	-2	Serious error
 */
NOMANGLE static int FindDeviceInfoByUSBDevice(_In_ KLST_DEVINFO_HANDLE deviceInfo, _Out_ DeviceInfoInternal_t ** pDest);

/**
 * \brief	Check if USB devise is same with device from internal list
 *
 * \param	deviceInfo LibusbK device information structure.
 * \param	deviceInfoInternal	Device Info Internal
 *
 * \retval	True if same devices
 */
NOMANGLE static BOOL IsSameUSBDevice(_In_ KLST_DEVINFO_HANDLE deviceInfo, _In_ DeviceInfoInternal_t deviceInfoInternal);








#endif /* __GLOBAL_DEVICES_LISTS_H__ */