USB Parallel Port Interfacing

Parallel Ports are a vanishing technology. Few, if any, modern desktop computers have them.

There are however very inexpensive USB to printer "cables" that provide a replacement for the vanishing "parallel port", at least for the purpose of connecting a parallel printer. These gadgets usually advertise themselves as supporting an IEEE-1284 printer device.

To answer a question that many are asking (and to run off on a bit of a tangent), these devices do NOT emulate the registers of a legacy ISA parallel port. They cannot and never will. This means that if you have a device (and usually software to go with it) that expects to find "parallel port registers" at base addresses of 0x378 or 0x278, you are SOL (Sadly outa luck).

Most of the devices of this sort that I have gotten my hands on contain a Prolific Technologies 2305 chip. The datasheet calls this a "PL-2305 USB-to-IEEE-1284 Bridge Controller". If you look at the datasheet you will discover that this device includes a microcontroller (and if you really understand what is going on, you will realize that it must) that serves as a protocol translator between the USB interface and the printer interface. Here is a "reference schematic" for a circuit using this device.

Devices built around this device are usually marketed as "cables", with the PL-2305 chip tucked away inside the end that connects to the printer. They usually cost about $10.00 - making them an attractive bargain. The question is, what can be done in the way of using one of these to read or control bits.

When I plug one of the devices I have into my linux machine, it is recognized as a USB device with Vendor 0x067B and device 0x2305:

trona kernel: [1949229.913021] usb 2-5: new full-speed USB device number 9 using ohci_hcd
trona kernel: [1949230.102756] usb 2-5: New USB device found, idVendor=067b, idProduct=2305
trona kernel: [1949230.102760] usb 2-5: New USB device strings: Mfr=1, Product=2, SerialNumber=0
trona kernel: [1949230.102763] usb 2-5: Product: IEEE-1284 Controller
trona kernel: [1949230.102765] usb 2-5: Manufacturer: Prolific Technology Inc.
trona kernel: [1949230.111852] usblp0: USB Bidirectional printer dev 9 if 0 alt 1 proto 2 vid 0x067B pid 0x2305
trona mtp-probe: checking bus 2, device 9: "/sys/devices/pci0000:00/0000:00:02.0/usb2/2-5"
trona mtp-probe: bus: 2, device: 9 was not an MTP device

So linux sets up a device /dev/usblp0 to talk to this device. Note that if you read the Prolific datasheet, you will find that they make provision for customers to reprogram the chip with different vendor and device codes. This means that if you have a "cable" that identifies itself let's say as an Epson device of some kind, it may still be a Prolific chip inside.

So the question now is how to write software that accesses the "usblp" driver that is hooked up behind the special file /dev/usblp0. Hand in hand with this goes the question of how to build hardware that we can connect to the 25 pin connector. If you are still thinking of using some software that talks to registers at 0x278 or 0x378, it is time for a reality check. It ain't happening!

You can go read the IEEE-1284 specification (which is not a bad idea, at least take a look at some of the summaries or paraphrases online). You will find that the specification supports 5 different modes. It is by no means clear which of these modes the Prolific chip supports, but it certainly supports EPP mode (and a look at the driver source usblp.c will also shed additional light). EPP mode provides an 8 bit data bus, a collection of handshake lines, and a protocol for clocking data in and out. The concept of clocking in and out are critical. It will not be possible to simply write data to the Prolific and have it appear on the pins corresponding to the data bus. (This is not totally true, it would be possible to write one byte of data, which would sit there forever waiting to be acknowleged by the handshake -- the parallel bus would then be locked up and subsequent writes would be suspended).

EPP mode supports data reads and writes, along with address reads and writes. This means it would be possible with two 8 bit latches and two 8 bit buffers to have 16 bits in and 16 bits out by building a simple circuit. Working out the details is an exercise I leave to the reader.

In his blog, a fellow named Steven Harms fiddled with this a bit. I compiled and ran his program (in 2012 on a linux 3.3.2 kernel) and it failed to get the protocols.

In another blog, a fellow actually built a circuit to latch data and display a little light show on a set of 8 LED's.


Have any comments? Questions? Drop me a line!