summaryrefslogtreecommitdiffstats
path: root/usb-devices
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:13:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:13:39 +0000
commit18d2dadb3c9132b52fdc88f509ea9005b9eebd5f (patch)
tree8e399598f572b2e88c16ddd26fb1fe601dd0e64b /usb-devices
parentInitial commit. (diff)
downloadusbutils-upstream.tar.xz
usbutils-upstream.zip
Adding upstream version 1:017.upstream/1%017upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xusb-devices198
-rw-r--r--usb-devices.1.in55
2 files changed, 253 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
diff --git a/usb-devices.1.in b/usb-devices.1.in
new file mode 100644
index 0000000..3667dd9
--- /dev/null
+++ b/usb-devices.1.in
@@ -0,0 +1,55 @@
+.\" SPDX-License-Identifier: GPL-2.0-only
+.\" Copyright (c) 2004 Greg Kroah-Hartman <greg@kroah.com>
+.\" Copyright (c) 2004 Randy Dunlap <rdunlap@xenotime.net>
+.\" Copyright (c) 2004 Frans Pop <elendil@planet.nl>
+.TH usb-devices 1 "23 June 2009" "usbutils-VERSION" "Linux USB Utilities"
+.IX usb-devices
+.SH NAME
+usb-devices \- print USB device details
+.SH SYNOPSIS
+.B usb-devices
+
+.SH DESCRIPTION
+.B usb-devices
+is a shell script that can be used to display details of USB
+buses in the system and the devices connected to them.
+
+The output of the script is similar to the \fIusb/devices\fP file
+available either under \fI/proc/bus\fP (if usbfs is mounted), or under
+\fI/sys/kernel/debug\fP (if debugfs is mounted there). The script is
+primarily intended to be used if the file is not available.
+
+In contrast to the \fIusb/devices\fP file, this script only lists
+\fIactive\fP interfaces (those marked with a "*" in the \fIusb/devices\fP
+file) and their endpoints.
+
+Be advised that there can be differences in the way information is sorted,
+as well as in the format of the output.
+
+.SH RETURN VALUE
+If sysfs is not mounted, a non-zero exit code is returned.
+
+.SH FILES
+.TP
+.B /sys/bus/usb/devices/usb*
+The part of the sysfs tree the script walks through to assemble the
+printed information.
+.TP
+.B /proc/bus/usb/devices
+Location where the \fIusb/devices\fP file can normally be found for
+Linux kernels before 2.6.31, if usbfs is mounted.
+.TP
+.B /sys/kernel/debug/usb/devices
+Location where the \fIusb/devices\fP file can normally be found for
+Linux kernel 2.6.31 and later, if debugfs is mounted.
+
+.SH SEE ALSO
+.BR lsusb (8),
+.BR usbview (8).
+
+.SH AUTHORS
+Greg Kroah-Hartman <greg@kroah.com>
+.P
+Randy Dunlap <rdunlap@xenotime.net>
+.P
+Frans Pop <elendil@planet.nl>