/*
[]=================================================================[]
	DeviceDemo.cpp

	Copyright (C) 2001 Feitian Tech. Co. Ltd. All rights reserved.
	by Water Bird
	Created at 17-5-2001   8:33

	Comment : Demostrating the device management functions of the
			  ePass 1000.
[]=================================================================[]
*/

#include <Windows.h>
#include <Process.h>
#include <Stdio.h>
#include <conio.h>
#include "DeviceDemo.h"
#include "../common/eps1kDemo.h"
#include "../common/eps1kUtility.h"

// Global variables.
unsigned char APP_NAME[]     = "Dev_Demo";
unsigned char APP_GUID_STR[] = "3263B99A-659E-4600-9370-ADA3DA149371";
GUID guid;
bool bDeviceSelected = false;

int
main(void)
{
    EPAS_STATUS epsRet;
    EPAS_HANDLE handle;

	// Init the 16 bytes guid data-structure.
	// It is the same as APP_GUID_STR.
	guid.Data1    = 0x3263B99A;
	guid.Data2    = 0x659E;
	guid.Data3	  = 0x4600;
	guid.Data4[0] = 0x93;
	guid.Data4[1] = 0x70;
	guid.Data4[2] = 0xAD;
	guid.Data4[3] = 0xA3;
	guid.Data4[4] = 0xDA;
	guid.Data4[5] = 0x14;
	guid.Data4[6] = 0x93;
	guid.Data4[7] = 0x71;

    ShowDemoTitle();

    epsRet = epas_CreateContext(
        &handle,
        0,
        EPAS_API_VERSION
        );

    if(CheckOP(epsRet, "Create context handle"))
    {
        //char szTokenName[64];
        //unsigned long pulSN[2];

		// Select a device to open.
        SelectDevice(handle);

        // Show the information of device opened currently.
        epsRet = ShowDeviceInfo(handle);
        CheckOP(epsRet, "Show device information");

		// Create a directory by EPAS_DIR_BY_GUID
		epsRet = CreateDirByGUID( handle );
		CheckOP(epsRet, "Create directory by GUID");

		// Close the device special by handle.
		epsRet = epas_CloseDevice(handle);
        CheckOP(epsRet, "Close device");

		// Open device special by GUID_STR.
		epsRet = OpenDeviceByGUID_STR(handle);
        CheckOP(epsRet, "Open device by GUID_STR");

		epsRet = DeleteDirByGUID(handle);
        CheckOP(epsRet, "Delete directory by GUID");

        // Close the device special by handle.
        epsRet = epas_CloseDevice(handle);
        CheckOP(epsRet, "Close device");

        // Free the context handle and do NOT use it any more.
        epsRet = epas_DeleteContext(handle);
        CheckOP(epsRet,"Delete context handle");
    }

    return (0);
} // End of main().

void
__cdecl
BlinkDeviceLED(EPAS_HANDLE handle)
{
	unsigned long ulLedState = EPAS_PROP_LED_ON;
	EPAS_STATUS   epsRet     = FT_SUCCESS;

	while( FT_SUCCESS == epsRet && !bDeviceSelected )
	{
		epsRet = epas_SetProperty( handle,          // handle to the current device
								   ulLedState,      // flags, the LED state to set
								   NULL,            // Reference data, not used.
								   NULL,            // Property data, not used
								   0                // Property data size, not used.
								 );
		if ( FT_SUCCESS == epsRet && !bDeviceSelected )
		{
			// Toggle the LED state
			if ( ulLedState == EPAS_PROP_LED_ON )
			{
				ulLedState = EPAS_PROP_LED_OFF;
				Sleep( 100 );
			}
			else
			{
				ulLedState = EPAS_PROP_LED_ON;
				Sleep( 500 );
			}
		}
	} 
	// Turn the LED on for the current device
	epas_SetProperty( handle,
				      EPAS_PROP_LED_ON,
					  NULL,
					  NULL,
					  0 
					  );
	_endthread();
} // End of BlinkDeviceLED().

