zed.0xff.me

printing from OSX & iOS to Canon MF-4018 shared via WNDR3700

0. Reason for this all

HP Photosmart 5510

Just bought an HP Photosmart 5510 with wifi & ePrint and my MacBook Air found and installed it via wifi without the need of any drivers or anything.

Canon MF4018

But I also have older Canon MF4018, connected directly to WNDR3700 via usb, and which I failed to set up for printing from my Macs via wifi.

1. Drivers

Netgear WNDR3700

The main reason why I failed is Canon’s drivers for MF4018 (or MF4010, their printing functions are the same). They only have more or less usable drivers for Windows and Linux, closed-source and bad designed, with a lot of proprietary stuff.

There is a way to make your OpenWRT router act like a print server for Windows & Linux clients, but it refuses to work with OSX client.

And even if we’ll somehow force it to work with OSX client, it will still need a lot of Canon drivers installed on Mac and carefully configured. And definitely will not work with iOS

2. Workaround

You can use one simple workaround if you have an x86 or x86_64 computer running 24/7 at your place. Or if you want to manually turn it on every time when you need to print something.

You can then install CUPS on your device, or use a Windows Printer Sharing.

Unacceptable for me. I only have WNDR3700 on ar71xx platform, and AppleTV2 on ARM Cortex A8 running nearly 24/7 at my home.

3. An Insight

If I can’t run an x86 PC 24/7 at my place — who or what can stop me to run it somewhere on Internet?!

(I already have a pair of servers on Internet, so let’s increase their load average a little :)

IMPORTANT: You’ll need to have a Real IP address at your place, or some other way of receiving data from your Internet server, like a SSH tunnel.

4. Step-by-step guide

  1. WNDR3700 (or other OpenWrt-based router, or DD-WRT one, or wl500g)
    1. Connect MF4018 via usb
    2. Set up p910nd
    3. Open port 9100 in firewall:
      iptables -A INPUT -j ACCEPT -p tcp -s your.internet.server.real.ip --dport 9100
  2. Internet server
    1. install CUPS
    2. install Canon Proprietary drivers: for example UFRII/UFRII LT Printer Driver for Linux v2.20
    3. Add a printer:
      lpadmin -p mf4010 -P CNCUPSMF4010ZK.ppd -v socket://my.home.real.ip:9100 -o printer-is-shared=true
    4. enable CUPS Internet sharing:
    5. set up CUPS and/or firewall to only allow connections from YOUR home/office network
  3. Optional steps, needed only for seamless printer autoconfiguration for OSX/iOS devices
    1. Configure
      1. Internet server: use airprint-generate to generate a .service file for your printer
      2. edit generated file: add <host-name>my.internet.server.real.ip</host-name>
      3. WNDR3700: install avahi-daemon, feed it with previously generated file, start it
    2. Now in OSX “Add Printers” Dialog just click “+” and it should see your printer, iOS should see your printer when you’ll try to print some photo

my autogenerated & edited mf4010.service file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0"?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
  <name replace-wildcards="yes">Canon MF4018</name>
  <service>
    <type>_ipp._tcp</type>
    <subtype>_universal._sub._ipp._tcp</subtype>
    <port>631</port>
    <host-name>my.internet.server.real.ip</host-name>       <!-- EDIT THIS -->
    <txt-record>txtvers=1</txt-record>
    <txt-record>qtotal=1</txt-record>
    <txt-record>Transparent=T</txt-record>
    <txt-record>URF=none</txt-record>
    <txt-record>rp=printers/mf4010</txt-record>
    <txt-record>note=laser</txt-record>
    <txt-record>product=(GPL Ghostscript)</txt-record>
    <txt-record>printer-state=3</txt-record>
    <txt-record>printer-type=0x821484</txt-record>
    <txt-record>pdl=application/octet-stream,application/pdf,application/postscript,image/gif,image/jpeg,image/png,image/tiff,text/html,text/plain,application/vnd.cups-banner,application/vnd.cups-postscript,application/vnd.cups-raw,application/vnd.hp-hpgl,image/x-bitmap</txt-record>
  </service>
