/usr/bin/tlp-usblist is in tlp 1.1-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #!/usr/bin/perl
# tlp-usblist - list usb device info with autosuspend attributes
#
# Copyright (c) 2018 Thomas Koch <linrunner at gmx.net>
# This software is licensed under the GPL v2 or later.
package tlp_usblist;
use strict;
use warnings;
# --- Constants
use constant USBD => "/sys/bus/usb/devices";
# --- Global vars
my %usbdevices;
my $udev;
my $no_runtimepm = 0;
# --- Subroutines
# Read content from a sysfile
# $_[0]: input file
# return: content / empty string if nonexistent or not readable
sub catsysf {
my $sysval = "";
if (open (SYSF, "$_[0]")) {
chomp ($sysval = <SYSF>);
close (SYSF);
}
return $sysval;
}
# Read device driver from DEVICE/uevent
# $_[0]: (sub)device base path
# return: driver / empty string if uevent nonexistent or not readable
sub getdriver {
my $driver = "";
if ( open (SYSF, "$_[0]/uevent") ) {
# read file line by line
while (<SYSF>) {
# match line content and return DRIVER= value
if ( s/^DRIVER=(.*)/$1/ ) {
chomp ($driver = $_);
last; # break loop
}
}
close (SYSF);
}
return $driver
}
# Get drivers associated with USB device by iterating subdevices
# $_[0]: device base path
# return: driver list / "no driver" if none found
sub usbdriverlist {
my $driverlist = "";
my $subdev;
# iterate subdevices
foreach $subdev (glob "$_[0]/*:*") {
# get subdevice driver
my $driver = getdriver ("$subdev");
if ( $driver ) {
if (index ($driverlist, $driver) == -1) {
if ($driverlist) { $driverlist = $driverlist . ", " . $driver; }
else { $driverlist = $driver; }
} # if index
} # if $driver
} # foreach $subdev
if (! $driverlist) { $driverlist = "no driver"; }
return $driverlist
}
# --- MAIN
# Check if Runtime PM is enabled
$no_runtimepm = 1 if ( ! glob USBD . "/*/power/autosuspend*");
# Read USB device tree attributes as arrays into %usbdevices hash, indexed by Bus_Device
foreach $udev (grep { ! /:/ } glob USBD . "/*") {
my ($asf, $asv);
my ($cnf, $cnv);
my $usbv = "(autosuspend not available)";
# get device id
my $usbk = sprintf ("%03d_%03d", catsysf ("$udev/busnum"), catsysf ("$udev/devnum") );
# look for autosuspend_delay_ms then autosuspend (deprecated)
foreach $asf ( "autosuspend_delay_ms", "autosuspend" ) {
if ( length ( $asv = catsysf ("$udev/power/$asf") ) ) {
# autosuspend* exists --> check for control then level (deprecated)
foreach $cnf ( "control", "level" ) {
if ( $cnv = catsysf ("$udev/power/$cnf") ) {
if ( $asf eq "autosuspend_delay_ms" ) {
$usbv = sprintf ("%s = %-5s %s = %5d", $cnf, $cnv . ",", $asf, $asv);
} else {
$usbv = sprintf ("%s = %-5s %s = %2d", $cnf, $cnv . ",", $asf, $asv);
}
last; # break loop
}
}
last; # break loop
}
}
# save formatted result in hash
@{$usbdevices{$usbk}} = ($udev, $usbv);
}
# Output device list with attributes and drivers
foreach (`lsusb 2> /dev/null`) {
my ($bus, $dev, $usbid, $desc) = /Bus (\S+) Device (\S+): ID (\S+)[ ]+(.*)/;
my $usbk = $bus . "_" . $dev;
$desc ||= "<unknown>";
print "Bus $bus Device $dev ID $usbid $usbdevices{$usbk}[1] -- $desc ("
. usbdriverlist ($usbdevices{$usbk}[0]) . ")\n";
}
exit 4 if ( $no_runtimepm == 1 );
exit 0;
|