bool
SelectDevice(EPAS_HANDLE handle)
{
	EPAS_STATUS   status;
	unsigned long threadHandle;
	int			  ch;

	// Set the device selected flag
	bDeviceSelected = 0;

	// Open the first device.
	status = epas_OpenDevice( handle,			// handle to the device
							  EPAS_OPEN_FIRST,	// flags, open first device
							  NULL				// flag data, not used.
							);

	if ( FT_SUCCESS == status )
	{
		// Blinking the device's LED to indicate this is the current device selected.
		threadHandle = _beginthread( BlinkDeviceLED, 4096, handle );

        printf( "\nTo select device which LED is blinking, press the ENTER key.\n" );
        printf( "Or any other key to try the next device.\n\n" );

        // Wait until a device has been selected.
		while ( !bDeviceSelected && FT_SUCCESS == status )
		{

			ch = _getch();
			
			if ( ch == '\r' ) // User has selected the current device.
			{
				// Set the global flag to terminate the thread.
				bDeviceSelected = true;
				// Wait for the thread to terminate.
				WaitForSingleObject( (HANDLE)threadHandle, -1 );
			}
			else // user wants to try the next device
			{
				// Set the global flag to terminate the thread.
				bDeviceSelected = true;
				// Wait for the thread to terminate
				WaitForSingleObject( (HANDLE)threadHandle, -1 );
				// Reset the flag
				bDeviceSelected = false;
				// Open the next device
				status = epas_OpenDevice( handle,			// handle to the device
										  EPAS_OPEN_NEXT,	// flags, open next device
										  NULL				// flag data, not used
										);

				if ( FT_SUCCESS == status )
				{
					// Start the thread again to blink the current device's LED
					threadHandle = _beginthread( BlinkDeviceLED, 4096, handle );
				}
                else
                {
					// If there are no "next device" any more, blink LED of first device again.
    				status = epas_OpenDevice( handle,			// handle to the device
	    									  EPAS_OPEN_FIRST,	// flags, open next device
		    								  NULL				// flag data, not used
			    							);
                    if ( FT_SUCCESS == status )
                    {
                        // Start the thread again to blink the current device's LED
                        threadHandle = _beginthread( BlinkDeviceLED, 4096, handle );
                    }
                }
			}
		}
	}
	return( bDeviceSelected );
} // End of SelectDevice().

EPAS_STATUS
CreateDirByGUID(EPAS_HANDLE handle)
{
	EPAS_STATUS epsRet;
	EPAS_DIRINFO di;

	epsRet = epas_CreateDir(handle,
							EPAS_CREATE_AUTO_ID | EPAS_DIR_BY_GUID,
							//APP_NAME
							0,
							(unsigned char*)&guid,
							&di,
							sizeof(EPAS_DIRINFO)
						   );
	return epsRet;
} // End of CreateDirByGUID().

EPAS_STATUS
DeleteDirByGUID(EPAS_HANDLE handle)
{
	EPAS_STATUS epsRet;

	epsRet = epas_DeleteDir(handle,
							EPAS_DELETE_RECURSIVE | EPAS_DIR_BY_GUID,
							0,
							(unsigned char*)&guid
						   );
	return epsRet;
} // End of DeleteDirByGUID().

EPAS_STATUS
OpenDeviceByGUID_STR(EPAS_HANDLE handle)
{
	// Search all device attached.
	EPAS_STATUS epsRet;

	// Try to open the first device by GUID_STR.
	epsRet = epas_OpenDevice(
		handle,
		EPAS_OPEN_FIRST | EPAS_OPEN_BY_GUID_STR,
		APP_GUID_STR
		);

	// If first device not conte.
	// Or the first device is in use, try next one.
	if (FT_ITEM_NOT_FOUND == epsRet ||
		FT_DEVICE_IN_USE  == epsRet)
	{
		while (1)
		{
			epsRet = epas_OpenDevice(
				handle,
				EPAS_OPEN_NEXT | EPAS_OPEN_BY_GUID_STR,
				APP_GUID_STR
				);

			if (FT_ITEM_NOT_FOUND == epsRet ||
				FT_DEVICE_IN_USE  == epsRet)
			{
				continue;
			}

			break;
		}
	}
	return epsRet;
} // End of OpenDeviceByGUID_STR().