</service-group>

Setting up a scan server on OpenWrt & NetGear WNDR3700

1. Install OpenWrt trunk for ar71xx

Follow openwrt wiki WNDR3700 page for detailed instructions.
I used openwrt-ar71xx-generic-wndr3700-squashfs-factory.img and it worked like a charm. Your firmware image may be different, especially if you have WNDR3700 V2. Read wiki carefully.

Note that trunk build does not have HTTP GUI by default. If you want GUI you have to login with telnet and do:

1
2
3
4
opkg update
opkg install luci
/etc/init.d/uhttpd start
/etc/init.d/uhttpd enable

Or just don’t use trunk. stable branch has the GUI by default.

As for me, I’m happy with CLI (no GUI at all) because it saves precious kilobytes of internal flash (5Mb total is available for user)

2. Configure your wired/wireless networks.

Use HTTP GUI or CLI, see WNDR3700 page or other pages in OpenWrt wiki

2½. [optional] set up extroot

Or you may exhaust all your router free “disk” space very fast.

Or you may be smart enough to fit everything in your router’s default flash memory.

Or your router may have much more that 5Mb of flash available :)

at this step I used a small 2-port unpowered USB hub with integrated microSD card reader + 256Mb microSD card

3. Connect your USB scanner & install USB support packages

1
2
opkg update
opkg install kmod-usb2 usbutils kmod-leds-wndr3700-usb

repeating opkg update is not necessary if you did update before and did not rebooted your device.

Ensure your scanner is visible as USB device (mine is Canon MF4018):

1
2
3
4
root@OpenWrt:~# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 003: ID 04a9:26b4 Canon, Inc. MF4010 series

4. Install SANE frontends & backends

1
opkg install sane-frontends sane-backends

Ensure your scanner is recognized by SANE:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@OpenWrt:~# sane-find-scanner 

  # sane-find-scanner will now attempt to detect your scanner. If the
  # result is different from what you expected, first make sure your
  # scanner is powered up and properly connected to your computer.

  # No SCSI scanners found. If you expected something different, make sure that
  # you have loaded a kernel SCSI driver for your SCSI adapter.
  # Also you need support for SCSI Generic (sg) in your operating system.
  # If using Linux, try "modprobe sg".

found USB scanner (vendor=0x04a9 [Canon Inc.], product=0x26b4 [MF4010]) at libusb:001:003
  # Your USB scanner was (probably) detected. It may or may not be supported by
  # SANE. Try scanimage -L and read the backend's manpage.

  # Not checking for parallel port scanners.

  # Most Scanners connected to the parallel port or other proprietary ports
  # can't be detected by this program.

note that “found USB scanner” string.

Try to scan something:

1
2
3
4
5
6
7
root@OpenWrt:~# scanimage
P6
# SANE data follows
640 877
255

***SKIPPING A LOT OF GARBAGE***

you should see a lot of garbage (raw scan data) on your screen, it can be interrupted with Ctrl+C.

5. Set up HTTP

1
opkg install uhttpd jpeg-tools

now edit /etc/config/uhttpd, especially necessary if you have GUI installed. As for me, I only commented out listening on port 443.

grab small HTML/JS/CGI code from my openwrt-scan-server github repo (free hint: look for “Downloads” button at right ;)
and put it to /www dir on your router.

Note that current OpenWrt repos do not have ImageMagick tools available, so if you want a nice image resolution + file size info – you have to install imagemagick-jpeg package and use my identify binary (only for ar71xx platform, see at bin/ar71xx/identify in my github repo, put it in /usr/bin on your router)

6. Test

Navigate to your router’s address: http://192.168.1.1 (you may have another one).
You should see something like this: