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

//
// McxLapbConnect tries to setup the link level.
//
// Arguments:
//	file	Handle of the serial port, returned by CreateFile.
//	active	TRUE if we send SABM, FALSE if we just wait for a call.
//	wait	TRUE if we want to wait until the remote answers.
//		In this case all other events are disabled.
//
// Returns:
//	TRUE on success, FALSE on failure (in this case
//	GetLastError gives the cause of the failure).
//	FALSE + error ERROR_DEVICE_BUSY if wait=TRUE and the link can't be set.
//
// Side effect:
//	If TRUE is returned, McxInitAsyncLapbWaitComm() has been called.
//
BOOLEAN
McxLapbConnect(HANDLE file, BOOLEAN active, BOOLEAN wait)
{
	PMCC_CMD pcommand;
	DWORD retCount;
	UCHAR lapbState;
	DWORD count = MCX_DIRECT_IO_BUFFER_SIZE(1);

	pcommand = malloc(count);
	pcommand->Cb.opcode = PRCTL;
	pcommand->Cb.par[1-1] = 0;		// dummy channel
	pcommand->Cb.par[2-1] = 0;
	pcommand->Cb.par[3-1] = 0;
	pcommand->Cb.par[4-1] = 0;
	pcommand->Cb.par[5-1] = 0;
	pcommand->Cb.par[6-1] = 0;
	pcommand->Cb.par[7-1] = ABMLINKUP;
	pcommand->Cb.par[8-1] = 0;
	pcommand->Cb.par[9-1] = active ? MCX_LNKUP_ACTIVE : MCX_LNKUP_PASSIVE;
	pcommand->Cb.length = 0;	// no data area
	if(!AcksysCmdAuto(file, pcommand)) {
		free(pcommand);
		return FALSE;
	}
	McxInitAsyncLapbWaitComm();
	if(wait) {
		DWORD events;

		if(!SetCommMask(file, EV_MCXLAPB)) {
			MessageBox(NULL,
				"SetCommMask",
				"Unexpected error",
				MB_OK+MB_ICONSTOP);
			exit(1);
		}
		do {
			if(McxLapbWait(file) == (DWORD)-1) {
				MessageBox(NULL,
					"LapbWait",
					"Unexpected error",
					MB_OK+MB_ICONSTOP);
				exit(1);
			}
			pcommand->Cb.par[7-1] = ABMSTATE;
			pcommand->Cb.length = 1;	// returned data
			if(!AcksysCmdAuto(file, pcommand)) {
				McxFreeAsyncLapbWaitComm();
				free(pcommand);
				return FALSE;
			}
			lapbState = pcommand->Data[0];
		}while(lapbState & MCX_ISLNKTRANS);

		if(lapbState == MCX_LINK_OFF) {
			SetLastError(ERROR_NOT_READY);
			McxFreeAsyncLapbWaitComm();
			free(pcommand);
			return FALSE;
		}
	}
	free(pcommand);
	return TRUE;
}
