IPP has taken over the world of general purpose printing. Its latest evolution, "IPP Everywhere" allows printer capabilities (duplex, trays, and so on) to be retrieved directly from the printer over the network. This means that printers no longer have to convey these capabilities to clients out-of-band in the form of a PPD file. "Driverless" printing is now a reality!
As a result, CUPS has deprecated support for traditional printer drivers. In the future, only queues using the everywhere driver will be supported.
IPP Everywhere printers are discovered on a local network via mDNS. The driverless list command will use Avahi to browse for printers and display their URIs. A CUPS queue can then be configured for a discovered printer with lpadmin -p queuename -v device-uri -m everywhere. The queue's PPD will be generated by CUPS based on the queried printer capabilities. Such such a queue can be identified by examining the generated PPD for a line containing *PCFileName "ippeve.ppd".
The PPD generator from cups-filters can also be used if the queue is configured with lpadmin -p queuename -v device-uri -m driverless:device-uri.
Legacy printers
What of traditional printers that don't support IPP? These are now relegated to the ever-growing class of legacy technology. Once CUPS goes ahead with dropping support for non-IPP Everywhere printers, presumably the mechanism for printing to them will move to cups-filters and we'll have to run an additional printer server which CUPS will see as an IPP Everywhere printer; this sever will use the traditional filters to convert print jobs to the printer's native PDL and send them on their way.
IPP over USB
IPP uses HTTP as its transport, which in turn uses TCP/IP. But manufacturers will continue to produce printers that are connected via USB and are not accessible via any network address. How do they fit into this new IPP-only world?
The answer is that an IPP transport is defined over USB. We could call this IPP/USB, as opposed to IPP/IP which would use the traditional HTTP transport (which itself uses TCP/IP).
The IPP USB Specification (from the USB-IF web site explains that an IPP/USB printer must have at least two USB interfaces, so that the printer status can be monitored on one interface while a job is being sent on another. The interfaces must have the following properties:
- bInterfaceClass
- 0x07 (base class for printers)
- bInterfaceSubClass
- 0x01 (subclass for printer devices)
- bInterfaceProtocol
- 0x04 (IPP USB interface)
The interfaces must also have a descriptor as follows:
- bCapabiltiesType
- 0x00 (IPP Basic Capabilities Descriptor)
- wBasicCapabilities
- 16 bits indicating whether whether the printer can print, scan, fax, hosts an embedded web server, and so on
- iIPPVersionsSupported
- Comma delimited list of IPP versions supported, or 0x00 if this information should be retrieved over IPP
- iIPPPrinterUUID
The "printer-uuid" IPP attribute value for the printer at /ipp/print, or 0x00 if this information should be retrieved over IPP
All IPP/USB requests are sent to the USB interface's Bulk OUT endpoint, and responses are read from the interface's Bulk IN endpoint.
IPP/USB HTTP requests are HTTP/1.1, which requires the presence of a Host header. Host: localhost is mandated to fulfil this requirement.
The printer lives at /ipp/print. If the printer embeds a general purpose web server then it can be found at /. /icon.png can provide a 128x128 icon of the printer for display to the user.
ippusbxd implements IPP/USB on Linux. It proxies requests that its web server receives through to an IPP/USB printer. It's a little bit noddy because the end-user needs to decide whether it should listen on localhost (in which case Avahi won't work without being patched), or a dummy interface that the end-user has to create and assign an address to.
This could probably be improved by having ippusbxd create the dummy interface, assigning it an IPv6 ULA so that the network address is guaranteed not to conflict with any other network. It can then publish the address with a unique name (e.g., ippusbxd-$HOSTNAME.local and publish a service for each printer it discovers under this hostname.