Skip to content

TIPS: Using a USB Printer with a KVM hosted Virtual Machine like QEMU KVM (Linux)

mounaiban edited this page Mar 8, 2022 · 4 revisions

NOTE: This guide is being retained as a historical reference, but will no longer be updated. It has been superseded by the device and application-agnostic guide Rootless Write Access to USB Devices with udev Rules.

This guide has been verified with QEMU 4.2.1 on Linux 5.8.13 on 2020-10-15

Rationale

There are benefits to using Virtual Machines (VMs) during the development cycle of captdriver when time-critical debugging and analysis operations are not involved. For example, preliminary testing can be performed quickly over multiple operating systems or new releases of CUPS to verify that the drivers are likely to work on the host. VMs support quick and safe operation of snapshots to quickly and completely undo changes and their effects on a virtualised operating system.

Write Access to USB Devices

USB printers can be used with VMs hosted by KVM in Linux, but attempts to run the VM without root privileges may result in restricted functionality of the device, leading to mysterious errors and loss of device function in the VM.

These problems are caused by the system blocking write access to USB devices. For printers, this means being unable to use the device at all, a side-effect of a security policy intended to prevent rogue actors from exploiting weaknesses which may be found in USB devices.

Such problems are usually accompanied by system errors that are reported to a terminal that is receiving messages from stderr, such as a terminal session that is running qemu-kvm from a shell command line:

libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/001/008: Permission denied
libusb: error [_get_usbfs_fd] libusb requires write access to USB device nodes.
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/001/008: Permission denied
libusb: error [_get_usbfs_fd] libusb requires write access to USB device nodes.
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/001/008: Permission denied

...

The message would be repeated ad nauseum.

Workaround: Enable Rootless Writes to USB Devices

To enable rootless write access a USB devices, a rule has to be established under udev. This is done by creating a plain text file in the /etc/udev/rules.d/ directory, and filling it with rules which are written in a declarative language.

Files must have a name that end with .rules to be considered by udev, and should be prefixed with a number followed by a single hyphen, to aid with sorting, which ultimately determines the precedence of the rules. A rules file named 69-hp-laserjet.rules has precedence over 99-canon-lbp.rules

Creating a udev rule

In this example, a rule for a USB printer has been added to a file, /etc/udev/rules.d/99-lbp3k-qemu-rootless.rules, with only a single entry:

ACTION=="add",SUBSYSTEMS=="usb",ATTRS{idVendor}=="04a9",ATTRS{idProduct}=="1337",MODE="0666"

PROTIP: Please pay attention to the single equal between MODE and "0666". Under the udev rule language, MODE is a variable-setting operation, while the others are in fact lookup operations.

PROTIP: If the system seems to ignore the rules file, it may be because the number at the beginning of its name is too low. Try numbers from 60 and 69 inclusive.

This effectively opens up a USB device with a vendor-product ID of 04a9:1337 to write access by all users on the system. Replugging or power-cycling the USB device may be necessary for the new rule to take effect.

Obtaining the product and vendor IDs

The product-vendor ID of a USB device may be obtained by running lsusb, as seen in the example below:

$: lsusb
...

Bus 001 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 008: ID 04a9:1337 Canon, Inc. CAPT Device

Trivia

The MODE setting in this example directly controls the permissions of the device's file. Recall that the printer was connected on Bus 001, as Device 008. This makes the device's corresponding file /dev/bus/usb/001/008.

Also recall that we have set the device permission to "0666" in udev, which means read and write for all users. Verify that fact by listing the device file:

$ ls -l /dev/bus/usb/001/008
crw-rw-rw-. 1 root lp 007, 20 Mar 20 00:00 /dev/bus/usb/001/008 

When the rule is removed, by commenting it out in the rules file or deleting it outright, the permissions revert to their defaults after the device is reconnected. On many recent Linux systems, this means a read-only lockdown against unprivileged users:

$ ls -l /dev/bus/usb/001/008
crw-rw-r--. 1 root lp 007, 20 Mar 20 00:00 /dev/bus/usb/001/008 

PROTIP: This corresponds with a mode of 664

With root privileges, one can subvert this using chmod, at least until the device is reconnected...

References

Greg Kroah-Hartman, Kay Sievers, Dan Stekloff, et. al. udev: Linux Dynamic Device Management. Accessed 2020-03-20.

Linux Gazette. udev rules ca't [sic] auto mount my pen drive. Accessed 2020-10-15.

This 2009 letter published on The Linux Gazette offers a good explanation on how the number prefixes on names of the rules files should be used. The unfortunate typo in the title may prevent it from appearing in search engine results, depending on the search terms used.

Mike Szczys. How To Write Udev Rules. Accessed 2020-10-15.

Bookmarks

Installation Guide

Targeted Printers

Essential Test Suite

Unofficial Introduction to CAPT (Executive Summary)

Support Levels

Rootless Write Access To USB Devices

Miscellaneous Tips

Wishlists

Other Canon Printer-Related Projects

SPECS: 0xA1A1 Command and Response Format

Home Page

Search for pages starting with

  • SPECS for notes on the operation of the CAPT data formats and communications protocol
  • TESTING for guidelines on testing Captdriver
  • TIPS for potentially helpful information on studying the project or the CAPT format-protocol
Clone this wiki locally