kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			604 wiersze
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			604 wiersze
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
/* sane - Scanner Access Now Easy.
 | 
						|
   Copyright (C) 1998 Christian Bucher
 | 
						|
   Copyright (C) 1998 Kling & Hautzinger GmbH
 | 
						|
   This file is part of the SANE package.
 | 
						|
 | 
						|
   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.
 | 
						|
 | 
						|
   As a special exception, the authors of SANE give permission for
 | 
						|
   additional uses of the libraries contained in this release of SANE.
 | 
						|
 | 
						|
   The exception is that, if you link a SANE library with other files
 | 
						|
   to produce an executable, this does not by itself cause the
 | 
						|
   resulting executable to be covered by the GNU General Public
 | 
						|
   License.  Your use of that executable is in no way restricted on
 | 
						|
   account of linking the SANE library code into it.
 | 
						|
 | 
						|
   This exception does not, however, invalidate any other reasons why
 | 
						|
   the executable file might be covered by the GNU General Public
 | 
						|
   License.
 | 
						|
 | 
						|
   If you submit changes to SANE to the maintainers to be included in
 | 
						|
   a subsequent release, you agree by submitting the changes that
 | 
						|
   those changes may be distributed with this exception intact.
 | 
						|
 | 
						|
   If you write modifications of your own for SANE, it is your choice
 | 
						|
   whether to permit this exception to apply to your modifications.
 | 
						|
   If you do not wish that, delete this exception notice.
 | 
						|
 | 
						|
   This file implements the bi-directional parallel-port
 | 
						|
   interface.  */
 | 
						|
 | 
						|
/*
 | 
						|
  RESTRICTIONS:
 | 
						|
 | 
						|
  - This interface is very timing sensitive, be carefull with setting
 | 
						|
    debug levels.
 | 
						|
 */
 | 
						|
 | 
						|
#include "../include/sane/config.h"
 | 
						|
 | 
						|
#define BACKEND_NAME sanei_pio
 | 
						|
#include "../include/sane/sanei_backend.h"		/* pick up compatibility defs */
 | 
						|
 | 
						|
#ifdef HAVE_UNISTD_H
 | 
						|
# include <unistd.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#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 HAVE_SYS_HW_H
 | 
						|
# include <sys/hw.h>
 | 
						|
#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;
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
# define IO_SUPPORT_MISSING
 | 
						|
#endif
 | 
						|
 | 
						|
#include "../include/sane/sane.h"
 | 
						|
#include "../include/sane/sanei.h"
 | 
						|
#include "../include/sane/sanei_pio.h"
 | 
						|
 | 
						|
#if defined (HAVE_IOPERM) && !defined (IO_SUPPORT_MISSING)
 | 
						|
 | 
						|
#include <errno.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <limits.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <time.h>
 | 
						|
 | 
						|
#include "../include/sane/saneopts.h"
 | 
						|
 | 
						|
#define PORT_DEV	"/dev/port"
 | 
						|
 | 
						|
/*    base    278 (lpt2)
 | 
						|
   
 | 
						|
              ioport  stat    ctrl
 | 
						|
      offs    0       1       2
 | 
						|
      len     1       1       1     */
 | 
						|
 | 
						|
/* Port definitions (`N' at end begin of label means negated signal) */
 | 
						|
 | 
						|
#define PIO_IOPORT		0	/* rel. addr io port      */
 | 
						|
 | 
						|
#define PIO_STAT		1	/* rel. addr status port  */
 | 
						|
#define PIO_STAT_BUSY		(1<<7)	/*  BUSY   Pin            */
 | 
						|
#define PIO_STAT_NACKNLG	(1<<6)	/* ~ACKNLG Pin            */
 | 
						|
 | 
						|
#define PIO_CTRL		2	/* rel. addr control port */
 | 
						|
#define PIO_CTRL_IE		(1<<5)	/* Input enable           */
 | 
						|
#define PIO_CTRL_IRQE		(1<<4)	/* enable IRQ             */
 | 
						|
#define PIO_CTRL_DIR		(1<<3)	/* DIR pin, DIR=1 => out */
 | 
						|
#define PIO_CTRL_NINIT		(1<<2)	/* reset output           */
 | 
						|
