#!/bin/sh # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (c) 2009 Greg Kroah-Hartman # Copyright (c) 2009 Randy Dunlap # Copyright (c) 2009 Frans Pop 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 addr=`cat $eppath/bEndpointAddress` attr=`cat $eppath/bmAttributes` dir=`cat $eppath/direction` if [ "$dir" = in ]; then dir=I elif [ "$dir" = out ]; then dir=O elif [ "$dir" = both ]; then dir=B fi eptype=`cat $eppath/type` if [ "$eptype" = Control ]; then eptype="Ctrl" elif [ "$eptype" = Interrupt ]; then eptype="Int." fi maxps_hex="0x`cat $eppath/wMaxPacketSize`" # 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)))`)) interval=`cat $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 ifnum=`cat $ifpath/bInterfaceNumber` altset=`cat $ifpath/bAlternateSetting` numeps=`cat $ifpath/bNumEndpoints` class=`cat $ifpath/bInterfaceClass` subclass=`cat $ifpath/bInterfaceSubClass` protocol=`cat $ifpath/bInterfaceProtocol` if [ -L $ifpath/driver ]; then # v4: allow for no driver driver=`readlink $ifpath/driver` driver=`basename "$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() { devpath=$1 parent=$2 level=$3 count=$4 [ -d $devpath ] || return cd $devpath busnum=`cat busnum` devnum=`cat devnum` if [ $level -gt 0 ]; then port=$((${devpath##*[-.]} - 1)) else port=0 fi speed=`cat speed` maxchild=`cat maxchild` printf "\nT: Bus=%02i Lev=%02i Prnt=%02i Port=%02i Cnt=%02i Dev#=%3i Spd=%-3s MxCh=%2i\n" \ $busnum $level $parent $port $count $devnum $speed $maxchild ver=`cat version` devclass=`cat bDeviceClass` devsubclass=`cat bDeviceSubClass` devprotocol=`cat bDeviceProtocol` maxps0=`cat bMaxPacketSize0` numconfigs=`cat 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 vendid=`cat idVendor` prodid=`cat idProduct` revmajor=`cat bcdDevice | cut -c 1-2` revminor=`cat bcdDevice | cut -c 3-4` 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 numifs=`cat bNumInterfaces` cfgnum=`cat bConfigurationValue` attr=`cat bmAttributes` maxpower=`cat 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 /sys/bus/usb/devices/usb* do print_device $device 0 0 0 done