//
// Demonstration de l'utilisation des acces aux boites aux lettres
// des cartes MCC/MCX sous Win32, pour afficher leur contenu.
//
// (c)Acksys, 1997 -- JPT
//
#include <stdio.h>
#include <windows.h>
#include <winioctl.h>
#include <mcc_mcx.h>

#define DBGBUF	0x080
char buffer[DBGBUF];

print16bytes(unsigned char *p,int nb)
{
	int i;

	for(i=0;i<nb;i++){
		unsigned char c = *p++;
		if(c>' ' && c <0177)
			printf(" %c ",c);
		else
			printf("%02x ",c);
		if(i==7)printf("- ");
	}
	printf("\n");
}

long GetAddress(long old)
{
	char buf[10];
	long addr;
	char *endptr;

	printf("tapez l'adresse en notation langage C (%d/0x%x) ",old,old);
	fgets(buf,sizeof(buf),stdin);
	addr = strtol(buf,&endptr,0);
	if(endptr == buf)
		return old;
	return addr;
}

void Change(HANDLE hDevice, long start)
{
	DWORD retLen;		/* longueur renvoyee dans tous les appels */
	PMCX_AREA_DESCRIPTOR pAreaDesc;
	char buf[50];
	int i;
	long val;

	printf("tapez en hexa les valeurs a ecrire en %xH sinon [ENTREE]: ",
		start);
	i = 0;
	while(getchar() != '\n'){
		if(scanf("%x",&val) == 1)
			buffer[i++] = (char)val;
	}
	if(i == 0)
		return;

	pAreaDesc = malloc(MCX_AREA_DESCRIPTOR_SIZE(i));
	memcpy(pAreaDesc->Buffer,buffer,i);
	pAreaDesc->Operation = MCX_AREA_SET+MCX_AREA_MEMORY;
	pAreaDesc->StartAddress = start;
	pAreaDesc->Length = i;
	if(!DeviceIoControl(hDevice,IOCTL_SERIAL_ACCESS_AREA,
			pAreaDesc, MCX_AREA_DESCRIPTOR_SIZE(i), 
			NULL, 0, &retLen,
			NULL )){
		printf("AREA_SET: error %d\n", GetLastError());
	}
	Dump(hDevice, start, 128);
}

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

	hDevice = CreateFile(argv[1],GENERIC_WRITE|GENERIC_READ,
				0,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL);
	if(hDevice == INVALID_HANDLE_VALUE){
		printf("CreateFile: error %d\n", GetLastError());
		exit(1);
	}

	if(stricmp(argv[argc-1],"/p") == 0) {
		// Pause apres Open et avant affichage
		while(getchar() != '\n');
		argc--;
	}

	if(argc >= 3) {
		char *endptr;
		start = strtol(argv[2],&endptr,0);
		if(endptr == argv[2])
			start = 0;
	} else {
		start = GetAddress(0);
	}
	Dump(hDevice, start, 128);
	Change(hDevice, start);
	CloseHandle(hDevice);
}

Dump(HANDLE hDevice, long start, long len)
{
	DWORD retLen;		/* longueur renvoyee dans tous les appels */
	int nb;
	MCX_AREA_DESCRIPTOR areaDesc;

	printf("Dump du debut de la mailbox\n");
	start &= ~0xf;
	areaDesc.Operation = MCX_AREA_GET+MCX_AREA_MEMORY;
	areaDesc.StartAddress = start;
	areaDesc.Length = len;
	if(!DeviceIoControl(hDevice,IOCTL_SERIAL_ACCESS_AREA,
			&areaDesc, sizeof(areaDesc), 
			&buffer, len, &retLen,
			NULL )){
		printf("AREA_GET: error %d\n", GetLastError());
	}

	for(nb=0;nb*16<DBGBUF;nb++){
		printf("%04x ",start+nb*16);
		print16bytes(&buffer[nb*16],16);
	}
}