#define PIO_CTRL_FDXT		(1<<1)	/* Paper FEED (unused)    */
 | 
						|
#define PIO_CTRL_NSTROBE	(1<<0)	/* strobe pin             */
 | 
						|
 | 
						|
#define PIO_APPLYRESET		2000	/* reset in 10us at init time  */
 | 
						|
 | 
						|
#define DL40	 6
 | 
						|
#define DL50	 7
 | 
						|
#define DL60	 8
 | 
						|
#define DL61	 9
 | 
						|
#define DL70	10
 | 
						|
#define DL71	11
 | 
						|
 | 
						|
#ifdef NDEBUG
 | 
						|
# define DBG_INIT()
 | 
						|
#endif
 | 
						|
 | 
						|
typedef struct
 | 
						|
  {
 | 
						|
    u_long base;		/* i/o base address */
 | 
						|
    int fd;			/* >= 0 when using /dev/port */
 | 
						|
    int max_time_seconds;/* forever if <= 0 */
 | 
						|
    u_int in_use;		/* port in use? */
 | 
						|
  }
 | 
						|
PortRec, *Port;
 | 
						|
 | 
						|
static PortRec port[] =
 | 
						|
  {
 | 
						|
    {0x378, -1, 0, 0},
 | 
						|
    {0x278, -1, 0, 0}
 | 
						|
  };
 | 
						|
 | 
						|
extern int setuid (uid_t);
 | 
						|
 | 
						|
static inline int pio_outb (const Port port, u_char val, u_long addr);
 | 
						|
static inline int pio_inb (const Port port, u_char * val, u_long addr);
 | 
						|
static inline int pio_wait (const Port port, u_char val, u_char mask);
 | 
						|
static inline void pio_ctrl (const Port port, u_char val);
 | 
						|
static inline void pio_delay (const Port port);
 | 
						|
static inline void pio_init (const Port port);
 | 
						|
static void pio_reset (const Port port);
 | 
						|
static int pio_write (const Port port, const u_char * buf, int n);
 | 
						|
static int pio_read (const Port port, u_char * buf, int n);
 | 
						|
static int pio_open (const char *dev, SANE_Status * status);
 | 
						|
 | 
						|
static inline int 
 | 
						|
pio_outb (const Port port, u_char val, u_long addr)
 | 
						|
{
 | 
						|
 | 
						|
  if (-1 == port->fd)
 | 
						|
    outb (val, addr);
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (addr != (u_long)lseek (port->fd, addr, SEEK_SET))
 | 
						|
	return -1;
 | 
						|
      if (1 != write (port->fd, &val, 1))
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static inline int 
 | 
						|
pio_inb (const Port port, u_char * val, u_long addr)
 | 
						|
{
 | 
						|
 | 
						|
  if (-1 == port->fd)
 | 
						|
    *val = inb (addr);
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (addr != (u_long)lseek (port->fd, addr, SEEK_SET))
 | 
						|
	return -1;
 | 
						|
      if (1 != read (port->fd, val, 1))
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static inline int 
 | 
						|
pio_wait (const Port port, u_char val, u_char mask)
 | 
						|
{
 | 
						|
  int stat = 0;
 | 
						|
  long poll_count = 0;
 | 
						|
  time_t start = time(NULL);
 | 
						|
 | 
						|
  DBG (DL60, "wait on port 0x%03lx for %02x mask %02x\n",
 | 
						|
       port->base, (int) val, (int) mask);
 | 
						|
  DBG (DL61, "   BUSY    %s\n", (mask & PIO_STAT_BUSY) ?
 | 
						|
       (val & PIO_STAT_BUSY ? "on" : "off") : "-");
 | 
						|
  DBG (DL61, "   NACKNLG %s\n",
 | 
						|
       (mask & PIO_STAT_NACKNLG) ? (val & PIO_STAT_NACKNLG ? "on" : "off")
 | 
						|
       : "-");
 | 
						|
  for (;;)
 | 
						|
    {
 | 
						|
      ++poll_count;
 | 
						|
      stat = inb (port->base + PIO_STAT);
 | 
						|
      if ((stat & mask) == (val & mask))
 | 
						|
	{
 | 
						|
	  DBG (DL60, "got %02x after %ld tries\n", stat, poll_count);
 | 
						|
	  DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
 | 
						|
	  DBG (DL61, "   NACKNLG %s\n",
 | 
						|
	       stat & PIO_STAT_NACKNLG ? "on" : "off");
 | 
						|
 | 
						|
	  return stat;
 | 
						|
	}
 | 
						|
      if(poll_count>1000)
 | 
						|
        {
 | 
						|
          if ((port->max_time_seconds>0) && (time(NULL)-start >= port->max_time_seconds))
 | 
						|
	    break;
 | 
						|
          usleep(1);
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
  DBG (DL60, "got %02x aborting after %ld\n", stat, poll_count);
 | 
						|
  DBG (DL61, "   BUSY    %s\n", stat & PIO_STAT_BUSY ? "on" : "off");
 | 
						|
  DBG (DL61, "   NACKNLG %s\n", stat & PIO_STAT_NACKNLG ? "on" : "off");
 | 
						|
  DBG (1, "polling time out, abort\n");
 | 
						|
  exit (-1);
 | 
						|
}
 | 
						|
 | 
						|
static inline void
 | 
						|
pio_ctrl (const Port port, u_char val)
 | 
						|
{
 | 
						|
  DBG (DL60, "ctrl on port 0x%03lx %02x %02x\n",
 | 
						|
       port->base, (int) val, (int) val ^ PIO_CTRL_NINIT);
 | 
						|
 | 
						|
  val ^= PIO_CTRL_NINIT;
 | 
						|
 | 
						|
  DBG (DL61, "   IE      %s\n", val & PIO_CTRL_IE ? "on" : "off");
 | 
						|
  DBG (DL61, "   IRQE    %s\n", val & PIO_CTRL_IRQE ? "on" : "off");
 | 
						|
  DBG (DL61, "   DIR     %s\n", val & PIO_CTRL_DIR ? "on" : "off");
 | 
						|
  DBG (DL61, "   NINIT   %s\n", val & PIO_CTRL_NINIT ? "on" : "off");
 | 
						|
  DBG (DL61, "   FDXT    %s\n", val & PIO_CTRL_FDXT ? "on" : "off");
 | 
						|
  DBG (DL61, "   NSTROBE %s\n", val & PIO_CTRL_NSTROBE ? "on" : "off");
 | 
						|
 | 
						|
  outb (val, port->base + PIO_CTRL);
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
static inline void 
 | 
						|
pio_delay (const Port port)
 | 
						|
{
 | 
						|
  inb (port->base + PIO_STAT);	/* delay */
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
static inline void 
 | 
						|
pio_init (const Port port)
 | 
						|
{
 | 
						|
  pio_ctrl (port, PIO_CTRL_IE);
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
static void 
 | 
						|
pio_reset (const Port port)
 | 
						|
{
 | 
						|
  int n;
 | 
						|
 | 
						|
  DBG (DL40, "reset\n");
 | 
						|
 | 
						|
  for (n = PIO_APPLYRESET; --n >= 0;)
 | 
						|
    {
 | 
						|
      outb ((PIO_CTRL_IE | PIO_CTRL_NINIT) ^ PIO_CTRL_NINIT,
 | 
						|
	    port->base + PIO_CTRL);
 | 
						|
    }
 | 
						|
  pio_init (port);
 | 
						|
 | 
						|
  DBG (DL40, "end reset\n");
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
static int 
 | 
						|
pio_write (const Port port, const u_char * buf, int n)
 | 
						|
{
 | 
						|
  int k;
 | 
						|
 | 
						|
  DBG (DL40, "write\n");
 | 
						|
 | 
						|
  pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
  pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE);		/* praeoutput */
 | 
						|
  pio_wait (port, PIO_STAT_NACKNLG, PIO_STAT_NACKNLG);	/* acknlg */
 | 
						|
  pio_ctrl (port, PIO_CTRL_DIR);			/* output */
 | 
						|
 | 
						|
  for (k = 0; k < n; k++, buf++)
 | 
						|
    {
 | 
						|
      DBG (DL40, "write byte\n");
 | 
						|
#ifdef HANDSHAKE_BUSY
 | 
						|
      pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
#else
 | 
						|
      pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG,
 | 
						|
		PIO_STAT_BUSY | PIO_STAT_NACKNLG);	/* busyack */
 | 
						|
#endif
 | 
						|
      DBG (DL60, "out  %02x\n", (int) *buf);
 | 
						|
 | 
						|
      outb (*buf, port->base + PIO_IOPORT);
 | 
						|
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_NSTROBE);	/* outputstrobe */
 | 
						|
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_ctrl (port, PIO_CTRL_DIR);	/* output */
 | 
						|
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
 | 
						|
      DBG (DL40, "end write byte\n");
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef HANDSHAKE_BUSY
 | 
						|
  pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
#else
 | 
						|
  pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG,
 | 
						|
	    PIO_STAT_BUSY | PIO_STAT_NACKNLG);	/* busyack */
 | 
						|
#endif
 | 
						|
 | 
						|
  pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE);	/* praeoutput */
 | 
						|
  DBG (DL40, "end write\n");
 | 
						|
  return k;
 | 
						|
}
 | 
						|
 | 
						|
static int 
 | 
						|
pio_read (const Port port, u_char * buf, int n)
 | 
						|
{
 | 
						|
  int k;
 | 
						|
 | 
						|
  DBG (DL40, "read\n");
 | 
						|
 | 
						|
  pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
  pio_ctrl (port, PIO_CTRL_IE);	/* input */
 | 
						|
 | 
						|
  for (k = 0; k < n; k++, buf++)
 | 
						|
    {
 | 
						|
      DBG (DL40, "read byte\n");
 | 
						|
 | 
						|
#ifdef HANDSHAKE_BUSY
 | 
						|
      pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
#else
 | 
						|
      pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG);
 | 
						|
      /* busynack */
 | 
						|
#endif
 | 
						|
      pio_ctrl (port, PIO_CTRL_IE | PIO_CTRL_NSTROBE);	/* inputstrobe */
 | 
						|
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_delay (port);
 | 
						|
      pio_ctrl (port, PIO_CTRL_IE);	/* input */
 | 
						|
#ifdef HANDSHAKE_BUSY
 | 
						|
      pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
#else
 | 
						|
      pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG);
 | 
						|
      /* busynack */
 | 
						|
#endif
 | 
						|
 | 
						|
      *buf = inb (port->base + PIO_IOPORT);
 | 
						|
      DBG (DL60, "in   %02x\n", (int) *buf);
 | 
						|
      DBG (DL40, "end read byte\n");
 | 
						|
    }
 | 
						|
 | 
						|
  pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY);	/* busy */
 | 
						|
  pio_ctrl (port, PIO_CTRL_IE);	/* input */
 | 
						|
  DBG (DL40, "end read\n");
 | 
						|
  return k;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
     Open the device, <dev> must contain a valid port number (as string).   
 | 
						|
 */
 | 
						|
 | 
						|
static int 
 | 
						|
pio_open (const char *dev, SANE_Status * status)
 | 
						|
{
 | 
						|
  static int first_time = 1;
 | 
						|
  u_long base;
 | 
						|
  int n;
 | 
						|
 | 
						|
  if (first_time)
 | 
						|
    {
 | 
						|
      first_time = 0;
 | 
						|
 | 
						|
      DBG_INIT ();
 | 
						|
      /* set root uid */
 | 
						|
      if (0 > setuid (0))
 | 
						|
	{
 | 
						|
	  DBG (1, "sanei_pio_open: setuid failed: errno = %d\n", errno);
 | 
						|
	  *status = SANE_STATUS_INVAL;
 | 
						|
	  return -1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  /* read port number */
 | 
						|
  {
 | 
						|
    char *end;
 | 
						|
 | 
						|
    base = strtol (dev, &end, 0);
 | 
						|
 | 
						|
    if ((end == dev) || *end)
 | 
						|
      {
 | 
						|
	DBG (1, "sanei_pio_open: `%s' is not a valid port number\n", dev);
 | 
						|
	*status = SANE_STATUS_INVAL;
 | 
						|
	return -1;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  if (0 == base)
 | 
						|
    {
 | 
						|
      DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base);
 | 
						|
      *status = SANE_STATUS_INVAL;
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
  for (n = 0; n < NELEMS (port); n++)
 | 
						|
    if (port[n].base == base)
 | 
						|
      break;
 | 
						|
 | 
						|
  if (NELEMS (port) <= n)
 | 
						|
    {
 | 
						|
      DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base);
 | 
						|
      *status = SANE_STATUS_INVAL;
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
  if (port[n].in_use)
 | 
						|
    {
 | 
						|
      DBG (1, "sanei_pio_open: port 0x%03lx is already in use\n", base);
 | 
						|
      *status = SANE_STATUS_DEVICE_BUSY;
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
  port[n].base = base;
 | 
						|
  port[n].fd = -1;
 | 
						|
  port[n].max_time_seconds = 10;
 | 
						|
  port[n].in_use = 1;
 | 
						|
 | 
						|
  if (ioperm (port[n].base, 3, 1))
 | 
						|
    {
 | 
						|
      DBG (1, "sanei_pio_open: cannot get io privilege for port 0x%03lx\n",
 | 
						|
	   port[n].base);
 | 
						|
      *status = SANE_STATUS_IO_ERROR;
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
  pio_reset (&port[n]);
 | 
						|
 | 
						|
  *status = SANE_STATUS_GOOD;
 | 
						|
  return n;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status 
 | 
						|
sanei_pio_open (const char *dev, int *fdp)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
 | 
						|
  *fdp = pio_open (dev, &status);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
void 
 | 
						|
sanei_pio_close (int fd)
 | 
						|
{
 | 
						|
  Port p = port + fd;
 | 
						|
 | 
						|
  if ((0 > fd) && (NELEMS (port) <= fd))
 | 
						|
    return;
 | 
						|
 | 
						|
  if (!p->in_use)
 | 
						|
    return;
 | 
						|
 | 
						|
  if (-1 != p->fd)
 | 
						|
    {
 | 
						|
      close (p->fd);
 | 
						|
      p->fd = -1;
 | 
						|
    }
 | 
						|
 | 
						|
  p->in_use = 0;
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_read (int fd, u_char * buf, int n)
 | 
						|
{
 | 
						|
  if ((0 > fd) && (NELEMS (port) <= fd))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  if (!port[fd].in_use)
 | 
						|
    return -1;
 | 
						|
 | 
						|
  return pio_read (&port[fd], buf, n);
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_write (int fd, const u_char * buf, int n)
 | 
						|
{
 | 
						|
  if ((0 > fd) && (NELEMS (port) <= fd))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  if (!port[fd].in_use)
 | 
						|
    return -1;
 | 
						|
 | 
						|
  return pio_write (&port[fd], buf, n);
 | 
						|
}
 | 
						|
 | 
						|
#else /* !HAVE_IOPERM */
 | 
						|
 | 
						|
#ifdef __BEOS__
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_pio_open (const char *dev, int *fdp)
 | 
						|
{
 | 
						|
	int fp;
 | 
						|
	
 | 
						|
	/* open internal parallel port */
 | 
						|
	fp=open("/dev/parallel/parallel1",O_RDWR);
 | 
						|
  
 | 
						|
  	*fdp=fp;
 | 
						|
  	if(fp<0) return SANE_STATUS_INVAL;
 | 
						|
  	return(SANE_STATUS_GOOD);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void 
 | 
						|
sanei_pio_close (int fd)
 | 
						|
{
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_read (int fd, u_char * buf, int n)
 | 
						|
{
 | 
						|
	return(read(fd,buf,n));
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_write (int fd, const u_char * buf, int n)
 | 
						|
{
 | 
						|
  	return(write(fd,buf,n));
 | 
						|
}
 | 
						|
 | 
						|
#else /* !__BEOS__ */
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_pio_open (const char *dev, int *fdp)
 | 
						|
{
 | 
						|
  *fdp = -1;
 | 
						|
  return SANE_STATUS_INVAL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void 
 | 
						|
sanei_pio_close (int fd)
 | 
						|
{
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_read (int fd, u_char * buf, int n)
 | 
						|
{
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
int 
 | 
						|
sanei_pio_write (int fd, const u_char * buf, int n)
 | 
						|
{
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
#endif /* __BEOS__ */
 | 
						|
 | 
						|
#endif /* !HAVE_IOPERM */
 |