/*
	--- English/Anglais ---

	--- French/Francais ---
	Ce programme permet
	- d'afficher l'état courant d'un port LAPB ou compatible,
	- d'attendre un état précis provoqué par la carte ou le remote,
	- d'attendre N changements d'état
	- d'attendre indéfiniment tous les changements d'état.
	Dans tous les cas tous les changements d'état intermédiaires sont affichés.

	waitstat <port> 0			affiche l'état courant et sort
	waitstat <port> 5			affiche les 5 premiers changements et sort
	waitstat <port> connected	affiche les changements et sort quand connected
	waitstat <port>				affiche indéfiniment les changements

Historique
	1.0	version initiale
*/

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

#define ARG_PROG	argv[0]
#define ARG_PORT	argv[1]
#define ARG_EVENT	argv[2]

void
main(int argc,char **argv)
{
	HANDLE port;
	BOOLEAN wait, active;		// uniquement pour la clarte
	char ConsoleTitle[100];
	DWORD Events;
	DWORD ExpectedState;
	int evtcount, evtmax;
	int lastState = MCX_LINK_OFF;
	char comname[4+6+1];

	if(argc < 2 || strlen(ARG_PORT) > 6) {
usage:
		fprintf(stderr,"\n");
		fprintf(stderr,"Usage: %s comport [eventcount|state]\n", ARG_PROG);
		fprintf(stderr,"\n");
		fprintf(stderr,"\tcomport, i.e. COM10\n");
		fprintf(stderr,"\tstate: exit on state (DISCONNECTED, CONNECTED, "
						"GOINGUP, GOINGDOWN\n");
		fprintf(stderr,"\teventcount: exit on so many events\n");
		exit(1);
	}
	if(argc > 2) {
		if(ARG_EVENT[0] < '0' || ARG_EVENT[0] > '9') {
			if(stricmp(ARG_EVENT,"DISCONNECTED") == 0) ExpectedState = 128;
			else if(stricmp(ARG_EVENT,"CONNECTED") == 0) ExpectedState = 129;
			else if(stricmp(ARG_EVENT,"GOINGUP") == 0) ExpectedState = 132;
			else if(stricmp(ARG_EVENT,"GOINGDOWN") == 0) ExpectedState = 134;
			else goto usage;
			printf("Waiting for %s state\n",
				McxLapbStateToString(ExpectedState));
			evtcount = -1;
		} else {
			ExpectedState = 0;
			evtcount = atoi(ARG_EVENT);
		}
	} else {
		evtcount = -1;
	}
	printf("%s v1.0. Hit CTRL-C to stop\n", ARG_PROG);
	sprintf(comname,"\\\\.\\%s",ARG_PORT);

	sprintf(ConsoleTitle,"%s using %s for %s events",
		ARG_PROG, ARG_PORT, ARG_EVENT);
	if(!SetConsoleTitle(ConsoleTitle)) {
		printf("SetConsoletitle: error %d\n", GetLastError());
	}

	port = CreateFile(comname,GENERIC_WRITE|GENERIC_READ, 0,
				NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if(port == INVALID_HANDLE_VALUE){
		printf("CreateFile(%s): error %d\n", comname, GetLastError());
		exit(1);
	}

	McxInitAsyncLapbWaitComm();
	SetCommMask(port,EV_MCXLAPB);
	lastState = McxLapbState(port);
	printf("Initial state: %s\n", McxLapbStateToString(lastState));
	for(;evtcount;){
		int state;

		if(ExpectedState && ExpectedState == lastState) break;

		switch(Events = McxLapbWait(port)) {
		case 0: fprintf(stderr,"LapbWait:no event!\n"); break;
		case -1: fprintf(stderr,"LapbWait error!\n"); goto sortie;
		}

		state = McxLapbState(port);
		if(lastState != state){
			printf("State change: %s -> %s\n",
				McxLapbStateToString(lastState),
				McxLapbStateToString(state));
			lastState = state;
		}
		if(evtcount != -1) evtcount--;
	}
sortie:
	McxFreeAsyncLapbWaitComm();
	if(!CloseHandle(port)){
		printf("CloseHandle: error %d\n", GetLastError());
	}
}
