///////////////////////////////////////////////////
// Dio.c
// 720020-11891
//
// Applied Data Systems
//
// See Dio.h for a description and history
//
///////////////////////////////////////////////////

#include "windows.h"
#include "DIOapp.h"
#include "DIO.h"

// GetMask(HANDLE hDioPort, DWORD *pdwMask)
// Retrieves the current DIO driver mask.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// pdwMask - Pointer to the DWORD where the driver mask will be stored.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL GetMask(HANDLE hDioPort, DWORD *pdwMask)
{
	BOOL bRet = TRUE;
	DWORD dwNumberOfBytesRead;

	if(!DeviceIoControl(	hDioPort, 
							DIO_IOCTL_GET_DRIVER_MASK, 
							NULL, 
							0, 
							pdwMask, 
							sizeof(*pdwMask),
							&dwNumberOfBytesRead, 
							NULL ))
	{
		RETAILMSG(	TRUE, (_T("DeviceIoControl : GetLastError() returned 0x%x"), 
					GetLastError()));
		bRet = FALSE;
	}
	return bRet;
}	

// SetMask(HANDLE hDioPort, DWORD dwMask)
// Sets the DIO driver mask.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// dwMask - DWORD containing the driver mask to be set.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL SetMask(HANDLE hDioPort, DWORD dwMask)
{
	BOOL bRet = TRUE;
	DWORD dwNumberOfBytesWritten;

	if(!DeviceIoControl(	hDioPort, 
							DIO_IOCTL_SET_DRIVER_MASK, 
							&dwMask, 
							sizeof(DWORD), 
							NULL, 
							0,
							&dwNumberOfBytesWritten, 
							NULL ))
	{
		RETAILMSG(	TRUE, (_T("DeviceIoControl : GetLastError() returned 0x%x"), 
					GetLastError()));
		bRet = FALSE;
	}
	return bRet;
}

// SetDirection(HANDLE hDioPort, DWORD dwDir)
// Sets the direction of the DIO lines.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// dwDir - DWORD containing the DIO direction to set.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL SetDirection(HANDLE hDioPort, DWORD dwDir)
{
	BOOL bRet = TRUE;
	DWORD dwNumberOfBytesWritten;

	if(!DeviceIoControl(	hDioPort, 
							DIO_IOCTL_SET_DIRECTION, 
							&dwDir, 
							sizeof(DWORD), 
							NULL, 
							0,
							&dwNumberOfBytesWritten, 
							NULL ))
	{
		RETAILMSG(	TRUE, (_T("DeviceIoControl : GetLastError() returned 0x%x"), 
					GetLastError()));
		bRet = FALSE;
	}
	return bRet;
}

// GetDirection(HANDLE hDioPort, DWORD *pdwDir)
// Retrieves the current direction of the DIO lines.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// pdwDir - Pointer to the DWORD where the DIO direction will be stored.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL GetDirection(HANDLE hDioPort, DWORD *pdwDir)
{
	BOOL bRet = TRUE;
	DWORD dwNumberOfBytesRead;

	if(!DeviceIoControl(	hDioPort, 
							DIO_IOCTL_GET_DIRECTION, 
							NULL, 
							0, 
							pdwDir, 
							sizeof(DWORD),
							&dwNumberOfBytesRead, 
							NULL ))
	{
		RETAILMSG(	TRUE, (_T("DeviceIoControl : GetLastError() returned 0x%x"), 
					GetLastError()));
		bRet = FALSE;
	}
	return bRet;
}	

// ReadDio(HANDLE hDioPort, DWORD *pdwDio)
// Retrieves the level state of the DIO lines.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// pdwDio - Pointer to the DWORD where the DIO level state will be stored.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL ReadDio(HANDLE hDioPort, DWORD *pdwDio)
{
	BOOL bRet = TRUE;
	DWORD dwBytesRead;

	if(!ReadFile(hDioPort, pdwDio, sizeof(DWORD), &dwBytesRead, NULL))
	{
		RETAILMSG(TRUE, (_T("ReadFile : GetLastError() returned 0x%x"), GetLastError()));
		bRet = FALSE;
	}

	return bRet;
}

// WriteDio(HANDLE hDioPort, DWORD dwDio)
// Writes the level state of the DIO lines.  Prints an error message on
// the debug port if an error occurs.
//
// hDioPort - Handle to the DIO port
// dwDio - DWORD containing the DIO level state to set.
// 
// returns: TRUE if successful, FALSE if an error occured.
BOOL WriteDio(HANDLE hDioPort, DWORD dwDio)
{
	BOOL bRet = TRUE;
	DWORD dwBytesWritten;

	if(!WriteFile(hDioPort, &dwDio, sizeof(DWORD), &dwBytesWritten, NULL))
	{
		RETAILMSG(TRUE, (_T("WriteFile : GetLastError() returned 0x%x"), GetLastError()));
		bRet = FALSE;
	}

	return bRet;
}

// GetUserDword(const char *szStr)
// Prompts user to enter a DWORD in hexadecimal format.  Reads input
// as a string and parses it for a valid hexadecimal number.  User is
// prompted to re-enter until a valid number is obtained.
//
// szStr - Pointer to the constant prompt string to be used.
// 
// returns: DWORD containing the number entered by the user.
DWORD GetUserDword(const char *szStr)
{
	char szBuf[20];
	BOOL bValid = FALSE;
	DWORD dwDio;

	do {
		printf(szStr);
		scanf("%s", szBuf);
		if (!sscanf(szBuf, "%x", &dwDio))
			printf("Invalid input, please re-enter: ");
		else bValid = TRUE;
	} while (!bValid);
	
	return dwDio;
}