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