Code:
/*
* Parallel port control program
*
* Copyright 2002 Stefan Bachmaier <stefan@tracefog.de>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This program can read and write the control, data and status bits on the parallel port.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include </usr/src/linux/include/asm/io.h>
#define DATA 0x378 /*
* printer port base address
*/
#define STATUS DATA+1 /*
* status bits are 1 byte behind
*/
#define CONTROL DATA+2 /*
* control bits are 2 bytes behind
*/
/*
<= in DB25 Cent Name of Reg
=> out pin pin Signal Bit Function Notes
------ ---- ---- -------- --- -----------------------------
=> 2 2 Data 0 D0 Set to least significant data
=> 3 3 Data 1 D1 ...
=> 4 4 Data 2 D2 ...
=> 5 5 Data 3 D3 ...
=> 6 6 Data 4 D4 ...
=> 7 7 Data 5 D5 ...
=> 8 8 Data 6 D6 ...
=> 9 9 Data 7 D7 Set to most significant data
<= 15 32 /Error S3+ Low for Error/Offline/PaperEnd
<= 13 13 Select S4+ High for printer selected
<= 12 12 PaperEnd S5+ High for out of paper
<= 10 10 /Ack S6+ IRQ Low Pulse ~ 5 uS, after accept
<= 11 11 Busy S7- High for Busy/Offline/Error
=> 1 1 /Strobe C0- Set Low pulse >0.5 us to send
=> 14 14 /AutoFd C1- Set Low to autofeed one line
=> 16 31 /Init C2+ Set Low pulse > 50uS to init
=> 17 36 /SelectIn C3- Set Low to select printer
== 18-25 19-30, Ground
33,17,16
*/
short data = 0;
short status = 0;
short control = 0;
short x = 0, y = 0;
int c = 0, cr = 0;
int set_status = 0;
short quiet_mode = 0;
void printparams ();
void printbits ();
int main (int argc, char *argv[])
{
if (ioperm (DATA, 3, 1))
{
fprintf (stderr, "Couldn't get the port at %x\ntry it as root.\n", DATA);
exit (1);
}
data = inb (DATA);
control = inb (CONTROL);
// invert bit 0, 2 and 3 (1101)
control ^= 0x0b;
while (1)
{
cr = getopt (argc, argv, "q");
if (cr == -1)
break;
switch (cr)
{
case 'q':
quiet_mode = 1;
break;
}
}
if (argc < 2)
{
printparams ();
printbits ();
return 0;
}
if ((argc - optind) != 2)
{
printf ("wrong params!\n");
printparams ();
return 0;
}
c = argv[optind][0];
if (argv[optind][1] != 0 || !((c >= '0' && c <= '8') || c == 'q' || c == 'w' || c == 'e' || c == 'r' || c == 't'))
{
printf ("wrong params!\n");
printparams ();
return 0;
}
set_status = 1;
if (strcmp (argv[optind + 1], "on") != 0)
{
set_status = 0;
if (strcmp (argv[optind + 1], "off") != 0)
{
set_status = 2;
if (strcmp (argv[optind + 1], "toggle") != 0)
{
printf ("you must provide the status (on|off|toggle)!\n");
return 0;
}
}
}
if (!quiet_mode)
printf ("Pin #%c, status: %s (%d)\n", c, argv[optind + 1], set_status);
x = -1;
// DATA pins 2-9
if (c == '0')
{
x = 1;
}
if (c == '1')
{
x = 2;
}
if (c == '2')
{
x = 4;
}
if (c == '3')
{
x = 8;
}
if (c == '4')
{
x = 16;
}
if (c == '5')
{
x = 32;
}
if (c == '6')
{
x = 64;
}
if (c == '7')
{
x = 128;
}
if (c == '8')
{
x = 255;
}
// SELECT, INIT, /AUTO_FEED, /STROBE at pins 17, 16, 14 and 1
y = -1;
if (c == 'q')
{
y = 15;
}
if (c == 'w')
{
y = 1;
}
if (c == 'e')
{
y = 2;
}
if (c == 'r')
{
y = 4;
}
if (c == 't')
{
y = 8;
}
if (x != -1)
{
switch (set_status)
{
case 0:
// put off
if (x == 255)
data = 0;
else
data = (data & (~x));
break;
case 1:
// set to on
if (x == 255)
data = 255;
else
data = (data | x);
break;
case 2:
// toggle
if (x == 255)
{
data ^= 255;
}
else
{
// bit schon gesetzt? falls schon ausmask. falls nicht einmask.
data = ((data & x) == x) ? (data & (~x)) : (data | x);
}
break;
default:
printf ("you must provide the status (on|off|toggle)!\n");
return 0;
break;
}
outb (data, DATA);
}
if (y != -1)
{
switch (set_status)
{
case 0:
// put off
if (y == 0)
control = 15;
else
control = (control & (~y));
break;
case 1:
// set to on
if (y == 15)
control = 15;
else
control = (control | y);
break;
case 2:
// toggle
if (y == 15)
{
control ^= 15;
}
else
{
// bit schon gesetzt? falls schon ausmask. falls nicht einmask.
control = ((control & y) == y) ? (control & (~y)) : (control | y);
}
break;
default:
printf ("you must provide the status (on|off|toggle)!\n");
return 0;
break;
}
outb (control ^ 0x0b, CONTROL);
}
if (!quiet_mode)
printbits ();
ioperm (DATA, 3, 0);
return 0;
}
void printparams ()
{
printf ("usage: lpic [-q] <pin number> <off|on|toggle>\n");
printf ("toggles level of pin\n");
printf ("where <number> is from 0-8 (8=all) or one of q,w,e,r,t (q=all), pin on, off or toggle.\n");
return;
}
void printbits ()
{
int db = 0;
int pb = 0;
int cb = 0;
status = inb (STATUS);
// invert bit 7 (1000000)
status ^= 128;
if (data & 1)
db += 1;
if (data & 2)
db += 10;
if (data & 4)
db += 100;
if (data & 8)
db += 1000;
if (data & 16)
db += 10000;
if (data & 32)
db += 100000;
if (data & 64)
db += 1000000;
if (data & 128)
db += 10000000;
if (status & 8)
pb += 1;
if (status & 16)
pb += 10;
if (status & 32)
pb += 100;
if (status & 64)
pb += 1000;
if (status & 128)
pb += 10000;
if (status & 1)
cb += 1;
if (control & 2)
cb += 10;
if (control & 4)
cb += 100;
if (control & 8)
cb += 1000;
printf ("-------------\n");
printf ("Data Bits: [%08d] (%d)\n", db, data);
printf ("Data0:\t\t0(pin 2)\t%s\n", data & 1 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data1:\t\t1(pin 3)\t%s\n", data & 2 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data2:\t\t2(pin 4)\t%s\n", data & 4 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data3:\t\t3(pin 5)\t%s\n", data & 8 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data4:\t\t4(pin 6)\t%s\n", data & 16 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data5:\t\t5(pin 7)\t%s\n", data & 32 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data6:\t\t6(pin 8)\t%s\n", data & 64 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Data7:\t\t7(pin 9)\t%s\n", data & 128 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("-------------\n");
printf ("Control Bits: [%04d] (%d)\n", cb, control);
printf ("/Strobe:\tw(pin 1)\t%s\n", control & 1 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("/Auto_feed:\te(pin 14)\t%s\n", control & 2 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("Init:\t\tr(pin 16)\t%s\n", control & 4 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("/SelectIn:\tt(pin 17)\t%s\n", control & 8 ? "HIGH\t(+5V)" : "LOW\t(GND)");
printf ("-------------\n");
printf ("Input Bits: [%05d] (%d)\n", pb, status);
printf ("Error:\t\t(pin 15)\t%s\n", status & 8 ? "OPEN\t(N/C)" : "CLOSE\t(GND)");
printf ("Select:\t\t(pin 13)\t%s\n", status & 16 ? "OPEN\t(N/C)" : "CLOSE\t(GND)");
printf ("Paperend:\t(pin 12)\t%s\n", status & 32 ? "OPEN\t(N/C)" : "CLOSE\t(GND)");
printf ("Ack:\t\t(pin 10)\t%s\n", status & 64 ? "OPEN\t(N/C)" : "CLOSE\t(GND)");
printf ("/Busy:\t\t(pin 11)\t%s\n", status & 128 ? "OPEN\t(N/C)" : "CLOSE\t(GND)");
printf ("-------------\n");
return;
}
Lesezeichen