diff -Nru ipp-usb-0.9.19/conf.go ipp-usb-0.9.20/conf.go --- ipp-usb-0.9.19/conf.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/conf.go 2022-03-15 08:07:06.000000000 +0000 @@ -82,6 +82,7 @@ // Load quirks quirksDirs := []string{ PathQuirksDir, + PathConfQuirksDir, filepath.Join(exepath, "ipp-usb-quirks"), } diff -Nru ipp-usb-0.9.19/debian/changelog ipp-usb-0.9.20/debian/changelog --- ipp-usb-0.9.19/debian/changelog 2021-11-30 22:05:04.000000000 +0000 +++ ipp-usb-0.9.20/debian/changelog 2022-03-26 10:19:43.000000000 +0000 @@ -1,16 +1,9 @@ -ipp-usb (0.9.19-2ubuntu2) jammy; urgency=medium +ipp-usb (0.9.20-1) unstable; urgency=medium - * No-change rebuild against Go 1.17 + * Update to new upstream version 0.9.20. + * debian/control: add myself to Uploaders: - -- William 'jawn-smith' Wilson Tue, 30 Nov 2021 16:05:04 -0600 - -ipp-usb (0.9.19-2ubuntu1) impish; urgency=medium - - * Recovered accidentally ignored Ubuntu delta: - + debian/rules: - - Build without lto for now - - -- Till Kamppeter Fri, 3 Sep 2021 23:00:00 +0200 + -- Thorsten Alteholz Sat, 26 Mar 2022 11:19:43 +0100 ipp-usb (0.9.19-2) unstable; urgency=medium @@ -20,14 +13,6 @@ -- Didier Raboud Fri, 03 Sep 2021 09:10:00 +0200 -ipp-usb (0.9.19-1ubuntu1) impish; urgency=medium - - * Resynchronize on Debian, remaining Ubuntu change - * debian/rules: - - Build without lto for now - - -- Sebastien Bacher Tue, 15 Jun 2021 10:36:30 +0200 - ipp-usb (0.9.19-1) experimental; urgency=low * New 0.9.19 upstream release diff -Nru ipp-usb-0.9.19/debian/control ipp-usb-0.9.20/debian/control --- ipp-usb-0.9.19/debian/control 2021-11-30 22:05:04.000000000 +0000 +++ ipp-usb-0.9.20/debian/control 2022-03-26 10:19:43.000000000 +0000 @@ -1,6 +1,6 @@ Source: ipp-usb -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Printing Team +Maintainer: Debian Printing Team +Uploaders: Thorsten Alteholz Section: comm Priority: optional Build-Depends: diff -Nru ipp-usb-0.9.19/debian/rules ipp-usb-0.9.20/debian/rules --- ipp-usb-0.9.19/debian/rules 2021-09-03 20:31:23.000000000 +0000 +++ ipp-usb-0.9.20/debian/rules 2022-03-26 10:16:44.000000000 +0000 @@ -1,7 +1,5 @@ #!/usr/bin/make -f -export DEB_BUILD_MAINT_OPTIONS = optimize=-lto - export DH_OPTIONS %: diff -Nru ipp-usb-0.9.19/ipp.go ipp-usb-0.9.20/ipp.go --- ipp-usb-0.9.19/ipp.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/ipp.go 2022-03-15 08:07:06.000000000 +0000 @@ -49,14 +49,31 @@ attrs := newIppDecoder(msg) ippinfo, ippScv := attrs.decode(usbinfo) - // Probe for fax support - uri = fmt.Sprintf("http://localhost:%d/ipp/faxout", port) - if _, err2 := ippGetPrinterAttributes(log, c, uri); err2 == nil { - log.Debug(' ', "IPP FaxOut service detected") + // Check for fax support + canFax := false + if usbinfo.BasicCaps&UsbIppBasicCapsFax != 0 { + // Note, as device lists Fax on its basic capabilities, + // this probe most likely is not needed, but as the + // ipp-usb version 0.9.19 and earlier used to guess + // for fax support based on the /ipp/faxout probe, + // not on device capabilities, lets leave it here + // for now, just in case. Firmwares in general are + // too buggy, I can't trust them :-( + uri = fmt.Sprintf("http://localhost:%d/ipp/faxout", port) + if _, err2 := ippGetPrinterAttributes(log, c, uri); err2 == nil { + canFax = true + log.Debug(' ', "IPP FaxOut service detected") + } else { + log.Error('!', "IPP FaxOut probe failed: %s", err2) + } + } else { + log.Debug(' ', "IPP FaxOut service not in capabilities") + } + + if canFax { ippScv.Txt.Add("Fax", "T") ippScv.Txt.Add("rfo", "ipp/faxout") } else { - log.Debug(' ', "IPP FaxOut service not present") ippScv.Txt.Add("Fax", "F") } @@ -98,8 +115,24 @@ goipp.TagLanguage, goipp.String("en-US"))) msg.Operation.Add(goipp.MakeAttribute("printer-uri", goipp.TagURI, goipp.String(uri))) - msg.Operation.Add(goipp.MakeAttribute("requested-attributes", - goipp.TagKeyword, goipp.String("all"))) + + rq := goipp.Attribute{Name: "requested-attributes"} + rq.Values.Add(goipp.TagKeyword, goipp.String("color-supported")) + rq.Values.Add(goipp.TagKeyword, goipp.String("document-format-supported")) + rq.Values.Add(goipp.TagKeyword, goipp.String("media-size-supported")) + rq.Values.Add(goipp.TagKeyword, goipp.String("mopria-certified")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-device-id")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-dns-sd-name")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-icons")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-info")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-kind")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-location")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-make-and-model")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-more-info")) + rq.Values.Add(goipp.TagKeyword, goipp.String("printer-uuid")) + rq.Values.Add(goipp.TagKeyword, goipp.String("sides-supported")) + rq.Values.Add(goipp.TagKeyword, goipp.String("urf-supported")) + msg.Operation.Add(rq) log.Add(LogTraceIPP, '>', "IPP request:"). IppRequest(LogTraceIPP, '>', msg). diff -Nru ipp-usb-0.9.19/ipp-usb.8 ipp-usb-0.9.20/ipp-usb.8 --- ipp-usb-0.9.19/ipp-usb.8 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/ipp-usb.8 2022-03-15 08:07:06.000000000 +0000 @@ -1,75 +1,50 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "IPP\-USB" "8" "February 2021" "" "ipp-usb.8" -. +.\" generated with Ronn-NG/v0.9.1 +.\" http://github.com/apjanke/ronn-ng/tree/0.9.1 +.TH "IPP\-USB" "8" "March 2022" "" "ipp-usb.8" .SH "NAME" \fBipp\-usb\fR \- Daemon for IPP over USB printer support -. .SH "DESCRIPTION" \fBipp\-usb\fR daemon enables driver\-less printing and scanning on USB\-only AirPrint\-compatible printers and MFPs\. -. .P It works by connecting to the device by USB using IPP\-over\-USB protocol, and exposing the device to the network, including DNS\-SD (ZeroConf) advertising\. -. .P IPP printing, eSCL scanning and web console are fully supported\. -. .SH "SYNOPSIS" -. .SS "Usage:" \fBipp\-usb mode [options]\fR -. .SS "Modes are:" -. .TP \fBstandalone\fR run forever, automatically discover IPP\-over\-USB devices and serve them all -. .TP \fBudev\fR like standalone, but exit when last IPP\-over\-USB device is disconnected -. .TP \fBdebug\fR logs duplicated on console, \-bg option is ignored -. .TP \fBcheck\fR check configuration and exit -. .SS "Options are" -. .TP \fB\-bg\fR run in background (ignored in debug mode) -. .SH "CONFIGURATION" \fBipp\-usb\fR searched for its configuration file in two places: 1\. \fB/etc/ipp\-usb/ipp\-usb\.conf\fR 2\. \fBipp\-usb\.conf\fR in the directory where executable file is located -. .P Configuration file syntax is very similar to \.INI files syntax\. It consist of named sections, and each section contains a set of named variables\. Comments are started from # or ; characters and continues until end of line: -. .IP "" 4 -. .nf - # This is a comment [section 1] variable 1 = value 1 ; and another comment variable 2 = value 2 -. .fi -. .IP "" 0 -. .SS "Network parameters" Network parameters are all in the \fB[network]\fR section: -. .IP "" 4 -. .nf - [network] # TCP ports for HTTP will be automatically allocated in the following range http\-min\-port = 60000 @@ -86,18 +61,12 @@ # Enable or disable IPv6 ipv6 = enable # enable | disable -. .fi -. .IP "" 0 -. .SS "Logging configuration" Logging parameters are all in the \fB[logging]\fR section: -. .IP "" 4 -. .nf - [logging] # device\-log \- what logs are generated per device # main\-log \- what common logs are generated @@ -127,18 +96,12 @@ # Enable or disable ANSI colors on console console\-color = enable # enable | disable -. .fi -. .IP "" 0 -. .SS "Quirks" -Some devices, due to their firmware bugs, require special handling, called device\-specific \fBquirks\fR\. \fBipp\-usb\fR loads quirks from the \fB/usr/share/ipp\-usb/quirks/*\.conf\fR files\. These files have \.INI\-file syntax with the content that looks like this: -. +Some devices, due to their firmware bugs, require special handling, called device\-specific \fBquirks\fR\. \fBipp\-usb\fR loads quirks from the \fB/usr/share/ipp\-usb/quirks/*\.conf\fR files and from the \fB/etc/ipp\-usb/quirks/*\.conf\fR files\. The \fB/etc/ipp\-usb/quirks\fR directory is for system quirks overrides or admin changes\. These files have \.INI\-file syntax with the content that looks like this: .IP "" 4 -. .nf - [HP LaserJet MFP M28\-M31] http\-connection = keep\-alive @@ -151,73 +114,53 @@ # Default configuration [*] http\-connection = "" -. .fi -. .IP "" 0 -. .P -For each discovered device, its model name is matched against sections of the quirks files\. Section name may contain glob\-style wildcards: \fB*\fR that matches any sequence of characters and \fB?\fR, that matches any single character\. To match one of these characters (\fB*\fR and \fB?\fR) literally, use backslash as escape\. -. +For each discovered device, its model name is matched against sections of the quirks files\. The section name contains an exact model name, which contains \fBiManufacturer\fR+\fBiProduct\fR entries from \fBlsusb \-v\fR command output, or it may contain glob\-style wildcards: \fB*\fR that matches any sequence of characters and \fB?\fR , that matches any single character\. To match one of these characters (\fB*\fR and \fB?\fR) literally, use backslash as escape\. .P All matching sections from all quirks files are taken in consideration, and applied in priority order\. Priority is computed using the following algorithm: -. -.IP "\(bu" 4 +.IP "\[ci]" 4 When matching model name against section name, amount of non\-wildcard matched characters is counted, and the longer match wins -. -.IP "\(bu" 4 +.IP "\[ci]" 4 Otherwise, section loaded first wins\. Files are loaded in alphabetical order, sections read sequentially -. .IP "" 0 -. .P If some parameter exist in multiple sections, used its value from the most priority section -. .P The following parameters are defined: -. .TP \fBblacklist = true | false\fR If \fBtrue\fR, the matching device is ignored by the \fBipp\-usb\fR -. .TP \fBhttp\-XXX = YYY\fR Set XXX header of the HTTP requests forwarded to device to YYY\. If YYY is empty string, XXX header is removed -. .TP \fBusb\-max\-interfaces = N\fR Don\'t use more that N USB interfaces, even if more is available -. +.P +In case of you found out about your device needs a quirk to work properly or it does not work with \fBipp\-usb\fR at all, although it provides IPP\-over\-USB interface, please report the isues at https://github\.com/OpenPrinting/ipp\-usb\. The possible quirk for the device can be added to the project itself and fix the situation for all device\'s owners\. .SH "FILES" -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/etc/ipp\-usb/ipp\-usb\.conf\fR: the daemon configuration file -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/var/log/ipp\-usb/main\.log\fR: the main log file -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/var/log/ipp\-usb/\.log\fR: per\-device log files -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/var/ipp\-usb/dev/\.state\fR: device state (HTTP port allocation, DNS\-SD name) -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/var/ipp\-usb/lock/ipp\-usb\.lock\fR: lock file, that helps to prevent multiple copies of daemon to run simultaneously -. -.IP "\(bu" 4 +.IP "\[ci]" 4 \fB/usr/share/ipp\-usb/quirks/*\.conf\fR: device\-specific quirks (see above) -. +.IP "\[ci]" 4 +\fB/etc/ipp\-usb/quirks/*\.conf\fR: device\-specific quirks defined by sysadmin (see above) .IP "" 0 -. .SH "COPYRIGHT" Copyright (c) by Alexander Pevzner (pzz@apevzner\.com) -. .br All rights reserved\. -. .P This program is licensed under 2\-Clause BSD license\. See LICENSE file for details\. -. .SH "SEE ALSO" cups(1) diff -Nru ipp-usb-0.9.19/ipp-usb.8.md ipp-usb-0.9.20/ipp-usb.8.md --- ipp-usb-0.9.19/ipp-usb.8.md 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/ipp-usb.8.md 2022-03-15 08:07:06.000000000 +0000 @@ -114,8 +114,9 @@ Some devices, due to their firmware bugs, require special handling, called device-specific **quirks**. `ipp-usb` loads quirks from the -`/usr/share/ipp-usb/quirks/*.conf` files. These files have .INI-file -syntax with the content that looks like this: +`/usr/share/ipp-usb/quirks/*.conf` files and from the `/etc/ipp-usb/quirks/*.conf` +files. The `/etc/ipp-usb/quirks` directory is for system quirks overrides or +admin changes. These files have .INI-file syntax with the content that looks like this: [HP LaserJet MFP M28-M31] http-connection = keep-alive @@ -131,9 +132,10 @@ http-connection = "" For each discovered device, its model name is matched against sections -of the quirks files. Section name may contain glob-style wildcards: `*` that -matches any sequence of characters and `?`, that matches any single -character. To match one of these characters (`*` and `?`) literally, +of the quirks files. The section name contains an exact model name, +which contains `iManufacturer`+`iProduct` entries from `lsusb -v` command output, +or it may contain glob-style wildcards: `*` that matches any sequence of characters and `?` +, that matches any single character. To match one of these characters (`*` and `?`) literally, use backslash as escape. All matching sections from all quirks files are taken in consideration, @@ -160,6 +162,12 @@ * `usb-max-interfaces = N`: Don't use more that N USB interfaces, even if more is available +In case of you found out about your device needs a quirk to work properly +or it does not work with `ipp-usb` at all, although it provides IPP-over-USB +interface, please report the isues at https://github.com/OpenPrinting/ipp-usb. +The possible quirk for the device can be added to the project itself +and fix the situation for all device's owners. + ## FILES * `/etc/ipp-usb/ipp-usb.conf`: @@ -179,6 +187,8 @@ * `/usr/share/ipp-usb/quirks/*.conf`: device-specific quirks (see above) + * `/etc/ipp-usb/quirks/*.conf`: device-specific quirks defined by sysadmin (see above) + ## COPYRIGHT Copyright (c) by Alexander Pevzner (pzz@apevzner.com)
diff -Nru ipp-usb-0.9.19/paths.go ipp-usb-0.9.20/paths.go --- ipp-usb-0.9.19/paths.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/paths.go 2022-03-15 08:07:06.000000000 +0000 @@ -12,6 +12,9 @@ // PathConfDir defines path to configuration directory PathConfDir = "/etc/ipp-usb" + // PathConfQuirksDir defines path to quirks files in configuration directory + PathConfQuirksDir = "/etc/ipp-usb/quirks" + // PathQuirksDir defines path to quirks files PathQuirksDir = "/usr/share/ipp-usb/quirks" diff -Nru ipp-usb-0.9.19/pnp.go ipp-usb-0.9.20/pnp.go --- ipp-usb-0.9.19/pnp.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/pnp.go 2022-03-15 08:07:06.000000000 +0000 @@ -27,7 +27,7 @@ // pnpRetryTime returns time of next retry of failed device initialization func pnpRetryTime() time.Time { - return time.Now().Add(DNSSdRetryInterval) + return time.Now().Add(DevInitRetryInterval) } // pnpRetryExpired checks if device initialization retry time expired @@ -44,7 +44,7 @@ devByAddr := make(map[UsbAddr]*Device) retryByAddr := make(map[UsbAddr]time.Time) sigChan := make(chan os.Signal, 1) - ticker := time.NewTicker(DNSSdRetryInterval / 4) + ticker := time.NewTicker(DevInitRetryInterval / 4) tickerRunning := true signal.Notify(sigChan, @@ -120,7 +120,7 @@ ticker.Stop() tickerRunning = false case !tickerRunning && len(retryByAddr) != 0: - ticker = time.NewTicker(DNSSdRetryInterval / 4) + ticker = time.NewTicker(DevInitRetryInterval / 4) tickerRunning = true } diff -Nru ipp-usb-0.9.19/README.md ipp-usb-0.9.20/README.md --- ipp-usb-0.9.19/README.md 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/README.md 2022-03-15 08:07:06.000000000 +0000 @@ -94,6 +94,115 @@ Follow this link for downloads: https://download.opensuse.org/repositories/home:/pzz/ +## The ipp-usb Snap + +ipp-usb is also available as a Snap in the Snap Store: https://snapcraft.io/ipp-usb + +Before you install the Snap, uninstall any already existing +installation of ipp-usb. + +Simply install it via any GUI client for the Snap Store (Like "Ubuntu +Software") or via command line: + + sudo snap install --edge ipp-usb + +Now you can connect and disconnect IPP-over-USB devices and ipp-usb +gets started by the Snap whenever needed. Also devices which are +already connected during boot, start, or update of the Snap are +considered. + +The Snap is also automatically updated when further development on +ipp-usb happens. + +The configuration file is here: + + /var/snap/ipp-usb/common/etc/ipp-usb.conf + +You can edit it and afterwards restart the Snap to use the changed +configuration. + +Incompatibilities of particular devices are handled by workarounds +defined in the quirk files. You find them here: + + /var/snap/ipp-usb/common/quirks + +You can add your own quirk files (but if they solve your problem, +please report an issue here, with your quirk file attached, so that +others with the same problem will get helped, too). + +For quick tests you can also edit the existing files, but they will +get replaced (and so your changes lost) on the next update of the +Snap, as we are changing them on any report of further device +incompatibilities. + +The log file is here + + /var/snap/ipp-usb/common/var/log + +and device state files (to assure that each device appears on the same +port and with the same DNS-SD service name) are here: + + /var/snap/ipp-usb/common/var/dev + +You can also build the Snap locally. This is useful when + +* You want to modify ipp-usb +* You want to learn about snapping Go projects +* You want to learn about how to use UDEV from within a Snap (note that a Snap cannot install UDEV rules into the system) + +To do so, run from the main directory of this source repository + + snapcraft snap + +and then install the resulting Snap with + + sudo snap install --dangerous ipp-usb*.snap + +An installed Snap from the Snap Store will get overwritten/replaced by your Snap. + +Some technical notes about this Snap: + +Snapping the Go project with one Go library taken from upstream (and +not from Ubuntu Core) was rather straight-forward. Only observation +was that the Go plugin seems not to do "make install". So I had to use +an "override-build" to manually install the auxiliary files +(ipp-usb.conf, quirk files). I also have adapted the auxiliary file +and state directories in paths.go in the "override-build" scriptlet. + +The real challenge of this Snap was to trigger ipp-usb on the +appearing (and also the presence) of IPP-over-USB devices. + +In the classic installation of ipp-usb (via "make install" or RPM/DEB +package installation) a UDEV rules file and a systemd service file (in +systemd-udev/) are installed, so that the system automatically triggers +the launch of ipp-usb when an appropriate device is connected or +already present. A Snap is not able to do so. It cannot install any +files into the system. It can only bring its own, static file system +and create files only in its own state directory. These locations are +not scanned for UDEV rules. + +So the Snap must discover the devices without its own UDEV rules, but +it still can use UDEV. The trick is to do a generic monitoring of UDEV +events and filtering out the USB devices with IPP-over-USB interface +(7/1/4). If such a device appears, we trigger and ipp-usb launch. We +also check on startup of the Snap whether there is such a device +already and if so, we also trigger an ipp-usb launch. + +ipp-usb is run, as in the classic installation, with "udev" +argument. This way it stops by itself when there is no device any more +(and we do not need to observe the disappearal events of the devices) +and it is assured that only one single instance of ipp-usb is running. + +To do this with low coding effort I use the UDEV command line tool +udevadm in a shell script (snap/local/run-ipp-usb). Once it runs in +"monitor" mode to observe the UDEV events. Then we parse the output +lines to only consider the ones for a device appearing and run +"udevadm info -q property" on each device path, to get the properties +and filter the 7/1/4 interface. In the beginning we use "udevadm +trigger" to find the already passed appearal event of a device which +is already present. So the shell script is an auxiliary daemon to +start ipp-usb when needed. + ## Installation from source You will need to install the following packages (exact name depends diff -Nru ipp-usb-0.9.19/snap/local/run-ipp-usb ipp-usb-0.9.20/snap/local/run-ipp-usb --- ipp-usb-0.9.19/snap/local/run-ipp-usb 1970-01-01 00:00:00.000000000 +0000 +++ ipp-usb-0.9.20/snap/local/run-ipp-usb 2022-03-15 08:07:06.000000000 +0000 @@ -0,0 +1,53 @@ +#!/bin/sh + +#set -e -x + +# Create needed directories +mkdir -p $SNAP_COMMON/etc +mkdir -p $SNAP_COMMON/var/log +mkdir -p $SNAP_COMMON/var/lock +mkdir -p $SNAP_COMMON/var/dev +mkdir -p $SNAP_COMMON/quirks + +# Put config files in place +cp $SNAP/usr/share/ipp-usb/quirks/* $SNAP_COMMON/quirks +if [ ! -f $SNAP_COMMON/etc/ipp-usb.conf ]; then + cp $SNAP/etc/ipp-usb.conf $SNAP_COMMON/etc/ +fi + +# Monitor appearing/disappearing of USB devices +udevadm monitor -k -s usb | while read START OP DEV REST; do + START_IPP_USB=0 + if test "$START" = "KERNEL"; then + # First lines of "udevadm monitor" output, check for already plugged + # devices. Consider only IPP-over-USB devices (interface 7/1/4) + if [ `udevadm trigger -v -n --subsystem-match=usb --property-match=ID_USB_INTERFACES='*:070104:*' | wc -l` -gt 0 ]; then + # IPP-over-USB device already connected + START_IPP_USB=1 + fi + elif test "$OP" = "add"; then + # New device got added + if [ -z $DEV ]; then + # Missing device path + continue + else + # Does the device support IPP-over-USB (interface 7/1/4)? + # Retry 5 times as sometimes the ID_USB_INTERFACES property is not + # immediately set + for i in 1 2 3 4 5; do + # Give some time for ID_USB_INTERFACES property to appear + sleep 0.02 + # Check ID_USB_INTERFACE for 7/1/4 interface + if udevadm info -q property -p $DEV | grep -q ID_USB_INTERFACES=.*:070104:.*; then + # IPP-over-USB device got connected now + START_IPP_USB=1 + break + fi + done + fi + fi + if [ $START_IPP_USB = 1 ]; then + # Start ipp-usb + $SNAP/sbin/ipp-usb udev + fi +done diff -Nru ipp-usb-0.9.19/snap/snapcraft.yaml ipp-usb-0.9.20/snap/snapcraft.yaml --- ipp-usb-0.9.19/snap/snapcraft.yaml 1970-01-01 00:00:00.000000000 +0000 +++ ipp-usb-0.9.20/snap/snapcraft.yaml 2022-03-15 08:07:06.000000000 +0000 @@ -0,0 +1,89 @@ +name: ipp-usb +base: core20 +version: git +summary: IPP-over-USB - Driverless IPP printing on USB-connected printers +description: | + ipp-usb is a daemon to allow driverless IPP printing on USB-connected + printers.It emulates an IPP network printer on the local machine, giving + full access to the physical printer: Printing, scanning, fax out, and + the admin web interface. + +grade: stable +confinement: strict + +# Only build on the architectures supported +architectures: + - build-on: amd64 + - build-on: arm64 + - build-on: armhf + +apps: + ipp-usb: + command: scripts/run-ipp-usb + daemon: simple + plugs: [avahi-control, network, network-bind, raw-usb, hardware-observe] + +parts: + goipp: + plugin: go + source: https://github.com/OpenPrinting/goipp.git + source-type: git + override-prime: "" + + ipp-usb: + plugin: go + source: . + source-type: git + override-build: | + set -eux + # Correct hard-coded paths in paths.go + # Not only the config file ipp-usb.conf will be put into a user-editable + # space but also the quirks file, so that the user can add and debug + # quirks + perl -p -i -e 's:/etc/:/var/snap/ipp-usb/common/etc/:' paths.go + perl -p -i -e 's:/var/ipp-usb:/var/snap/ipp-usb/common/var:' paths.go + perl -p -i -e 's:/usr/share/ipp-usb/quirks:/var/snap/hplip-printer-app/common/quirks:' paths.go + perl -p -i -e 's:/var/log/ipp-usb:/var/snap/ipp-usb/common/var/log:' paths.go + # Build the executable + snapcraftctl build + # Place the executable in /sbin, it's a system daemon + mv ../install/bin ../install/sbin + # Install the config file and the quirk files + mkdir -p ../install/etc + cp ipp-usb.conf ../install/etc + mkdir -p ../install/usr/share/ipp-usb/quirks + cp ipp-usb-quirks/* ../install/usr/share/ipp-usb/quirks + build-packages: + - libavahi-client-dev + - libavahi-common-dev + - libusb-1.0-0-dev + - ronn + - perl-base + stage-packages: + - libavahi-client3 + - libavahi-common3 + - libusb-1.0-0 + - udev + prime: + - etc + - -etc/init.d + - -etc/udev + - sbin + - -sbin/systemd-hwdb + - lib + - -lib/modprobe.d + - -lib/systemd + - -lib/udev + - usr/lib + - -usr/lib/tmpfiles.d + - usr/share/ipp-usb + after: [goipp] + + scripts: + plugin: dump + source: snap/local/ + organize: + run-ipp-usb: scripts/ + prime: + - scripts/ + after: [ipp-usb] diff -Nru ipp-usb-0.9.19/usbcommon.go ipp-usb-0.9.20/usbcommon.go --- ipp-usb-0.9.19/usbcommon.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/usbcommon.go 2022-03-15 08:07:06.000000000 +0000 @@ -171,17 +171,54 @@ // UsbDeviceInfo represents USB device information type UsbDeviceInfo struct { // Fields, directly decoded from USB - Vendor uint16 // Vendor ID - Product uint16 // Device ID - SerialNumber string // Device serial number - Manufacturer string // Manufacturer name - ProductName string // Product name - PortNum int // USB port number + Vendor uint16 // Vendor ID + Product uint16 // Device ID + SerialNumber string // Device serial number + Manufacturer string // Manufacturer name + ProductName string // Product name + PortNum int // USB port number + BasicCaps UsbIppBasicCaps // Device basic capabilities // Precomputed fields MfgAndProduct string // Product with Manufacturer prefix, if needed } +// UsbIppBasicCaps represents device basic capabilities bits, +// according to the IPP-USB specification, section 4.3 +type UsbIppBasicCaps int + +// Basic capabilities bits, see IPP-USB specification, section 4.3 +const ( + UsbIppBasicCapsPrint UsbIppBasicCaps = 1 << iota + UsbIppBasicCapsScan + UsbIppBasicCapsFax + UsbIppBasicCapsOther + UsbIppBasicCapsAnyHTTP +) + +// String returns a human-readable representation of UsbAddr +func (caps UsbIppBasicCaps) String() string { + s := []string{} + + if caps&UsbIppBasicCapsPrint != 0 { + s = append(s, "print") + } + + if caps&UsbIppBasicCapsScan != 0 { + s = append(s, "scan") + } + + if caps&UsbIppBasicCapsFax != 0 { + s = append(s, "fax") + } + + if caps&UsbIppBasicCapsAnyHTTP != 0 { + s = append(s, "http") + } + + return strings.Join(s, ",") +} + // Fix up precomputed fields func (info *UsbDeviceInfo) FixUp() { mfg := strings.TrimSpace(info.Manufacturer) diff -Nru ipp-usb-0.9.19/usbio_libusb.go ipp-usb-0.9.20/usbio_libusb.go --- ipp-usb-0.9.19/usbio_libusb.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/usbio_libusb.go 2022-03-15 08:07:06.000000000 +0000 @@ -9,6 +9,7 @@ package main import ( + "encoding/binary" "errors" "sync" "sync/atomic" @@ -472,6 +473,7 @@ // Decode device descriptor info.Vendor = uint16(c_desc.idVendor) info.Product = uint16(c_desc.idProduct) + info.BasicCaps = devhandle.usbIppBasicCaps() buf := make([]byte, 256) @@ -504,6 +506,54 @@ return info, nil } +// usbIppBasicCaps reads and decodes printer's +// Class-specific Device Info Descriptor to obtain device +// capabilities +// +// See IPP USB specification, section 4.3 for details +// +// This function never fails. In a case of errors, it fall backs +// to the reasonable default +func (devhandle *UsbDevHandle) usbIppBasicCaps() (caps UsbIppBasicCaps) { + // Safe default + caps = UsbIppBasicCapsPrint | + UsbIppBasicCapsScan | + UsbIppBasicCapsFax | + UsbIppBasicCapsAnyHTTP + + // Buffer length + const bufLen = 256 + + // Obtain class-specific Device Info Descriptor + // See IPP USB specification, section 4.3 for details + buf := make([]byte, bufLen) + rc := C.libusb_get_descriptor( + (*C.libusb_device_handle)(devhandle), + 0x21, 0, + (*C.uchar)(unsafe.Pointer(&buf[0])), + bufLen) + + if rc < 0 { + // Some devices doesn't properly return class-specific + // device descriptor, so ignore an error + return + } + + if rc < 10 { + // Malformed response, fall back to default + return + } + + // Decode basic capabilities bits + bits := binary.LittleEndian.Uint16(buf[6:8]) + if bits == 0 { + // Paranoia. If no caps, return default + return + } + + return UsbIppBasicCaps(bits) +} + // OpenUsbInterface opens an interface func (devhandle *UsbDevHandle) OpenUsbInterface(addr UsbIfAddr) ( *UsbInterface, error) { diff -Nru ipp-usb-0.9.19/usbtransport.go ipp-usb-0.9.20/usbtransport.go --- ipp-usb-0.9.19/usbtransport.go 2021-05-20 20:30:02.000000000 +0000 +++ ipp-usb-0.9.20/usbtransport.go 2022-03-15 08:07:06.000000000 +0000 @@ -81,6 +81,7 @@ Debug(' ', " Product: %s", transport.info.ProductName). Debug(' ', " SerialNumber: %s", transport.info.SerialNumber). Debug(' ', " MfgAndProduct: %s", transport.info.MfgAndProduct). + Debug(' ', " BasicCaps: %s", transport.info.BasicCaps). Nl(LogDebug) log.Debug(' ', "Device quirks:")