Step-by-step tutorial to enable Airprint and Google Cloud Print using Optware - mostly load-and-go, very little editing, no patching… tested and required ipkg files are supplied….
0. Assumptions and Necessary Equipment:
- Broadcom-based router with 2 USB ports (can be via a powered USB hub), flashed with TomatoUSB (or DD-WRT)
- the router's hostname should NOT be Airprint (that could create some confusion)
- your router's settings should not block Multicast traffic
- ssh access via terminal/console to your router, and a familiarity w/ CLI operations
- USB printer that is supported by p910nd (nearly all USB printers are), w/ USB cable
- home/office network that has full access to internet
- desk-/lap-top running Linux/OS X/Windows, with drivers for the USB printer already loaded and known-working
- linux printing support for your USB printer needs to be researched and well-understood
- Optware (preferably a new/fresh installation) set up on a partition with a lot of space, at least 500MB. This could be via a USB drive or CIFS mount with an ext2 loop-mounted partition. A really good choice is a USB 2.5 inch hard drive, if you have such a drive to spare - a hard drive is more durable in this setting than a flash drive. For a good primer on Optware a la Broadcomm routers, see this tutorial : http://tomatousb.org/tut:optware-installation
- check that your Optware setup has the proper startup and shutdown script loops installed in your router : see Notes: Optware initscript loops below
- Strongly consider setting up swap space for your router.
- Understanding of the need for TWO print streams, one for iOS clients, another for desktop and laptop clients
- you understand how to edit and save a file with the nano editor
1. Get your USB printer working with your TomatoUSB or DD-WRT router.
TomatoUSB : Go to webif: Admininstration -> USB -> enable USB printer and printer sharing.
reference: http://tomatousb.org/tut:configure-printer-in-windows
DD-WRT : Go to webif:
reference: https://sites.google.com/site/wl520gu/
http://www.dd-wrt.com/wiki/index.php/Printer_Sharing
In either case, what is happening here is that you are enabling your USB printer to be connected to the router and network using the p910nd printer daemon. p910nd's function is to listen on the router's port 9100 for printer traffic, and to pass it directly to your attached USB printer.
Why use p910nd? Because:
- it works well
- it uses virtually no resources & saves your router's memory and cpu cycles for CUPS to do the iOS/Cloud-based printing
- it is already included in your router
TEST: You should be able to print from any desktop or laptop computer that is connected
via network to your TomatoUSB (or DD-WRT) router.
2. Install Base Packages: CUPS, Avahi and printer support
A. Download the tarball TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c.tar.gz , and to install some of its contents.
i. move to /opt, download the tarball, untar it, and install base packages
cd /opt
wget http://dl.dropboxusercontent.com/u/1015928/ddwrt/airprint-materials/TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c.tar.gz
tar zxvf TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c.tar.gz
cd TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c/
ii. install the following custom packages and supporting packages (this will pull a lot of extra packages down - perhaps 20 minutes)
ipkg-opt install cups_1.5.4-2_mipsel.ipk poppler_0.12.4-1_mipsel.ipk ghostscript_8.71-3_mipsel.ipk dbus_1.2.16-2_mipsel.ipk avahi_0.6.30-2_mipsel.ipk nano py26-lxml perl coreutils
iii. if you have an HP printer, then your driver may be in this ipkg
ipkg-opt install hplip_3.11.10-1_mipsel.ipk
… or… if you have something other than an HP Printer, you can try the Gutenprint drivers (I haven't tested them extensively)
ipkg-opt install cups-driver-gutenprint_5.2.9-1_mipsel.ipk gutenprint_5.2.9-1_mipsel.ipk
iv. add users for avahi and dbus
echo "netdev:x:1:" >> /tmp/etc/group
echo "avahi:x:2:" >> /tmp/etc/group
echo "avahi:x:2:2:avahi daemon:/opt/sbin/avahi-daemon:/bin/false" >> /tmp/etc/passwd
Note: enable this for subsequent reboots, also, by adding it to your startup script in Admin:Scripts:Firewall. but make sure it happens after your opt/ partition mounts, but before the initscripts at /opt/etc/init.d/Snn are executed.
v. Start all three daemons:
/opt/etc/init.d/S20dbus start
/opt/etc/init.d/S22avahi-daemon start
/opt/etc/init.d/S88cupsd start
and confirm that they are running:
ps | tail
their output should appear similar to this
ps | tail
9367 root 1816 S -sh
9458 root 1220 S dropbear -p 22 -a
9459 root 1816 S -sh
14620 root 0 SW [pdflush]
14709 root 6068 S /opt/sbin/snmpd -c /opt/etc/snmpd.conf
15015 messageb 1760 S /opt/bin/dbus-daemon --system
15021 avahi 2576 S avahi-daemon: running [airdiskdevbox.local]
15028 root 5012 S /opt/sbin/cupsd -C /opt/etc/cups/cupsd.conf
15046 root 1696 R ps
15047 root 1688 R tail
For instance, we can see dbus, avahi and cupsd all running.
TEST: Load CUPS Webif via web browser. See if you can load the webif @ your_router's_ip:631
B. Configure USB printer, configure via CUPS as an AppSocket/HP JetDirect printer
In a web browser, go to your_router's_ip:631, and click on the Administration tab, then choose Add Printer
i. Enter a URI for your USB printer that will direct CUPS to treat it as a port 9100 printer.
I've used both of these with success. Note that this _does_ work with non-jet-direct printers.
URI: socket://127.0.0.1:9100
or
URI: file:///dev/usb/lp0
ii. Name, Description and Location as fit your needs. *Make sure you check the box to "Share This Printer"*
iii. Choose your Make (press Continue), and then your Model (press Add Printer) (note that the Model field make take a minute to fully populate if you've chose a 'popular' Make.)
iv. Set any default policies (I chose stop-printer)
TEST: … by printing a Test Page (Maintenance -> Print Test Page)
Troubleshooting:
- make sure that back in Step 1, your printer was actually working as it should be
- if multiple drivers are available for your printer, try another driver, keeping a careful record of which drivers and what specific setting worked or didn't work
C. (Optional but recommended) Create Avahi service files to enable advertisement for the regular Desktop/Laptop print stream
i. create a generic p910nd service file, supply it with your own values
nano /opt/etc/avahi/services/p9100-printer.service
enter this as the content for the service file: accurate information will auto-identify your printer's make and model
<service-group>
<name replace-wildcards="yes"> my-printers-name @ my-host-name </name>
<service protocol="any">
<type>_pdl-datastream._tcp</type>
<port>9100</port>
<txt-record>product=( my-printers-make-and-model-according-to-CUPS )</txt-record>
</service>
</service-group>
…for my HP C4480 attached to a router with hostname AirTest, it looks just like this:
<service-group>
<name replace-wildcards="yes">HP PhotoSmart C4480 @ AirTest:9100</name>
<service protocol="any">
<type>_pdl-datastream._tcp</type>
<port>9100</port>
<txt-record>product=(HP Photosmart C4400 series)</txt-record>
</service>
</service-group>
The product= txt-record is important to have correct, so that any computer attaching via Bonjour can autoconfigure the drivers.
ii. reload avahi-daemon so that the new service files are recognized
/opt/etc/init.d/S22avahi-daemon reload
TEST: Choose printer via Bonjour/mDNS/Avahi-enabled system, and print a test page for it.
iii. Optional: Advertise your CUPS Admininstrative WebIF via a service file like this:
nano /opt/etc/avahi/services/CUPS-admin.service
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">CUPS Webif@TomatoUSB/DDWRT</name>
<service>
<type>_http._tcp</type>
<port>631</port>
</service>
</service-group>
This will allow you to find the CUPS Admin Webif automatically with any Bonjour/Avahi-capable web browser.
3. Install AirPrint Support
A. Install the required packages
cd /opt/TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c/
ipkg-opt install py26-cups_1.9.62-1_mipsel.ipk py26-setuptools_0.6c11-3_mipsel.ipk
B. Fix the URF/pdf stuff that occured in iOS6
i. add mime info to make it compatible with Apple's AirPrint requirements
echo "image/urf application/pdf 100 pdftoraster" > /opt/share/cups/mime/airprint.convs
echo "image/urf urf string(0,UNIRAST<00>)" > /opt/share/cups/mime/airprint.types
ii. restart CUPS {an absolute MUST!}
/opt/etc/init.d/S88cupsd restart
C. We use TJFontaine's python script to read CUPS's parameters of the printer and turn them into an Avahi service file for Airprint
i. Go back to the support dir, where I've included a copy of the script, since download of it requires an ssl-aware wget - which neither TomatoUSB nor DDWRT have natively.
cd /opt/TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c/
python2.6 airprint-generate.py
mv *.service /opt/etc/avahi/services/
Execution of the airprint-generate.py script is normally nonverbose : it should -not- create any screen output. If it does
then there is problem somewhere, most likely.
ii. Reload avahi-daemon to make it advertise your AirPrint service.
/opt/etc/init.d/S22avahi-daemon reload
TEST: Choose printer via an iPhone with iOS 4.2 or greater, and try printing a simple test page.
Troubleshooting:
- check CUPS log for errors
- check avahi-daemon log for errors
- check router's firewall to see that Multicast is enabled (or try disabling it!)
- same for SPI - several reports mention that disabling it may help
- on your iPhone's web browser, open <ip-address-of-your-router>:631 , and check to see that the CUPS Administrative page loads as it should. Go to your printer via the admin buttons and print a test page for it
- if your setup works intermittently, document when it does and doesn't work: in my case, one of my domains (provisioned by google) had some services and ports blocked during certain times. I was puzzled for a few days until I realized what was going on.
4. Install Google Cloud Print support
A. Go back to the support directory
cd /opt/TomatoUSB-DDWRT_Airprint-Cloudprint_support-03282013c/
B. Install the required python modules
ipkg-opt install py26-cloudprint_0.9-4_mipsel.ipk py26-daemon_1.6-1_mipsel.ipk py26-lockfile_0.9.1-1_mipsel.ipk py26-cups_1.9.62-1_mipsel.ipk py26-setuptools_0.6c11-3_mipsel.ipk
C. If you are using DD-WRT, then modify /opt/etc/init.d/S90cloudprint-daemon near line 20 (If you are using TomatoUSB, then no change is required - the default setting is for TomatoUSB)
# location of root cloudprint credential/authentication files
# **** ENABLE either the DD-WRT or the TomatoUSB section below, ===but not both===!
# on DD-WRT
#AUTHFILEROOT="/tmp/root/.cloudprintauth"
#SASLFILEROOT="/tmp/root/.cloudprintauth.sasl"
# on TomatoUSB
AUTHFILEROOT="/tmp/home/root/.cloudprintauth"
SASLFILEROOT="/tmp/home/root/.cloudprintauth.sasl"
Only if you are running DD-WRT, then use nano or the editor of your choice to change it to this:
# location of root cloudprint credential/authentication files
# **** ENABLE either the DD-WRT or the TomatoUSB section below, but not both!
# on DD-WRT
AUTHFILEROOT="/tmp/root/.cloudprintauth"
SASLFILEROOT="/tmp/root/.cloudprintauth.sasl"
# on TomatoUSB
#AUTHFILEROOT="/tmp/home/root/.cloudprintauth"
#SASLFILEROOT="/tmp/home/root/.cloudprintauth.sasl"
D. setup your account credentials (you'll have to enter your gmail account info):
/opt/etc/init.d/S90cloudprint-daemon setup
E. then start it
/opt/etc/init.d/S90cloudprint-daemon start
F. Optional - cron job restart/reauthenticate
i. Install cron (or use the router's native crontab)
ipkg-opt install cron
ii. setup a cronjob to reauthenticate your printer periodically, (every 24 hours or so, adjust to your liking/needs/what works for you)
add something like the string below to your crontab, and execute it as often as needed (perhaps once a day)
0 1 * * * root /opt/etc/init.d/S90cloudprint-daemon stop && /bin/sleep 1 && /opt/etc/init.d/S90cloudprint-daemon logout && /bin/sleep 1 && /opt/etc/init.d/S90cloudprint-daemon start
TEST: from a gmail account, print a document (eg. email) with the gmail/cloudprint interface, and
choose your Cloud Print printer as the printer.
Troubleshooting:
- check for errors : cat /var/log/messages and cat /opt/var/log/cups/error_log
Notes:
Optware initscript loops
To ensure that all daemons start, stop and then start again upon reboot, make sure that you use something like:
in the TomatoUSB Firewall script, after your /opt is mounted:
sleep 2
for f in /opt/etc/init.d/S* ; do [ -x $f ] && $f start ; done
sleep 2
and then in your TomatoUSB Shutdown script:
for f in /opt/etc/init.d/S* ; do [ -x $f ] && $f stop ; done
Changes to CUPS
- patched to avoid the -pie/-fpie problem w/ older binutils
- upgraded to 1.5.4
- built against python 2.6
- ipk includes a custom /opt/etc/cups/cupsd.conf which needs few, if any, modifications
- in the ipk file, added custom init script /opt/etc/init.d/S88cupsd with start, stop and restart options
Changes to Ghostscript
- stayed with 8.71, as 9.02 showed significant overload of the router's CPU when processing
- patched gs call line with an appended "-r144" to fix the crash that pani mentioned
Changes to HPLIP
- no longer linked to sane-backends, as that seemed to cause some problems
Changes to python
- unified dependencies for all packages in this group to point to only python 2.6, thus reducing the total space requirement greatly
Changes to cloudprint.py
- in the ipk file, added custom init script /opt/etc/init.d/S90cloudprint-daemon with setup, logout, start, stop and restart options
- in cloudprint.py, fixed sasl auth filename and path
- in cloudprint.py, added logging for printjob ticketUrl to google.com
References:
- http://ubuntuforums.org/showthread.php?t=2060594&page=2&p=12254866#post12254866
- TJ Fontaine's article with details about airprint-generate.py http://atxconsulting.com/posts/Automatically_generate_AirPrint_Avahi_service_files_for_CUPS_printers/
My working combination as of 3/28/2013:
adduser - 1.10.3-1 - a multi-call binary for login and user account administration
avahi - 0.6.30-2 -
bzip2 - 1.0.6-1 - Very high-quality data compression program
cups - 1.5.4-1 -
cyrus-sasl-libs - 2.1.23-2 - Provides client or server side authentication (see RFC 2222).
dbus - 1.2.16-2 -
expat - 2.0.1-1 - XML Parser library
fontconfig - 2.8.0-0 - Font configuration library
freetype - 2.3.6-1 - Free truetype library
gconv-modules - 2.2.5-7 - Provides gconv modules missing from the firmware. These are used by glibc iconv() implementation.
gdbm - 1.8.3-4 - GNU dbm is a set of database routines that use extensible hashing. It works similar to the standard UNIX dbm routines.
ghostscript - 8.71-3 -
hplip - 3.11.7-1 - { also tested and working with 3.11.10 }
ipkg-opt - 0.99.163-10 - The Itsy Package Manager
libcurl - 7.24.0-1 - Curl is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FI
libdaemon - 0.14-1 - A lightweight C library that eases the writing of UNIX daemons.
libdb - 4.2.52-3 - Berkeley DB Libraries
libjpeg - 6b-3 - collection of jpeg tools
liblcms - 1.19-1 - A small-footprint, speed optimized color management engine.
libpng - 1.2.44-1 - Portable Network Graphics Libraries
libtiff - 3.9.5-1 - Tag Image File Format Libraries
libuclibc++ - 0.2.2-9 - C++ standard library designed for use in embedded systems
libusb - 0.1.12-2 - Library for interfacing to the USB subsystem.
libxml2 - 2.7.8-1 - Libxml2 is the XML C parser and toolkit developed for the Gnome project.
libxslt - 1.1.26-2 - An XML Stylesheet processor based on libxml2
nano - 2.2.6-1 - A pico like editor
ncurses - 5.7-3 - NCurses libraries
ncursesw - 5.7-2 - NCurses libraries with wide char support
net-snmp - 5.4.2.1-1 - net-SNMP is a suite of applications used to implement SNMP v1, SNMP v2c and SNMP v3 using both IPv4 and IPv6
openjpeg - 1.3-1 - The OpenJPEG library is an open-source JPEG 2000 codec.
openldap-libs - 2.3.43-2 - Open Lightweight Directory Access Protocol
openssl - 0.9.7m-6 - Openssl provides the ssl implementation in libraries libcrypto and libssl, and is needed by many other applications and librari
poppler - 0.12.4-1 -
psmisc - 22.13-1 - A set of some small useful utilities that use the proc filesystem.
py26-cloudprint - 0.9-3 -
py26-cups - 1.9.62-1 -
py26-daemon - 1.6-1 -
py26-lockfile - 0.9.1-1 -
py26-lxml - 2.2.8-1 - A Pythonic binding for the libxml2 and libxslt libraries.
py26-setuptools - 0.6c11-3 -
python26 - 2.6.8-1 - Python is an interpreted, interactive, object-oriented programming language.
readline - 6.1-2 - The GNU Readline library provides a set of functions for use by applications that allow users to edit command lines as they are
sqlite - 3.7.14.1-1 - SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.
uclibc-opt - 0.9.28-13 - micro C library for embedded Linux systems
zlib - 1.2.5-1 - zlib is a library implementing the 'deflate' compression system.
Various Broadcom Routers Running TomatoUSB (or DD-WRT) with Airprint & Cloud Print
See my Repo's at http://github.com/davygravy
Extra/Newer Optware ipks not in the dd-wrt/nslu2 feed
davy's 1-wire weather, courtesy of TomatoUSB, Optware & Maxi