//
// Demonstration de l'execution des commandes specifiques aux
// cartes MCC/MCX sous Win32 : Creation d'une nouvelle commande par ADDCM,
// insertion de fonctions d'emission reception par ADDTX et ADDRX.
//
// (c)Acksys, 1997 -- JPT
//
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <windows.h>
#include <winioctl.h>
#include <mcc_mcx.h>

int SilentFlag = 0;
int Function = 0;

void
main(int argc, char **argv)
{
	HANDLE hDevice;
	char **params;

	params = argv+1;	// exclure nom du programme
	argc--;			// nb de parametres
	while(argc > 0 && (params[0][0] == '-' || params[0][0] == '/')){
		switch(params[0][1]){
		case 's': case 'S':
			SilentFlag = 1;
			break;
		case 'c': case 'C':
			Function = ADDCM;
			break;
		case 'r': case 'R':
			Function = ADDRX;
			break;
		case 't': case 'T':
			Function = ADDTX;
			break;
		}
		if(params[0][2] == '\0'){
			params++;
			argc--;
		}else
			params[0] += 2;
	}

	if(argc != 2 || Function == 0){
		if(!SilentFlag){
		    printf("usage: %s [/s] [/c,r,t] serialport commandfile\n",
		    	argv[0]);
		    printf("/s (silent) only displays opcode and errcode\n");
		    printf("/c ADDCM\n");
		    printf("/r ADDRX\n");
		    printf("/t ADDTX\n");
		}
		exit(1);
	}
	hDevice = CreateFile(params[0],GENERIC_WRITE|GENERIC_READ,
				0,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL);
	if(hDevice == INVALID_HANDLE_VALUE){
		if(!SilentFlag)
			printf("CreateFile: error %d\n", GetLastError());
		exit(1);
	}
	AddCommand(hDevice,params[1]);
	CloseHandle(hDevice);
}

AddCommand(HANDLE hDevice, char *nom)
{
	PMCC_CMD Addcm;		/* ADDCM and its params will be stored here */
	DWORD retLen;		/* longueur renvoyee dans tous les appels */
	int cmdLen;		/* longueur de la structure de commande */
	struct stat stats;
	int fileLen;

	if(stat(nom,&stats) == -1){
		if(!SilentFlag)
			perror(nom);
		exit(1);
	}
	fileLen = stats.st_size;

	cmdLen = MCX_DIRECT_IO_BUFFER_SIZE(fileLen);
	Addcm = malloc(cmdLen);
	// init opcode et parametres
	Addcm->Cb.opcode = Function;
	Addcm->Cb.par[1-1] = (unchar)fileLen;
	Addcm->Cb.par[2-1] = (unchar)(fileLen>>8);
	// init des donnees
	Addcm->Cb.length = fileLen;
	ReadNewCommandFromDisk(nom,Addcm->Data,fileLen);

	if(!DeviceIoControl(hDevice,IOCTL_SERIAL_CMD,
			Addcm, cmdLen, 
			Addcm, cmdLen, &retLen,
			NULL )){
		if(!SilentFlag)
			printf("ADDCM: Win32 error %d\n", GetLastError());
		exit(1);
	}
	if(Addcm->Cb.status != 0){
		if(!SilentFlag)
			printf("ADDCM: failed, status %d\n",Addcm->Cb.status);
		exit(1);
	}
	if(Function == ADDCM){
		if(!SilentFlag)
			printf("ADDCM: opcode %d, errcode %d\n",
					Addcm->Cb.par[0],Addcm->Cb.par[1]);
		else
			printf("%d %d\n",Addcm->Cb.par[0],Addcm->Cb.par[1]);
	}else{
		if(!SilentFlag)
			printf("Done.");
	}
	exit(0);
}

ReadNewCommandFromDisk(char *nom, char *buf, int fileLen)
{
	int fd;
	PMCC_CMD Addcm;

	if((fd = open(nom,O_RDONLY|O_BINARY)) == -1){
		if(!SilentFlag)
			perror(nom);
		exit(1);
	}
	if(read(fd,buf,fileLen) != fileLen){
		if(!SilentFlag)
			perror(nom);
		exit(1);
	}
	close(fd);
}
