diff options
Diffstat (limited to 'tools/mustek600iin-off.c')
-rw-r--r-- | tools/mustek600iin-off.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/tools/mustek600iin-off.c b/tools/mustek600iin-off.c new file mode 100644 index 0000000..d2c6754 --- /dev/null +++ b/tools/mustek600iin-off.c @@ -0,0 +1,199 @@ +/* + off.c - Switch the Mustek 600 II N off + + This utility accesses the I/O-ports directly and must therefore be + run with euid root, or must at least have access to /dev/port. + Compile with: + gcc -DHAVE_SYS_IO_H -O2 -Wall -s -o off off.c + The -O2 optimization is needed to allow inline functions ! + Copyright (C) 1997-1999 Andreas Czechanowski, DL4SDC + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + andreas.czechanowski@ins.uni-stuttgart.de + */ + +#include "../include/sane/config.h" +#include "../include/sane/sanei.h" + +#define MUSTEK_CONF STRINGIFY(PATH_SANE_CONFIG_DIR) "/mustek.conf" +#define PORT_DEV "/dev/port" + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef HAVE_SYS_IO_H +# include <sys/io.h> /* use where available (glibc 2.x, for example) */ +#elif HAVE_ASM_IO_H +# include <asm/io.h> /* ugly, but backwards compatible */ +#elif defined(__i386__) && defined (__GNUC__) + +static __inline__ void +outb (u_char value, u_long port) +{ + __asm__ __volatile__ ("outb %0,%1"::"a" (value), "d" ((u_short) port)); +} + +static __inline__ u_char +inb (u_long port) +{ + u_char value; + + __asm__ __volatile__ ("inb %1,%0":"=a" (value):"d" ((u_short) port)); + return value; +} +#endif + +char *Mustek_Conf = MUSTEK_CONF; + +int allowed_ports[] = +{ + 0x26b, 0x26c, + 0x2ab, 0x2ac, + 0x2eb, 0x2ec, + 0x22b, 0x22c, + 0x32b, 0x32c, + 0x36b, 0x36c, + 0x3ab, 0x3ac, + 0x3eb, 0x3ec, + -1 +}; + +void +usage (void) +{ + fprintf (stderr, "Usage: off [port]\n" + " switches the Mustek 600 II N off that is connected to\n" + " base address <port>. If address is not given, reads it\n" + " from SANE config file <%s>.\n", Mustek_Conf); +} + +void +noaccess (int portaddr) +{ + fprintf (stderr, "Access to port 0x%03x not allowed !\n", portaddr); +} + +int +check_port (int portaddr) +{ + int i, j; + + for (i = 0; (j = allowed_ports[i]) != -1; i++) + { + if (j == portaddr) + return j; + } + return -1; +} + +int +str2int (char *ch) +{ + int i; + + i = strtol (ch, NULL, 0); + return i; +} + +int +main (int argc, char **argv) +{ + char *cp; + int portaddr = 0; + FILE *fp; + int pfd; + + /* get config file name from environment if variable is set */ + if (NULL != (cp = getenv ("MUSTEK_CONF"))) + { + Mustek_Conf = cp; + } + + /* if port is explicitly given, try this one */ + if (argc > 1) + { + portaddr = str2int (argv[1]); + } + /* else try to look it up from SANE's mustek.conf file */ + else if (NULL != (fp = fopen (MUSTEK_CONF, "r"))) + { + char line[256]; + + while (NULL != fgets (line, 255, fp)) + { + if ('#' == *line) + continue; + if (0 != (portaddr = str2int (line))) + break; + } + fclose (fp); + } + else + { + fprintf (stderr, "Mustek config file <%s> not found\n", Mustek_Conf); + usage (); + exit (1); + } + + if (check_port (portaddr) < 0 || check_port (portaddr + 1) < 0) + { + fprintf (stderr, "invalid port address specified !\n"); + usage (); + exit (1); + } + + /* we need the control port, not the data port, so... */ + portaddr++; + + fprintf (stderr, "using control port address 0x%03x\n", portaddr); + /* try to get I/O permission from the kernel */ + if (ioperm (portaddr, 1, 1) == 0) + { + outb (0x00, portaddr); + } + /* else try to open /dev/port to access the I/O port */ + else if ((pfd = open (PORT_DEV, O_RDWR, 0666)) >= 0) + { + char offcmd[] = + {0x00}; + + if ((lseek (pfd, portaddr, SEEK_SET) != portaddr) + || (write (pfd, offcmd, 1) != 1)) + { + perror ("error handling /dev/port"); + exit (1); + } + close (pfd); + } + else + { + fprintf (stderr, "Could not get port access:\n" + "Neither via ioperm(), nor via /dev/port.\n" + "This program must be run setuid root,\n" + "or the user must have access to /dev/port.\n"); + exit (1); + } + printf ("successfully sent OFF-command to control port at 0x%03x.\n", + portaddr); + + exit (0); +} |