blob: 53b9a7f8f2c7c8c337dee781c5f4cb47db511280 [file] [log] [blame]
Martin Roth0ad5fbd2020-12-24 12:06:38 -07001#!/usr/bin/env bash
Stefan Tauner47d66632016-05-02 23:16:57 +02002
Patrick Georgi7333a112020-05-08 20:48:04 +02003# SPDX-License-Identifier: GPL-2.0-only
Stefan Tauner47d66632016-05-02 23:16:57 +02004
5LANG=C
6# Some tools emit errors that don't matter (bugs in lspci/PCI firmware and lsusb).
7# To shown them anyway (e.g. for debugging) comment next line.
8exec 2>/dev/null
9
10if [ "$1" = "-h" ]; then
11 printf "Usage: $0 [-h | path to dmesg log]
12
13This script tries to find USB ports compatible with USB2/EHCI debug devices and
14helps you to find their physical locations. To that end, attach at least one
15uniquely identifiable device to a USB port and run this script. The device needs
16to be visible in the output of \"lsusb -t\" (debug devices are often *not*!).
17
18After determining compatibility of the USB controllers the script will print the
19devices attached to the debug port as shown by lsusb. If nothing shows up simply
20switch ports and repeat the process.
21
22Note: usually only one port is supported for debugging.\n"
23 exit 0
24fi
25uid=`id -u`
26if [ "$uid" -ne 0 ]; then
27 echo "Must be run as root. Exiting."
28 exit 1
29fi
30dmesgfile=$1
31
32find_devs_in_tree () {
33 bus=$1
34 port=$2
35 busstr=`printf "Bus %02d" "$bus"`
36 portstr="Port $port"
37
38 hubs_to_ignore="8087:0020 8087:0024"
39 reqlvl=1
40
41 found=
42 # Iterate over the output of lsusb -t because it contains the physical port numbers
43 while IFS='' read -r line; do
44 # We need to keep track of the current bus "branch"
45 # Look out for lines starting with /: (that indicate a bus)
46 if [ "${line#*/:}" != "$line" ]; then
47 if [ "${line#*$busstr}" != "$line" ]; then
48 cur_bus=$busstr
49 else
50 cur_bus=
51 fi
52 continue
53 fi
54
55 # Skip all lines not belonging to the wanted bus number
56 if [ "$cur_bus" != "$busstr" ]; then
57 continue
58 fi
59
60 # Calculate current USB tier/level
61 spaces="${line%%[!' ']*}"
62 curlvl=$((${#spaces} / 4))
63 if [ $curlvl -ne $reqlvl ]; then
64 continue
65 fi
66
67 # Fetch USB IDs of the current device
68 dev=`echo ${line#*Dev } | cut -d ',' -f 1`
69 lsusbline=`lsusb -s "$bus":"$dev"`
70 if [[ ! "$lsusbline" =~ .*([[:xdigit:]]{4}:[[:xdigit:]]{4}) ]]; then
71 printf "Unexpected output from \"%s\": \"%s\"\n" "lsusb -s $bus:$dev" "$usbline"
72 exit 1
73 fi
74 ids=${BASH_REMATCH[1]}
75
76 # Skip over rate matching hubs
77 if [[ "$hubs_to_ignore" == *"$ids"* ]]; then
78 ((reqlvl += 1))
79 continue
80 fi
81
82 # Check for matching physical USB port
83 if [ "${line#*$portstr}" != "$line" ]; then
84 echo "$lsusbline"
85 return
86 fi
87 done<< EOF
88$(lsusb -t)
89EOF
90 if [ -z "$found" ]; then
91 echo "none"
92 fi
93}
94
95debug_lspci_devs=`lspci -nvvD |
96 grep -i "^[0-9a-f]\|debug port" |
97 grep -iB1 --no-group-separator "debug port" |
98 grep -vi "debug port" |
99 cut -f 1 -d" " |
100 sort |
101 xargs echo`
102
103if [ -z "$debug_lspci_devs" ]; then
104 printf "No USB controller with debug capability found by lspci.\n
105Possible reasons: lspci too old, USB controller does not support a debug device, ... Exiting.\n"
106 exit 1
107fi
108printf "The following PCI devices support a USB debug port (says lspci): $debug_lspci_devs\n"
109
110debug_dmesg_devs_with_port=`( test -z "$dmesgfile" &&
111 dmesg ||
112 cat "$dmesgfile") |
113 grep -i "ehci.*debug port" |
114 sed "s/.* \([0-9a-f]*:*[0-9a-f]\{2\}:[0-9a-f]\{2\}\.[0-9a-f]\).*ebug port /\1 /" |
115 sort`
116
117debug_dmesg_devs=`echo "$debug_dmesg_devs_with_port" |
118 cut -f 1 -d" " |
119 xargs echo`
120
121if [ -z "$debug_dmesg_devs" ]; then
122 printf "dmesg does not show any supported ports.\n
123Possible reasons: dmesg scrolled off, kernel too old, USB controller does not support a debug device, ... Exiting.\n
124Note: You can specify a file containing kernel messages as an argument to this program (e.g. /var/log/dmesg)."
125 exit 1
126fi
127
128if [ "$debug_lspci_devs" != "$debug_dmesg_devs" ]; then
129 echo "lspci and the kernel do not agree on USB debug device support. Exiting."
130 exit 1
131fi
132
133printf "and the kernel agrees, good.\n\n"
134
135while true; do
136 for dev in $debug_dmesg_devs; do
137 bus=`lsusb -v |
138 grep "^Bus\|iSerial.*" |
139 grep -B1 --no-group-separator "iSerial.*$dev" |
140 grep "^Bus" |
141 sed "s/Bus *0*\([0-9a-f]*\).*/\1/"`
142 port=`echo "$debug_dmesg_devs_with_port" |
143 grep "^$dev" |
144 cut -f 2 -d" "`
145
146 echo "Device(s) currently connected to the debug-capable port $port on PCI device $dev, USB bus $bus:"
147
148 find_devs_in_tree "$bus" "$port"
149 echo
150 done
151
152 echo "Enter 'q' to abort or anything else to repeat"
153 read -r r
154 if [ $? -ne 0 -o "$r" = "q" ]; then
155 break;
156 fi
157done
158
159exit 0