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…