Blame src/access_ppdev.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 <errno.h>
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
#endif
Packit d36e9b
#include <sys/stat.h>
Packit d36e9b
#ifdef __unix__
Packit d36e9b
#include <unistd.h>
Packit d36e9b
#endif
Packit d36e9b
Packit d36e9b
#include "access.h"
Packit d36e9b
#include "config.h"
Packit d36e9b
#include "debug.h"
Packit d36e9b
#include "default.h"
Packit d36e9b
#include "delay.h"
Packit d36e9b
#include "ieee1284.h"
Packit d36e9b
#include "detect.h"
Packit d36e9b
#include "parport.h"
Packit d36e9b
Packit d36e9b
#ifdef HAVE_LINUX
Packit d36e9b
Packit d36e9b
#include "ppdev.h"
Packit d36e9b
Packit d36e9b
struct ppdev_priv 
Packit d36e9b
{
Packit d36e9b
  struct timeval inactivity_timer;
Packit d36e9b
  int nonblock;
Packit d36e9b
  int current_flags;
Packit d36e9b
};
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
find_capabilities (int fd, int *c)
Packit d36e9b
{
Packit d36e9b
  int m;
Packit d36e9b
Packit d36e9b
  /* Work around a 2.4.x kernel bug by claiming the port for this
Packit d36e9b
   * even though we shouldn't have to. */
Packit d36e9b
  if (ioctl (fd, PPCLAIM))
Packit d36e9b
    goto guess;
Packit d36e9b
Packit d36e9b
  if (ioctl (fd, PPGETMODES, &m))
Packit d36e9b
    {
Packit d36e9b
      ioctl (fd, PPRELEASE);
Packit d36e9b
 guess:
Packit d36e9b
      *c |= CAP1284_ECP | CAP1284_ECPRLE | CAP1284_EPP;
Packit d36e9b
      return;
Packit d36e9b
    }
Packit d36e9b
  ioctl (fd, PPRELEASE);
Packit d36e9b
Packit d36e9b
  if (m & PARPORT_MODE_PCSPP)
Packit d36e9b
    *c |= CAP1284_RAW;
Packit d36e9b
  if (m & PARPORT_MODE_EPP)
Packit d36e9b
    *c |= CAP1284_EPP;
Packit d36e9b
  if (m & PARPORT_MODE_ECP)
Packit d36e9b
    *c |= CAP1284_ECP | CAP1284_ECPRLE;
Packit d36e9b
  if (m & PARPORT_MODE_DMA)
Packit d36e9b
    *c |= CAP1284_DMA;
Packit d36e9b
  if (!(m & PARPORT_MODE_TRISTATE))
Packit d36e9b
    *c &= ~(CAP1284_BYTE | CAP1284_ECPSWE);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
init (struct parport *pport, int flags, int *capabilities)
Packit d36e9b
{
Packit d36e9b
  struct parport_internal *port = pport->priv;
Packit d36e9b
Packit d36e9b
  if (flags & ~F1284_EXCL)
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  port->access_priv = malloc (sizeof (struct ppdev_priv));
Packit d36e9b
  if (!port->access_priv)
Packit d36e9b
    return E1284_NOMEM;
Packit d36e9b
Packit d36e9b
  ((struct ppdev_priv *)port->access_priv)->nonblock = 0;
Packit d36e9b
  ((struct ppdev_priv *)port->access_priv)->current_flags = 0;
Packit d36e9b
  port->fd = open (port->device, O_RDWR | O_NOCTTY);
Packit d36e9b
Packit d36e9b
  /* Retry with udev/devfs naming, if available */
Packit d36e9b
  if (port->fd < 0)
Packit d36e9b
    {
Packit d36e9b
      if (port->udevice)
Packit d36e9b
	port->fd = open (port->udevice, O_RDWR | O_NOCTTY);
Packit d36e9b
Packit d36e9b
      if (port->fd < 0)
Packit d36e9b
	{
Packit d36e9b
	  free (port->access_priv);
Packit d36e9b
	  return E1284_INIT;
Packit d36e9b
	}
Packit d36e9b
      else
Packit d36e9b
	{
Packit d36e9b
	  pport->filename = port->udevice;
Packit d36e9b
	}
Packit d36e9b
    }
Packit d36e9b
  else
Packit d36e9b
    {
Packit d36e9b
      pport->filename = port->device;
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  port->current_mode = M1284_COMPAT;
Packit d36e9b
  if (flags & F1284_EXCL)
Packit d36e9b
    {
Packit d36e9b
      if (ioctl (port->fd, PPEXCL))
Packit d36e9b
	{
Packit d36e9b
	  close (port->fd);
Packit d36e9b
	  free (port->access_priv);
Packit d36e9b
	  return E1284_INIT;
Packit d36e9b
	}
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  if (port->interrupt == -1)
Packit d36e9b
    /* Our implementation of do_nack_handshake relies on interrupts
Packit d36e9b
     * being available.  They aren't, so use the default one instead. */
Packit d36e9b
    port->fn->do_nack_handshake = default_do_nack_handshake;
Packit d36e9b
  else if (capabilities)
Packit d36e9b
    *capabilities |= CAP1284_IRQ;
Packit d36e9b
Packit d36e9b
  if (capabilities)
Packit d36e9b
    find_capabilities (port->fd, capabilities);
Packit d36e9b
Packit d36e9b
  return E1284_OK;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
cleanup (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  free (port->access_priv);
Packit d36e9b
  if (port->fd >= 0)
Packit d36e9b
    close (port->fd);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
claim (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  debugprintf ("==> claim\n");
Packit d36e9b
  if (ioctl (port->fd, PPCLAIM))
Packit d36e9b
    {
Packit d36e9b
      debugprintf ("<== E1284_SYS\n");
Packit d36e9b
      return E1284_SYS;
Packit d36e9b
    }
Packit d36e9b
  debugprintf ("<== E1284_OK\n");
Packit d36e9b
  return E1284_OK;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
release (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  ioctl (port->fd, PPRELEASE);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
get_irq_fd (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  /* We _don't_ dup the file descriptor because reference counting is
Packit d36e9b
   * done at the port, and we don't want it to be valid after the port
Packit d36e9b
   * has been closed. */
Packit d36e9b
  return port->fd;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
clear_irq (struct parport_internal *port, unsigned int *count)
Packit d36e9b
{
Packit d36e9b
  int c;
Packit d36e9b
Packit d36e9b
  if (ioctl (port->fd, PPCLRIRQ, &c))
Packit d36e9b
    return E1284_SYS;
Packit d36e9b
Packit d36e9b
  if (count)
Packit d36e9b
    *count = c;
Packit d36e9b
Packit d36e9b
  return E1284_OK;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
read_data (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  unsigned char reg;
Packit d36e9b
  if (ioctl (port->fd, PPRDATA, &reg))
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  return reg;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
write_data (struct parport_internal *port, unsigned char reg)
Packit d36e9b
{
Packit d36e9b
  ioctl (port->fd, PPWDATA, ®);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
read_status (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  unsigned char reg;
Packit d36e9b
  if (ioctl (port->fd, PPRSTATUS, &reg))
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  return debug_display_status (reg ^ S1284_INVERTED);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
read_control (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  unsigned char reg;
Packit d36e9b
  const unsigned char rm = (C1284_NSTROBE |
Packit d36e9b
			    C1284_NAUTOFD |
Packit d36e9b
			    C1284_NINIT |
Packit d36e9b
			    C1284_NSELECTIN);
Packit d36e9b
  if (ioctl (port->fd, PPRCONTROL, &reg))
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  return (reg ^ C1284_INVERTED) & rm;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
data_dir (struct parport_internal *port, int reverse)
Packit d36e9b
{
Packit d36e9b
  if (ioctl (port->fd, PPDATADIR, &reverse))
Packit d36e9b
    return E1284_SYS;
Packit d36e9b
  return E1284_OK;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
write_control (struct parport_internal *port, unsigned char reg)
Packit d36e9b
{
Packit d36e9b
  const unsigned char wm = (C1284_NSTROBE |
Packit d36e9b
			    C1284_NAUTOFD |
Packit d36e9b
			    C1284_NINIT |
Packit d36e9b
			    C1284_NSELECTIN);
Packit d36e9b
  if (reg & 0x20)
Packit d36e9b
    {
Packit d36e9b
      printf ("use ieee1284_data_dir to change data line direction!\n");
Packit d36e9b
      data_dir (port, 1);
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  reg &= wm;
Packit d36e9b
  reg ^= C1284_INVERTED;
Packit d36e9b
  ioctl (port->fd, PPWCONTROL, ®);
Packit d36e9b
  debug_display_control (reg);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
frob_control (struct parport_internal *port,
Packit d36e9b
			  unsigned char mask,
Packit d36e9b
			  unsigned char val)
Packit d36e9b
{
Packit d36e9b
  struct ppdev_frob_struct ppfs;
Packit d36e9b
Packit d36e9b
  if (mask & 0x20)
Packit d36e9b
    {
Packit d36e9b
      printf ("use ieee1284_data_dir to change data line direction!\n");
Packit d36e9b
      data_dir (port, val & 0x20);
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  /* Deal with inversion issues. */
Packit d36e9b
  ppfs.mask = mask;
Packit d36e9b
  ppfs.val = val ^ (mask & C1284_INVERTED);
Packit d36e9b
  debugprintf ("frob_control: ioctl(%d, PPFCONTROL, { mask:%#02x, val:%#02x }\n",
Packit d36e9b
	   port->fd, ppfs.mask, ppfs.val);
Packit d36e9b
  ioctl (port->fd, PPFCONTROL, &ppfs);
Packit d36e9b
  debug_frob_control (mask, val);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
wait_status (struct parport_internal *port,
Packit d36e9b
	     unsigned char mask, unsigned char val,
Packit d36e9b
	     struct timeval *timeout)
Packit d36e9b
{
Packit d36e9b
  /* This could be smarter: if we're just waiting for nAck, and we
Packit d36e9b
   * have interrutps to work with, we can just wait for an interrupt
Packit d36e9b
   * rather than polling. */
Packit d36e9b
Packit d36e9b
  /* Simple-minded polling.  TODO: Use David Paschal's method for this. */
Packit d36e9b
  struct timeval deadline, now;
Packit d36e9b
  gettimeofday (&deadline, NULL);
Packit d36e9b
  deadline.tv_sec += timeout->tv_sec;
Packit d36e9b
  deadline.tv_usec += timeout->tv_usec;
Packit d36e9b
  deadline.tv_sec += deadline.tv_usec / 1000000;
Packit d36e9b
  deadline.tv_usec %= 1000000;
Packit d36e9b
Packit d36e9b
  do
Packit d36e9b
    {
Packit d36e9b
      unsigned char st = debug_display_status (read_status (port));
Packit d36e9b
      if ((st & mask) == val)
Packit d36e9b
	return E1284_OK;
Packit d36e9b
Packit d36e9b
      delay (IO_POLL_DELAY);
Packit d36e9b
      gettimeofday (&now, NULL);
Packit d36e9b
    }
Packit d36e9b
  while (now.tv_sec < deadline.tv_sec ||
Packit d36e9b
	 (now.tv_sec == deadline.tv_sec &&
Packit d36e9b
	  now.tv_usec < deadline.tv_usec));
Packit d36e9b
Packit d36e9b
  return E1284_TIMEDOUT;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
do_nack_handshake (struct parport_internal *port,
Packit d36e9b
		   unsigned char ct_before,
Packit d36e9b
		   unsigned char ct_after,
Packit d36e9b
		   struct timeval *timeout)
Packit d36e9b
{
Packit d36e9b
  fd_set rfds;
Packit d36e9b
  int count;
Packit d36e9b
Packit d36e9b
  if (ioctl (port->fd, PPCLRIRQ, &count))
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  if (ioctl (port->fd, PPWCTLONIRQ, &ct_after))
Packit d36e9b
    return E1284_NOTAVAIL;
Packit d36e9b
Packit d36e9b
  write_control (port, ct_before);
Packit d36e9b
Packit d36e9b
  FD_ZERO (&rfds);
Packit d36e9b
  FD_SET (port->fd, &rfds);
Packit d36e9b
Packit d36e9b
  switch (select (port->fd + 1, &rfds, NULL, NULL, timeout))
Packit d36e9b
    {
Packit d36e9b
    case 0:
Packit d36e9b
      return E1284_TIMEDOUT;
Packit d36e9b
Packit d36e9b
    case -1:
Packit d36e9b
      return E1284_NOTAVAIL;
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  ioctl (port->fd, PPCLRIRQ, &count);
Packit d36e9b
  if (count != 1)
Packit d36e9b
    {
Packit d36e9b
      printf ("Multiple interrupts caught?\n");
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  return E1284_OK;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
which_mode (int mode, int flags)
Packit d36e9b
{
Packit d36e9b
  int m;
Packit d36e9b
Packit d36e9b
  if (mode & (M1284_FLAG_DEVICEID | M1284_FLAG_EXT_LINK))
Packit d36e9b
    return mode;
Packit d36e9b
Packit d36e9b
  switch (mode)
Packit d36e9b
    {
Packit d36e9b
    case M1284_NIBBLE:
Packit d36e9b
    case M1284_BYTE:
Packit d36e9b
    case M1284_COMPAT:
Packit d36e9b
    case M1284_ECPRLE:
Packit d36e9b
    case M1284_ECPSWE:
Packit d36e9b
    case M1284_EPPSWE:
Packit d36e9b
      m = mode;
Packit d36e9b
      break;
Packit d36e9b
Packit d36e9b
    case M1284_ECP:
Packit d36e9b
      if (flags & F1284_RLE)
Packit d36e9b
	m = IEEE1284_MODE_ECPRLE;
Packit d36e9b
      else if (flags & F1284_SWE)
Packit d36e9b
	m = IEEE1284_MODE_ECPSWE;
Packit d36e9b
      else if (flags & ~F1284_NONBLOCK)
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("flags is %x, but only F1284_RLE, F1284_SWE "
Packit d36e9b
		   "and F1284_NONBLOCK are implemented\n", flags);
Packit d36e9b
	  return E1284_NOTIMPL;
Packit d36e9b
	}
Packit d36e9b
      else m = IEEE1284_MODE_ECP;
Packit d36e9b
      break;
Packit d36e9b
Packit d36e9b
    case M1284_EPP:
Packit d36e9b
      if (flags & F1284_SWE)
Packit d36e9b
	m = IEEE1284_MODE_EPPSWE;
Packit d36e9b
      else if (flags & ~(F1284_FASTEPP | F1284_NONBLOCK))
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("flags is %x, but only F1284_SWE and F1284_NONBLOCK "
Packit d36e9b
		   "are implemented\n", flags);
Packit d36e9b
	  return E1284_NOTIMPL;
Packit d36e9b
	}
Packit d36e9b
      else m = IEEE1284_MODE_EPP;
Packit d36e9b
      break;
Packit d36e9b
Packit d36e9b
    default:
Packit d36e9b
      debugprintf ("Unknown mode %x\n", mode);
Packit d36e9b
      return E1284_NOTIMPL;
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  return m;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
translate_error_code (ssize_t e)
Packit d36e9b
{
Packit d36e9b
  if (e == -EAGAIN)
Packit d36e9b
    return E1284_TIMEDOUT;
Packit d36e9b
  if (e < 0)
Packit d36e9b
    return E1284_SYS;
Packit d36e9b
  return e;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
set_mode (struct parport_internal *port, int mode, int flags, int addr)
Packit d36e9b
{
Packit d36e9b
  struct ppdev_priv *priv = port->access_priv;
Packit d36e9b
  int m = which_mode (mode, flags);
Packit d36e9b
  int f = 0;
Packit d36e9b
  int ret = E1284_OK;
Packit d36e9b
Packit d36e9b
  if (m < 0)
Packit d36e9b
    return m;
Packit d36e9b
Packit d36e9b
  m |= addr ? IEEE1284_ADDR : IEEE1284_DATA;
Packit d36e9b
  if (port->current_mode != m)
Packit d36e9b
    {
Packit d36e9b
      ret = translate_error_code (ioctl (port->fd, PPSETMODE, &m);;
Packit d36e9b
      if (!ret)
Packit d36e9b
	port->current_mode = m;
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  if (mode == M1284_EPP && (flags & F1284_FASTEPP))
Packit d36e9b
    f |= PP_FASTREAD | PP_FASTWRITE;
Packit d36e9b
Packit d36e9b
  if (priv->current_flags != f
Packit d36e9b
      && mode == M1284_EPP) /* flags are only relevant for EPP right now */
Packit d36e9b
    {
Packit d36e9b
      ret = translate_error_code (ioctl (port->fd, PPSETFLAGS, &f);;
Packit d36e9b
      if (!ret)
Packit d36e9b
	priv->current_flags = f;
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
do_nonblock (struct parport_internal *port, int flags)
Packit d36e9b
{
Packit d36e9b
  struct ppdev_priv *priv = port->access_priv;
Packit d36e9b
  if ((flags & F1284_NONBLOCK) && !priv->nonblock)
Packit d36e9b
    {
Packit d36e9b
      /* Enable O_NONBLOCK */
Packit d36e9b
      int f = fcntl (port->fd, F_GETFL);
Packit d36e9b
Packit d36e9b
      if (f == -1)
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("do_nonblock: fcntl failed on F_GETFL\n");
Packit d36e9b
	  return -1;
Packit d36e9b
	}
Packit d36e9b
Packit d36e9b
      f |= O_NONBLOCK;
Packit d36e9b
      if (fcntl (port->fd, F_SETFL, f))
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("do_nonblock: fcntl failed on F_SETFL\n");
Packit d36e9b
	  return -1;
Packit d36e9b
	}
Packit d36e9b
    }
Packit d36e9b
  else if ((!(flags & F1284_NONBLOCK)) && priv->nonblock)
Packit d36e9b
    {
Packit d36e9b
      /* Disable O_NONBLOCK */
Packit d36e9b
      int f = fcntl (port->fd, F_GETFL);
Packit d36e9b
Packit d36e9b
      if (f == -1)
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("do_nonblock: fcntl failed on F_GETFL\n");
Packit d36e9b
	  return -1;
Packit d36e9b
	}
Packit d36e9b
Packit d36e9b
      f &= O_NONBLOCK;
Packit d36e9b
      if (fcntl (port->fd, F_SETFL, f))
Packit d36e9b
	{
Packit d36e9b
	  debugprintf ("do_nonblock: fcntl failed on F_SETFL\n");
Packit d36e9b
	  return -1;
Packit d36e9b
	}
Packit d36e9b
    }
Packit d36e9b
Packit d36e9b
  return 0;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static int
Packit d36e9b
negotiate (struct parport_internal *port, int mode)
Packit d36e9b
{
Packit d36e9b
  int m = which_mode (mode, 0);
Packit d36e9b
  int ret;
Packit d36e9b
Packit d36e9b
  debugprintf ("==> negotiate (to %#02x)\n", mode);
Packit d36e9b
Packit d36e9b
  ret = ioctl (port->fd, PPNEGOT, &m);
Packit d36e9b
  if (!ret)
Packit d36e9b
  {
Packit d36e9b
    port->current_mode = mode;
Packit d36e9b
  } else {
Packit d36e9b
    if (errno == EIO)
Packit d36e9b
      {
Packit d36e9b
	debugprintf ("<== E1284_NEGFAILED\n");
Packit d36e9b
	return E1284_NEGFAILED;
Packit d36e9b
      }
Packit d36e9b
Packit d36e9b
    if (errno == ENXIO)
Packit d36e9b
      {
Packit d36e9b
	debugprintf ("<== E1284_REJECTED\n");
Packit d36e9b
	return E1284_REJECTED;
Packit d36e9b
      }
Packit d36e9b
  }
Packit d36e9b
Packit d36e9b
  m = translate_error_code (ret);
Packit d36e9b
  debugprintf ("<== %d\n", m);
Packit d36e9b
  return m;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static void
Packit d36e9b
terminate (struct parport_internal *port)
Packit d36e9b
{
Packit d36e9b
  int m = IEEE1284_MODE_COMPAT;
Packit d36e9b
  if (!ioctl (port->fd, PPNEGOT, &m))
Packit d36e9b
    port->current_mode = IEEE1284_MODE_COMPAT;
Packit d36e9b
Packit d36e9b
  /* Seems to be needed before negotiation. */
Packit d36e9b
  delay (IO_POLL_DELAY);
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
nibble_read (struct parport_internal *port, int flags,
Packit d36e9b
	     char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_NIBBLE, 0, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (read (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
compat_write (struct parport_internal *port, int flags,
Packit d36e9b
	      const char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_COMPAT, 0, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (write (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
byte_read (struct parport_internal *port, int flags,
Packit d36e9b
	   char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_BYTE, 0, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (read (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
epp_read_data (struct parport_internal *port, int flags,
Packit d36e9b
	       char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_EPP, flags, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (read (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
epp_write_data (struct parport_internal *port, int flags,
Packit d36e9b
		const char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_EPP, flags, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (write (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
epp_read_addr (struct parport_internal *port, int flags,
Packit d36e9b
	       char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_EPP, flags, 1);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (read (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
epp_write_addr (struct parport_internal *port, int flags,
Packit d36e9b
		const char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_EPP, flags, 1);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (write (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
ecp_read_data (struct parport_internal *port, int flags,
Packit d36e9b
	       char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_ECP, flags, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (read (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
ecp_write_data (struct parport_internal *port, int flags,
Packit d36e9b
		const char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_ECP, flags, 0);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (write (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static ssize_t
Packit d36e9b
ecp_write_addr (struct parport_internal *port, int flags,
Packit d36e9b
		const char *buffer, size_t len)
Packit d36e9b
{
Packit d36e9b
  int ret;
Packit d36e9b
  ret = do_nonblock (port, flags);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = set_mode (port, M1284_ECP, flags, 1);
Packit d36e9b
  if (!ret)
Packit d36e9b
    ret = translate_error_code (write (port->fd, buffer, len));
Packit d36e9b
  return ret;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
static struct timeval *
Packit d36e9b
set_timeout (struct parport_internal *port, struct timeval *timeout)
Packit d36e9b
{
Packit d36e9b
  struct ppdev_priv *priv = port->access_priv;
Packit d36e9b
  ioctl (port->fd, PPGETTIME, &priv->inactivity_timer);
Packit d36e9b
  ioctl (port->fd, PPSETTIME, timeout);
Packit d36e9b
  return &priv->inactivity_timer;
Packit d36e9b
}
Packit d36e9b
Packit d36e9b
const struct parport_access_methods ppdev_access_methods =
Packit d36e9b
{
Packit d36e9b
  init,
Packit d36e9b
  cleanup,
Packit d36e9b
Packit d36e9b
  claim,
Packit d36e9b
  release,
Packit d36e9b
Packit d36e9b
  NULL, /* inb */
Packit d36e9b
  NULL, /* outb */
Packit d36e9b
Packit d36e9b
  get_irq_fd,
Packit d36e9b
  clear_irq,
Packit d36e9b
Packit d36e9b
  read_data,
Packit d36e9b
  write_data,
Packit d36e9b
  default_wait_data,
Packit d36e9b
  data_dir,
Packit d36e9b
Packit d36e9b
  read_status,
Packit d36e9b
  wait_status,
Packit d36e9b
Packit d36e9b
  read_control,
Packit d36e9b
  write_control,
Packit d36e9b
  frob_control,
Packit d36e9b
Packit d36e9b
  do_nack_handshake,
Packit d36e9b
Packit d36e9b
  negotiate,
Packit d36e9b
  terminate,
Packit d36e9b
  default_ecp_fwd_to_rev,
Packit d36e9b
  default_ecp_rev_to_fwd,
Packit d36e9b
  nibble_read,
Packit d36e9b
  compat_write,
Packit d36e9b
  byte_read,
Packit d36e9b
  epp_read_data,
Packit d36e9b
  epp_write_data,
Packit d36e9b
  epp_read_addr,
Packit d36e9b
  epp_write_addr,
Packit d36e9b
  ecp_read_data,
Packit d36e9b
  ecp_write_data,
Packit d36e9b
  default_ecp_read_addr,
Packit d36e9b
  ecp_write_addr,
Packit d36e9b
  set_timeout
Packit d36e9b
};
Packit d36e9b
Packit d36e9b
/*
Packit d36e9b
 * Local Variables:
Packit d36e9b
 * eval: (c-set-style "gnu")
Packit d36e9b
 * End:
Packit d36e9b
 */
Packit d36e9b
Packit d36e9b
#else /* Not Linux, no ppdev */
Packit d36e9b
Packit d36e9b
/* Null struct to keep the compiler happy */
Packit d36e9b
const struct parport_access_methods ppdev_access_methods =
Packit d36e9b
{
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL, /* inb */
Packit d36e9b
  NULL, /* outb */
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL,
Packit d36e9b
  NULL 
Packit d36e9b
};
Packit d36e9b
Packit d36e9b
Packit d36e9b
Packit d36e9b
#endif /* HAVE_LINUX */