summaryrefslogtreecommitdiffstats
path: root/usb-devices
diff options
context:
space:
mode:
Diffstat (limited to 'usb-devices')
-rwxr-xr-xusb-devices198
1 files changed, 198 insertions, 0 deletions
diff --git a/usb-devices b/usb-devices
new file mode 100755
index 0000000..f5763da
--- /dev/null
+++ b/usb-devices
@@ -0,0 +1,198 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (c) 2009 Greg Kroah-Hartman <greg@kroah.com>
+# Copyright (c) 2009 Randy Dunlap <rdunlap@xenotime.net>
+# Copyright (c) 2009 Frans Pop <elendil@planet.nl>
+#
+# When checking with shellcheck ignore
+# "In POSIX sh, local is undefined."
+# every modern shell supports it.
+# shellcheck disable=SC3043
+
+print_string() {
+ file=$1
+ name=$2
+ if [ -f "$file" ]; then
+ echo "S: $name=$(cat "$file")"
+ fi
+}
+
+class_decode() {
+ class=$1 # v4: in hex
+
+ case $class in
+ "00") echo ">ifc " ;;
+ "01") echo "audio" ;;
+ "02") echo "commc" ;;
+ "03") echo "HID " ;;
+ "05") echo "PID " ;;
+ "06") echo "still" ;;
+ "07") echo "print" ;;
+ "08") echo "stor." ;;
+ "09") echo "hub " ;;
+ "0a") echo "data " ;;
+ "0b") echo "scard" ;;
+ "0d") echo "c-sec" ;;
+ "0e") echo "video" ;;
+ "0f") echo "perhc" ;;
+ "10") echo "av " ;;
+ "11") echo "blbrd" ;;
+ "12") echo "bridg" ;;
+ "dc") echo "diagd" ;;
+ "e0") echo "wlcon" ;;
+ "ef") echo "misc " ;;
+ "fe") echo "app. " ;;
+ "ff") echo "vend." ;;
+ "*") echo "unk. " ;;
+ esac
+}
+
+print_endpoint() {
+ eppath=$1
+
+ read -r addr < "$eppath/bEndpointAddress"
+ read -r attr < "$eppath/bmAttributes"
+ read -r dir < "$eppath/direction"
+
+ if [ "$dir" = "in" ]; then
+ dir="I"
+ elif [ "$dir" = "out" ]; then
+ dir="O"
+ elif [ "$dir" = "both" ]; then
+ dir="B"
+ fi
+
+ read -r eptype < "$eppath/type"
+ if [ "$eptype" = Control ]; then
+ eptype="Ctrl"
+ elif [ "$eptype" = Interrupt ]; then
+ eptype="Int."
+ fi
+
+ read -r maxps_hex < "$eppath/wMaxPacketSize"
+ maxps_hex="0x$maxps_hex"
+ # Extract MaxPS size (bits 0-10) and multiplicity values (bits 11-12)
+
+ maxps=$(($(printf "%4i*%s\n" $((maxps_hex & 0x7ff)) \
+ $((1 + ((maxps_hex >> 11) & 0x3))))))
+
+ read -r interval < "$eppath/interval"
+
+ printf "E: Ad=%s(%s) Atr=%s(%s) MxPS=%4s Ivl=%s\n" \
+ "$addr" "$dir" "$attr" "$eptype" "$maxps" "$interval"
+}
+
+print_interface() {
+ ifpath=$1
+
+ read -r ifnum < "$ifpath/bInterfaceNumber"
+ read -r altset < "$ifpath/bAlternateSetting"
+ read -r numeps < "$ifpath/bNumEndpoints"
+ read -r class < "$ifpath/bInterfaceClass"
+ read -r subclass < "$ifpath/bInterfaceSubClass"
+ read -r protocol < "$ifpath/bInterfaceProtocol"
+
+ if [ -L "$ifpath/driver" ]; then # v4: allow for no driver
+ driver=$(readlink "$ifpath/driver")
+ driver=${driver##*/}
+ else
+ driver="(none)"
+ fi
+ classname=$(class_decode "$class")
+ printf "I: If#=%2i Alt=%2i #EPs=%2i Cls=%s(%s) Sub=%s Prot=%s Driver=%s\n" \
+ "0x${ifnum#0}" "${altset#0}" "0x${numeps#0}" "$class" "$classname" "$subclass" \
+ "$protocol" "$driver"
+
+ for endpoint in "$ifpath"/ep_??
+ do
+ if [ -L "$endpoint" ] || [ -d "$endpoint" ]; then # v4: verify endpoint exists
+ print_endpoint "$endpoint"
+ fi
+ done
+}
+
+print_device() {
+ local devpath=$1
+ local parent=$2
+ local level=$3
+ local count=$4
+
+ [ -d "$devpath" ] || return
+ cd "$devpath" || return
+
+ read -r busnum < "busnum"
+ read -r devnum < "devnum"
+
+ if [ "$level" -gt 0 ]; then
+ port=$((${devpath##*[-.]} - 1))
+ else
+ port=0
+ fi
+
+ read -r speed < "speed"
+ read -r maxchild < "maxchild"
+ printf "\nT: Bus=%02i Lev=%02i Prnt=%02i Port=%02i Cnt=%02i Dev#=%3i Spd=%-4s MxCh=%2i\n" \
+ "$busnum" "$level" "$parent" "$port" "$count" "$devnum" "$speed" "$maxchild"
+
+ read -r ver < "version"
+ read -r devclass < "bDeviceClass"
+ read -r devsubclass < "bDeviceSubClass"
+ read -r devprotocol < "bDeviceProtocol"
+ read -r maxps0 < "bMaxPacketSize0"
+ read -r numconfigs < "bNumConfigurations"
+ classname="$(class_decode "$devclass")"
+ printf "D: Ver=%5s Cls=%s(%s) Sub=%s Prot=%s MxPS=%2i #Cfgs=%3i\n" \
+ "$ver" "$devclass" "$classname" "$devsubclass" "$devprotocol" \
+ "$maxps0" "$numconfigs"
+
+ read -r vendid < "idVendor"
+ read -r prodid < "idProduct"
+ read -r bcddevice < "bcdDevice"
+ revmajor="${bcddevice%%??}"
+ revminor="${bcddevice##??}"
+ printf "P: Vendor=%s ProdID=%s Rev=%s.%s\n" \
+ "$vendid" "$prodid" "$revmajor" "$revminor"
+
+ print_string manufacturer "Manufacturer"
+ print_string product Product
+ print_string serial SerialNumber
+
+ read -r numifs < "bNumInterfaces"
+ read -r cfgnum < "bConfigurationValue"
+ read -r attr < "bmAttributes"
+ read -r maxpower < "bMaxPower"
+ printf "C: #Ifs=%2i Cfg#=%2i Atr=%s MxPwr=%s\n" \
+ "$numifs" "$cfgnum" "$attr" "$maxpower"
+
+ # There's not really any useful info in endpoint 00
+ #print_endpoint $devpath/ep_00
+
+ for interface in "$busnum"-*:?.*
+ do
+ print_interface "$devpath/$interface"
+ done
+
+ devcount=0
+ for subdev in "$busnum"-*
+ do
+ echo "$subdev" | grep -Eq "^$busnum-[0-9]+(\.[0-9]+)*$" \
+ || continue
+
+ devcount=$((devcount + 1))
+ if [ -d "$devpath/$subdev" ]; then
+ print_device "$devpath/$subdev" \
+ "$devnum" "$((level +1))" "$devcount"
+ fi
+ done
+}
+
+if [ ! -d /sys/bus ]; then
+ echo "Error: directory /sys/bus does not exist; is sysfs mounted?" >&2
+ exit 1
+fi
+
+for device in $(find /sys/bus/usb/devices -name 'usb*' -printf '%f\n' | sort -V)
+do
+ print_device "/sys/bus/usb/devices/$device" 0 0 0
+done