Programmierung der Paralelen Schnittstelle

Jan-Benedict Glaw jbglaw at lug-owl.de
Thu Mar 2 01:00:18 CET 2000


On Wed, Mar 01, 2000 at 11:44:26AM +0100, Volker Gueth wrote:
> Hi,
> 
> Hat schon mal jemand die Paralelle Schnittstelle unter Linux Programmiert?
> Wo findet man vernünftige Doku und Beispielprogramme? Programmiersprache
> wahrscheinlich C.

Also... Du hast mehrere Möglichkeiten. Wie auch immer, die sind alle ganz
einfach. Klar;)

1. setuid-root-Programm:
        Du machst einen iopl()-Aufruf und gehst dann mit inb()/outb()
        an das Dingen. Ist leider Architektur-abhängig...

2. Zugriff durch /dev/port(s):
        Als Datei öffnen, und dann 'reinschreiben. Im Prinzip wie oben,
        nur richten sich die Rechte jetzt nach den Rechten des device
	nodes. Auch Architektur-abhängig.

3. Zugriff durch das neue ppdev-Modul:
	Das ist die beste Lösung;) Zugriff durch einen device node und
	*Architekturunabhängig*. Aber: Funkt erst ab 2.3.x. Wie auch immer:
	Ich kann's empfehlen! Ich pack mal dafür noch ein Beispiel-Programm,
	das allerdings *nicht* läuft, an. Es ist kurz, zeigt aber die 
	Prinzipien ganz gut;)

MfG, JBG
PS: Ist das für die Meßdatenerfassingssache?

-- 
Fehler eingestehen, Größe zeigen: Nehmt die Rechtschreibreform zurück!!!
keyID=0x8399E1BB fingerprint=250D 3BCF 7127 0D8C A444 A961 1DBD 5E75 8399 E1BB
-------------- next part --------------
/*
 * Virtual printer
 *
 * Copyright (C) 1999, Tim Waugh <tim at cyberelk.demon.co.uk>
 *
 * 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.
 *
 * The task is: using a custom cable, pretend to be a parallel port
 * peripheral.
 *
 * The cable to use is an IEEE1284 DB25/DB25 cable with these tweaks:
 * 
 * nStrobe   <-> nAck         1  <-> 10
 * nAutofd   <-> Busy         11 <-> 14
 * nSelectin <-> Select       17 <-> 13
 * nInit     <-> nFault       15 <-> 16
 *
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include "parport.h"
#include "ppdev.h"

/* If we were really a peripheral, what would we call our control lines? */
#define Busy		PARPORT_CONTROL_AUTOFD
#define nAck		PARPORT_CONTROL_STROBE
#define nFault		PARPORT_CONTROL_INIT
#define nSelectIn	PARPORT_CONTROL_SELECT

static void syntax (void)      
{
  fprintf (stderr,
	   "Usage: vlp [OPTIONS] PORT\n"
	   "   or: vlp [-h|--help]\n"
	   "Pretend to be a printer on PORT.\n\n"
	   "  --ecp	use ECP (unimplemented)\n"
	   "  --epp	use EPP (unimplemented)\n");
  exit (0);
}

/* Wait for an interrupt, or until tv has elapsed. */
static int await_irq (int fd, struct timeval *tv)
{
  fd_set rfds;
  FD_ZERO (&rfds);
  FD_SET (fd, &rfds);
  return !select (fd + 1, &rfds, NULL, NULL, tv);
}

/* Get a handle to a parallel port device. */
static int open_pardevice (const char *dev)
{
  struct timeval tv;
  int reverse = 1;
  int busy = nAck | nSelectIn;
  int fd = open (dev, O_RDONLY | O_NOCTTY);
  int count;

  if (fd == -1)
    {
      perror (dev);
      return fd;
    }

  /* We need exclusive access to the port, since we have no intention of
   * releasing it. */
  if (ioctl (fd, PPEXCL) || ioctl (fd, PPCLAIM))
    {
      fprintf (stderr, "vlp: cannot gain exclusive access to port\n");
      close (fd);
      return -1;
    }

  /* Set control lines to indicate that we are not yet ready for data. */
  ioctl (fd, PPWCONTROL, &busy);

  /* Put data lines in reverse. */
  if (ioctl (fd, PPDATADIR, &reverse))
    {
      fprintf (stderr, "vlp: cannot reverse data lines\n");
      ioctl (fd, PPRELEASE);
      close (fd);
      return -1;
    }

  /* Clear out any pending interrupts. */
  ioctl (fd, PPCLRIRQ, &count);
  
  return fd;
}

void read_ecp (int fd)
{
  int mode = IEEE1284_MODE_ECP;
  int phase = IEEE1284_PH_REV_IDLE;
  if (ioctl (fd, PPSETMODE, &mode))
    {
	  perror ("SETMODE");
	  return;
	}
  if (ioctl (fd, PPSETPHASE, &phase))
    {
	  perror ("SETPHASE");
	  return;
	}
  for (;;) {
    char buffer[100];
    ssize_t got = read (fd, buffer, 100);
    if (got < 0)
      {
	perror ("read");
	return;
      }
    fwrite (buffer, got, 1, stdout);
  }
}

int main (int argc, char *argv[])
{
  int fd;
  int mode = -1;

  for (;;)
    {
      static struct option long_opts[] =
      {
	{ "help", 0, 0, 'h' },
	{ "ecp", 0, 0, 'c' },
	{ "epp", 0, 0, 'p' },
	{ 0, 0, 0, 0 }
      };
      int c = getopt_long (argc, argv, "h", long_opts, NULL);

      if (c == -1)
	break;

      if (c == 'h')
	syntax ();

      switch (c)
	{
	case 'c':
	  mode = IEEE1284_MODE_ECP;
	  break;

	case 'p':
	  fprintf (stderr, "This option is unimplemented. Sorry.\n");
	  exit (1);
	}
    }

  if (argc - optind != 1)
    syntax ();

  fd = open_pardevice (argv[optind]);
  if (fd == -1)
    return 1;

  switch (mode) {
  case -1:
    break;
  case IEEE1284_MODE_ECP:
    read_ecp (fd);
    return 0;
  }

  for (;;)
    {
      int irqc;
      int busy = nAck | nFault;
      int acking = nFault;
      int ready = Busy | nAck | nFault;
      char ch;

      /* Set up the control lines when an interrupt happens. */
      ioctl (fd, PPWCTLONIRQ, &busy);

      /* Now we're ready. */
      ioctl (fd, PPWCONTROL, &ready);

      if (await_irq (fd, NULL))
	/* Caught a signal? */
	continue;

      /* We are now marked as busy. */

      /* Fetch the data. */
      ioctl (fd, PPRDATA, &ch);

      /* Clear the interrupt. */
      ioctl (fd, PPCLRIRQ, &irqc);
      if (irqc > 1)
	fprintf (stderr, "Arghh! Missed %d interrupt%s!\n", irqc - 1,
						irqc == 2 ? "s" : "");

      /* Ack it. */
      ioctl (fd, PPWCONTROL, &acking);
      usleep (2);
      ioctl (fd, PPWCONTROL, &busy);

      putchar (ch);
    }

  return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: not available
URL: <http://lug-owl.de/pipermail/linux/attachments/20000302/9d1d1720/attachment.sig>


More information about the Linux mailing list