kopia lustrzana https://gitlab.com/sane-project/backends
200 wiersze
4.5 KiB
C
200 wiersze
4.5 KiB
C
/*
|
|
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);
|
|
}
|