#include <windows.h>
#include <winioctl.h>
#include <mcxproto.h>

#include <stdio.h>
#define DBG_SYSCALL	if(0)fprintf

//
// McxLapbSetup tries to setup the link level.
//
// Arguments:
//	name		Name of the MCX serial port for the Operating System.
//	isHost		TRUE if we receive both clocks.
//	isNullModem	TRUE if we receive the RX clock and send the TX clock.
//	datalen		Maximum Information field length.
//	openFlags	Flags for CreateFile (FILE_FLAG_OVERLAPPED, etc.).
//
//	if isHost and isNullModem are both FALSE, we will send RX and TX clocks.
//	In this case, or if isNullModem is TRUE, the speed should be set just
//	after McxLapbSetup returns and before trying to connect, using
//	Get/SetCommState with the returned handle.
//
// Returns:
//	The handle of the serial port, available for ReadFile, etc.
//	INVALID_HANDLE_VALUE if any Win32 API fails (in this case,
//	GetLastError gives the cause of the failure).
//
HANDLE McxLapbSetup(char *name, BOOLEAN isHost, BOOLEAN isNullModem,
		unsigned long datalen, DWORD openFlags)
{
	HANDLE file;
	MCX_SYNCHRONIZATION_PARAMETERS sp;
	DWORD retCount;
	UCHAR lapbState;
	DWORD count = MCX_DIRECT_IO_BUFFER_SIZE(0);

	if((file=CreateFile(name,GENERIC_WRITE|GENERIC_READ,
				0,
				NULL,
				OPEN_EXISTING,
				openFlags,
				NULL)) == INVALID_HANDLE_VALUE){
		DBG_SYSCALL(stderr,"CreateFile");
		return INVALID_HANDLE_VALUE;
	}

	sp.SynchronousMode = MCX_SYNC_LAPB;
	sp.Duplex = MCX_WAY_FULLDUPLEX;
	if(isNullModem) {
		sp.TransmitClockSource = MCX_CLOCK_BRG;
		sp.ReceiveClockSource = MCX_CLOCK_RXC;
	} else if(isHost) {
		sp.TransmitClockSource = MCX_CLOCK_TXCI;
		sp.ReceiveClockSource = MCX_CLOCK_RXC;
	} else /*isNetwork*/ {
		sp.TransmitClockSource = MCX_CLOCK_BRG;
		sp.ReceiveClockSource = MCX_CLOCK_BRG;
	}
	sp.TxClockPinSource = MCX_CLOCK_BRG;
	sp.Version = 1;
	sp.Options = 0;
	sp.DataLength = datalen;
	sp.Protocol.Lapb.Role = isHost	? MCXLAPB_ROLE_CLIENT
					: MCXLAPB_ROLE_NETWORK;
	sp.Protocol.Lapb.K = MCX_LAPB_DEFAULT;
	sp.Protocol.Lapb.N2 = MCX_LAPB_DEFAULT;
	sp.Protocol.Lapb.T1 = MCX_LAPB_DEFAULT;
	sp.Protocol.Lapb.T2 = MCX_LAPB_DEFAULT;
	sp.Protocol.Lapb.T3 = MCX_LAPB_DEFAULT;
	sp.Protocol.Lapb.Spare = MCX_LAPB_DEFAULT;

	if(!AcksysIoControl(file, IOCTL_SERIAL_SET_SYNC_STATE,
			&sp, sizeof(sp), NULL, 0, &retCount) ) {
		CloseHandle(file);
		DBG_SYSCALL(stderr,"SET_SYNC_STATE");
		return INVALID_HANDLE_VALUE;
	}
	/* monter les signaux de controle */
	if( !EscapeCommFunction(file,SETDTR) ) {
		CloseHandle(file);
		DBG_SYSCALL(stderr,"SETDTR");
		return INVALID_HANDLE_VALUE;
	}
	if( !EscapeCommFunction(file,SETRTS) ) {
		DBG_SYSCALL(stderr,"SETRTS");
		CloseHandle(file);
		return INVALID_HANDLE_VALUE;
	}

	return file;
}
