#!/bin/bash # omarchy:summary=Returns true when a fingerprint reader is present # omarchy:hidden=true # Detect straight from sysfs so this works before fprintd/usbutils are # installed (the fingerprint setup pulls those in). USB vendor IDs listed here # ship fingerprint readers; multi-purpose vendors (e.g. Elan/STMicro, which # also make USB touchscreens) are left out to avoid nagging laptops with no # reader — those still match on the product string below when present. fingerprint_vendors=" 27c6 138a 06cb 08ff 1c7a 147e " usb_devices_path="${OMARCHY_USB_DEVICES_PATH:-/sys/bus/usb/devices}" # libfprint drives every reader it supports from userspace over libusb, so a # real reader sits there with no kernel driver bound to any of its interfaces. # The other things these vendors build — Synaptics webcam bridges (usbio-bridge # on the Dell XPS 14), touchpads and touchscreens (usbhid), cameras (uvcvideo) # — all bind one. Only the vendor-ID guess needs this; a device that names # itself a fingerprint reader is trusted outright. has_kernel_driver() { local intf driver for intf in "$1"/*:*; do [[ -e $intf/driver ]] || continue # usbfs is the exception: libusb claims an interface through it, so a reader # fprintd is enrolling or verifying against binds a driver for as long as it # holds the claim. That is userspace driving the device — what a reader is # supposed to look like — so it must not read as a kernel driver here. driver=$(readlink -f "$intf/driver") [[ ${driver##*/} == "usbfs" ]] || return 0 done return 1 } for dev in "$usb_devices_path"/*; do # The device's own product descriptor usually names it, e.g. "Goodix # Fingerprint USB Device" — driver-independent and vendor-agnostic. if [[ -r $dev/product ]]; then product=$(<"$dev/product") product=${product,,} # Elan's match-on-chip readers report "ELAN:ARM-M4" and Fingerprint Cards' # report "FPC Sensor Controller" or "FPC L:0000 FW:1425046" — the family or # the manufacturer rather than the function. Both vendors are left out of # the list above on purpose (Elan also makes touchscreens), so without these # they match nothing. FPC leads the string on every reader on record, and # three letters are little to match on, so require the prefix. [[ $product == *fingerprint* || $product == *biometric* || $product == *elan:arm-m4* || $product == "fpc "* ]] && exit 0 fi if [[ -r $dev/idVendor ]]; then vendor=$(<"$dev/idVendor") [[ $fingerprint_vendors == *" $vendor "* ]] && ! has_kernel_driver "$dev" && exit 0 fi done exit 1