August 6, 2016

Getting a HP P1109w printer to work on Ubuntu 16.04 Xenial

As usual, Linux needs a bit of under-the-hood wrenching to get things working. HP is actually doing Linux support commendably compared to its peers (see hplip). However, in this case a bit of extra grease was needed.

Symptoms: Printer is detected automatically. A test page fails to print. CUPS logs say:

hp[14727]: io/hpmud/musb.c 2095: Invalid usb_open: Permission denied

Solution: Note that this will potentially mess up any HP scanners you have installed. If the P1109 is your only HP device, no problem. I do not claim this to be the correct, the most appropriate, or the right solution. It worked for me. Your mileage may vary.

  1. Edit the /lib/udev/rules.d/56-hpmud.rules file (with root access)
  2. Comment out the line ATTR{idVendor}=="03f0", ENV{ID_USB_INTERFACES}=="*:0701??:*|*:08????:", OWNER="root", GROUP="lp", MODE="0664", ENV{libsane_matched}="yes", ENV{hp_test}="yes", ENV{ID_HPLIP}="1" by adding # in front.
  3. Add the following line below the commented line: ATTR{idVendor}=="03f0", ENV{ID_USB_INTERFACES}=="*:0701??:*|*:08????:", OWNER="root", GROUP="lp", MODE="0664", ENV{hp_test}="yes", ENV{ID_HPLIP}="1"
  4. sudo udevadm control --reload-rules
  5. Disconnect and reconnect the USB cable into the printer to cause the new rules to be applied on a new USB device.
  6. Done, the test page should now print.

This issue has been reported to hplip as Bug 1610623 on 2016-08-06.

The Gory Details

# ls -l /dev/bus/usb/001
total 0
crw-rw-r--  1 root root  189, 0 Aug  6 05:12 001
crw-rw-r--  1 root root  189, 1 Aug  6 05:12 002
crw-rw-r--  1 root root  189, 2 Aug  6 05:12 003
crw-rw-r--  1 root root  189, 3 Aug  6 05:12 004
crw-rw-r--+ 1 root saned 189, 7 Aug  6 21:34 005

saned is the scanning subsystem user. This is not a “default” device behavior; note that all other devices are group root, the printer is the only one with group saned. Printers are also supposed to be accessible by lp (Linux Printing).

Who changes the group? The udev rules for saned:

# grep "GROUP=\"saned" /lib/udev/rules.d/* 
/lib/udev/rules.d/99-saned.rules:ENV{libsane_matched}=="yes", GROUP="saned"

Is the libsane_matched string set for the device representing the printer? Yes:

# udevadm info -q all -n /dev/bus/usb/001/005
P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1
...
E: ID_HPLIP=1
E: ID_MODEL=HP_LaserJet_Professional_P1109w
E: ID_USB_INTERFACES=:070102:ff0210:
E: ID_VENDOR_ID=03f0
...
E: hp_test=yes
E: libsane_matched=yes

Are saned rules to blame? No:

# grep "03f0" /lib/udev/rules.d/40-libsane.rules | grep "102a"
#

Who else sets libsane_matched? hpmud:

# grep -r "libsane_matched" /lib/udev/rules.d
...
56-hpmud.rules:ATTR{idVendor}=="03f0", ENV{ID_USB_INTERFACES}=="*:0701??:*|*:08????:", OWNER="root", GROUP="lp", MODE="0664", ENV{libsane_matched}="yes", ENV{hp_test}="yes", ENV{ID_HPLIP}="1"
69-libmtp.rules:ENV{ID_MTP_DEVICE}!="1", ENV{MTP_NO_PROBE}!="1", ENV{COLOR_MEASUREMENT_DEVICE}!="1", ENV{libsane_matched}!="yes", ATTR{bDeviceClass}=="00|02|06|ef|ff", PROGRAM="mtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum}", RESULT=="1", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
70-uaccess.rules:ENV{libsane_matched}=="yes", TAG+="uaccess"

Did the rule specified in 56-hpmud.rules apply? Yes (see udevadm output above)

Theory of the immediate cause of the bug: the group was set to lp by the rule in 56-hpmud.rules, but the same rule also marks (some? all? a subset of?) HP printers as scanners (which quite a few all-in-one devices, in fact, are). The unintended consequence is that a later rule (99-saned) changes the group to saned, overriding the group setting made by 56-hpmud, so the device is not accessible by the printing subsystem.

I have no idea how all-in-ones are managed in Linux, as they should be accessible by both groups–presumably setfacl would be the right solution. However, this is just a printer, and I don’t have any other HP scanners, so I can just change the rule 56-hpmud to not apply the libsane_matched tag, so that the lp group assignment will remain unchanged.