Blame src/detect.c

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
 */