#!/bin/bash # # ls1394 - list connected FireWire devices # # Requires Linux 2.6. # This implementation uses only information from sysfs. # Option --fetch-oui-db requires sed and one of wget or curl. # # TODO: Print information about unit directories. # Print information about host devices. # Improve speed if many devices are present. # # Check http://me.in-berlin.de/~s5r6/linux1394/ls1394/ for updates. # # Recognized environment variables, mainly for use in installation scripts: # LS1394_OUIDB, LS1394_OUITXT, LS1394_FETCH prog="ls1394" version="v20070103" # defaults opt_verbose="" opt_bus="" opt_node="" opt_company="" opt_guid="" opt_active="" opt_remote="" opt_ouidb=${LS1394_OUIDB:-"/usr/share/misc/oui.db"} opt_ouitxt=${LS1394_OUITXT:-"http://standards.ieee.org/regauth/oui/oui.txt"} which wget >/dev/null 2>&1 && def_fetch="wget -O -" || def_fetch="curl" opt_fetch=${LS1394_FETCH:-$def_fetch} opt_dofetch="" # helpers function print_usage () { echo >&2 "\ Usage: $prog [-h|--help] [-v|--verbose] [-s [[bus]:][device]]\ [-d [companyid:][guid]] [-a|--active] [-r|--remote] [-i file]\ [--fetch-oui-db] [-V|--version]" } function print_help () { cat >&2 <<-EOF Usage: $prog [options] List FireWire devices Options: -h, --help Show this help -v, --verbose Increase verbosity -s [[bus]:][node] Show only devices at selected bus (in decimal) and/or with specified node number (node ID or physical ID, in hexadecimal) -d [companyid:][guid] Show only devices with specified company ID or GUID (in hexadecimal) -a, --active Show only nodes with active link and general ROM -r, --remote Show only remote nodes -i file Use specified company ID (OUI) database instead of $opt_ouidb --fetch-oui-db Read $opt_ouitxt and save $opt_ouidb; required for translation of company IDs to company names; location of $(basename "$opt_ouidb") can be overridden by -i file -V, --version Show version of program EOF } # attributes to show node_attributes_list=("capabilities" "vendor_id" "vendor_name_kv") # evaluate options while [ -n "$1" ] do case "$1" in -h|--help) print_help; exit $?;; -v|--verbose) opt_verbose="y";; -s) shift; opt_node="$1";; -d) shift; opt_guid="$1";; -a|--active) opt_active="y";; -r|--remote) opt_remote="y";; -i) shift; opt_ouidb="$1";; --fetch-oui-db) opt_dofetch="y";; -V|--version) echo "$prog $version"; exit $?;; -av|-va) opt_verbose="y" opt_active="y";; -rv|-vr) opt_verbose="y" opt_remote="y";; -ar|-ra) opt_active="y" opt_remote="y";; -arv|-avr|-rav|-rva|-var|-vra) opt_verbose="y" opt_active="y" opt_remote="y";; *) echo >&2 "$prog: Invalid option $1" print_usage; exit 1;; esac shift done if [ "${opt_node%:*}" != "$opt_node" ] then opt_bus="${opt_node%%:*}" opt_node="${opt_node##*:}" fi if [ "${opt_guid%:*}" != "$opt_guid" ] then opt_company="${opt_guid%%:*}" opt_guid="${opt_guid##*:}" fi if [ -z "$opt_ouidb" ] then echo >&2 "$prog: Option -i must be followed by filename" print_usage exit 1 fi # install oui.db if [ "$opt_dofetch" = "y" ] then $opt_fetch "$opt_ouitxt" | egrep -e '(base 16).*\w+.*$' | sed -e 's/\s*(base 16)\s*/ /' > "$opt_ouidb" exit $? fi # normalize output of other utilities unset LANG # check for oui.db if [ -n "$opt_verbose" -a ! -f "$opt_ouidb" ] then echo >&2 "$prog: $opt_ouidb: No such file" echo >&2 "Try to install it with \"$prog --fetch-oui-db [-i file]\"" x="/usr/src/linux/drivers/ieee1394/oui.db" [ -f "$x" ] && echo >&2 "or use \"$prog -i $x\"" echo >&2 fi # get buses sys=$(mount -t sysfs | cut -f3 -d' ') [ -z "$sys" ] && echo >&2 "$prog: Sysfs not mounted" && exit 1 x="$sys/class/ieee1394_host/" [ ! -d "$x" ] && echo >&2 "$prog: $x: No such directory" && exit 1 x=$(ls "$x" | cut -c8-) [ -z "$x" ] && echo >&2 "$prog: No FireWire hosts" && exit 0 bus_id_list=($x) bus_count=${#bus_id_list[@]} # iterate over buses for ((b=0; b<$bus_count; ++b)) do bus_id=${bus_id_list[$b]} [ -n "$opt_bus" -a "$opt_bus" != "$bus_id" ] && continue x="$sys/class/ieee1394_host/fw-host$bus_id/device" [ ! -L "$x" ] && echo >&2 "$prog: $x: No such link" && exit 1 x=$(readlink -f "$x") [ ! -d "$x" ] && echo >&2 "$prog: $x: No such directory" && exit 1 bus_device="$x" x="$bus_device/in_bus_reset" [ -f "$x" ] && [ "$(< "$x")" = "1" ] && echo >&2 "$prog: Bus $b is in reset" && continue x="$bus_device/node_count" [ ! -f "$x" ] && echo >&2 "$prog: $x: No such file" && exit 1 node_count="$(< "$x")" [ -z "$node_count" ] && echo >&2 "$prog: $x: No nodes" && exit 1 # iterate over nodes for ((n=0; n<"$node_count"; ++n)) do node_id=$(printf "%x" $((0xffc0 + $n))) [ -n "$opt_node" \ -a "$opt_node" != "$node_id" \ -a "$opt_node" != "$n" \ -a "$opt_node" != $(printf "%x" "$n") ] && continue node_guid="" node_is_local="" #find GUID for node_device in "$bus_device/"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f] do x="$node_device/in_limbo" [ -f "$x" ] && [ "$(< "$x")" = "1" ] && continue x="$node_device/nodeid" [ -f "$x" ] || continue [ $(< "$x") = "0x$node_id" ] || continue node_guid=$(basename "$node_device") break; done if [ -z "$node_guid" ] then [ "$opt_active" = "y" ] && continue [ -n "$opt_guid" -o -n "$opt_company" ] && continue else [ -n "$opt_guid" \ -a "$opt_guid" != "$node_guid" ] && continue [ -n "$opt_company" \ -a "$opt_company" != "${node_guid:0:6}" ] && continue x="$bus_device/host_id" if [ -L "$x" -a \ "$(basename "$(readlink -f "$x")")" = "$node_guid" ] then [ "$opt_remote" = "y" ] && continue node_is_local="y" fi fi # show node information printf "%s:%s %s" "$bus_id" "$node_id" "${node_guid:-"unknown"}" if [ -n "$node_guid" ] then [ -f "$opt_ouidb" ] && printf " %s" "$(egrep -i -e "^${node_guid:0:6}" \ "$opt_ouidb" | cut -c8-)" for x in $(find "$node_device/" -name "model_name_kv") do printf " \'%s\'" "$(< "$x")" done [ "$node_is_local" = "y" ] && printf " (local)" fi echo [ -z "$opt_verbose" ] && continue if [ -n "$node_guid" ] then x="$node_device/bus_options" if [ -f "$x" ] then y="$(cut -f-6 -d' ' < "$x")" [ -n "$y" ] && printf "\t%s\n" "$y" y="$(cut -f7- -d' ' < "$x")" [ -n "$y" ] && printf "\t%s\n" "$y" fi for x in "${node_attributes_list[@]}" do y="$node_device/$x" [ -f "$y" ] || continue y="$(< "$y")" printf "\t%s: %s" "$x" "$y" if [ "$x" = "vendor_id" -a \ -n "$y" -a -f "$opt_ouidb" ] then printf " %s" "$(egrep -i -e "^${y:2}"\ "$opt_ouidb" | cut -c8-)" fi echo done fi # TODO: show unit directories information echo done done