Hamlib/rotators/ts7400/include/peekpoke.c

165 wiersze
3.1 KiB
C

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
unsigned int parseBinary(char *str)
{
unsigned int val = 0;
if (*str == 'b')
{
str++;
while (*str)
{
if (*str == '0')
{
val <<= 1;
}
else if (*str == '1')
{
val = (val << 1) + 1;
}
else
{
goto binaryError;
}
}
}
return val;
binaryError:
fprintf(stderr, "Unrecognized numeric value: %s\n", str);
exit(0);
}
unsigned int parseNumber(char *str)
{
unsigned int addr = 0;
if (!sscanf(str, "0x%x", &addr))
{
if (!sscanf(str, "%u", &addr))
{
addr = parseBinary(str);
}
}
return addr;
}
/*
Features that the old peekXX/pokeXX did not have:
1. Support for 8/16/32 bit READ/WRITE in one function
2. Support for decimal and binary values
3. The value return is returned (to become the status code)
*/
int main(int argc, char **argv)
{
off_t addr, page;
int fd, bits, dowrite = 0, doread = 1;
unsigned char *start;
unsigned short *shortdat, shortval;
unsigned int *intdat, intval;
if (argc < 3 || argc > 5)
{
fprintf(stderr, "Usage: peekpoke BIT_WIDTH ADDRESS <VALUE <x>>\n");
fprintf(stderr, "<x> can be anything; suppresses read-back on write\n");
return 0;
}
sscanf(argv[1], "%d", &bits);
if (bits != 8 && bits != 16 && bits != 32)
{
fprintf(stderr, "Error: BIT_WIDTH must be 8, 16, or 32\n");
return 0;
}
addr = parseNumber(argv[2]);
if (argc > 3) // peekpoke BITS ADDRESS VALUE x
{
intval = parseNumber(argv[3]);
if (argc > 4) { doread = 0; }
dowrite = 1;
}
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1)
{
perror("open(/dev/mem):");
return 0;
}
page = addr & 0xfffff000;
start = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, page);
if (start == MAP_FAILED)
{
perror("mmap:");
close(fd);
return 0;
}
if (bits == 8)
{
unsigned char *chardat, charval;
charval = (unsigned char)intval;
chardat = start + (addr & 0xfff);
if (dowrite)
{
*chardat = charval;
}
if (doread)
{
intval = (unsigned int) * chardat;
}
}
else if (bits == 16)
{
shortval = (unsigned short)intval;
shortdat = (unsigned short *)(start + (addr & 0xfff));
if (dowrite)
{
*shortdat = shortval;
}
if (doread)
{
intval = (unsigned int) * shortdat;
}
}
else // bits == 32
{
intdat = (unsigned int *)(start + (addr & 0xfff));
if (dowrite)
{
*intdat = intval;
}
if (doread)
{
intval = *intdat;
}
}
if (doread)
{
printf("0x%X\n", intval);
}
close(fd);
return intval;
}