#!/bin/sh

# The Surface Laptop 7 SPI-HID firmware does not reliably complete the
# in-driver reset-resume transaction. Remove the devices while the system is
# still awake and probe them from a known power-on state after resume instead.

driver=/sys/bus/spi/drivers/spi_hid_of
devices="spi1.0 spi0.0"

unbind_devices() {
	# Let iptsd close hidraw cleanly before removing the HID devices. If the
	# daemon is left running, teardown attempts feature reports against a device
	# that is already disappearing and adds several seconds of timeouts.
	systemctl stop 'iptsd@*.service'
	udevadm settle

	for device in $devices; do
		[ -L "/sys/bus/spi/devices/$device/driver" ] || continue
		if ! printf '%s' "$device" > "$driver/unbind"; then
			echo "Failed to unbind SPI-HID device $device before sleep" >&2
		fi
	done
}

bind_devices() {
	for device in $devices; do
		attempt=0
		while [ "$attempt" -lt 3 ]; do
			[ -L "/sys/bus/spi/devices/$device/driver" ] && break
			if printf '%s' "$device" > "$driver/bind"; then
				break
			fi
			attempt=$((attempt + 1))
			sleep 1
		done

		if [ ! -L "/sys/bus/spi/devices/$device/driver" ]; then
			echo "Failed to bind SPI-HID device $device after sleep" >&2
		fi
	done

	udevadm settle
}

case "$1" in
	pre)
		unbind_devices
		;;
	post)
		bind_devices
		;;
esac

# A recovery failure must be visible in the journal, but must not make every
# otherwise successful suspend cycle report a failed system-sleep hook.
exit 0
