The printer is accessible through /dev/lp0; in the same way, the
parallel port itself is accessible through /dev/parport0. The
difference is in the level of control that you have over the wires
in the parallel port cable.
With the printer driver, a user-space program (such as the
printer spooler) can send bytes in "printer protocol". Briefly,
this means that for each byte, the eight data lines are set up,
then a "strobe" line tells the printer to look at the data lines,
and the printer sets an "acknowledgement" line to say that it got
the byte. The printer driver also allows the user-space program to
read bytes in "nibble mode", which is a way of transferring data
from the peripheral to the computer half a byte at a time (and so
it's quite slow).
In contrast, the ppdev driver (accessed via /dev/parport0)
allows you to:
examine status lines,
set control lines,
set/examine data lines (and control the direction of the
data lines),
wait for an interrupt (triggered by one of the status
lines),
find out how many new interrupts have occurred,
set up a response to an interrupt,
use IEEE 1284 negotiation (for telling peripheral which
transfer mode, to use)
transfer data using a specified IEEE 1284 mode.
Programming interface
The ppdev interface is largely the same as that of other
character special devices, in that it supports open, close, read,
write, and ioctl. The constants for the ioctl commands are in
include/linux/ppdev.h.
Starting and stopping: open and close
The device node /dev/parport0 represents any device that
is connected to parport0, the first parallel port in the system.
Each time the device node is opened, it represents (to the process
doing the opening) a different device. It can be opened more than
once, but only one instance can actually be in control of the
parallel port at any time. A process that has opened /dev/parport0
shares the parallel port in the same way as any other device
driver. A user-land driver may be sharing the parallel port with
in-kernel device drivers as well as other user-land drivers.
Control: ioctl
Most of the control is done, naturally enough, via the
ioctl call. Using ioctl, the user-land driver can control both the
ppdev driver in the kernel and the physical parallel port itself.
The ioctl call takes as parameters a file descriptor (the one
returned from opening the device node), a command, and optionally
(a pointer to) some data.
PPCLAIM
Claims access to the port. As a user-land device driver
writer, you will need to do this before you are able to actually
change the state of the parallel port in any way. Note that some
operations only affect the ppdev driver and not the port, such as
PPSETMODE; they can be performed while access to the port is not
claimed.
PPEXCL
Instructs the kernel driver to forbid any sharing of the
port with other drivers, i.e. it requests exclusivity. The PPEXCL
command is only valid when the port is not already claimed for use,
and it may mean that the next PPCLAIM ioctl will fail: some other
driver may already have registered itself on that port.
Most device drivers don't need exclusive access to the
port. It's only provided in case it is really needed, for example
for devices where access to the port is required for extensive
periods of time (many seconds).
Note that the PPEXCL ioctl doesn't actually claim the port
there and then---action is deferred until the PPCLAIM ioctl is
performed.
PPRELEASE
Releases the port. Releasing the port undoes the effect of
claiming the port. It allows other device drivers to talk to their
devices (assuming that there are any).
PPYIELD
Yields the port to another driver. This ioctl is a kind of
short-hand for releasing the port and immediately reclaiming it. It
gives other drivers a chance to talk to their devices, but
afterwards claims the port back. An example of using this would be
in a user-land printer driver: once a few characters have been
written we could give the port to another device driver for a
while, but if we still have characters to send to the printer we
would want the port back as soon as possible.
It is important not to claim the parallel port for too
long, as other device drivers will have no time to service their
devices. If your device does not allow for parallel port sharing at
all, it is better to claim the parallel port exclusively (see
PPEXCL).
PPNEGOT
Performs IEEE 1284 negotiation into a particular mode.
Briefly, negotiation is the method by which the host and the
peripheral decide on a protocol to use when transferring data.
An IEEE 1284 compliant device will start out in
compatibility mode, and then the host can negotiate to another mode
(such as ECP).
The ioctl parameter should be a pointer to an int; values
for this are in incluce/linux/parport.h and include:
IEEE1284_MODE_COMPAT
IEEE1284_MODE_NIBBLE
IEEE1284_MODE_BYTE
IEEE1284_MODE_EPP
IEEE1284_MODE_ECP
The PPNEGOT ioctl actually does two things: it performs
the on-the-wire negotiation, and it sets the behaviour of
subsequent read/write calls so that they use that mode (but see
PPSETMODE).
PPSETMODE
Sets which IEEE 1284 protocol to use for the read and
write calls.
The ioctl parameter should be a pointer to an int.
PPGETMODE
Retrieves the current IEEE 1284 mode to use for read and
write.
PPGETTIME
Retrieves the time-out value. The read and write calls
will time out if the peripheral doesn't respond quickly enough. The
PPGETTIME ioctl retrieves the length of time that the peripheral is
allowed to have before giving up.
The ioctl parameter should be a pointer to a struct
timeval.
PPSETTIME
Sets the time-out. The ioctl parameter should be a pointer
to a struct timeval.
PPGETMODES
Retrieves the capabilities of the hardware (i.e. the modes
field of the parport structure).
PPSETFLAGS
Sets flags on the ppdev device which can affect future I/O
operations. Available flags are:
PP_FASTWRITE
PP_FASTREAD
PP_W91284PIC
PPWCONTROL
Sets the control lines. The ioctl parameter is a pointer
to an unsigned char, the bitwise OR of the control line values in
include/linux/parport.h.
PPRCONTROL
Returns the last value written to the control register, in
the form of an unsigned char: each bit corresponds to a control
line (although some are unused). The ioctl parameter should be a
pointer to an unsigned char.
This doesn't actually touch the hardware; the last value
written is remembered in software. This is because some parallel
port hardware does not offer read access to the control
register.
The control lines bits are defined in
include/linux/parport.h:
PARPORT_CONTROL_STROBE
PARPORT_CONTROL_AUTOFD
PARPORT_CONTROL_SELECT
PARPORT_CONTROL_INIT
PPFCONTROL
Frobs the control lines. Since a common operation is to
change one of the control signals while leaving the others alone,
it would be quite inefficient for the user-land driver to have to
use PPRCONTROL, make the change, and then use PPWCONTROL. Of
course, ea