3 # Copyright 2008 Carl-Daniel Hailfinger
4 # Copyright 2015 Stefan Tauner
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
16 # Some tools emit errors that don't matter (bugs in lspci/PCI firmware and lsusb).
17 # To shown them anyway (e.g. for debugging) comment next line.
20 if [ "$1" = "-h" ]; then
21 printf "Usage: $0 [-h | path to dmesg log]
23 This script tries to find USB ports compatible with USB2/EHCI debug devices and
24 helps you to find their physical locations. To that end, attach at least one
25 uniquely identifiable device to a USB port and run this script. The device needs
26 to be visible in the output of \"lsusb -t\" (debug devices are often *not*!).
28 After determining compatibility of the USB controllers the script will print the
29 devices attached to the debug port as shown by lsusb. If nothing shows up simply
30 switch ports and repeat the process.
32 Note: usually only one port is supported for debugging.\n"
36 if [ "$uid" -ne 0 ]; then
37 echo "Must be run as root. Exiting."
42 find_devs_in_tree
() {
45 busstr
=`printf "Bus %02d" "$bus"`
48 hubs_to_ignore
="8087:0020 8087:0024"
52 # Iterate over the output of lsusb -t because it contains the physical port numbers
53 while IFS
='' read -r line
; do
54 # We need to keep track of the current bus "branch"
55 # Look out for lines starting with /: (that indicate a bus)
56 if [ "${line#*/:}" != "$line" ]; then
57 if [ "${line#*$busstr}" != "$line" ]; then
65 # Skip all lines not belonging to the wanted bus number
66 if [ "$cur_bus" != "$busstr" ]; then
70 # Calculate current USB tier/level
71 spaces
="${line%%[!' ']*}"
72 curlvl
=$
((${#spaces} / 4))
73 if [ $curlvl -ne $reqlvl ]; then
77 # Fetch USB IDs of the current device
78 dev
=`echo ${line#*Dev } | cut -d ',' -f 1`
79 lsusbline
=`lsusb -s "$bus":"$dev"`
80 if [[ ! "$lsusbline" =~ .
*([[:xdigit
:]]{4}:[[:xdigit
:]]{4}) ]]; then
81 printf "Unexpected output from \"%s\": \"%s\"\n" "lsusb -s $bus:$dev" "$usbline"
84 ids
=${BASH_REMATCH[1]}
86 # Skip over rate matching hubs
87 if [[ "$hubs_to_ignore" == *"$ids"* ]]; then
92 # Check for matching physical USB port
93 if [ "${line#*$portstr}" != "$line" ]; then
100 if [ -z "$found" ]; then
105 debug_lspci_devs
=`lspci -nvvD |
106 grep -i "^[0-9a-f]\|debug port" |
107 grep -iB1 --no-group-separator "debug port" |
108 grep -vi "debug port" |
113 if [ -z "$debug_lspci_devs" ]; then
114 printf "No USB controller with debug capability found by lspci.\n
115 Possible reasons: lspci too old, USB controller does not support a debug device, ... Exiting.\n"
118 printf "The following PCI devices support a USB debug port (says lspci): $debug_lspci_devs\n"
120 debug_dmesg_devs_with_port
=`( test -z "$dmesgfile" &&
123 grep -i "ehci.*debug port" |
124 sed "s/.* \([0-9a-f]*:*[0-9a-f]\{2\}:[0-9a-f]\{2\}\.[0-9a-f]\).*ebug port /\1 /" |
127 debug_dmesg_devs
=`echo "$debug_dmesg_devs_with_port" |
131 if [ -z "$debug_dmesg_devs" ]; then
132 printf "dmesg does not show any supported ports.\n
133 Possible reasons: dmesg scrolled off, kernel too old, USB controller does not support a debug device, ... Exiting.\n
134 Note: You can specify a file containing kernel messages as an argument to this program (e.g. /var/log/dmesg)."
138 if [ "$debug_lspci_devs" != "$debug_dmesg_devs" ]; then
139 echo "lspci and the kernel do not agree on USB debug device support. Exiting."
143 printf "and the kernel agrees, good.\n\n"
146 for dev
in $debug_dmesg_devs; do
148 grep "^Bus\|iSerial.*" |
149 grep -B1 --no-group-separator "iSerial.*$dev" |
151 sed "s/Bus *0*\([0-9a-f]*\).*/\1/"`
152 port
=`echo "$debug_dmesg_devs_with_port" |
156 echo "Device(s) currently connected to the debug-capable port $port on PCI device $dev, USB bus $bus:"
158 find_devs_in_tree
"$bus" "$port"
162 echo "Enter 'q' to abort or anything else to repeat"
164 if [ $?
-ne 0 -o "$r" = "q" ]; then