#!/bin/bash

# Copyright 2008 Carl-Daniel Hailfinger
# Any attached USB hubs will totally mess up the results

LANG=C
dmesgfile=$1
function get_all_fast_usb_devs
{
	export bus="foo"
	lsusb -t |
	sed "s/Bus \([0-9]*\)[. ]Port.*/Bus \1/" |
	sed "s/^[^[:alnum:]]*\(Port\|Bus\)/\1/;s/:/ /" |
	while read a b c; do
		test "$a" = "Bus" && {
			bus="$b"
		} || {
			 echo "Bus $bus $a $b $c"
		}
	done |
	grep 480M
}

debug_lspci_devs=`lspci -nvvD |
	grep -i "^[0-9a-f]\|debug port" |
	grep -iB1 "debug port" |
	grep -i "^[0-9a-f]" |
	cut -f 1 -d" " |
	sort |
	xargs echo`
test -z "$debug_lspci_devs" &&
	debug_lspci_devs="None"
echo "The following PCI devices support a USB debug port (says lspci): $debug_lspci_devs"
test "$debug_lspci_devs" = "None" &&
	echo "Possible reasons: lspci not run as root, lspci too old, USB controller does not support a debug device"
debug_dmesg_devs_with_port=`( test -z "$dmesgfile" &&
	dmesg ||
	cat "$dmesgfile") |
	grep -i "ehci.*debug port" |
	sed "s/.* \([0-9a-f]*:*[0-9a-f]\{2\}:[0-9a-f]\{2\}\.[0-9a-f]\).*ebug port /\1 /" |
	sort -u`
debug_dmesg_devs=`echo "$debug_dmesg_devs_with_port" |
	cut -f 1 -d" " |
	xargs echo`
test -z "$debug_dmesg_devs" && debug_dmesg_devs="None"
echo "The following PCI devices support a USB debug port (says the kernel): $debug_dmesg_devs"
test "$debug_dmesg_devs" = "None" && {
	echo "Possible reasons: dmesg scrolled off (try modprobe -r ehci_hcd; modprobe ehci_hcd), kernel too old, USB controller does not support a debug device"
	test "$debug_lspci_devs" != "None" &&
		echo "You can specify a file containing kernel bootup messages as argument to this program"
	}
test "$debug_lspci_devs" != "$debug_dmesg_devs" &&
	echo "lspci and the kernel do not agree on PCI devices with USB debug support."
debug_common_devs=`echo "$debug_dmesg_devs $debug_lspci_devs" |
	sed "s/ /\n/g" |
	sort |
	uniq -c |
	grep "^[[:blank:]]\+2[[:blank:]]" |
	sed "s/.*[[:blank:]]//" |
	xargs echo`
test -z "$debug_common_devs" && debug_common_devs="None"
echo "Common subset is: $debug_common_devs"
test "$debug_common_devs" = "None" && {
	echo "No USB controller with debug capability found"
	exit 1
	}
all_fast_usb_devs=`get_all_fast_usb_devs`
echo "The following debug ports exist:"
for dev in $debug_common_devs; do
	bus=`find /sys/bus/pci/devices/$dev/ -name busnum |
		xargs cat |
		sort -u`
	port=`echo "$debug_dmesg_devs_with_port" |
		grep "^$dev" |
		cut -f 2 -d" "`
	echo "PCI device $dev, USB bus $bus, USB physical port $port"
	echo "  Attached devices:"
	echo "$all_fast_usb_devs" |
		grep "Bus 0*$bus Port 0*$port" |
		sed "s/^/  /"
	done
echo "Currently connected high-speed devices:"
echo "$all_fast_usb_devs"
