#!/bin/bash

# foo2zjs-loadfw:
#
# Firmware download script for HP1000/1005/1020 USB laser printers.
# Works on udev- and CUPS-based systems.
#
# Used to download firmware automatically into the printer when it
# is powered up or plugged into the USB port.
#
# The inspiration fo this script is from:
#  Oscar Santacreu. Alicante-Spain (2002)
#  Mike Morgan (2004)
#  Modified by Stefan Schweizer (2005) to work as a udev-RUN-script
#  Rewritten by Ivan Shapovalov <intelfx@intelfx.name> (2016) to work with CUPS

#
# Directory to find downloadable HP firmware files sihpMMMM.dl
#
FWDIR_ZJS=/usr/share/foo2zjs/firmware
FWDIR_XQX=/usr/share/foo2xqx/firmware

#
# The CUPS USB backend program
#
USB_BACKEND=/usr/lib/cups/backend/usb

#
# Figure out how to log our messages
#
log() {
	echo "$@" >&2
}

#
# Figure out the model number and firmware file from the arguments
#
DEVPATH="$1"
eval $(udevadm info -q property -x "$DEVPATH")
MODEL="$FOO2ZJS_FW_MODEL"
SERIAL="$ID_SERIAL_SHORT"

log "Downloading firmware for printer model '$MODEL' serial '$SERIAL' at devpath '$DEVPATH'"

if ! [[ "$MODEL" ]]; then
	log "Model number is empty (borked udev configuration?)"
	exit 1
fi

case "$MODEL" in
P1005)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_XQX
	;;
P1006)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_XQX
	;;
P1007)
	FWMODEL=P1005		# Alias
	FWDIR=$FWDIR_XQX
	;;
P1008)
	FWMODEL=P1006		# Alias
	FWDIR=$FWDIR_XQX
	;;
P1505)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_XQX
	;;
P1505n)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_XQX
	;;
1000)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_ZJS
	;;
1005)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_ZJS
	;;
1018)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_ZJS
	;;
1020)
	FWMODEL=$MODEL
	FWDIR=$FWDIR_ZJS
	;;
*)
	log "Unsupported model tag: $MODEL (borked udev configuration?)"
	exit 1
	;;
esac

FW="$FWDIR/sihp$FWMODEL.dl"

if [[ ! -f "$FW" ]]; then
	log "Missing firmware file: $FW"
	exit 1
fi

#
# Now detect the printer URI. In theory, each USB device provides a "serial number",
# which is included in the CUPS URI... If only it was so easy. Not all devices provide a serial number.
#

if [[ "$SERIAL" ]]; then
	function match() {
		[[ $1 == *serial=$SERIAL* ]]
	}
else
	# in case serial number is not provided, match by model number
	# and check absence of FWVER tag in the IEEE1284 descriptor string
	log "Serial number is empty, working around"
	function match() {
		[[ $2 == *$MODEL* && ! $2 == *FWVER:* ]]
	}
fi

$USB_BACKEND 2>/dev/null | while read line; do
	# word-split the line
	eval "line=( $line )"
	direct="${line[0]}"
	uri="${line[1]}"
	deviceid="${line[4]}"

	if [[ $direct == direct && $uri == usb://* ]] && match "$uri" "$deviceid"; then
		log "Got printer: URI='$uri' deviceid='$deviceid'"

		if DEVICE_URI="$uri" $USB_BACKEND 1 1 1 1 '' "$FW" 2>/dev/null; then
			log "Firmware download OK"
		else
			log "Firmware download failed"
		fi
	fi
done
