/*
 * ACKCHOPT.C: Set/get channel options
 */
#include <windows.h>
#include <winioctl.h>
#include <mcc_mcx.h>
#include "ack_w32.h"

/*
 * AcksysChannelOptionOne() executes IOCTL_SERIAL_MCX_OPTIONS for options
 * that require at most one input parameter and one output result.
 *
 * 'value' is the input parameter; the prototype casts it into a DWORD,
 * its size is known using the option code.
 *
 * The output parameter is cast into a DWORD by the return type. Unused bits
 * are set to zero. The user can then recast it into a smaller type if needed.
 *
 * Check errors via GetLastError(), which returns NO_ERROR on success.
 */
DWORD
AcksysChannelOptionOne(HANDLE hfd, DWORD optionCode, DWORD value)
{
	MCX_OPTION option;
	DWORD count;

	/* set struct elements */
	option.Option = optionCode;
	count = (optionCode>>8) & 0xff;
	if(count == sizeof(unsigned char))
		option.Value.Char[0] = (unsigned char)value;
	else if(count == sizeof(short))
		option.Value.Short[0] = (short)value;
	else
		option.Value.Long[0] = (long)value;

	/* call the driver */
	if(!AcksysIoControl(hfd,IOCTL_SERIAL_MCX_OPTIONS,
			&option,sizeof(option),
			&option,sizeof(option),&count)) {
		count = GetLastError();
		printf("MCX_OPTIONS Ioctl: error %d\n",count);
		SetLastError(count);
		return FALSE;
	}

	/* set return values */
	SetLastError(NO_ERROR);
	count = optionCode & 0xff;
	if(count == sizeof(unsigned char))
		return (long)option.Value.Char[0];
	else if(count == sizeof(short))
		return (long)(unsigned short)option.Value.Short[0];
	else
		return option.Value.Long[0];
}
