/*
* Simple general purpose I/O port control program for Linux
* Written and copyright by Tomi Engdahl 2005
* (e-mail: tomi.engdahl@hut.fi)
*
*
* Supported port identifiers
* LPT1DATA
* LPT1STATUS
* LPT1HANDSHAKE
* JOYSTICK
*
*
* Supported commands
*
* PRINT DEC Read data, gives output as decimal number
* PRINT HEX Read data, gives output as hexadecimal number
* PRINT BIN Read data, gives output as binary number
* PRINTBITS bits Reads the specified bits in the specified order (0..7)
*
* WRITE Writes register value to port
* READ Reads value from specified port to register
*
* SETVALUE value Sets the given value to register
* AND value Performs AND with given value and register
* OR value Performs OR with given value and register
* XOR value Performs XOR with given value and register
* SETBITS bits Sets given bits to 1 in register
* RESETBITS bits Sets given bits to 0 in register
* TOGGLEBITS bits Toggles specified bit values
*
* value can be gives as decimal number or heaxadecimal starting with 0x
* bits is a list of bit position identifiers from 0 to 7
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#define MAX_ARGUMENT_LEN 8
/*
* String compare routine, gives 1 when strings match, 0 otherwise
*/
int stringMatch(char * str1, char * str2)
{
if (strcmp(str1,str2) == 0)
{
return 1;
}
return 0;
}
/*
* Routine to convert port
*/
int PortIDtoAddress(char * portID)
{
if (stringMatch(portID, "LPT1DATA"))
{
return 0x0378;
}
if (stringMatch(portID, "LPT1STATUS"))
{
return (0x0379 + 1);
}
if (stringMatch(portID, "LPT1HANDSHAKE"))
{
return (0x0378 + 2);
}
if (stringMatch(portID, "JOYSTICK"))
{
return 0x0201;
}
fprintf(stderr, "Error: Invalid port name %s\n", portID), exit(1);
return 0;
}
int ReadPort(char * portID)
{
int iobase;
iobase = PortIDtoAddress(portID);
if (iobase==0) fprintf(stderr, "Error: Invalid port address %s\n", portID), exit(1);
if (ioperm(iobase,1,1))
{
fprintf(stderr, "Error: Couldn't get the port at %x\n", iobase), exit(1);
}
else
{
return inb(iobase);
}
return 0;
}
int WritePort(char * portID, int value)
{
int base;
base = PortIDtoAddress(portID);
if (base==0) fprintf(stderr, "Error: Invalid port address\n", base), exit(1);
if (ioperm(base,1,1))
{
fprintf(stderr, "Error: Couldn't get the port at %x\n", base), exit(1);
}
else
{
outb(value, base);
}
return 0;
}
void bin_prnt_byte(int x)
{
int n;
for(n=0; n<8; n++)
{
if((x & 0x80) !=0)
{
printf("1");
}
else
{
printf("0");
}
x = x<<1;
}
}
int printBits(int value,char *specifier)
{
int index=0;
int mask=0;
while ((index < MAX_ARGUMENT_LEN) && (specifier[index]!=0))
{
switch (specifier[index])
{
case '0':
if ((value & 1) != 0) printf("1"); else printf("0");
break;
case '1':
if ((value & 2) != 0) printf("1"); else printf("0");
break;
case '2':
if ((value & 4) != 0) printf("1"); else printf("0");
break;
case '3':
if ((value & 8) != 0) printf("1"); else printf("0");
break;
case '4':
if ((value & 16) != 0) printf("1"); else printf("0");
break;
case '5':
if ((value & 32) != 0) printf("1"); else printf("0");
break;
case '6':
if ((value & 64) != 0) printf("1"); else printf("0");
break;
case '7':
if ((value & 128) != 0) printf("1"); else printf("0");
break;
default:
fprintf(stderr, "Error: Wrong bit position specifier.\n"), exit(1);
break;
}
index++;
}
printf("\n");
return 0;
}
/*
* Converts bit string like 0123456789
*/
int bitsToMask(char * specifier)
{
int index=0;
int mask=0;
while ((index < MAX_ARGUMENT_LEN) && (specifier[index]!=0))
{
switch (specifier[index])
{
case '0':
mask = mask | 1;
break;
case '1':
mask = mask | 2;
break;
case '2':
mask = mask | 4;
break;
case '3':
mask = mask | 8;
break;
case '4':
mask = mask | 16;
break;
case '5':
mask = mask | 32;
break;
case '6':
mask = mask | 64;
break;
case '7':
mask = mask | 128;
break;
default:
fprintf(stderr, "Error: Wrong bit position specifier.\n"), exit(1);
break;
}
index++;
}
return mask;
}
int processCommand(char * command, char * argument, int * argcount, char * portId, int * portData)
{
int mask;
*argcount=1; // defualt takes on argument
if (stringMatch(command,"read"))
{
*argcount=0; // this command did no use any arguments
*portData=ReadPort(portId);
}
else if (stringMatch(command,"write"))
{
*argcount=0; // this command did no use any arguments
WritePort(portId, *portData);
}
else if (stringMatch(command,"print"))
{
if (stringMatch(argument,"dec"))
{
printf("%i\n",*portData);
}
else if (stringMatch(argument,"hex"))
{
printf("%x\n",*portData);
}
else if (stringMatch(argument,"bin"))
{
bin_prnt_byte(*portData);
printf("\n");
}
else
{
fprintf(stderr, "Error: Wrong PRINT argument.\n"), exit(1);
}
}
else if (stringMatch(command,"printbits"))
{
printBits(*portData,argument);
}
else if (stringMatch(command,"setvalue"))
{
*portData=atoi(argument);
}
else if (stringMatch(command,"and"))
{
mask=atoi(argument);
*portData = (*portData) & mask;
}
else if (stringMatch(command,"or"))
{
mask=atoi(argument);
*portData = (*portData) | mask;
}
else if (stringMatch(command,"xor"))
{
mask=atoi(argument);
*portData = (*portData) ^ mask;
}
else if (stringMatch(command,"setbits") || stringMatch(command,"setbit"))
{
mask=bitsToMask(argument);
*portData = (*portData) | mask;
}
else if (stringMatch(command,"resetbits") || stringMatch(command,"resetbit"))
{
mask=bitsToMask(argument) ^ 0xFF;
*portData = (*portData) & mask;
}
else if (stringMatch(command,"togglebits") || stringMatch(command,"togglebit"))
{
mask=bitsToMask(argument);
*portData = (*portData) ^ mask;
}
return 0;
}
int main(int argc, char **argv)
{
int value;
int argIndex;
int acount;
int portData;
char * portId;
if (argc<2)
fprintf(stderr, "Error: Wrong number of arguments.\n"), exit(1);
portId=argv[1];
portData=0;
argIndex=2; // start from first argument after port definition
while (argIndex < argc)
{
if ((argIndex+1) < argc)
{
processCommand(argv[argIndex],argv[argIndex+1],&acount,portId,&portData);
}
else
{
processCommand(argv[argIndex],argv[argIndex+1],&acount,portId,&portData);
}
argIndex=argIndex+acount+1;
}
return 0;
}