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

//
// McxLapbDisconnect terminates the link level.
//
// Arguments:
//	file	Handle of the serial port, returned by CreateFile.
//	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 stopped.
//
BOOLEAN
McxLapbDisconnect(HANDLE file, 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;
	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] = ABMLINKDN;
	pcommand->Cb.par[8-1] = 0;
	pcommand->Cb.length = 0;	// no data area
	if(!AcksysCmdAuto(file, pcommand)) {
		free(pcommand);
		return FALSE;
	}
	free(pcommand);
	if(wait) {
		DWORD events;

		if(!SetCommMask(file, EV_MCXLAPB)) {
			MessageBox(NULL,
				"LapbDisconnect/SetCommMask",
				"Unexpected error",
				MB_OK+MB_ICONSTOP);
			exit(1);
		}
		if(McxLapbState(file) != MCX_LINK_OFF) {
			do {
				if(McxLapbWait(file) == -1) {
					MessageBox(NULL,
						"LapbDisconnect/WaitCommEvent",
						"Unexpected error",
						MB_OK+MB_ICONSTOP);
					exit(1);
				}
				lapbState = McxLapbState(file);
				if(lapbState == 0) {
					MessageBox(NULL,
						"LapbDisconnect/LapbState",
						"Unexpected error: NULL state",
						MB_OK+MB_ICONSTOP);
					exit(1);
				}
			}while(lapbState & MCX_ISLNKTRANS);

			if(lapbState == MCX_LINK_ON) {
				SetLastError(ERROR_NOT_READY);
				return FALSE;
			}
		}
	}
	McxFreeAsyncLapbWaitComm();
	return TRUE;
}
