|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* libieee1284 - IEEE 1284 library
|
|
Packit |
d36e9b |
* Copyright (C) 2001, 2002 Tim Waugh <twaugh@redhat.com>
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
d36e9b |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
d36e9b |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
d36e9b |
* (at your option) any later version.
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
d36e9b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
d36e9b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
d36e9b |
* GNU General Public License for more details.
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* You should have received a copy of the GNU General Public License
|
|
Packit |
d36e9b |
* along with this program; if not, write to the Free Software
|
|
Packit |
d36e9b |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
d36e9b |
*/
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include "config.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include <fcntl.h>
|
|
Packit |
d36e9b |
#include <stdio.h>
|
|
Packit |
d36e9b |
#include <string.h>
|
|
Packit |
d36e9b |
#if !(defined __MINGW32__ || defined _MSC_VER)
|
|
Packit |
d36e9b |
#include <sys/ioctl.h>
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
#include <io.h> /* open(), close() */
|
|
Packit |
d36e9b |
#define O_NOCTTY 0
|
|
Packit |
d36e9b |
#define S_ISDIR(mode) ((mode) & _S_IFDIR ? 1 : 0)
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#include <sys/stat.h>
|
|
Packit |
d36e9b |
#include <sys/types.h>
|
|
Packit |
d36e9b |
#ifdef __unix__
|
|
Packit |
d36e9b |
#include <unistd.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include "debug.h"
|
|
Packit |
d36e9b |
#include "detect.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#ifdef HAVE_LINUX
|
|
Packit |
d36e9b |
#ifdef HAVE_SYS_IO_H
|
|
Packit |
d36e9b |
#include <sys/io.h>
|
|
Packit |
d36e9b |
#endif /* HAVE_SYS_IO_H */
|
|
Packit |
d36e9b |
#include "ppdev.h"
|
|
Packit |
d36e9b |
#elif defined(HAVE_OBSD_I386)
|
|
Packit |
d36e9b |
/* for i386_get_ioperm and i386_set_ioperm */
|
|
Packit |
d36e9b |
#include <machine/sysarch.h>
|
|
Packit |
d36e9b |
#elif defined(HAVE_SOLARIS)
|
|
Packit |
d36e9b |
#include <sys/ddi.h>
|
|
Packit |
d36e9b |
#include <sys/sunddi.h>
|
|
Packit |
d36e9b |
#elif defined(HAVE_CYGWIN_NT)
|
|
Packit |
d36e9b |
#ifdef __CYGWIN__
|
|
Packit |
d36e9b |
#include <w32api/windows.h>
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
#include <windows.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int capabilities;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Look for parport entries in /proc.
|
|
Packit |
d36e9b |
* Linux 2.2.x has /proc/parport/.
|
|
Packit |
d36e9b |
* Linux 2.4.x has /proc/sys/dev/parport/. */
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
check_proc_type (void)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
int which = 0;
|
|
Packit |
d36e9b |
struct stat st;
|
|
Packit |
d36e9b |
if (stat ("/proc/sys/dev/parport", &st) == 0 &&
|
|
Packit |
d36e9b |
S_ISDIR (st.st_mode))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
which = PROC_SYS_DEV_PARPORT_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("This system has /proc/sys/dev/parport\n");
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
else if (stat ("/proc/parport", &st) == 0 &&
|
|
Packit |
d36e9b |
S_ISDIR (st.st_mode) &&
|
|
Packit |
d36e9b |
st.st_nlink > 2)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
which = PROC_PARPORT_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("This system has /proc/parport\n");
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
capabilities |= which;
|
|
Packit |
d36e9b |
return which;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Try to find a device node that works. */
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
check_dev_node (const char *type)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
char name[50]; /* only callers are in detect_environment */
|
|
Packit |
d36e9b |
int fd;
|
|
Packit |
d36e9b |
int i;
|
|
Packit |
d36e9b |
#ifdef HAVE_LINUX
|
|
Packit |
d36e9b |
int is_parport;
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (i = 0; i < 8; i++) {
|
|
Packit |
d36e9b |
sprintf (name, "/dev/%s%d", type, i);
|
|
Packit |
d36e9b |
fd = open (name, O_RDONLY | O_NOCTTY);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#ifdef HAVE_LINUX
|
|
Packit |
d36e9b |
is_parport = !strncmp (type, "parport", 7);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if ((fd < 0) && is_parport) {
|
|
Packit |
d36e9b |
/* Try with udev/devfs naming */
|
|
Packit |
d36e9b |
debugprintf("%s isn't accessible, retrying with udev/devfs naming...\n", name);
|
|
Packit |
d36e9b |
sprintf (name, "/dev/%ss/%d", type, i);
|
|
Packit |
d36e9b |
fd = open (name, O_RDONLY | O_NOCTTY);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (fd >= 0) {
|
|
Packit |
d36e9b |
#ifdef HAVE_LINUX
|
|
Packit |
d36e9b |
if (is_parport)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Try to claim the device. This will
|
|
Packit |
d36e9b |
* force the low-level port driver to get loaded. */
|
|
Packit |
d36e9b |
if (ioctl (fd, PPCLAIM) == 0)
|
|
Packit |
d36e9b |
ioctl (fd, PPRELEASE);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
close (fd);
|
|
Packit |
d36e9b |
debugprintf ("%s is accessible\n", name);
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
} else {
|
|
Packit |
d36e9b |
debugprintf("%s isn't accessible\n", name);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Is /dev/port accessible? */
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
check_dev_port (void)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
int fd = open ("/dev/port", O_RDWR | O_NOCTTY);
|
|
Packit |
d36e9b |
if (fd >= 0) {
|
|
Packit |
d36e9b |
close (fd);
|
|
Packit |
d36e9b |
capabilities |= DEV_PORT_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("/dev/port is accessible\n");
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Can we use direct I/O with inb and outb? */
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
check_io (void)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
#ifdef HAVE_OBSD_I386
|
|
Packit |
d36e9b |
u_long *iomap;
|
|
Packit |
d36e9b |
if ((iomap = malloc(1024/8)) == NULL) return 0;
|
|
Packit |
d36e9b |
if ((i386_get_ioperm(iomap) == 0) && (i386_set_ioperm(iomap) == 0)) {
|
|
Packit |
d36e9b |
capabilities |= IO_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("We can use i386_get_ioperm()\n");
|
|
Packit |
d36e9b |
free(iomap);
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
free(iomap);
|
|
Packit |
d36e9b |
#elif defined(HAVE_FBSD_I386)
|
|
Packit |
d36e9b |
int fd;
|
|
Packit |
d36e9b |
if ((fd = open("/dev/io", O_RDONLY)) >= 0) {
|
|
Packit |
d36e9b |
capabilities |= IO_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf("We can use /dev/io\n");
|
|
Packit |
d36e9b |
close(fd);
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
#elif defined(HAVE_LINUX)
|
|
Packit |
d36e9b |
#ifdef HAVE_SYS_IO_H
|
|
Packit |
d36e9b |
if (ioperm (0x378 /* say */, 3, 1) == 0) {
|
|
Packit |
d36e9b |
ioperm (0x378, 3, 0);
|
|
Packit |
d36e9b |
capabilities |= IO_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("We can use ioperm()\n");
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
debugprintf ("We cannot use ioperm() : not supported\n");
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
#endif /* HAVE_SYS_IO_H */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#elif defined(HAVE_SOLARIS)
|
|
Packit |
d36e9b |
int fd;
|
|
Packit |
d36e9b |
if (fd=open("/devices/pseudo/iop@0:iop", O_RDWR) > 0) {
|
|
Packit |
d36e9b |
capabilities |= IO_CAPABLE;
|
|
Packit |
d36e9b |
debugprintf ("We can use iop\n");
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
debugprintf ("We can't use IOP, nothing will work\n");
|
|
Packit |
d36e9b |
#elif defined(HAVE_CYGWIN_9X)
|
|
Packit |
d36e9b |
/* note: 95 allows apps direct IO access */
|
|
Packit |
d36e9b |
debugprintf ("Taking a guess on port availability (win9x)\n");
|
|
Packit |
d36e9b |
capabilities |= IO_CAPABLE;
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Can we use win32 style I/O (cygwin environment) */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
check_lpt (void)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
#ifdef HAVE_CYGWIN_NT
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
HANDLE hf = CreateFile("\\\\.\\$VDMLPT1", GENERIC_READ | GENERIC_WRITE,
|
|
Packit |
d36e9b |
0, NULL, OPEN_EXISTING, 0, NULL);
|
|
Packit |
d36e9b |
if (hf == INVALID_HANDLE_VALUE) return 0;
|
|
Packit |
d36e9b |
CloseHandle(hf);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
capabilities |= LPT_CAPABLE;
|
|
Packit |
d36e9b |
return 1;
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Figure out what we can use to talk to the parallel port.
|
|
Packit |
d36e9b |
* We aren't allowed to use the things set in forbidden though. */
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
detect_environment (int forbidden)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
#define FORBIDDEN(bit) (forbidden & bit)
|
|
Packit |
d36e9b |
int dev_node_parport = 0;
|
|
Packit |
d36e9b |
static int detected = 0;
|
|
Packit |
d36e9b |
if (detected && !forbidden) return 0;
|
|
Packit |
d36e9b |
detected = 1;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
capabilities = 0;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Find out what access mechanisms there are. */
|
|
Packit |
d36e9b |
if (!FORBIDDEN(PPDEV_CAPABLE))
|
|
Packit |
d36e9b |
dev_node_parport = check_dev_node ("parport");
|
|
Packit |
d36e9b |
if (dev_node_parport)
|
|
Packit |
d36e9b |
capabilities |= PPDEV_CAPABLE;
|
|
Packit |
d36e9b |
if (!FORBIDDEN (IO_CAPABLE))
|
|
Packit |
d36e9b |
check_io ();
|
|
Packit |
d36e9b |
if (!FORBIDDEN (DEV_PORT_CAPABLE))
|
|
Packit |
d36e9b |
check_dev_port ();
|
|
Packit |
d36e9b |
if (!FORBIDDEN (LPT_CAPABLE))
|
|
Packit |
d36e9b |
check_lpt ();
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Find out what kind of /proc structure we have. */
|
|
Packit |
d36e9b |
if (!dev_node_parport) /* Don't load lp if we'll use ppdev (claim will fail if F1284_EXCL). */
|
|
Packit |
d36e9b |
check_dev_node ("lp"); /* causes low-level port driver to be loaded */
|
|
Packit |
d36e9b |
check_proc_type ();
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* Local Variables:
|
|
Packit |
d36e9b |
* eval: (c-set-style "gnu")
|
|
Packit |
d36e9b |
* End:
|
|
Packit |
d36e9b |
*/
|