What happens when I print a page? How does it discover available printers? What does a printer driver provide?
These are some of the questions I had for a while especially the discovery side because I, too, once suffered from “my desktop cannot find the printer”.
This writing is based on working with Ubuntu 26 and CUPS 2.4.1. Every commands and output from now should assume the aforemented environment unless otherwise noted.
CUPS
CUPS (Common UNIX Printing System) is an open source printing system. “Printing system” is a pretty vague terminology and, to be more vague, it is a system that handles discovery and management of printers and handling of print jobs so that the input content gets forwarded to the physical printer; it provides abstraction that user can print a content with a button.
cups service
The cups doc service is the printing system running as a daemon. Every time a print dialog is opened,
an application queries the cups service which queues (i.e. printers) are available.
The config file for cups is at /etc/cups/cupsd.conf.
| |
Discovery and cups-browsed sevice
When using modern OS and printers, the OS (Ubuntu, MacOS, etc) automatically makes the printer available when they are connected to the network using mDNS (multicast DNS) and DNS-SD (SND service discovery). These method allows the device to announce its address so other nodes on the network can be discovered without involving a DNS server.
A host must listen on mDNS port 5353 in order to discover them.
In Ubuntu, daemon that automatically discovers and adds the printer is called cups-browsed.
So if your desktop does not detect a printer or lost connection, it’s worth looking at firewall configs or if printer was added with an IP and it changed beceause router’s DHCP allocated a different IP.
Printer drivers (PPD, filters)
Each printers come with their own features such as automatic cutter for label printer or duplex printing, and also different machine level interpretation. These information is in the driver which contains the *.ppd file and is a text-readable file. It contains the printer model name, options and filters (filters will be explained later) among many other things.
Note that the following is abbreviated and incomplete ppd file.
| |
What’s interesting about the file is it contains information to render the printing options dialog. Localization and contraints (when a setting’s value is invalid) is contained in the file.
Printer management
As mentioned earlier, cups-browsed may auto-discover a printer but user can also manually define one.
CUPS daemon conveniently provides a management UI and is available at http://localhost:631 if the
daemon config is set to allow UI. WebInterface in cupsd.conf controls the web UI availability.
For those who prefer CLI, lpadmin is available add or modify printers.
CUPS keeps the added printers at /etc/cups/printers.conf. However, it is crucial to not
modify this file directly while CUPS is running as it maintains a runtime copy and flushes, so
a change in the config file may not be readily available to CUPS or even lost.
Command lpstat -a will print all available printers. Note that a similar command lpstat -e
will show all available printers on the network.
Print job
When we open up a print dialog and submit a content to print, we are submitting a job to a CUPS destination. In the context of CUPS, the term “queue”, “printer” or “destination” are sometimes used interchangeably.
One can also use CLI lp to print a content.
Host to CUPS protocol is called IPP (Internet Printing Protocol). Printer on the other hand, may accept a different protocols such as raw TCP socket, IPP, etc. The differences are handled by CUPS and the printer driver such that applications wanting to print can simply talk in IPP with CUPS.
The print job contains the content such as PDF, printing parameters such as how many pages to print and printer specific params such as color options, job ID among other things.
The printing content’s type can vary. It could be an image, a document like PDF, plaintext, etc. There needs to be a way normalize this and also convert into a machine code the printer can understand – this done by filters.
CUPS filters
Filters are essentially a function that converts a file from one media type to another. A CLI
tool cupsfilter (now deprecated) can be used to test which filters a printing job would go
through.
| |
which outputs something like this
| |
--list-filterI’m only interested in what filteres are used and not the actual result after applying the filter.-eUse the filters defined in the PPD file. Without this, it wouldn’t use the filters in PPD.-pPPD file-mDestination MIME file type. For printer, must useprinter/foo.-oPrinter options. In the example above, I only specified a single option.
The output tells which filters doc.pdf would go through (pdftopdf -> gstoraster -> PPD defined filter).
How does CUPS know how to go through that steps? PPD file’s specifies which MIME type it should
produce and *.convs and *.types files contains which filters and the associated cost.c:wa
filter MIME (media type). *.convs and *.types
In our PPD file above, it contained the following line *cupsFilter: "application/vnd.cups-raster 0 /opt/myprinter_vendor/cups/lib/filter/abcdefg_filter".
This tells we want the result of MIME type to be application/vnd.cups-raster) and then apply the
abcdefg_filter afterwards, and lastly, send the resulting data to the printer. How it converts
are defined in the *.convs and *.types files.
In /usr/share/cups/mime, there are various *.convs and *.types files.
| |
The convs file defines the cost associated with converting from one MIME type to another.
Note that this capability is not unique to CUPS. See mime.convs(5)
| |
This tells it costs 66 to convert from application/pdf to application/cnd.cups-pdf if it
uses pdftopdf filter.
The types file defines how to determine a MIME type in the file’s magic bytes.
Also again, this capability is not unique to CUPS. See mime.types(5)
| |
So given these files, it finds the path to convert to application/vnd.cups-raster. (Note that
it is possible to have two paths with the same cost. I was not able to find documentation what
would happend in this case.)
After producing the CUPS raster format, it then goes through the driver specific filter and produces the data format the printer can understand.
The filters are installed from cups-filters package. An interesting observation is that filters
are binaries installed on the host, so the versions and resolved filter chain
could differ depending on the host and result in differing print quality.
Although I personally have not encounted this issue, it appears to be true, and hopefully, a rare case. MacOS, for example, also uses CUPS but have their own filters that are proprietary as a result of their own Core Graphics Framework.
Things worth learning more
- Print job state and management.
- CUPS has a notion of “class” which, from my limited understanding, is grouping of printers.
- CUPS v3.
- Driverless printing.
- How does printing work on Windows.