home *** CD-ROM | disk | FTP | other *** search
- .oO Phrack 50 Oo.
-
- Volume Seven, Issue Fifty
-
- 11 of 16
-
-
- H A R D W A R E I N T E R F A C I N G F O R T H E
- L I N U X O P E R A T I N G S Y S T E M
-
- By The Professor <professr@hackerz.org>
-
- Computer control of real world devices has been an out of reach fantasy for
- most people. In the past, it has rarely been seen outside the R&D labs of
- hardware design companies, universities, and a few dedicated hobbyist's
- basements. It takes not only a skilled programmer, but also a person that can
- design and build small circuits.
-
- In this article, I will show you how to use a standard IBM/PC parallel
- printer port to control devices, such as bells, relays, and lights. I will
- also show you how to take input from devices such as DTMF decoder IC's, analog
- to digital converters, and switches.
-
- To access the I/O port, the compiled program must be either executed by root
- or be suid root. This could be a potential system security hazard so be
- warned. In order to grant permissions to the port, one must use the function
- ioperm().
-
- Syntax (also see the man page):
-
- #include <unistd.h>
- ioperm(BASE_ADDRESS,NUM,PERMISSION_BIT);
-
- The first parameter is the port number to set permissions of.
- The second parameter is the number of consecutive ports to set permissions of.
- (i.e. if num==3, BASE_ADDRESS, BASE_ADDRESS+1, and BASE_ADDRESS+2 are set).
- The third parameter is 1 to give the program permissions or 0 to remove them.
-
- Sending and receiving data via the port is done with the commands, inb() and
- outb().
-
- Syntax:
-
- #include <asm/io.h>
- value=inb(address); (address can be BASE_ADDRESS+1 or BASE_ADDRESS+2)
- outb(value,BASE_ADDRESS);
-
-
- O U T P U T
-
- Making individual output data lines of a parallel printer port "turn on" is as
- simple as selecting them with a corresponding binary value. Pin 2 (D0) is the
- least significant bit and pin 9 (D7) is the most significant bit. If you
- wanted bits 0, 2, 3, 4, and 6 to "turn on" or go high (+5v) while leaving 1,
- 5, and 7 low (ground) you would first convert the binary value to decimal and
- then send that value to the port. (actually, there is no reason why you can't
- just send the binary value to the port)
-
- D7 D6 D5 D4 D3 D2 D1 D0
- 0 1 0 1 1 1 0 1 == 1011101 == 93
-
- outb(93,BASE_ADDRESS);
-
- If you want all lines low or "off", you send a 0.
- If you want them all high or "on", you send 255.
-
- Controlling the status of the individual bits of the I/O port is a simple
- way of controlling solid state relays, optocouplers, LED's and so on. You
- could very easily and very safely control a high wattage lighting system in
- this manner. (assuming you are using solid state relays with back EMF
- protection). This could/would be good for closet cultivators experimenting
- with the horticulture of cannabis sativa or any other plant. Have you ever
- wanted things such as lights and irrigation systems to come on or turn off at
- certain times? That's what your crontab file is for! The possibilities are
- endless.
-
-
- I N P U T
-
- Standard IBM/PC parallel printer ports have nine control lines capable of
- inputting real world data. Each printer port has three address locations. The
- base address is used to transmit data. The next address can input five data
- bits, using pins 11, 10, 12, 13, and 15 (referred to as BASE_ADDRESS+1 I7
- through I3), and the third port address can input or output a nibble of
- information using pins 17, 16, 14, and 1 (referred to as BASE_ADDRESS+2 I3
- through I0). The third port address pins must be set HIGH so we can read from
- BASE_ADDRESS+2. I'll show you how in the example.
-
- The inputs are all active LOW, meaning your device must short them to ground
- to create a signal (switch, analog to digital converter, DTMF decoder, etc).
- This is not a problem, as most devices already do this. The ones that don't,
- just use an inverter.
-
- The simplest method of inputting eight data bits is to read the high nibble
- from the (BASE_ADDRESS+1) and the low nibble from the (BASE_ADDRESS+2). These
- two nibbles can be logically ORed together to form a data byte. Some of the
- data bits are hard-wired on the printer card for active HIGH operation. To
- get around this, I use four sections of a 7404 hex inverter to re-invert the
- inverted data lines.
-
- I7 I6 I5 I4 I3 I2 I1 I0 BASE_ADDRESS+1 INPUT LINES
- 11 10 12 13 15 -- -- -- PIN NUMBER (-- = NOT USED)
-
- I7 I6 I5 I4 I3 I2 I1 I0 BASE_ADDRESS+2 INPUT LINES
- -- -- -- -- 17 16 14 1 PIN NUMBER (-- = NOT USED)
-
- Notice both I3's of both ports are used. Pin 15 (ERROR) is the 9th input
- of a standard IBM/PC parallel printer port. No offense to this pin, but it's
- a pain in the ass to use and I only use it when I *have* to. Through
- software, I disregard it.
-
- Check out this example:
-
- /* next line sets all open collector output pins HIGH
- so we can read from BASE_ADDRESS+2) */
- outb(inb(BASE_ADDRESS+2) || 15 , BASE_ADDRESS+2);
- High_Nibble = inb(BASE_ADDRESS+1);
- Low_Nibble = inb(BASE_ADDRESS+2);
- High_Nibble = High_Nibble & 0xF0; /* 0xF0 = 11110000 */
- Low_Nibble = Low_Nibble & 0x0F; /* 0x0F = 00001111 */
- Data_Byte = High_Nibble | Low_Nibble;
-
- Pretty simple, eh? This means you can use I7 through I4 in BASE_ADDRESS+1
- and I3 through I0 in BASE_ADDRESS+2 to give you 8 bits of data input.
-
- All of the data lines must use a pull up resistor. This includes the
- hard-wired active HIGH pins *after* the 7404 inverter. This lets any device
- produce both a high and low logic signal. Pull up resistors simply pull all
- the data lines high so software sees all 0's unless you short a pin to ground.
- (Remember these are all active LOW inputs -ground means 1)
-
- Pins 14, 17, 1, and 11 are all hard-wired for active HIGH operation. These
- are the pins that are signaled through the 7404 inverter IC (which makes them
- just like the rest of the pins for ease of use).
-
- NOTES:
-
- *** When compiling programs using these routines, use the -O2 optimize flag,
- or else you'll have some headaches.
-
- Port 888 is the 1st parallel printer port (LPT1)
-
- I am not responsible for your mistakes. If you plug 120vAC directly into
- your parallel port, I guarantee you'll destroy your computer. Use optically
- isolated solid state relays to switch high current.
-
- For any more info regarding I/O port programming, schematics to some fun
- projects, or to send a complaint, e-mail professr@hackerz.org
-
- If you don't like my code, keep in mind that I design hardware for a living.
- I am not a programmer, nor have I ever claimed to be one. My programs are
- elegant on occasion, but mostly just get the job done without actually doing
- it the best way.
-
- If you want schematics showing how to hook up the 7404 to the port, mail me.
-
- I have some interesting things there regarding circuit design. One of my
- favorites is a software package called "PADS" Personal Automated Design
- Software. It is a CAD package for schematics and PCBoard Design. The copy
- on my web page is a public domain demo. This demo is fully functional in
- every way. It only limits you to something like 20 IC's, 300 tie points, etc.
- I usually do not go over these limits.
-
- Maybe this article will replace the IO-Port [mini] How-To 'cause that is only
- about 24 lines of text.
-
- E X A M P L E S
- A N D
- D I A G R A M
-
- /* simple program to send data via parallel port */
-
- #include <unistd.h>
- #include <asm/io.h>
- #define BASE_ADDRESS 888 /* 1st Parallel Port */
-
- main() {
- int port_data=0;
- int Data_Byte=255;
- ioperm(BASE_ADDRESS,3,1); /* set permission on port */
- outb(Data_Byte,BASE_ADDRESS);
- printf("Sent 255 to port %d to turn all pins HIGH\n",BASE_ADDRESS);
- ioperm(BASE_ADDRESS,3,0); /* take away port permission */
- return(0);
- }
- /* end of simple program to send data via parallel port */
- /****************************************************************************/
- /* simple program to take in 8 bit input via parallel port */
-
- #include <unistd.h>
- #include <asm/io.h>
- #define BASE_ADDRESS 888 /* 1st Parallel Port */
-
- main() {
- int port_data=0;
- int High_Nibble, Low_Nibble, Data_Byte;
- ioperm(BASE_ADDRESS,3,1); /* set permission on port */
- outb(inb(BASE_ADDRESS+2) || 15 , BASE_ADDRESS+2);
- High_Nibble = inb(BASE_ADDRESS+1);
- Low_Nibble = inb(BASE_ADDRESS+2);
- High_Nibble = High_Nibble & 0xF0; /* 0xF0 = 11110000 */
- Low_Nibble = Low_Nibble & 0x0F; /* 0x0F = 00001111 */
- Data_Byte = High_Nibble | Low_Nibble;
- printf("LN=%d HN=%d DB=%d\n",Low_Nibble,High_Nibble,Data_Byte);
- ioperm(BASE_ADDRESS,3,0); /* take away port permission */
- return(0);
- }
- /* end of simple program to take in 8 bit input via parallel port */
- /****************************************************************************/
- I I I I I
- 0 6 7 5 4
-
- P
- A
- _ P
- S E S
- T R E
- R _ B | L
- O A U E E
- B D D D D D D D D C S N C
- E 0 1 2 3 4 5 6 7 K Y D T
- _____________________________________
- 1 (o o o o o o o o o o o o o) 13
- 14 \ o o o o o o o o o o o o/ 25
- `---------------------------------'
- _ _ | PINS 18 |
- A E I S |<----THROUGH 25---->|
- U R N E | GROUND |
- T R I L
- O O T |
- | R I
- F N
- E P
- E U
- D * T ** ERROR LINE IS NOT USED AS I3
- * (DISREGARDED VIA SOFTWARE)
- I I I I
- 1 3 2 3
-
- /******************** End of my little text file / how-to *******************/
-
- EOF
-