Adding a printer to CUPS

The GNOME 3 printer settings module looks like it will be great. The plan for adding a new printer is deceptively ambitious: the user interface design is that you click “+”, choose a printer device, and then click “Add” and the job is done.

For those unfamiliar with printing, this sounds easy enough. To make the user interface as easy to use as that takes more work than you would think at first glance. It’s the direction I’ve been moving towards in system-config-printer.

Here is a description of the issues involved.

  1. Once you’ve found a printer, you then have to choose a driver for it.
  2. Once you have a driver, it may need adjusting so that the installable
    options are correct.

Choosing a driver

The thing to know about choosing a driver is that it is not well-defined. CUPS takes care not to take sides or pick favourites, and leaves it to the client application to decide which driver to use and indeed which drivers are likely to work for the printer.

There is no way to be certain you have a complete list of drivers that will work for a given printer. The most reliable way of matching up printers and drivers is to have each PPD file list all of the IEEE 1284 Device IDs for devices that it supports. This practice is not wide-spread, although there has been progress towards this in Fedora.

In response to a CUPS-Get-Devices IPP request, CUPS will have given you attributes describing the device: device-id, device-make-and-model, device-info and so on. Likewise, each driver has attributes in the response to CUPS-Get-PPDs describing itself, including ppd-make-and-model. However, device-make-and-model is not quite the same type of thing as ppd-make-and-model.

The device-make-and-model describes the make and model of the device. The ppd-make-and-model describes the make and model of the printer that the driver is written for, as well as the driver itself.

There is no canonical list of printer manufacturer names, and printer manufacturers routinely write their names differently, e.g. HP, Hewlett-Packard, Hewlett Packard, HEWLETT PACKARD, etc.

There are very often discrepancies between how the device describes its model name and how PPDs describe it, especially when it comes to drivers that support a range of models.

Since Fedora 13 we’ve had special RPM tags on driver packages which can be used to give the user the opportunity to install any packages containing drivers that are known to support this device, once we know the device-id. They are tagged with the make and model of the device as reported in its Device ID.

There isn’t really an easy way to pick the right driver. What system-config-printer does is filter the available drivers using a variety of methods to find a list of the drivers that might support the printer, and then sort them into a preference order based on some XML-coded rules.  Ways of finding candidate drivers include:

  • Matching MFG and MDL fields of the Device ID (but not all PPDs contain Device IDs)
  • Converting the ppd- and device-make-and-model strings at runtime into semi-canonical representations in hopes of getting a match that way (but this will not always be successful)
  • Looking for what look like model numbers and making this successively generic, e.g. 2215… 2210… 2200… 2000 (but the driver stands less chance of working the more generic the match)
  • Matching CMD fields of the Device ID (but this is only good for finding “generic” drivers, e.g. PCL)

After this, some PPDs are eliminated: those that seem to match but which depend on an optional PostScript module which is not present in this device. If the Device IDs match in the MFG and MDL fields, but the PPD’s CMD field has POSTSCRIPT and the device’s CMD field does not, the PPD is likely no good. (This is a recent convention but has been adopted by Ricoh.)

The reason for sorting PPDs into a preference order is that there are lots of situations where one driver is most likely better than another.  The situations are numerous but include:

  • If the manufacturer has supplied a driver, use that.
  • Otherwise, if we can send PostScript straight to the printer, we should probably do that rather than sending raster data.
  • …except if the printer does not come with a large amount of memory, in which case raster drivers may be more reliable.
  • Gutenprint is usually a high quality driver to use, so use that when possible.
  • …except if we’re printing to a colour laserjet, because Gutenrprint only provides black and white output at the moment.
  • Native CUPS drivers are generally preferred to the older-style Foomatic drivers.

…and so on.  I wrote about the mechanism used in system-config-printer a while ago.  The current rules are here.

Note that there may not be any driver you can choose that will work. There is no “fail-safe” driver that will work for all printers — not even sending them ASCII text or some sort of bitmap.

Setting installable options

Now, assuming you have chosen the right driver it may need some tweaking once it has been assigned. This is because printers have optional parts, e.g. extra memory, duplexer units, binders, staplers etc.

CUPS provides a way to ask the printer to tell CUPS what those settings are: it’s a special print job of type CUPS-Command that says “AutoConfigure”. There are attributes that will tell you whether CUPS-Command jobs are accepted, and if so whether the AutoConfigure command job is accepted. If this is the case, sending this small job should complete the set-up of the PPD.

Most (if not all) non-PostScript printer drivers do not support the CUPS-Command format, however. If there are installable options in this case (which you can detect by seeing if there is an InstallableOptions group in the PPD), the only way to avoid asking the user about them is to hope the defaults are safe to use as they are.






2 responses to “Adding a printer to CUPS”

  1. Jiri avatar

    Very nice and complex.
    It has put all the puzzle pieces together for me.
    Thank you Tim!

  2. Anon avatar

    WDOXD? – “What does OSX do?”

    This all sounds extremely complicated. Thank goodness you’re hiding it away!