AirPrint in Leopard PowerPC (10.5, G4 mini)

Being fundamentally fed up with Apple’s (let’s face it, somewhat arbitrary) AirPrint limitations, and without wanting to mess up my configuration unduly, I recently spent a few hours yak shaving and getting CUPS to work on my NSLU2 using cups-pdf - an ordeal I won’t recommend to anyone, and which nevertheless rendered a very slow print server that I’ve only seldom used.

But then it dawned on me that I could do basically the same with my G4 mini, and that to do so only required some Bonjour tweaking.

There are (or so I gather) two basic requirements for iOS to recognize your shared printer on the network (asides from compatibility, format support, etc., etc.):

  • It being announced with a _universal subtype (i.e., _universal._sub._ipp._tcp)
  • It sporting an URF text record (URF=none will do, and is the honest to goodness truth when you’re reporting the printer’s capabilities)

With those two pieces of information in hand, I then proceeded to shave another (smaller, but feisty) yak in the shape of dns-sd, which is easily one of the most obtuse pieces of software ever written.

As an aside, and before we dive in, a note for later reference: Some of the original hacks relied on adding an extra line to the cupsd MIME types (in mime.types or local.types) like so:

image/urf urf (0,UNIRAST<00>)

…but that only helped with faking URF support since Snow Leopard apparently does the Bonjour announcements properly already, so I had to resort to doing the whole thing from scratch.

On a Leopard/10.5 system, set up your printers as usual, marking them as “shared”. Then pop open a Terminal window and type dns-sd -B _ipp._tcp:

$ dns-sd -B _ipp._tcp
Browsing for _ipp._tcp
Timestamp     A/R Flags if Domain                    Service Type              Instance Name
23:44:33.832  Add     3  4 local.                    _ipp._tcp.                Hewlett-Packard PSC 900 Series @ mini
23:44:33.833  Add     2  4 local.                    _ipp._tcp.                Officejet 4500 G510g-m [6A5DF2] @ mini
^C
$

I want to mirror the first one for AirPrint, so first I get the detailed record by typing:

$ dns-sd -L "Hewlett-Packard PSC 900 Series @ mini" _ipp
Lookup Hewlett-Packard PSC 900 Series @ mini._ipp._tcp.local
23:44:48.814  Hewlett-Packard\032PSC\032900\032Series\032@\032mini._ipp._tcp.local. can be reached at mini.local.:631
 txtvers=1 qtotal=1 rp=printers/Hewlett_Packard_PSC_900_Series ty=HP\ PSC\ 950\ -\ Gutenprint\ v5.1.3 note=7D product=\(GPL\ Ghostscript\) printer-state=3 printer-type=0x900E Transparent=T Binary=T Color=T pdl=application/pdf,application/postscript,application/vnd.cups-raster,application/octet-stream,image/png
^C

Notice that it already announces PDF support, which is what iOS will rely upon for printing.

Then I grab the text record bits, tack on URF=none at the end, and register another service entry as _ipp._tcp,_universal (that was the tough bit to figure out, since the docs don’t cover registering subtypes):

$ dns-sd -R "AirPrint" _ipp._tcp,_universal local. 631 txtvers=1 qtotal=1 rp=printers/Hewlett_Packard_PSC_900_Series ty=HP\ PSC\ 950\ -\ Gutenprint\ v5.1.3 note=7D product=\(GPL\ Ghostscript\) printer-state=3 printer-type=0x900E Transparent=T Binary=T Color=T pdl=application/pdf,application/postscript,application/vnd.cups-raster,application/octet-stream,image/png URF=none
Registering Service AirPrint._ipp._tcp,_universal.local. port 631 TXT txtvers=1 qtotal=1 rp=printers/Hewlett_Packard_PSC_900_Series ty=HP\ PSC\ 950\ -\ Gutenprint\ v5.1.3 note=7D product=\(GPL\ Ghostscript\) printer-state=3 printer-type=0x900E Transparent=T Binary=T Color=T pdl=application/pdf,application/postscript,application/vnd.cups-raster,application/octet-stream,image/png URF=none
23:45:35.404  Got a reply for service AirPrint._ipp._tcp.local.: Name now registered and active

And bingo, mad printing ensued.

This should be easy enough to replicate in Python or Objective-C, but I’ll leave that as an exercise for my readership (since it makes sense that you keep track of printer state updates and mirror those).

Doing a shell script of some sort might be easier, though.

And now you can wonder why Apple hasn’t made this more widely available, given that I’m using a (for all intents and purposes) dead printer and got it to work with an obsolete version of their desktop OS…