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

#define DBG_WAIT	if(1)fprintf
//
// McxLapbStateToString returns a string describing the argument LAPB state
//
// Arguments:
//	state	LAPB state code
//
// Returns:
//	pointer to a string label for the state
//
char *
McxLapbStateToString(int state)
{
	static char *etats[] = {"UNKNOWN", "DISCONNECTED", "CONNECTED",
			"UNKNOWN(130)", "UNKNOWN(131)",
			"GOING UP", "UNKNOWN(133)", "GOING DOWN"};
	if(state < 127 || state > 134)
		state = 127;
	return etats[state-127];
}

//
// McxLapbState returns the current link state.
//
// Arguments:
//	file	Handle of the serial port, returned by CreateFile.
//
// Returns:
//	one of MCX_LINK_OFF, MCX_LINK_ON, MCX_LINK_GO_UP, MCX_LINK_GO_DN
//	or 0 if failure (in this case GetLastError() gives the cause).
//	MessageBox in case of an (unlikely) failure (subject to change).
//
McxLapbState(HANDLE file)
{
	PMCC_CMD pcommand;
	UCHAR state;
	DWORD retCount;
	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] = ABMSTATE;
	pcommand->Cb.length = 1;	// returned data
	if(AcksysCmdAuto(file, pcommand)) {
		state = (UCHAR)pcommand->Data[0];	// pas d'extension de signe
	} else {
		state = 0;
	}
	free(pcommand);
	return state;
}

static HANDLE
McxInitOverlap(OVERLAPPED *ovr)
{
	if(!ovr->hEvent) {
		ovr->hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
		if(ovr->hEvent == NULL)
			DBG_WAIT(stderr,"Event failed, code %d\n",
				GetLastError());
	}
	return ovr->hEvent;
}


static OVERLAPPED WaitCommOverlap;

HANDLE McxInitAsyncLapbWaitComm()
{
	return McxInitOverlap(&WaitCommOverlap);
}

void McxFreeAsyncLapbWaitComm()
{
	if(WaitCommOverlap.hEvent)
		CloseHandle(WaitCommOverlap.hEvent);
	WaitCommOverlap.hEvent = NULL;
}

DWORD McxLapbWait(HANDLE port)
{
	DWORD count;
	DWORD events;

	DBG_WAIT(stderr,"Wait...");
	if(!WaitCommEvent(port,&events,&WaitCommOverlap)) {
	    if(GetLastError() != ERROR_IO_PENDING) {
		// debloque par un SetCommMask ?
		if(GetCommMask(port,&count) && count == 0)
			return 0;
		fprintf(stderr,"WaitComm failed, code %d\n",GetLastError());
		return -1;
	    }
	    if(!GetOverlappedResult(port, &WaitCommOverlap, &count,TRUE)) {
		fprintf(stderr,"Wait-GetOver failed, code %d\n",
			GetLastError());
		return -1;
	    }
	    if(!ResetEvent(WaitCommOverlap.hEvent)) {
		fprintf(stderr,"Wait-Reset failed, code %d\n",
			GetLastError());
		return -1;
	    }
	}
	return events;
}
