#! /bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2020, Google LLC. All rights reserved.
# Author: Saravana Kannan
function help() {
cat /dev/null)
for SL in $SUPPLIER_LINKS;
do
SYNC_STATE=$(cat $SL/sync_state_only)
# sync_state_only links are proxy dependencies.
# They can also have cycles. So, don't follow them.
if [ "$SYNC_STATE" != '0' ]
then
continue
fi
SUPPLIER=$(realpath $SL/supplier)
if [ ! -e $SUPPLIER/driver -a ${ALLOW_NO_DRIVER} -eq 0 ]
then
continue
fi
CONSUMERS+=($SUPPLIER)
OUT_LIST+=(${CON} ${SUPPLIER})
RET=0
done
return $RET
}
function detail_compat() {
f=$1/of_node/compatible
if [ -e $f ]
then
echo -n $(cat $f)
else
echo -n $1
fi
}
function detail_module() {
f=$1/driver/module
if [ -e $f ]
then
echo -n $(basename $(realpath $f))
else
echo -n $1
fi
}
function detail_driver() {
f=$1/driver
if [ -e $f ]
then
echo -n $(basename $(realpath $f))
else
echo -n $1
fi
}
function detail_fwnode() {
f=$1/firmware_node
if [ ! -e $f ]
then
f=$1/of_node
fi
if [ -e $f ]
then
echo -n $(realpath $f)
else
echo -n $1
fi
}
function detail_graphviz() {
if [ "$2" != "ROOT" ]
then
echo -n "\"$(basename $2)\"->\"$(basename $1)\""
else
echo -n "\"$(basename $1)\""
fi
}
function detail_tsort() {
echo -n "\"$2\" \"$1\""
}
function detail_device() { echo -n $1; }
alias detail=detail_device
ALLOW_NO_DRIVER=0
ALLOW_DEVLINKS=1
ALLOW_PARENTS=1
while [ $# -gt 0 ]
do
ARG=$1
case $ARG in
--help)
help
exit 0
;;
-c)
alias detail=detail_compat
;;
-m)
alias detail=detail_module
;;
-d)
alias detail=detail_driver
;;
-f)
alias detail=detail_fwnode
;;
-g)
alias detail=detail_graphviz
;;
-t)
alias detail=detail_tsort
;;
--allow-no-driver)
ALLOW_NO_DRIVER=1
;;
--exclude-devlinks)
ALLOW_DEVLINKS=0
;;
--exclude-parents)
ALLOW_PARENTS=0
;;
*)
# Stop at the first argument that's not an option.
break
;;
esac
shift
done
function detail_chosen() {
detail $1 $2
}
if [ $# -eq 0 ]
then
help
exit 1
fi
CONSUMERS=($@)
OUT_LIST=()
# Do a breadth first, non-recursive tracking of suppliers. The parent is also
# considered a "supplier" as a device can't probe without its parent.
i=0
while [ $i -lt ${#CONSUMERS[@]} ]
do
CONSUMER=$(realpath ${CONSUMERS[$i]})
i=$(($i+1))
if already_seen ${CONSUMER}
then
continue
fi
# If this is not a device with a driver, we don't care about its
# suppliers.
if [ ! -e ${CONSUMER}/driver -a ${ALLOW_NO_DRIVER} -eq 0 ]
then
continue
fi
ROOT=1
# Add suppliers to CONSUMERS list and output the consumer details.
#
# We don't need to worry about a cycle in the dependency chain causing
# infinite loops. That's because the kernel doesn't allow cycles in
# device links unless it's a sync_state_only device link. And we ignore
# sync_state_only device links inside add_suppliers.
if add_suppliers ${CONSUMER}
then
ROOT=0
fi
if add_parent ${CONSUMER}
then
ROOT=0
fi
if [ $ROOT -eq 1 ]
then
OUT_LIST+=(${CONSUMER} "ROOT")
fi
done
# Can NOT combine sort and uniq using sort -suk2 because stable sort in toybox
# isn't really stable.
dev_to_detail | sort -k2 -k1 | uniq -f 1 | sort | cut -f2-
exit 0