aboutsummaryrefslogtreecommitdiffstats
path: root/inxi
diff options
context:
space:
mode:
Diffstat (limited to 'inxi')
-rwxr-xr-xinxi977
1 files changed, 686 insertions, 291 deletions
diff --git a/inxi b/inxi
index e071ba5..3fdaf85 100755
--- a/inxi
+++ b/inxi
@@ -48,8 +48,8 @@ use POSIX qw(ceil uname strftime ttyname);
## INXI INFO ##
my $self_name='inxi';
-my $self_version='3.3.21';
-my $self_date='2022-08-22';
+my $self_version='3.3.22';
+my $self_date='2022-10-08';
my $self_patch='00';
## END INXI INFO ##
@@ -1938,6 +1938,7 @@ sub display_data {
['weston','--version'],
['wlr-randr',''],
['xdpyinfo',''],
+ ['xdriinfo',''],
['Xorg','-version'],
['xprop','-root'],
['xrandr',''],
@@ -2945,11 +2946,11 @@ sub check_items {
}
elsif ($type eq 'recommended display information programs'){
if ($bsd_type){
- @data = qw(glxinfo wmctrl xdpyinfo xprop xrandr);
+ @data = qw(glxinfo wmctrl xdpyinfo xprop xdriinfo xrandr);
$info_os = 'info-bsd';
}
else {
- @data = qw(glxinfo wmctrl xdpyinfo xprop xrandr);
+ @data = qw(glxinfo wmctrl xdpyinfo xprop xdriinfo xrandr);
}
$b_program = 1;
$item = 'Program';
@@ -3007,7 +3008,7 @@ sub check_items {
}
else {
@data = qw(/dev /dev/disk/by-id /dev/disk/by-label /dev/disk/by-path
- /dev/disk/by-uuid /sys/class/dmi/id);
+ /dev/disk/by-uuid /sys/class/dmi/id /sys/class/hwmon);
}
$b_dir = 1;
$item = 'Directory';
@@ -3089,9 +3090,6 @@ sub item_data {
my ($type) = @_;
my $data = {
# Directory Data
- '/sys/class/dmi/id' => {
- 'info' => '-M system, motherboard, bios',
- },
'/dev' => {
'info' => '-l,-u,-o,-p,-P,-D disk partition data',
},
@@ -3113,6 +3111,12 @@ sub item_data {
'/sys' => {
'info' => '',
},
+ '/sys/class/dmi/id' => {
+ 'info' => '-M system, motherboard, bios',
+ },
+ '/sys/class/hwmon' => {
+ 'info' => '-s sensor data (fallback if no lm-sensors)',
+ },
# File Data
'/etc/lsb-release' => {
'info' => '-S distro version data (older version)',
@@ -3377,7 +3381,7 @@ sub item_data {
'rpm' => 'systemd or sysvinit',
},
'sensors' => {
- 'info' => '-s sensors output',
+ 'info' => '-s sensors output (optional, /sys supplies most)',
'info-bsd' => '',
'apt' => 'lm-sensors',
'pacman' => 'lm-sensors',
@@ -3475,6 +3479,13 @@ sub item_data {
'pacman' => 'xorg-xdpyinfo',
'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdpyinfo)',
},
+ 'xdriinfo' => {
+ 'info' => '-G (X) DRI driver (if missing, fallback to Xorg log)',
+ 'info-bsd' => '-G (X) DRI driver (if missing, fallback to Xorg log',
+ 'apt' => 'X11-utils',
+ 'pacman' => 'xorg-xdriinfo',
+ 'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdriinfo)',
+ },
'xprop' => {
'info' => '-S (X) desktop data',
'info-bsd' => '-S (X) desktop data',
@@ -5194,7 +5205,7 @@ sub get {
if ($arg){
my $wl = 'bluetooth|compiler|cpu|dboot|dmidecode|elbrus|ipmi|logical|lspci|';
$wl .= 'partitions|pciconf|pcictl|pcidump|raid-btrfs|raid-hw|raid-lvm|';
- $wl .= 'raid-md|raid-soft|raid-zfs|sensors|swaymsg|sysctl|';
+ $wl .= 'raid-md|raid-soft|raid-zfs|sensors|sensors-sys|swaymsg|sysctl|';
$wl .= 'uptime|usbconfig|usbdevs|vmstat|wl-info|wlr-randr|xorg-log|xrandr';
for (split(',',$arg)){
if ($_ =~ /\b($wl)\b/){
@@ -5220,7 +5231,7 @@ sub get {
my ($opt,$arg) = @_;
if ($arg){
my $wl = 'colors|cpuinfo|display|dmidecode|hddtemp|lsusb|man|meminfo|';
- $wl .= 'no-dig|no-doas|no-html-wan|no-sudo|pkg|rpm||usb-sys|';
+ $wl .= 'no-dig|no-doas|no-html-wan|no-sudo|pkg|rpm|sensors-sys|usb-sys|';
$wl .= 'vmstat|wayland|wmctrl';
for (split(',',$arg)){
if ($_ =~ /\b($wl)\b/){
@@ -5340,6 +5351,8 @@ sub get {
else {
main::error_handler('bad-arg',$opt,$arg);
}},
+ 'sensors-sys' => sub {
+ $force{'sensors-sys'} = 1;},
'sensors-use:s' => sub {
my ($opt,$arg) = @_;
if ($arg){
@@ -5790,7 +5803,8 @@ sub show_options {
LMP version."],
['2', '-G', '', "GPU arch (AMD/Intel/Nvidia only); Specific vendor/product
information (if relevant); PCI/USB ID of device; Direct rendering status
- (in X); Screen number GPU is running on (Nvidia only)."],
+ (in X); Screen number GPU is running on (Nvidia only); device temp (Linux,
+ if found)."],
['2', '-i', '', "For IPv6, show additional scope addresses: Global, Site,
Temporary, Unknown. See --limit for large counts of IP addresses."],
['2', '-I', '', "Default system GCC. With -xx, also shows other installed
@@ -5802,7 +5816,8 @@ sub show_options {
['2', '-L', '', "For VG > LV, and other Devices, dm:"],
['2', '-m,--memory-modules', '', "Max memory module size (if available)."],
['2', '-N', '', "Specific vendor/product information (if relevant);
- PCI/USB ID of device; Version/port(s)/driver version (if available)."],
+ PCI/USB ID of device; Version/port(s)/driver version (if available); device
+ temperature (Linux, if found)."],
['2', '-o,-p,-P', '', "Add mapped: name if partition mapped."],
['2', '-r', '', "Packages, see -Ix."],
['2', '-R', '', "md-raid: second RAID Info line with extra data:
@@ -5828,7 +5843,6 @@ sub show_options {
['2', '-A', '', "Chip vendor:product ID for each audio device; PCIe speed,
lanes (if found)."],
['2', '-B', '', "Serial number."],
- ['2', '-C', '', "Add microarchitecture level."],
['2', '-D', '', "Disk transfer speed; NVMe lanes; Disk serial number; LVM
volume group free space (if available); disk duid (some BSDs)."],
['2', '-E', '', "Chip vendor:product ID, LMP subversion; PCIe speed, lanes
@@ -5911,11 +5925,12 @@ sub show_options {
also sets --extra=3:"],
['2', '-A', '', "If available: list of alternate kernel modules/drivers
for device(s); PCIe lanes-max: gen, speed, lanes (if relevant)."],
- ['2', '-C', '', "If available: CPU generation, process node, built years; CPU
- socket type, base/boost speeds (dmidecode+root/sudo/doas required); Full
- topology line, with cores, threads, threads per core, granular cache data,
- smt status; CPU vulnerabilities (bugs); family, model-id, stepping - format:
- hex (decimal) if greater than 9; microcode format: hex."],
+ ['2', '-C', '', "If available: microarchitecture level (64 bit AMD/Intel
+ only).CPU generation, process node, built years; CPU socket type, base/boost
+ speeds (dmidecode+root/sudo/doas required); Full topology line, with cores,
+ threads, threads per core, granular cache data, smt status; CPU
+ vulnerabilities (bugs); family, model-id, stepping - format: hex (decimal)
+ if greater than 9; microcode format: hex."],
['2', '-d,-D', '', "If available: logical and physical block sizes; drive
family; maj:min, USB drive specifics; SMART report."],
['2', '-E', '', "If available: in Report:, adds Info: line: acl-mtu,
@@ -6023,9 +6038,9 @@ sub show_options {
['1', '', '--sensors-default', "Removes configuration item SENSORS_USE and
SENSORS_EXCLUDE. Same as default behavior."],
['1', '', '--sensors-exclude', "[sensor[s] name, comma separated] Exclude
- supplied sensor array[s] for -s output (lm-sensors, Linux only)."],
+ supplied sensor array[s] for -s output (lm-sensors, /sys. Linux only)."],
['1', '', '--sensors-use', "[sensor[s] name, comma separated] Use only
- supplied sensor array[s] for -s output (lm-sensors, Linux only)."],
+ supplied sensor array[s] for -s output (lm-sensors, /sys. Linux only)."],
['1', '', '--sleep', "[0-x.x] Change CPU sleep time, in seconds, for -C
(default:^$cpu_sleep). Allows system to catch up and show a more accurate CPU
use. Example:^$self_name^-Cxxx^--sleep^0.15"],
@@ -6787,6 +6802,7 @@ sub message {
'monitor-wayland' => 'no compositor data',
'note-check' => 'check',
'note-est' => 'est.',
+ 'note-not-reliable' => 'not reliable',
'nv-current' => "current (as of $id)",
'nv-legacy-active' => "legacy-active (EOL~$id)",
'nv-legacy-eol' => 'legacy (EOL)',
@@ -6818,11 +6834,15 @@ sub message {
'root-suggested' => 'try sudo/root',# gdm only
'screen-wayland' => 'no compositor data',
'screen-xvesa' => 'no Xvesa data',
- 'sensors-data-bsd' => "$id sensor data found but not usable.",
- 'sensors-data-bsd-ok' => 'No sensor data found. Are sensors present?',
- 'sensors-data-ipmi' => 'No ipmi sensor data found.',
- 'sensors-data-linux' => 'No sensor data found. Is lm-sensors configured?',
- 'sensors-ipmi-root' => 'Unable to run ipmi sensors. Root privileges required.',
+ 'sensor-data-bsd' => "$id sensor data found but not usable.",
+ 'sensor-data-bsd-ok' => 'No sensor data found. Are data sources present?',
+ 'sensor-data-bsd-unsupported' => 'Sensor data not available. Unsupported BSD variant.',
+ 'sensor-data-ipmi' => 'No ipmi sensor data found.',
+ 'sensor-data-ipmi-root' => 'Unable to run ipmi sensors. Root privileges required.',
+ 'sensors-data-linux' => 'No sensor data found. Missing /sys/class/hwmon, lm-sensors.',
+ 'sensor-data-lm-sensors' => 'No sensor data found. Is lm-sensors configured?',
+ 'sensor-data-sys' => 'No sensor data found in /sys/class/hwmon.',
+ 'sensor-data-sys-lm' => 'No sensor data found using /sys/class/hwmon or lm-sensors.',
'smartctl-command' => 'A mandatory SMART command failed. Various possible causes.',
'smartctl-open' => 'Unable to open device. Wrong device ID given?',
'smartctl-udma-crc' => 'Bad cable/connection?',
@@ -7575,21 +7595,21 @@ sub sound_server_output {
my ($program);
my ($j,$num) = (0,0);
foreach my $server (@{sound_server_data()}){
- next if $extra < 1 && (!$server->[2] || $server->[2] ne 'yes');
+ next if $extra < 1 && (!$server->[3] || $server->[3] ne 'yes');
$j = scalar @$rows;
- $server->[1] ||= 'N/A';
$server->[2] ||= 'N/A';
+ $server->[3] ||= 'N/A';
push(@$rows, {
- main::key($num++,1,1,'Sound Server') => $server->[0],
- main::key($num++,0,2,'v') => $server->[1],
- main::key($num++,0,2,'running') => $server->[2],
+ main::key($num++,1,1,$server->[0]) => $server->[1],
+ main::key($num++,0,2,'v') => $server->[2],
+ main::key($num++,0,2,'running') => $server->[3],
});
}
eval $end if $b_log;
}
sub sound_server_data {
eval $start if $b_log;
- my ($program,$running,$server,$version);
+ my ($program,$running,$server,$type,$version);
my $servers = [];
if (my $file = $system_files{'asound-version'}){
# avoid possible second line if compiled by user
@@ -7598,55 +7618,61 @@ sub sound_server_data {
$version = (split(/\s+/, $content))[-1];
$version =~ s/\.$//; # trim off period
$server = 'ALSA';
+ $type = 'Sound API';
$running = 'yes';
# not needed I think, if asound is there, it's running, but if that's
# not correct, can use one of the info/list/stat tests for aplay
# if (main::check_program('aplay') && main::grabber('aplay -l 2>/dev/null')){
# $running = 'yes';
# }
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
# sndstat file may be removed in linux oss
if (-e '/dev/sndstat' || ($program = main::check_program('ossinfo'))){
$server = 'OSS';
+ $type = 'Sound API';
#$version = main::program_version('oss','\S',2);
$version = (grep {/^hw.snd.version:/} @{$sysctl{'audio'}})[0] if $sysctl{'audio'};
$version = (split(/:\s*/,$version),1)[1] if $version;
$version =~ s|/.*$|| if $version;
# not a great test, but ok for now
$running = (-e '/dev/sndstat') ? 'yes' : 'no?';
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
if ($program = main::check_program('sndiod')){
$server = 'sndio';
+ $type = 'Sound Interface';
#$version = main::program_version('sndio','\S',2);
$running = (grep {/sndiod/} @ps_cmd) ? 'yes': 'no';
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
if ($program = main::check_program('jackd')){
$server = 'JACK';
+ $type = 'Sound Server';
$version = main::program_version($program,'^jackd',3,'--version',1);
$running = (grep {/jackd/} @ps_cmd) ? 'yes':'no' ;
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
# note: pactl info/list/stat could be used
if ($program = main::check_program('pactl')){
$server = 'PulseAudio';
+ $type = 'Sound Server';
$version = main::program_version($program,'^pactl',2,'--version',1);
$running = (grep {m|/pulseaudiod?\b|} @ps_cmd) ? 'yes':'no' ;
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
if ($program = main::check_program('pipewire')){
$server = 'PipeWire';
+ $type = 'Sound Server';
$version = main::program_version($program,'^Compiled with libpipe',4,'--version',1);
$running = (grep {/pipewire/} @ps_cmd) ? 'yes':'no' ;
- push(@$servers, [$server,$version,$running]);
- ($running,$server,$version) = ('','','');
+ push(@$servers, [$type,$server,$version,$running]);
+ ($running,$version) = ('','');
}
main::log_data('dump','sound servers: @$servers',$servers) if $b_log;
print Data::Dumper::Dumper $servers if $dbg[26];
@@ -8744,8 +8770,11 @@ sub full_output {
if ($b_admin && $cpu->{'gen'}){
$rows->[$j]{main::key($num++,0,3,'gen')} = $cpu->{'gen'};
}
- if ($extra > 1 && $properties->{'arch-level'}){
- $rows->[$j]{main::key($num++,0,2,'level')} = $properties->{'arch-level'};
+ if ($b_admin && $properties->{'arch-level'}){
+ $rows->[$j]{main::key($num++,1,2,'level')} = $properties->{'arch-level'}[0];
+ if ($properties->{'arch-level'}[1]){
+ $rows->[$j]{main::key($num++,0,3,'note')} = $properties->{'arch-level'}[1];
+ }
}
if ($b_admin){
if ($cpu->{'year'}){
@@ -10291,7 +10320,7 @@ sub cpu_properties {
$bits_sys = ($cpu->{'flags'} =~ /\blm\b/) ? 64 : 32;
}
# must run after to make sure we have cpu bits
- if (!%risc && $bits_sys && $bits_sys == 64 && $cpu->{'flags'}){
+ if ($b_admin && !%risc && $bits_sys && $bits_sys == 64 && $cpu->{'flags'}){
$arch_level = cp_cpu_level(
$cpu->{'flags'}
);
@@ -10999,7 +11028,7 @@ sub cp_cpu_arch {
$process = 'GF 12nm';
$year = '2018-21';}
# used this but it didn't age well: ^(2[0123456789ABCDEF]|
- elsif ($model =~ /^(31|47|60|68|71|90)$/){
+ elsif ($model =~ /^(31|47|60|68|71|90|98|A.)$/){
$arch = 'Zen 2';
$gen = '3';
$process = 'TSMC n7 (7nm)'; # some consumer maybe GF 14nm
@@ -11020,19 +11049,19 @@ sub cp_cpu_arch {
elsif ($family eq '19'){
# ext model 6,7, but no base models yet
# 10 engineering sample
- if ($model =~ /^(10|[67][0-9A-F])$/){
+ if ($model =~ /^(1.|6.|7.|A.)$/){
$arch = 'Zen 4';
$gen = '5';
$process = 'TSMC n5 (5nm)';
$year = '2022';}
# double check 40, 44
- elsif ($model =~ /^(40|44)$/){
+ elsif ($model =~ /^(4.)$/){
$arch = 'Zen 3+';
$gen = '4';
$process = 'TSMC n6 (7nm)';
$year = '2022';}
- # 21, 50: step 0;
- elsif ($model =~ /^(0|1|8|21|50)$/){
+ # 21, 50: step 0; known: 21, 3x, 50
+ elsif ($model =~ /^(0|1|8|2.|3.|5.)$/){
$arch = 'Zen 3';
$gen = '4';
$process = 'TSMC n7 (7nm)';
@@ -11094,72 +11123,73 @@ sub cp_cpu_arch {
}
}
# note, to test uncoment $cpu{'type'} = Elbrus in proc/cpuinfo logic
+ # ExpLicit Basic Resources Utilization Scheduling
elsif ($type eq 'elbrus'){
# E8CB
if ($family eq '4'){
if ($model eq '1'){
- $arch = 'Elbrus';
- $process = '';
- $year = '';}
+ $arch = 'Elbrus 2000 (gen-1)';
+ $process = 'Mikron 130nm';
+ $year = '2005';}
elsif ($model eq '2'){
- $arch = 'Elbrus-S';
- $process = '';
- $year = '';}
+ $arch = 'Elbrus-S (gen-2)';
+ $process = 'Mikron 90nm';
+ $year = '2010';}
elsif ($model eq '3'){
- $arch = 'Elbrus-4C';
- $process = '65nm';
- $year = '';}
+ $arch = 'Elbrus-4C (gen-3)';
+ $process = 'TSMC 65nm';
+ $year = '2014';}
elsif ($model eq '4'){
- $arch = 'Elbrus-2C+';
- $process = '90nm';
- $year = '';}
+ $arch = 'Elbrus-2C+ (gen-2)';
+ $process = 'Mikron 90nm';
+ $year = '2011';}
elsif ($model eq '6'){
- $arch = 'Elbrus-2CM';
- $process = '90nm';
- $year = '';}
+ $arch = 'Elbrus-2CM (gen-2)';
+ $note = $check;
+ $process = 'Mikron 90nm';
+ $year = '2011 (?)';}
elsif ($model eq '7'){
if ($stepping >= 2){
- $arch = 'Elbrus-8C1';
- $process = '28nm';
- $year = '';}
+ $arch = 'Elbrus-8C1 (gen-4)';
+ $process = 'TSMC 28nm';
+ $year = '2016';}
else {
- $arch = 'Elbrus-8C';
- $process = '28nm';
- $year = '';}
+ $arch = 'Elbrus-8C (gen-4)';
+ $process = 'TSMC 28nm';
+ $year = '2016';}
} # note: stepping > 1 may be 8C1
elsif ($model eq '8'){
- $arch = 'Elbrus-1C+';
+ $arch = 'Elbrus-1C+ (gen-4)';
$process = 'TSMC 40nm';
- $year = '';}
+ $year = '2016';}
# 8C2 morphed out of E8CV, but the two were the same die
elsif ($model eq '9'){
- $arch = 'Elbrus-8CV/8C2';
+ $arch = 'Elbrus-8CV/8C2 (gen-4/5)';
$process = 'TSMC 28nm';
$note = $check;
- $year = '';}
+ $year = '2016/2020';}
elsif ($model eq 'A'){
- $arch = 'Elbrus-12C';
- $process = 'TSMC 16nm'; # guess
- $year = '';}
+ $arch = 'Elbrus-12C (gen-6)';
+ $process = 'TSMC 16nm';
+ $year = '2021+';}
elsif ($model eq 'B'){
- $arch = 'Elbrus-16C';
+ $arch = 'Elbrus-16C (gen-6)';
$process = 'TSMC 16nm';
- $year = '';}
+ $year = '2021+';}
elsif ($model eq 'C'){
- $arch = 'Elbrus-2C3';
+ $arch = 'Elbrus-2C3 (gen-6)';
$process = 'TSMC 16nm';
- $year = '';}
+ $year = '2021+';}
else {
$arch = 'Elbrus-??';;
- $year = '';
$note = $check;
$year = '';}
}
elsif ($family eq '5'){
if ($model eq '9'){
- $arch = 'Elbrus-8C2';
+ $arch = 'Elbrus-8C2 (gen-4)';
$process = 'TSMC 28nm';
- $year = '';}
+ $year = '2020';}
else {
$arch = 'Elbrus-??';
$note = $check;
@@ -11168,17 +11198,21 @@ sub cp_cpu_arch {
}
elsif ($family eq '6'){
if ($model eq 'A'){
- $arch = 'Elbrus-12C';
- $process = 'TSMC 16nm'; # guess
- $year = '';}
+ $arch = 'Elbrus-12C (gen-6)';
+ $process = 'TSMC 16nm';
+ $year = '2021+';}
elsif ($model eq 'B'){
- $arch = 'Elbrus-16C';
+ $arch = 'Elbrus-16C (gen-6)';
$process = 'TSMC 16nm';
- $year = '';}
+ $year = '2021+';}
elsif ($model eq 'C'){
- $arch = 'Elbrus-2C3';
+ $arch = 'Elbrus-2C3 (gen-6)';
$process = 'TSMC 16nm';
- $year = '';}
+ $year = '2021+';}
+ # elsif ($model eq '??'){
+ # $arch = 'Elbrus-32C (gen-7)';
+ # $process = '?? 7nm';
+ # $year = '2025';}
else {
$arch = 'Elbrus-??';
$note = $check;
@@ -11302,10 +11336,6 @@ sub cp_cpu_arch {
$arch = 'M Tolapai'; # pentium M system on chip
$process = 'Intel 90nm';
$year = '2008';}
- elsif ($model =~ /^(1D)$/){
- $arch = 'Penryn';
- $process = 'Intel 45nm';
- $year = '2007-08';}
elsif ($model =~ /^(17)$/){
$arch = 'Penryn'; # 17:A:Core 2,Celeron-wolfdale,yorkfield
$process = 'Intel 45nm';
@@ -11319,6 +11349,10 @@ sub cp_cpu_arch {
$arch = 'Bonnell';
$process = 'Intel 45nm';
$year = '2008-13';} # atom Bonnell? 27?
+ elsif ($model =~ /^(1D)$/){
+ $arch = 'Penryn';
+ $process = 'Intel 45nm';
+ $year = '2007-08';}
# 25 may be nahelem in a stepping, check. Stepping 2 is westmere
elsif ($model =~ /^(25|2C|2F)$/){
$arch = 'Westmere'; # die shrink of nehalem
@@ -11363,7 +11397,7 @@ sub cp_cpu_arch {
$process = 'Intel 14nm';
$year = '2019';}
elsif ($stepping >= 8){
- $arch = 'Cooper Lake';
+ $arch = 'Cooper Lake'; # 55:A:14nm
$process = 'Intel 14nm';
$year = '2020';}
else {
@@ -11382,12 +11416,12 @@ sub cp_cpu_arch {
$arch = 'Skylake-S';
$process = 'Intel 14nm';
$year = '2015';}
- elsif ($model =~ /^(66)$/){
+ elsif ($model =~ /^(66|67)$/){
$arch = 'Cannon Lake';
$process = 'Intel 10nm';
$year = '2018';}
# 6 are servers, 7 not
- elsif ($model =~ /^(6A|6C|7D|7E)$/){
+ elsif ($model =~ /^(6A|6C|7D|7E|9F)$/){
$arch = 'Ice Lake';
$process = 'Intel 10nm';
$year = '2019-21';}
@@ -11399,10 +11433,22 @@ sub cp_cpu_arch {
$arch = 'Knights Mill';
$process = 'Intel 14nm';
$year = '2017-19';}
- elsif ($model =~ /^(8A|96|9C)$/){
- $arch = 'Tremont';
+ elsif ($model =~ /^(86)$/){
+ $arch = 'Tremont Snow Ridge'; # embedded
$process = 'Intel 10nm';
- $year = '2019';}
+ $year = '2020';}
+ elsif ($model =~ /^(87)$/){
+ $arch = 'Tremont Parker Ridge'; # embedded
+ $process = 'Intel 10nm';
+ $year = '2022';}
+ elsif ($model =~ /^(8A)$/){
+ $arch = 'Tremont Lakefield';
+ $process = 'Intel 10nm';
+ $year = '2020';} # ?
+ elsif ($model =~ /^(96)$/){
+ $arch = 'Tremont Elkhart Lake';
+ $process = 'Intel 10nm';
+ $year = '2020';} # ?
elsif ($model =~ /^(8C|8D)$/){
$arch = 'Tiger Lake';
$process = 'Intel 10nm';
@@ -11444,27 +11490,21 @@ sub cp_cpu_arch {
$arch = 'Sapphire Rapids';
$process = 'Intel 7 (10nm ESF)';
$year = '2021+';} # server
- elsif ($model =~ /^(97|9A)$/){
+ elsif ($model =~ /^(97|9A|BE)$/){
$arch = 'Alder Lake'; # socket LG 1700
$process = 'Intel 7 (10nm ESF)';
$year = '2021+';}
- ## IDS UNKNOWN, release late 2022
- # elsif ($model =~ /^()$/){
- # $arch = 'Raptor Lake'; # 13 gen, socket LG 1700,1800
- # $process = 'Intel 7 (10nm)';
- # $year = '2022+';}
- # elsif ($model =~ /^()$/){
- # $arch = 'Meteor Lake'; # 14 gen
- # $process = 'Intel 4';}
- # Granite Rapids: Intel 3 (7nm)
- # Arrow Lake - 15 gen
+ elsif ($model =~ /^(9A|9C)$/){
+ $arch = 'Tremont Jasper Lake';
+ $process = 'Intel 10nm';
+ $year = '2021+';} # ?
elsif ($model =~ /^(9E)$/){
if ($stepping == 9){
$arch = 'Kaby Lake';
$process = 'Intel 14nm';
$year = '2018';}
elsif ($stepping >= 10 && $stepping <= 13){
- $arch = 'Coffee Lake';
+ $arch = 'Coffee Lake'; # 9E:A,B,C,D
$process = 'Intel 14nm';
$year = '2018';}
else {
@@ -11473,16 +11513,36 @@ sub cp_cpu_arch {
$process = 'Intel 14nm';
$year = '2018';}
}
- elsif ($model =~ /^(A5)$/){
+ elsif ($model =~ /^(A5|A6)$/){
$arch = 'Comet Lake'; # stepping 0-5
$process = 'Intel 14nm';
$year = '2020';}
- elsif ($model =~ /^(A7)$/){
+ elsif ($model =~ /^(A7|A8)$/){
$arch = 'Rocket Lake'; # stepping 1
$process = 'Intel 14nm';
$year = '2021+';}
# More info: comet: shares family/model, need to find stepping numbers
- # Coming: meteor lake; granite rapids; diamond rapids
+ # Coming: meteor lake; granite rapids; emerald rapids, diamond rapids
+ ## IDS UNKNOWN, release late 2022
+ elsif ($model =~ /^(AA|AB|AC|B5)$/){
+ $arch = 'Meteor Lake'; # 14 gen
+ $process = 'Intel 4 (7nm)'; # confirm
+ $year = '2023+';}
+ elsif ($model =~ /^(AD|AE)$/){
+ $arch = 'Granite Rapids'; # ?
+ $process = 'Intel 3 (7nm+)'; # confirm
+ $year = '2024+';}
+ elsif ($model =~ /^(B6)$/){
+ $arch = 'Grand Ridge'; # 14 gen
+ $process = 'Intel 4 (7nm)'; # confirm
+ $year = '2023+';}
+ elsif ($model =~ /^(B7|BA)$/){
+ $arch = 'Raptor Lake'; # 13 gen, socket LG 1700,1800
+ $process = 'Intel 7 (10nm)';
+ $year = '2022+';}
+ # Granite Rapids: Intel 3 (7nm+)
+ # Arrow Lake - 15 gen, 20A (2nm), 2025
+ # Lunar Lake - 16 gn, 18A (1.8nm), 2025
}
# itanium 1 family 7 all recalled
elsif ($family eq 'B'){
@@ -11502,7 +11562,12 @@ sub cp_cpu_arch {
$process = 'Intel 180nm';
$year = '2000-01';}
elsif ($model =~ /^(2)$/){
- $arch = 'Netburst Northwood';
+ if ($stepping <= 4 || $stepping > 6){
+ $arch = 'Netburst Northwood';}
+ elsif ($stepping == 5){
+ $arch = 'Netburst Gallatin';}
+ else {
+ $arch = 'Netburst';}
$process = 'Intel 130nm';
$year = '2002-03';}
elsif ($model =~ /^(3)$/){
@@ -11510,6 +11575,7 @@ sub cp_cpu_arch {
$process = 'Intel 90nm';
$year = '2004-06';} # 6? Nocona
elsif ($model =~ /^(4)$/){
+ # these are vague, and same stepping can have > 1 core names
if ($stepping < 10){
$arch = 'Netburst Prescott'; # 4:1,9:prescott
$process = 'Intel 90nm';
@@ -11520,7 +11586,7 @@ sub cp_cpu_arch {
$year = '2005-06';} # 6? Nocona
}
elsif ($model =~ /^(6)$/){
- $arch = 'Netburst Presler';
+ $arch = 'Netburst Presler'; # 6:2,4,5:presler
$process = 'Intel 65nm';
$year = '2006';}
else {
@@ -11559,23 +11625,34 @@ sub cp_cpu_arch {
# Only AMD/Intel 64 bit cpus
sub cp_cpu_level {
eval $start if $b_log;
- my ($flags) = @_;
- my $level;
- if ($flags =~ /AVX512/i){
- $level = 'v4';
- }
- # ~2015: Haswell and Excavator
- elsif ($flags =~ /\b(AVX2|BMI[12]|F16C|FMA|LZCNT|MOVBE|OSXSAVE)\b/i){
- $level = 'v3';
- }
- # !2009: Nehalem and Jaguar
- elsif ($flags =~ /\b(CMPXCHG16B|[LS]AHF|POPCNT|SSS?E3|SSE4_[12])\b/i){
- $level = 'v2';
- }
- # baseline: all x86_64 cpus
- elsif ($flags =~ /\b(CX8|FPU|FXSR|MMX|OSFXSR|SCE|SSE2?)\b/i){
+ my %flags = map {$_ =>1} split(/\s+/,$_[0]);
+ my ($level,$note,@found);
+ # note, each later cpu level must contain all subsequent cpu flags
+ # baseline: all x86_64 cpus lm cmov cx8 fpu fxsr mmx syscall sse2
+ my @l1 = qw(cmov cx8 fpu fxsr lm mmx syscall sse2);
+ my @l2 = qw(cx16 lahf_lm popcnt sse4_1 sse4_2 ssse3);
+ my @l3 = qw(abm avx avx2 bmi1 bmi2 f16c fma movbe xsave);
+ my @l4 = qw(avx512f avx512bw avx512cd avx512dq avx512vl);
+ if ((@found = grep {$flags{$_}} @l1) && scalar(@found) == scalar(@l1)){
$level = 'v1';
+ # print 'v1: ', Data::Dumper::Dumper \@found;
+ if ((@found = grep {$flags{$_}} @l2) && scalar(@found) == scalar(@l2)){
+ $level = 'v2';
+ # print 'v2: ', Data::Dumper::Dumper \@found;
+ # It's not 100% certain that if flags exist v3/v4 supported. flags don't
+ # give full possible outcomes in these cases. See: docs/inxi-cpu.txt
+ if ((@found = grep {$flags{$_}} @l3) && scalar(@found) == scalar(@l3)){
+ $level = 'v3';
+ # print 'v3: ', Data::Dumper::Dumper \@found;
+ $note = main::message('note-check');
+ if ((@found = grep {$flags{$_}} @l4) && scalar(@found) == scalar(@l4)){
+ $level = 'v4';
+ # print 'v4: ', Data::Dumper::Dumper \@found;
+ }
+ }
+ }
}
+ $level = [$level,$note] if $level;
eval $end if $b_log;
return $level;
}
@@ -13305,7 +13382,7 @@ sub set_disk_vendors {
# HM320II HM320II HM
['(SAMSUNG|^(AWMB|[BC]DS20|[BC]WB|BJ[NT]|[BC]GND|CJN|CUT|[DG]3 Station|DUO\b|DUT|CKT|[GS]2 Portable|GN|HD\d{3}[A-Z]{2}$|(HM|SP)\d{2}|HS\d|M[AB]G\d[FG]|MCC|MCBOE|MCG\d+GC|[CD]JN|MZ|^G[CD][1-9][QS]|P[BM]\d|(SSD\s?)?SM\s?841)|^SSD\s?[89]\d{2}\s(DCT|PRO|QVD|\d+[GT]B)|\bEVO\b|SV\d|[BE][A-Z][1-9]QT|YP\b|[CH]N-M|MMC[QR]E)','SAMSUNG','Samsung',''], # maybe ^SM, ^HM
# Android UMS Composite?U1
- ['(SanDisk|0781|^(ABLCD|AFGCE|D[AB]4|DX[1-9]|Extreme|Firebird|S[CD]\d{2}G|SD(S[S]?[ADQ]|SL\d+G|SU\d)|SDW[1-9]|SEM[1-9]|\d[STU]|U(3\b|1\d0))|Clip Sport|Cruzer|iXpand|SSD (Plus|U1[01]0) [1-9]|ULTRA\s(FIT|trek|II)|X[1-6]\d{2})','(SanDisk|0781)','SanDisk',''],
+ ['(SanDisk|0781|^(A[BCD]LC[DE]|AFGCE|D[AB]4|DX[1-9]|Extreme|Firebird|S[CD]\d{2}G|SD(S[S]?[ADQ]|SL\d+G|SU\d)|SDW[1-9]|SE\d{2}|SEM[1-9]|\d[STU]|U(3\b|1\d0))|Clip Sport|Cruzer|iXpand|SSD (Plus|U1[01]0) [1-9]|ULTRA\s(FIT|trek|II)|X[1-6]\d{2})','(SanDisk|0781)','SanDisk',''],
# these are HP/Sandisk cobranded. DX110064A5xnNMRI ids as HP and Sandisc
['(^DX[1-9])','^(HP\b|SANDDISK)','Sandisk/HP',''], # ssd drive, must come before seagate ST test
# real, SSEAGATE Backup+; XP1600HE30002 | 024 HN (spinpoint) ; possible usb: 24AS
@@ -13330,7 +13407,7 @@ sub set_disk_vendors {
['^(DKR|HGST|Touro|54[15]0|7250|HC[CT]\d)','^HGST','HGST (Hitachi)',''], # HGST HUA
['^((ATA\s)?Hitachi|HCS|HD[PST]|DK\d|IC|(HDD\s)?HT|HU|HMS|HDE|0G\d|IHAT)','Hitachi','Hitachi',''],
# vb: VB0250EAVER but clashes with vbox; HP_SSD_S700_120G ;GB0500EAFYL GB starter too generic?
- ['^(HP\b|[MV]B[0-6]|G[BJ]\d|DF\d|F[BK]|0-9]|MM\d{4}|PSS|XR\d{4}|c350|v\d{3}[bgorw]$|x\d{3}[w]$|VK0|HC[CPY]\d|EX9\d\d)','^HP','HP',''],
+ ['^(HP\b|[MV]B[0-6]|G[BJ]\d|DF\d|F[BK]|0-9]|MM\d{4}|PSS|XR\d{4}|c350|v\d{3}[bgorw]$|x\d{3}[w]$|VK0|HC[CPY]\d|EX9\d\d|VO0)','^HP','HP',''],
['^(Lexar|LSD|JumpDrive|JD\s?Firefly|LX\d|WorkFlow)','^Lexar','Lexar',''], # mmc-LEXAR_0xb016546c; JD Firefly;
# these must come before maxtor because STM
['^STmagic','^STmagic','STmagic',''],
@@ -13433,7 +13510,7 @@ sub set_disk_vendors {
['^Disain','^Disain','Disain',''],
['^(Disney|PIX[\s]?JR)','^Disney','Disney',''],
['^(Doggo|DQ-|Sendisk|Shenchu)','^(doggo|Sendisk(.?Shenchu)?|Shenchu(.?Sendisk)?)','Doggo (SENDISK/Shenchu)',''],
- ['^(Dogfish|Shark)','^Dogfish(\s*Technology)?','Dogfish Technology',''],
+ ['^(Dogfish|M\.2 2242|Shark)','^Dogfish(\s*Technology)?','Dogfish Technology',''],
['^DragonDiamond','^DragonDiamond','DragonDiamond',''],
['^(DREVO\b|X1\s\d+[GT])','^DREVO','Drevo',''],
['^DSS','^DSS DAHUA','DSS DAHUA',''],
@@ -13452,6 +13529,7 @@ sub set_disk_vendors {
['^Epson','^Epson','Epson',''],
['^(Etelcom|SSD051)','^Etelcom','Etelcom',''],
['^EURS','^EURS','EURS',''],
+ ['^eVAULT','^eVAULT','eVAULT',''],
# NOTE: ESA3... may be IBM PCIe SAD card/drives
['^(EXCELSTOR|r technology)','^EXCELSTOR( TECHNO(LOGY)?)?','ExcelStor',''],
['^EYOTA','^EYOTA','EYOTA',''],
@@ -13459,7 +13537,7 @@ sub set_disk_vendors {
['^EZLINK','^EZLINK','EZLINK',''],
['^Fantom','^Fantom( Drive[s]?)?','Fantom Drives',''],
['^Fanxiang','^Fanxiang','Fanxiang',''],
- ['^Faspeed','^Faspeed','Faspeed',''],
+ ['^(Faspeed|K3[\s-])','^Faspeed','Faspeed',''],
['^FASTDISK','^FASTDISK','FASTDISK',''],
['^Festtive','^Festtive','Festtive',''],
['^FiiO','^FiiO','FiiO',''],
@@ -13475,7 +13553,7 @@ sub set_disk_vendors {
['^(Garmin|Fenix|Nuvi|Zumo)','^Garmin','Garmin',''],
['^Geil','^Geil','Geil',''],
['^GelL','^GelL','GelL',''], # typo for Geil? GelL ZENITH R3 120GB
- ['^(Generic|UY[67]|SLD)','^Generic','Generic',''],
+ ['^(Generic|G1J3|SCA128|SLD|UY[67])','^Generic','Generic',''],
['^(Genesis(\s?Logic)?|05e3)','(Genesis(\s?Logic)?|05e3)','Genesis Logic',''],
['^Geonix','^Geonix','Geonix',''],
['^Getrich','^Getrich','Getrich',''],
@@ -13540,6 +13618,7 @@ sub set_disk_vendors {
['^Jingyi','^Jingyi','Jingyi',''],
# NOTE: ITY2 120GB hard to find
['^JMicron','^JMicron(\s?Tech(nology)?)?','JMicron Tech',''], #JMicron H/W raid
+ ['^(Jual|RX7)','^Jual','Jual',''],
['^Kazuk','^Kazuk','Kazuk',''],
['(\bKDI\b|^OM3P)','\bKDI\b','KDI',''],
['^KLLISRE','^KLLISRE','KLLISRE',''],
@@ -13579,7 +13658,7 @@ sub set_disk_vendors {
['^(LG\b|Xtick)','^LG','LG',''],
['(LITE[-\s]?ON[\s-]?IT)','LITE[-]?ON[\s-]?IT','LITE-ON IT',''], # LITEONIT_LSS-24L6G
# PH6-CE240-L; CL1-3D256-Q11 NVMe LITEON 256GB
- ['(LITE[-\s]?ON|^PH[1-9]|^DMT|^CV\d-|L(8[HT]|AT|C[HST]|JH|M[HST]|S[ST])-)','LITE[-]?ON','LITE-ON',''],
+ ['(LITE[-\s]?ON|^PH[1-9]|^DMT|^CV\d-|L(8[HT]|AT|C[HST]|JH|M[HST]|S[ST])-|^S900)','LITE[-]?ON','LITE-ON',''],
['^LONDISK','^LONDISK','LONDISK',''],
['^Longline','^Longline','Longline',''],
['^LuminouTek','^LuminouTek','LuminouTek',''],
@@ -13627,7 +13706,7 @@ sub set_disk_vendors {
['^(MyDigitalSSD|BP[4X])','^MyDigitalSSD','MyDigitalSSD',''], # BP4 = BulletProof4
['^(Myson)','^Myson([\s-]?Century)?([\s-]?Inc\.?)?','Myson Century',''],
['^(Neo\s*Forza|NFS\d)','^Neo\s*Forza','Neo Forza',''],
- ['^(Netac|S535N)','^Netac','Netac',''],
+ ['^(Netac|OnlyDisk|S535N)','^Netac','Netac',''],
['^NFHK','^NFHK','NFHK',''],
# NGFF is a type, like msata, sata
['^Nik','^Nikimi','Nikimi',''],
@@ -13635,6 +13714,7 @@ sub set_disk_vendors {
['^ODYS','^ODYS','ODYS',''],
['^Olympus','^Olympus','Olympus',''],
['^Orico','^Orico','Orico',''],
+ ['^Ortial','^Ortial','Ortial',''],
['^OSC','^OSC\b','OSC',''],
['^oyunkey','^oyunkey','Oyunkey',''],
['^PALIT','PALIT','Palit',''], # ssd
@@ -13673,6 +13753,7 @@ sub set_disk_vendors {
['^SAMSWEET','^SAMSWEET','Samsweet',''],
['^SandForce','^SandForce','SandForce',''],
['^Sannobel','^Sannobel','Sannobel',''],
+ ['^(Sansa|fuse\b)','^Sansa','Sansa',''],
# SATADOM can be innodisk or supermirco: dom == disk on module
# SATAFIRM is an ssd failure message
['^(Sea\s?Tech|Transformer)','^Sea\s?Tech','Sea Tech',''],
@@ -13680,6 +13761,8 @@ sub set_disk_vendors {
# DIAMOND_040_GB
['^(SILICON\s?MOTION|SM\d|090c)','^(SILICON\s?MOTION|090c)','Silicon Motion',''],
['(Silicon[\s-]?Power|^SP[CP]C|^Silicon|^Diamond|^HasTopSunlightpeed)','Silicon[\s-]?Power','Silicon Power',''],
+ # simple drive could also maybe be hgst
+ ['^(Simple\s?Tech|Simple[\s-]?Drive)','^Simple\s?Tech','SimpleTech',''],
['^SINTECHI?','^SINTECHI?','SinTech (adapter)',''],
['^SiS\b','^SiS','SiS',''],
['Smartbuy','\s?Smartbuy','Smartbuy',''], # SSD Smartbuy 60GB; mSata Smartbuy 3
@@ -14077,6 +14160,7 @@ sub device_output {
return if !$devices{'graphics'};
my $rows = $_[0];
my ($j,$num) = (0,1);
+ my ($bus_id);
set_monitors_sys() if !$monitor_ids && -e '/sys/class/drm';
foreach my $row (@{$devices{'graphics'}}){
$num = 1;
@@ -14090,6 +14174,7 @@ sub device_output {
# print "$row->[0] $row->[3]\n";
$j = scalar @$rows;
my $device = main::trimmer($row->[4]);
+ ($bus_id) = ();
$device = ($device) ? main::clean_pci($device,'output') : 'N/A';
# have seen absurdly verbose card descriptions, with non related data etc
if (length($device) > 85 || $size{'max-cols'} < 110){
@@ -14153,7 +14238,7 @@ sub device_output {
}
}
if ($extra > 0){
- my $bus_id = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]";
+ $bus_id = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]";
if ($extra > 1 && $bus_id ne 'N/A'){
main::get_pcie_data($bus_id,$j,$rows,\$num,'gpu');
}
@@ -14169,6 +14254,12 @@ sub device_output {
if ($extra > 2 && $row->[1]){
$rows->[$j]{main::key($num++,0,2,'class-ID')} = $row->[1];
}
+ if (!$bsd_type && $extra > 0 && $bus_id ne 'N/A' && $bus_id =~ /\.0$/){
+ my $temp = main::get_device_temp($bus_id);
+ if ($temp){
+ $rows->[$j]{main::key($num++,0,2,'temp')} = $temp . ' C';
+ }
+ }
# print "$row->[0]\n";
}
eval $end if $b_log;
@@ -14383,18 +14474,23 @@ sub display_output(){
# The only wayland setups with x drivers have xorg, transitional that is.
if (@$x_drivers){
$rows->[$j]{main::key($num++,1,3,'X')} = '';
- my $driver = ($x_drivers->[0]) ? $x_drivers->[0] : 'N/A';
+ my $driver = ($x_drivers->[0]) ? join(',',@{$x_drivers->[0]}) : 'N/A';
$rows->[$j]{main::key($num++,1,4,'loaded')} = $driver;
if ($x_drivers->[1]){
- $rows->[$j]{main::key($num++,0,4,'unloaded')} = $x_drivers->[1];
+ $rows->[$j]{main::key($num++,0,4,'unloaded')} = join(',',@{$x_drivers->[1]});
}
if ($x_drivers->[2]){
- $rows->[$j]{main::key($num++,0,4,'failed')} = $x_drivers->[2];
+ $rows->[$j]{main::key($num++,0,4,'failed')} = join(',',@{$x_drivers->[2]});
}
if ($extra > 1 && $x_drivers->[3]){
- $rows->[$j]{main::key($num++,0,4,'alternate')} = $x_drivers->[3];
+ $rows->[$j]{main::key($num++,0,4,'alternate')} = join(',',@{$x_drivers->[3]});
}
}
+ if ($graphics{'dri-drivers'}){
+ # note: if want to exclude if matches gpu/x driver, loop through and test.
+ # Here using all dri drivers found.
+ $rows->[$j]{main::key($num++,1,3,'dri')} = join(',',@{$graphics{'dri-drivers'}});
+ }
my $drivers;
if (@$gpu_drivers){
$drivers = join(',',@$gpu_drivers);
@@ -15342,7 +15438,7 @@ sub get_model_serial {
# DISPLAY DATA X.org ##
sub display_data_x {
eval $start if $b_log;
- my ($prog_xdpyinfo,$prog_xrandr);
+ my ($prog_xdpyinfo,$prog_xdriinfo,$prog_xrandr);
if ($prog_xdpyinfo = main::check_program('xdpyinfo')){
xdpyinfo_data($prog_xdpyinfo);
}
@@ -15350,6 +15446,10 @@ sub display_data_x {
if ($prog_xrandr = main::check_program('xrandr')){
xrandr_data($prog_xrandr);
}
+ # if tool not installed, falls back to testing Xorg log file
+ if ($prog_xdriinfo = main::check_program('xdriinfo')){
+ xdriinfo_data($prog_xdriinfo);
+ }
if (!$graphics{'screens'}){
$graphics{'tty'} = tty_data();
}
@@ -15368,6 +15468,40 @@ sub display_data_x {
main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log;
eval $end if $b_log;
}
+sub xdriinfo_data {
+ eval $start if $b_log;
+ my $program = $_[0];
+ my (%dri_drivers,$screen,$xdriinfo);
+ if (!$fake{'xdriinfo'}){
+ $xdriinfo = main::grabber("$program $display_opt 2>/dev/null",'','strip','ref');
+ }
+ else {
+ # $xdriinfo = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-test-1.txt",'strip','ref');
+ }
+ foreach $screen (@$xdriinfo){
+ if ($screen =~ /^Screen (\d+):\s+(\S+)/){
+ $dri_drivers{$1} = $2 if $2 !~ /^not\b/;
+ }
+ }
+ if ($graphics{'screens'}){
+ # assign to the screen if it's found
+ foreach $screen (@{$graphics{'screens'}}){
+ if (defined $dri_drivers{$screen->{'screen'}} ){
+ $screen->{'dri-driver'} = $dri_drivers{$screen->{'screen'}};
+ }
+ }
+ }
+ # now the display drivers
+ foreach $screen (sort keys %dri_drivers){
+ if (!$graphics{'dri-drivers'} ||
+ !(grep {$dri_drivers{$screen} eq $_} @{$graphics{'dri-drivers'}})){
+ push (@{$graphics{'dri-drivers'}},$dri_drivers{$screen});
+ }
+ }
+ print 'x dri driver: ', Data::Dumper::Dumper \%dri_drivers if $dbg[17];
+ main::log_data('dump','%dri_drivers',\%dri_drivers) if $b_log;
+ eval $end if $b_log;
+}
sub xdpyinfo_data {
eval $start if $b_log;
my ($program) = @_;
@@ -15471,8 +15605,9 @@ sub xrandr_data {
$xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip','ref');
}
else {
+ $xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-4-displays-1.txt",'strip','ref');
# $xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-test-1.txt",'strip','ref');
- $xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-test-2.txt",'strip','ref');
+ # $xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-test-2.txt",'strip','ref');
}
# $graphics{'dimensions'} = (\@dimensions);
# we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
@@ -15755,9 +15890,7 @@ sub gpu_drivers_sys {
}
sub display_drivers_x {
eval $start if $b_log;
- my ($driver,%drivers);
my $driver_data = [];
- my ($alternate,$failed,$loaded,$sep,$unloaded) = ('','','','','');
if (my $log = $system_files{'xorg-log'}){
if ($fake{'xorg-log'}){
# $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/Xorg.0-voyager-serena.log";
@@ -15778,21 +15911,30 @@ sub display_drivers_x {
sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx tdfx tga trident tseng
unichrome v4l vboxvideo vesa vga via vmware vmwgfx voodoo));
$list = qr/$list/; # i only added perl 5.14, don't use
+ my ($b_use_dri,$dri,$driver,%drivers);
+ my ($alternate,$failed,$loaded,$unloaded);
+ my $pattern = 'Failed|Unload|Loading';
+ # preferred source xdriinfo because it's current and accurate, but fallback here
+ if (!$graphics{'dri-drivers'}){
+ $b_use_dri = 1;
+ $pattern .= '|DRI driver:';
+ }
+ $pattern = qr/$pattern/;
# it's much cheaper to grab the simple pattern match then do the expensive one
# in the main loop.
# @xorg = grep {/Failed|Unload|Loading/} @xorg;
- foreach (@$xorg){
- next if !/Failed|Unload|Loading/;
+ foreach my $line (@$xorg){
+ next if $line !~ /$pattern/i;
# print "$_\n";
# note that in file names, driver is always lower case
- if (/\sLoading.*($list)_drv\.so$/i){
+ if ($line =~ /\sLoading.*($list)_drv\.so$/i){
$driver=lc($1);
# we get all the actually loaded drivers first, we will use this to compare the
# failed/unloaded, which have not always actually been truly loaded
$drivers{$driver}='loaded';
}
# openbsd uses UnloadModule:
- elsif (/(Unloading\s|UnloadModule).*\"?($list)(_drv\.so)?\"?$/i){
+ elsif ($line =~ /(Unloading\s|UnloadModule).*\"?($list)(_drv\.so)?\"?$/i){
$driver=lc($2);
# we get all the actually loaded drivers first, we will use this to compare the
# failed/unloaded, which have not always actually been truly loaded
@@ -15808,14 +15950,14 @@ sub display_drivers_x {
# (II) Unloading nouveau
# (II) Failed to load module "nouveau" (already loaded, 0)
# (II) LoadModule: "modesetting"
- elsif (/Failed.*($list)\"?.*$/i){
+ elsif ($line =~ /Failed.*($list)\"?.*$/i){
# Set driver to lower case because sometimes it will show as
# RADEON or NVIDIA in the actual x start
$driver=lc($1);
# we need to make sure that the driver has already been truly loaded,
# not just discussed
if (exists $drivers{$driver} && $drivers{$driver} ne 'alternate'){
- if ($_ !~ /\(already loaded/){
+ if ($line !~ /\(already loaded/){
$drivers{$driver}='failed';
}
# reset the previous line's 'unloaded' to 'loaded' as well
@@ -15823,28 +15965,30 @@ sub display_drivers_x {
$drivers{$driver}='loaded';
}
}
- elsif ($_ =~ /module does not exist/){
+ elsif ($line =~ /module does not exist/){
$drivers{$driver}='alternate';
}
}
+ elsif ($b_use_dri && $line =~ /DRI driver:\s*(\S+)/i){
+ $dri = $1;
+ if (!$graphics{'dri-drivers'} ||
+ !(grep {$dri eq $_} @{$graphics{'dri-drivers'}})){
+ push(@{$graphics{'dri-drivers'}},$dri);
+ }
+ }
}
- my $sep = '';
foreach (sort keys %drivers){
if ($drivers{$_} eq 'loaded'){
- $sep = ($loaded) ? ',' : '';
- $loaded .= $sep . $_;
+ push(@$loaded,$_);
}
elsif ($drivers{$_} eq 'unloaded'){
- $sep = ($unloaded) ? ',' : '';
- $unloaded .= $sep . $_;
+ push(@$unloaded,$_);
}
elsif ($drivers{$_} eq 'failed'){
- $sep = ($failed) ? ',' : '';
- $failed .= $sep . $_;
+ push(@$failed,$_);
}
elsif ($drivers{$_} eq 'alternate'){
- $sep = ($alternate) ? ',' : '';
- $alternate .= $sep . $_;
+ push(@$alternate,$_);
}
}
if ($loaded || $unloaded || $failed || $alternate){
@@ -16195,7 +16339,8 @@ sub set_intel_data {
'years' => '2020-21',
},
{'arch' => 'Gen-12.2',
- 'ids' => '4626|4628|4682|4688|4690|4692|4693|46a3|46a6|46a8|46aa|46b3|46c3',
+ 'ids' => '4626|4628|4682|4688|468a|468b|4690|4692|4693|46a3|46a6|46a8|46aa|' .
+ '46b3|46c3',
'code' => '',
'process' => 'Intel 10nm',
'years' => '2021-22+',
@@ -16486,7 +16631,7 @@ sub set_nv_data {
{'arch' => 'Hopper',
'ids' => '',
'code' => 'GH1xx',
- 'pattern' => 'G?H[12]\d{2}',
+ 'pattern' => '\bG?H[12]\d{2}',
'process' => 'TSMC n4 (5nm)',
'series' => '515.xx+',
'status' => $status_current,
@@ -16495,8 +16640,8 @@ sub set_nv_data {
{'arch' => 'Lovelace',
'ids' => '',
'code' => 'AD1xx',
- 'pattern' => 'G?L\d{1,4}|RTX 40\d{2}',
- 'process' => 'TSMC n5 (5nm)',
+ 'pattern' => '\bG?L\d{1,4}|\bAD1\d{2}|RTX [6-8]0\d{2}',
+ 'process' => 'TSMC n4 (5nm)',
'series' => '515.xx+',
'status' => $status_current,
'years' => '2022-23+',
@@ -16528,8 +16673,8 @@ sub get_gpu_data {
eval $start if $b_log;
my ($gpu,$p_id,$name) = @_;
my ($info);
- # Reverse, newer will be more common geneerally than older, so save some cpu!
- # This means for amd/intel/nvidia current, the regex name search runs FIRST!
+ # Don't use reverse because if product ID is matched, we want that, not a looser
+ # regex match. Tried with reverse and led to false matches.
foreach my $item (reverse @$gpu){
next if !$item->{'ids'} && (!$item->{'pattern'} || !$name);
if (($item->{'ids'} && $p_id =~ /^($item->{'ids'})$/) ||
@@ -16718,8 +16863,9 @@ sub advanced_monitor_data {
push(@vert,$monitors->{$key}{'pos-y'});
}
}
- @horiz = sort(@horiz);
- @vert = sort(@vert);
+ # we need NUMERIC sort, because positions can be less than 1000!
+ @horiz = sort {$a <=> $b} @horiz;
+ @vert =sort {$a <=> $b} @vert;
my ($h,$v) = (scalar(@horiz),scalar(@vert));
# print Data::Dumper::Dumper \@horiz;
# print Data::Dumper::Dumper \@vert;
@@ -18272,9 +18418,12 @@ sub device_output {
my $bus_id = 'N/A';
# note: for arm/mips we want to see the single item bus id, why not?
# note: we can have bus id: 0002 / 0 which is valid, but 0 / 0 is invalid
- if (defined $row->[2] && $row->[2] ne '0' && defined $row->[3]){$bus_id = "$row->[2].$row->[3]"}
- elsif (defined $row->[2] && $row->[2] ne '0'){$bus_id = $row->[2]}
- elsif (defined $row->[3] && $row->[3] ne '0'){$bus_id = $row->[3]}
+ if (defined $row->[2] && $row->[2] ne '0' && defined $row->[3]){
+ $bus_id = "$row->[2].$row->[3]"}
+ elsif (defined $row->[2] && $row->[2] ne '0'){
+ $bus_id = $row->[2]}
+ elsif (defined $row->[3] && $row->[3] ne '0'){
+ $bus_id = $row->[3]}
if ($extra > 0){
if ($row->[9] && !$bsd_type){
my $version = main::get_module_version($row->[9]);
@@ -18290,7 +18439,9 @@ sub device_output {
main::get_pcie_data($bus_id,$j,$rows,\$num);
}
# as far as I know, wifi has no port, but in case it does in future, use it
- $rows->[$j]{main::key($num++,0,2,'port')} = $row->[8] if (!$b_wifi || ($b_wifi && $row->[8] ne 'N/A'));
+ if (!$b_wifi || ($b_wifi && $row->[8] ne 'N/A')){
+ $rows->[$j]{main::key($num++,0,2,'port')} = $row->[8];
+ }
$rows->[$j]{main::key($num++,0,2,'bus-ID')} = $bus_id;
}
if ($extra > 1){
@@ -18299,6 +18450,12 @@ sub device_output {
if ($extra > 2 && $row->[1]){
$rows->[$j]{main::key($num++,0,2,'class-ID')} = $row->[1];
}
+ if (!$bsd_type && $extra > 0 && $bus_id ne 'N/A' && $bus_id =~ /\.0$/){
+ my $temp = main::get_device_temp($bus_id);
+ if ($temp){
+ $rows->[$j]{main::key($num++,0,2,'temp')} = $temp . ' C';
+ }
+ }
if ($show{'network-advanced'}){
my @data;
if (!$bsd_type){
@@ -23022,10 +23179,12 @@ sub file_path {
package SensorItem;
my $gpu_data = [];
my $sensors_raw = {};
+my $max_fan = 15000;
sub get {
eval $start if $b_log;
- my ($b_data,$key1,$program,$val1,$sensors);
- my ($num,$rows) = (0,[]);
+ my ($b_data,$b_ipmi,$b_no_lm,$b_no_sys);
+ my ($message_type,$program,$val1,$sensors);
+ my ($key1,$num,$rows) = ('Message',0,[]);
my $source = 'sensors'; # will trip some type output if ipmi + another type
# we're allowing 1 or 2 ipmi tools, first the gnu one, then the
# almost certain to be present in BSDs
@@ -23036,54 +23195,99 @@ sub get {
$sensors = ipmi_data($program);
$b_data = sensors_output($rows,'ipmi',$sensors);
if (!$b_data){
- $key1 = 'Message';
- $val1 = main::message('sensors-data-ipmi');
- # $val1 = main::message('dev');
- push(@$rows,{main::key($num++,0,1,$key1) => $val1});
+ $val1 = main::message('sensor-data-ipmi');
+ push(@$rows,{
+ main::key($num++,1,1,'Src') => 'ipmi',
+ main::key($num++,0,1,$key1) => $val1,
+ });
}
- $source = 'lm-sensors'; # trips per sensor type output
}
else {
$key1 = 'Permissions';
- $val1 = main::message('sensors-ipmi-root');
- push(@$rows,{main::key($num++,0,1,$key1) => $val1});
+ $val1 = main::message('sensor-data-ipmi-root');
+ push(@$rows,{
+ main::key($num++,1,1,'Src') => 'ipmi',
+ main::key($num++,0,2,$key1) => $val1,
+ });
}
+ $b_ipmi = 1;
}
- if ($sysctl{'sensor'}){
- $sensors = sysctl_data();
- $b_data = sensors_output($rows,'sysctl-sensors',$sensors);
- if (!$b_data){
- $key1 = 'Message';
- $val1 = main::message('sensors-data-bsd',$uname[0]);
- push(@$rows,{main::key($num++,0,1,$key1) => $val1});
+ $b_data = 0;
+ if ($bsd_type){
+ if ($sysctl{'sensor'}){
+ $sensors = sysctl_data();
+ $source = 'sysctl' if $b_ipmi;
+ $b_data = sensors_output($rows,$source,$sensors);
+ if (!$b_data){
+ $source = 'sysctl';
+ $val1 = main::message('sensor-data-bsd',$uname[0]);
+ }
+ }
+ else {
+ if ($bsd_type =~ /^(free|open)bsd/){
+ $source = 'sysctl';
+ $val1 = main::message('sensor-data-bsd-ok');
+ }
+ else {
+ $source = 'N/A';
+ $val1 = main::message('sensor-data-bsd-unsupported');
+ }
}
}
else {
- if (!$fake{'sensors'} && $alerts{'sensors'}->{'action'} ne 'use'){
+ if (!$force{'sensors-sys'} &&
+ ($fake{'sensors'} || $alerts{'sensors'}->{'action'} eq 'use')){
+ load_lm_sensors();
+ $sensors = linux_sensors_data();
+ $source = 'lm-sensors' if $b_ipmi; # trips per sensor type output
+ $b_data = sensors_output($rows,$source,$sensors);
# print "here 1\n";
- if ($bsd_type && $bsd_type =~ /^(free|open)bsd/){
- $key1 = 'Message';
- $val1 = main::message('sensors-data-bsd-ok');
+ $b_no_lm = 1 if !$b_data;
+ }
+ # given recency of full /sys data, we want to prefer lm-sensors for a long time
+ # and use /sys as a fallback. This will handle servers, which often do not
+ # have lm-sensors installed, but do have /sys hwmon data.
+ if (!$b_data && -d '/sys/class/hwmon'){
+ load_sys_data();
+ $sensors = linux_sensors_data();
+ $source = '/sys'; # trips per sensor type output
+ $b_data = sensors_output($rows,$source,$sensors);
+ # print "here 2\n";
+ $b_no_sys = 1 if !$b_data;
+ }
+ if (!$b_data){
+ if ($b_no_lm || $b_no_sys){
+ if ($b_no_lm && $b_no_sys){
+ $source = 'lm-sensors+/sys';
+ $val1 = main::message('sensor-data-sys-lm');
+ }
+ elsif ($b_no_lm){
+ $source = 'lm-sensors';
+ $val1 = main::message('sensor-data-lm-sensors');
+ }
+ else {
+ $val1 = main::message('sensor-data-sys');
+ }
}
- else {
+ elsif (!$fake{'sensors'} && $alerts{'sensors'}->{'action'} ne 'use'){
+ # print "here 3\n";
+ $source = 'lm-sensors';
$key1 = $alerts{'sensors'}->{'action'};
- $val1 = $alerts{'sensors'}->{'message'};
$key1 = ucfirst($key1);
+ $val1 = $alerts{'sensors'}->{'message'};
}
- push(@$rows,{main::key($num++,0,1,$key1) => $val1,});
- }
- else {
- $sensors = lm_sensors_data();
- $b_data = sensors_output($rows,$source,$sensors);
- # print "here 2\n";
- if (!$b_data){
- $key1 = 'Message';
+ else {
+ $source = 'N/A';
$val1 = main::message('sensors-data-linux');
- push(@$rows,{main::key($num++,0,1,$key1) => $val1});
}
-
}
}
+ if (!$b_data){
+ push(@$rows,{
+ main::key($num++,1,1,'Src') => $source,
+ main::key($num++,0,2,$key1) => $val1,
+ });
+ }
eval $end if $b_log;
return $rows;
}
@@ -23095,129 +23299,128 @@ sub sensors_output {
my $num = 0;
my $j = scalar @$rows;
if (!$loaded{'gpu-data'} &&
- ($source eq 'sensors' || $source eq 'lm-sensors')){
+ ($source eq 'sensors' || $source eq 'lm-sensors' || $source eq '/sys')){
gpu_sensor_data();
}
# gpu sensors data might be present even if standard sensors data wasn't
return if !%$sensors && !@$gpu_data;
- $b_result = 1; ## need t trip data found conditions
+ $b_result = 1; ## need to trip data found conditions
my $temp_unit = (defined $sensors->{'temp-unit'}) ? " $sensors->{'temp-unit'}": '';
my $cpu_temp = (defined $sensors->{'cpu-temp'}) ? $sensors->{'cpu-temp'} . $temp_unit: 'N/A';
my $mobo_temp = (defined $sensors->{'mobo-temp'}) ? $sensors->{'mobo-temp'} . $temp_unit: 'N/A';
- my $cpu1_key = ($sensors->{'cpu2-temp'}) ? 'cpu-1': 'cpu' ;
- my $data_source = ($source eq 'ipmi' || $source eq 'lm-sensors') ? $source : '';
- push(@$rows, {
- main::key($num++,1,1,'System Temperatures') => $data_source,
- main::key($num++,0,2,$cpu1_key) => $cpu_temp,
- });
+ my $cpu1_key = ($sensors->{'cpu2-temp'}) ? 'cpu-1': 'cpu';
+ my ($l1,$l2,$l3) = (1,2,3);
+ if ($source ne 'sensors'){
+ $rows->[$j]{main::key($num++,1,1,'Src')} = $source;
+ ($l1,$l2,$l3) = (2,3,4);
+ }
+ $rows->[$j]{main::key($num++,1,$l1,'System Temperatures')} = '';
+ $rows->[$j]{main::key($num++,0,$l2,$cpu1_key)} = $cpu_temp;
if ($sensors->{'cpu2-temp'}){
- $rows->[$j]{main::key($num++,0,2,'cpu-2')} = $sensors->{'cpu2-temp'} . $temp_unit;
+ $rows->[$j]{main::key($num++,0,$l2,'cpu-2')} = $sensors->{'cpu2-temp'} . $temp_unit;
}
if ($sensors->{'cpu3-temp'}){
- $rows->[$j]{main::key($num++,0,2,'cpu-3')} = $sensors->{'cpu3-temp'} . $temp_unit;
+ $rows->[$j]{main::key($num++,0,$l2,'cpu-3')} = $sensors->{'cpu3-temp'} . $temp_unit;
}
if ($sensors->{'cpu4-temp'}){
- $rows->[$j]{main::key($num++,0,2,'cpu-4')} = $sensors->{'cpu4-temp'} . $temp_unit;
+ $rows->[$j]{main::key($num++,0,$l2,'cpu-4')} = $sensors->{'cpu4-temp'} . $temp_unit;
}
if (defined $sensors->{'pch-temp'}){
my $pch_temp = $sensors->{'pch-temp'} . $temp_unit;
- $rows->[$j]{main::key($num++,0,2,'pch')} = $pch_temp;
+ $rows->[$j]{main::key($num++,0,$l2,'pch')} = $pch_temp;
}
- $rows->[$j]{main::key($num++,0,2,'mobo')} = $mobo_temp;
+ $rows->[$j]{main::key($num++,0,$l2,'mobo')} = $mobo_temp;
if (defined $sensors->{'sodimm-temp'}){
my $sodimm_temp = $sensors->{'sodimm-temp'} . $temp_unit;
- $rows->[$j]{main::key($num++,0,2,'sodimm')} = $sodimm_temp;
+ $rows->[$j]{main::key($num++,0,$l2,'sodimm')} = $sodimm_temp;
}
if (defined $sensors->{'psu-temp'}){
my $psu_temp = $sensors->{'psu-temp'} . $temp_unit;
- $rows->[$j]{main::key($num++,0,2,'psu')} = $psu_temp;
+ $rows->[$j]{main::key($num++,0,$l2,'psu')} = $psu_temp;
}
if (defined $sensors->{'ambient-temp'}){
my $ambient_temp = $sensors->{'ambient-temp'} . $temp_unit;
- $rows->[$j]{main::key($num++,0,2,'ambient')} = $ambient_temp;
+ $rows->[$j]{main::key($num++,0,$l2,'ambient')} = $ambient_temp;
}
if (scalar @$gpu_data == 1 && defined $gpu_data->[0]{'temp'}){
my $gpu_temp = $gpu_data->[0]{'temp'};
my $gpu_type = $gpu_data->[0]{'type'};
my $gpu_unit = (defined $gpu_data->[0]{'temp-unit'} && $gpu_temp) ? " $gpu_data->[0]{'temp-unit'}" : ' C';
- $rows->[$j]{main::key($num++,1,2,'gpu')} = $gpu_type;
- $rows->[$j]{main::key($num++,0,3,'temp')} = $gpu_temp . $gpu_unit;
+ $rows->[$j]{main::key($num++,1,$l2,'gpu')} = $gpu_type;
+ $rows->[$j]{main::key($num++,0,$l3,'temp')} = $gpu_temp . $gpu_unit;
if ($extra > 1 && $gpu_data->[0]{'temp-mem'}){
- $rows->[$j]{main::key($num++,0,3,'mem')} = $gpu_data->[0]{'temp-mem'} . $gpu_unit;
+ $rows->[$j]{main::key($num++,0,$l3,'mem')} = $gpu_data->[0]{'temp-mem'} . $gpu_unit;
}
}
$j = scalar @$rows;
@fan_main = @{$sensors->{'fan-main'}} if $sensors->{'fan-main'};
@fan_default = @{$sensors->{'fan-default'}} if $sensors->{'fan-default'};
- my $fan_def = ($data_source) ? $data_source : '';
- if (!@fan_main && !@fan_default){
- $fan_def = ($fan_def) ? "$data_source N/A" : 'N/A';
- }
- $rows->[$j]{main::key($num++,1,1,'Fan Speeds (RPM)')} = $fan_def;
+ my $fan_def = (!@fan_main && !@fan_default) ? 'N/A' : '';
+ $rows->[$j]{main::key($num++,1,$l1,'Fan Speeds (RPM)')} = $fan_def;
my $b_cpu = 0;
for (my $i = 0; $i < scalar @fan_main; $i++){
next if $i == 0;# starts at 1, not 0
if (defined $fan_main[$i]){
if ($i == 1 || ($i == 2 && !$b_cpu)){
- $rows->[$j]{main::key($num++,0,2,'cpu')} = $fan_main[$i];
+ $rows->[$j]{main::key($num++,0,$l2,'cpu')} = $fan_main[$i];
$b_cpu = 1;
}
elsif ($i == 2 && $b_cpu){
- $rows->[$j]{main::key($num++,0,2,'mobo')} = $fan_main[$i];
+ $rows->[$j]{main::key($num++,0,$l2,'mobo')} = $fan_main[$i];
}
elsif ($i == 3){
- $rows->[$j]{main::key($num++,0,2,'psu')} = $fan_main[$i];
+ $rows->[$j]{main::key($num++,0,$l2,'psu')} = $fan_main[$i];
}
elsif ($i == 4){
- $rows->[$j]{main::key($num++,0,2,'sodimm')} = $fan_main[$i];
+ $rows->[$j]{main::key($num++,0,$l2,'sodimm')} = $fan_main[$i];
}
elsif ($i > 4){
$fan_number = $i - 4;
- $rows->[$j]{main::key($num++,0,2,"case-$fan_number")} = $fan_main[$i];
+ $rows->[$j]{main::key($num++,0,$l2,"case-$fan_number")} = $fan_main[$i];
}
}
}
for (my $i = 0; $i < scalar @fan_default; $i++){
next if $i == 0;# starts at 1, not 0
if (defined $fan_default[$i]){
- $rows->[$j]{main::key($num++,0,2,"fan-$i")} = $fan_default[$i];
+ $rows->[$j]{main::key($num++,0,$l2,"fan-$i")} = $fan_default[$i];
}
}
- $rows->[$j]{main::key($num++,0,2,'psu')} = $sensors->{'fan-psu'} if defined $sensors->{'fan-psu'};
- $rows->[$j]{main::key($num++,0,2,'psu-1')} = $sensors->{'fan-psu1'} if defined $sensors->{'fan-psu1'};
- $rows->[$j]{main::key($num++,0,2,'psu-2')} = $sensors->{'fan-psu2'} if defined $sensors->{'fan-psu2'};
+ $rows->[$j]{main::key($num++,0,$l2,'psu')} = $sensors->{'fan-psu'} if defined $sensors->{'fan-psu'};
+ $rows->[$j]{main::key($num++,0,$l2,'psu-1')} = $sensors->{'fan-psu1'} if defined $sensors->{'fan-psu1'};
+ $rows->[$j]{main::key($num++,0,$l2,'psu-2')} = $sensors->{'fan-psu2'} if defined $sensors->{'fan-psu2'};
# note: so far, only nvidia-settings returns speed, and that's in percent
if (scalar @$gpu_data == 1 && defined $gpu_data->[0]{'fan-speed'}){
my $gpu_fan = $gpu_data->[0]{'fan-speed'} . $gpu_data->[0]{'speed-unit'};
my $gpu_type = $gpu_data->[0]{'type'};
- $rows->[$j]{main::key($num++,1,2,'gpu')} = $gpu_type;
- $rows->[$j]{main::key($num++,0,3,'fan')} = $gpu_fan;
+ $rows->[$j]{main::key($num++,1,$l2,'gpu')} = $gpu_type;
+ $rows->[$j]{main::key($num++,0,$l3,'fan')} = $gpu_fan;
}
if (scalar @$gpu_data > 1){
$j = scalar @$rows;
- $rows->[$j]{main::key($num++,1,1,'GPU')} = '';
+ $rows->[$j]{main::key($num++,1,$l1,'GPU')} = '';
my $gpu_unit = (defined $gpu_data->[0]{'temp-unit'}) ? " $gpu_data->[0]{'temp-unit'}" : ' C';
foreach my $info (@$gpu_data){
# speed unit is either '' or %
my $gpu_fan = (defined $info->{'fan-speed'}) ? $info->{'fan-speed'} . $info->{'speed-unit'}: undef;
my $gpu_type = $info->{'type'};
my $gpu_temp = (defined $info->{'temp'}) ? $info->{'temp'} . $gpu_unit: 'N/A';
- $rows->[$j]{main::key($num++,1,2,'device')} = $gpu_type;
+ $rows->[$j]{main::key($num++,1,$l2,'device')} = $gpu_type;
if (defined $info->{'screen'}){
- $rows->[$j]{main::key($num++,0,3,'screen')} = $info->{'screen'};
+ $rows->[$j]{main::key($num++,0,$l3,'screen')} = $info->{'screen'};
}
- $rows->[$j]{main::key($num++,0,3,'temp')} = $gpu_temp;
+ $rows->[$j]{main::key($num++,0,$l3,'temp')} = $gpu_temp;
if ($extra > 1 && $info->{'temp-mem'}){
- $rows->[$j]{main::key($num++,0,3,'mem')} = $info->{'temp-mem'} . $gpu_unit;
+ $rows->[$j]{main::key($num++,0,$l3,'mem')} = $info->{'temp-mem'} . $gpu_unit;
}
if (defined $gpu_fan){
- $rows->[$j]{main::key($num++,0,3,'fan')} = $gpu_fan;
+ $rows->[$j]{main::key($num++,0,$l3,'fan')} = $gpu_fan;
}
if ($extra > 2 && $info->{'watts'}){
- $rows->[$j]{main::key($num++,0,3,'watts')} = $info->{'watts'};
+ $rows->[$j]{main::key($num++,0,$l3,'watts')} = $info->{'watts'};
}
- if ($extra > 2 && $info->{'mvolts'}){
- $rows->[$j]{main::key($num++,0,3,'mV')} = $info->{'mvolts'};
+ if ($extra > 2 && $info->{'volts-gpu'}){
+ $rows->[$j]{main::key($num++,0,$l3,$info->{'volts-gpu'}[1])} = $info->{'volts-gpu'}[0];
}
}
}
@@ -23229,24 +23432,36 @@ sub sensors_output {
$sensors->{'volts-5'} ||= 'N/A';
$sensors->{'volts-3.3'} ||= 'N/A';
$sensors->{'volts-vbat'} ||= 'N/A';
- $rows->[$j]{main::key($num++,1,1,'Power')} = $data_source;
- $rows->[$j]{main::key($num++,0,2,'12v')} = $sensors->{'volts-12'};
- $rows->[$j]{main::key($num++,0,2,'5v')} = $sensors->{'volts-5'};
- $rows->[$j]{main::key($num++,0,2,'3.3v')} = $sensors->{'volts-3.3'};
- $rows->[$j]{main::key($num++,0,2,'vbat')} = $sensors->{'volts-vbat'};
+ $rows->[$j]{main::key($num++,1,$l1,'Power')} = '';
+ $rows->[$j]{main::key($num++,0,$l2,'12v')} = $sensors->{'volts-12'};
+ $rows->[$j]{main::key($num++,0,$l2,'5v')} = $sensors->{'volts-5'};
+ $rows->[$j]{main::key($num++,0,$l2,'3.3v')} = $sensors->{'volts-3.3'};
+ $rows->[$j]{main::key($num++,0,$l2,'vbat')} = $sensors->{'volts-vbat'};
if ($extra > 1 && $source eq 'ipmi'){
$sensors->{'volts-dimm-p1'} ||= 'N/A';
$sensors->{'volts-dimm-p2'} ||= 'N/A';
- $rows->[$j]{main::key($num++,0,2,'dimm-p1')} = $sensors->{'volts-dimm-p1'} if $sensors->{'volts-dimm-p1'};
- $rows->[$j]{main::key($num++,0,2,'dimm-p2')} = $sensors->{'volts-dimm-p2'} if $sensors->{'volts-dimm-p2'};
- $rows->[$j]{main::key($num++,0,2,'soc-p1')} = $sensors->{'volts-soc-p1'} if $sensors->{'volts-soc-p1'};
- $rows->[$j]{main::key($num++,0,2,'soc-p2')} = $sensors->{'volts-soc-p2'} if $sensors->{'volts-soc-p2'};
+ if ($sensors->{'volts-dimm-p1'}){
+ $rows->[$j]{main::key($num++,0,$l2,'dimm-p1')} = $sensors->{'volts-dimm-p1'};
+ }
+ if ($sensors->{'volts-dimm-p2'}){
+ $rows->[$j]{main::key($num++,0,$l2,'dimm-p2')} = $sensors->{'volts-dimm-p2'};
+ }
+ if ($sensors->{'volts-soc-p1'}){
+ $rows->[$j]{main::key($num++,0,$l2,'soc-p1')} = $sensors->{'volts-soc-p1'};
+ }
+ if ($sensors->{'volts-soc-p2'}){
+ $rows->[$j]{main::key($num++,0,$l2,'soc-p2')} = $sensors->{'volts-soc-p2'};
+ }
}
if (scalar @$gpu_data == 1 && $extra > 2 &&
- ($gpu_data->[0]{'watts'} || $gpu_data->[0]{'mvolts'})){
- $rows->[$j]{main::key($num++,1,2,'gpu')} = $gpu_data->[0]{'type'};
- $rows->[$j]{main::key($num++,0,3,'watts')} = $gpu_data->[0]{'watts'} if $gpu_data->[0]{'watts'};
- $rows->[$j]{main::key($num++,0,3,'mV')} = $gpu_data->[0]{'mvolts'} if $gpu_data->[0]{'mvolts'};
+ ($gpu_data->[0]{'watts'} || $gpu_data->[0]{'volts-gpu'})){
+ $rows->[$j]{main::key($num++,1,$l2,'gpu')} = $gpu_data->[0]{'type'};
+ if ($gpu_data->[0]{'watts'}){
+ $rows->[$j]{main::key($num++,0,$l3,'watts')} = $gpu_data->[0]{'watts'};
+ }
+ if ($gpu_data->[0]{'volts-gpu'}){
+ $rows->[$j]{main::key($num++,0,$l3,$gpu_data->[0]{'volts-gpu'}[1])} = $gpu_data->[0]{'volts-gpu'}[0];
+ }
}
}
eval $end if $b_log;
@@ -23255,7 +23470,7 @@ sub sensors_output {
sub ipmi_data {
eval $start if $b_log;
my ($program) = @_;
- my ($b_cpu_0,$cmd,$file,@data,$fan_working,@row,$sys_fan_nu,$temp_working,
+ my ($b_cpu_0,$cmd,$file,@data,$fan_working,@row,$speed,$sys_fan_nu,$temp_working,
$working_unit);
my ($b_ipmitool,$i_key,$i_value,$i_unit);
my $sensors = {};
@@ -23368,7 +23583,8 @@ sub ipmi_data {
# note: can be cpu fan:, cpu fan speed:, etc.
elsif ($row[$i_key] =~ /^(CPU|Processor)[\s_]Fan/i ||
$row[$i_key] =~ /^SYS\.[0-9][\s_]?\(CPU\s?0\)$/i){
- $sensors->{'fan-main'}->[1] = int($row[$i_value]);
+ $speed = int($row[$i_value]);
+ $sensors->{'fan-main'}->[1] = $speed if $speed < $max_fan;
}
# note that the counters are dynamically set for fan numbers here
# otherwise you could overwrite eg aux fan2 with case fan2 in theory
@@ -23378,6 +23594,7 @@ sub ipmi_data {
elsif ($row[$i_key] =~ /^(SYS[\s_])?FAN[\s_]?([0-9A-F]+)/i){
$sys_fan_nu = hex($2);
$fan_working = int($row[$i_value]);
+ next if $fan_working > $max_fan;
$sensors->{'fan-default'} = () if !$sensors->{'fan-default'};
if ($sys_fan_nu =~ /^([0-9]+)$/){
# add to array if array index does not exist OR if number is > existing number
@@ -23392,13 +23609,16 @@ sub ipmi_data {
}
}
elsif ($row[$i_key] =~ /^(FAN PSU|PSU FAN)$/i){
- $sensors->{'fan-psu'} = int($row[$i_value]);
+ $speed = int($row[$i_value]);
+ $sensors->{'fan-psu'} = $speed if $speed < $max_fan;
}
elsif ($row[$i_key] =~ /^(FAN PSU1|PSU1 FAN)$/i){
- $sensors->{'fan-psu-1'} = int($row[$i_value]);
+ $speed = int($row[$i_value]);
+ $sensors->{'fan-psu-1'} = $speed if $speed < $max_fan;
}
elsif ($row[$i_key] =~ /^(FAN PSU2|PSU2 FAN)$/i){
- $sensors->{'fan-psu-2'} = int($row[$i_value]);
+ $speed = int($row[$i_value]);
+ $sensors->{'fan-psu-2'} = $speed if $speed < $max_fan;
}
if ($extra > 0){
if ($row[$i_key] =~ /^((.+\s|P[_]?)?\+?12V|PSU[12]_VOUT)$/i){
@@ -23435,12 +23655,11 @@ sub ipmi_data {
print Data::Dumper::Dumper $sensors if $dbg[31];
return $sensors;
}
-sub lm_sensors_data {
+sub linux_sensors_data {
eval $start if $b_log;
my $sensors = {};
my ($sys_fan_nu) = (0);
my ($adapter,$fan_working,$temp_working,$working_unit) = ('','','','','');
- load_lm_sensors();
foreach $adapter (keys %{$sensors_raw->{'main'}}){
next if !$adapter || ref $sensors_raw->{'main'}{$adapter} ne 'ARRAY';
# not sure why hwmon is excluded, forgot to add info in comments
@@ -23551,22 +23770,23 @@ sub lm_sensors_data {
$sensors->{'temp-unit'} = set_temp_unit($sensors->{'temp-unit'},$working_unit) if $working_unit;
}
# note: can be cpu fan:, cpu fan speed:, etc.
- elsif (!$sensors->{'fan-main'}->[1] && $_ =~ /^F?(CPU|Processor).*:([0-9]+)[\s]RPM/i){
- $sensors->{'fan-main'}->[1] = $2;
+ elsif (!defined $sensors->{'fan-main'}->[1] && $_ =~ /^F?(CPU|Processor).*:([0-9]+)[\s]RPM/i){
+ $sensors->{'fan-main'}->[1] = $2 if $2 < $max_fan;
}
- elsif (!$sensors->{'fan-main'}->[2] && $_ =~ /^F?(M\/B|MB|SYS|Motherboard).*:([0-9]+)[\s]RPM/i){
- $sensors->{'fan-main'}->[2] = $2;
+ elsif (!defined $sensors->{'fan-main'}->[2] && $_ =~ /^F?(M\/B|MB|SYS|Motherboard).*:([0-9]+)[\s]RPM/i){
+ $sensors->{'fan-main'}->[2] = $2 if $2 < $max_fan;
}
- elsif (!$sensors->{'fan-main'}->[3] && $_ =~ /F?(Power|P\/S|POWER).*:([0-9]+)[\s]RPM/i){
- $sensors->{'fan-main'}->[3] = $2;
+ elsif (!defined $sensors->{'fan-main'}->[3] && $_ =~ /F?(Power|P\/S|POWER).*:([0-9]+)[\s]RPM/i){
+ $sensors->{'fan-main'}->[3] = $2 if $2 < $max_fan;
}
- elsif (!$sensors->{'fan-main'}->[4] && $_ =~ /F?(dimm|mem|sodimm).*:([0-9]+)[\s]RPM/i){
- $sensors->{'fan-main'}->[4] = $2;
+ elsif (!defined $sensors->{'fan-main'}->[4] && $_ =~ /F?(dimm|mem|sodimm).*:([0-9]+)[\s]RPM/i){
+ $sensors->{'fan-main'}->[4] = $2 if $2 < $max_fan;
}
# note that the counters are dynamically set for fan numbers here
# otherwise you could overwrite eg aux fan2 with case fan2 in theory
# note: cpu/mobo/ps/sodimm are 1/2/3/4
elsif ($_ =~ /^F?(AUX|CASE|CHASSIS|FRONT|REAR).*:([0-9]+)[\s]RPM/i){
+ next if $2 > $max_fan;
$temp_working = $2;
for (my $i = 5; $i < 30; $i++){
next if defined $sensors->{'fan-main'}->[$i];
@@ -23578,9 +23798,10 @@ sub lm_sensors_data {
}
# in rare cases syntax is like: fan1: xxx RPM
elsif ($_ =~ /^FAN(1)?:([0-9]+)[\s]RPM/i){
- $sensors->{'fan-default'}->[1] = $2;
+ $sensors->{'fan-default'}->[1] = $2 if $2 < $max_fan;
}
elsif ($_ =~ /^FAN([2-9]|1[0-9]).*:([0-9]+)[\s]RPM/i){
+ next if $2 > $max_fan;
$fan_working = $2;
$sys_fan_nu = $1;
if ($sys_fan_nu =~ /^([0-9]+)$/){
@@ -23636,6 +23857,7 @@ sub lm_sensors_data {
}
}
}
+
print Data::Dumper::Dumper $sensors if $dbg[31];
process_data($sensors) if %$sensors;
main::log_data('dump','lm-sensors: %sensors',$sensors) if $b_log;
@@ -23694,8 +23916,8 @@ sub load_lm_sensors {
elsif ($adapter =~ /^(.*hwmon)-/){
$type = 'hwmon';
}
- # ath/iwl: wifi; enp/eno/eth: lan nic
- elsif ($adapter =~ /^(ath|iwl|en[op][0-9]|eth)[\S]+-/){
+ # ath/iwl: wifi; enp/eno/eth/i350bb: lan nic
+ elsif ($adapter =~ /^(ath|i350bb|iwl|en[op][0-9]|eth)[\S]+-/){
$type = 'network';
}
# put last just in case some other sensor type above had intel in name
@@ -23703,7 +23925,7 @@ sub load_lm_sensors {
$type = 'gpu';
}
elsif ($adapter =~ /^(acpitz)-/ && $adapter !~ /^(acpitz-virtual)-/ ){
- $type = 'board';
+ $type = 'acpitz';
}
else {
$type = 'main';
@@ -23726,6 +23948,159 @@ sub load_lm_sensors {
main::log_data('dump','lm-sensors data: %$sensors_raw',$sensors_raw) if $b_log;
eval $end if $b_log;
}
+sub load_sys_data {
+ eval $start if $b_log;
+ my ($device,$mon,$name,$label,$unit,$value,@values,%hwmons);
+ my ($j,$holder,$sensor,$type) = (0,'','','');
+ my $glob = '/sys/class/hwmon/hwmon*/';
+ $glob .= '{name,device,{curr,fan,in,power,temp}*_{input,label}}';
+ my @hwmon = main::globber($glob);
+ # print Data::Dumper::Dumper \@sensors_data;
+ @hwmon = sort @hwmon;
+ push(@hwmon,'END');
+ foreach my $item (@hwmon){
+ next if ! -e $item;
+ $item =~ m|/sys/class/hwmon/(hwmon\d+)/|;
+ $mon = $1;
+ $mon =~ s/hwmon(\d)$/hwmon0$1/ if $mon =~ /hwmon\d$/;
+ # if it's a new hwmon, dump all previous data to avoid carry-over
+ if (!defined $hwmons{$mon}){
+ $sensor = '';
+ $holder = '';
+ $j = 0;
+ }
+ if ($item =~ m/([^\/]+)_input$/){
+ $sensor = $1;
+ $value = main::reader($item,'strip',0);;
+ }
+ # add the label to the just created _input item, if valid
+ elsif ($item =~ m/([^\/]+)_label$/){
+ print "3: mon: $mon id: $sensor holder: $holder file: $item\n" if $dbg[51];
+ # if this doesn't match, something unexpected happened, like no _input for
+ # _label item. Seen that, real.
+ next if !$holder || $1 ne $holder;
+ if (defined $hwmons{$mon}->{'sensors'}[$j]{'id'}){
+ $sensor = $1;
+ $hwmons{$mon}->{'sensors'}[$j]{'label'} = main::reader($item,'strip',0);
+ }
+ }
+ if ($sensor && ($sensor ne $holder || $item eq 'END')){
+ print "2: mon: $mon id: $sensor holder: $holder file: $item\n" if $dbg[51];
+ # add the item, we'll add label after if it's located since it will be next
+ # in loop due to sort order.
+ if ($value){
+ push(@{$hwmons{$mon}->{'sensors'}},{
+ 'id' => $sensor,
+ 'value' => $value,
+ });
+ $j = $#{$hwmons{$mon}->{'sensors'}};
+ }
+ $holder = $sensor;
+ ($sensor,$value) = ('',undef,undef);
+ }
+ print "1: mon: $mon id: $sensor holder: $holder file: $item\n" if $dbg[51];
+ # print "$item\n";
+ if ($item =~ /name$/){
+ $name = main::reader($item,'strip',0);
+ if ($name =~ /^(drive|nvme)/){
+ $type = 'disk';
+ }
+ elsif ($name =~ /^(BAT)/i){
+ $type = 'bat';
+ }
+ # intel on die io controller, like southbridge/northbridge used to be
+ elsif ($name =~ /^(pch)/){
+ $type = 'pch';
+ }
+ elsif ($name =~ /^(.*hwmon)/){
+ $type = 'hwmon';
+ }
+ # ath/iwl: wifi; enp/eno/eth/i350bb: lan nic
+ elsif ($name =~ /^(ath|i350|iwl|en[op][0-9]|eth)[\S]/){
+ $type = 'network';
+ }
+ # put last just in case some other sensor type above had intel in name
+ elsif ($name =~ /^(amdgpu|intel|nouveau|radeon)/){
+ $type = 'gpu';
+ }
+ # not confirmed in /sys that name will be acpitz-virtual, verify
+ elsif ($name =~ /^(acpitz)/ && $name !~ /^(acpitz-virtual)/ ){
+ $type = 'acpitz';
+ }
+ else {
+ $type = 'main';
+ }
+ $hwmons{$mon}->{'name'} = $name;
+ $hwmons{$mon}->{'type'} = $type;
+ }
+ elsif ($item =~ /device$/){
+ $device = readlink($item);
+ print "device: $device\n" if $dbg[51];
+ $device =~ s|^.*/||;
+ $hwmons{$mon}->{'device'} = $device;
+ }
+ }
+ print '/sys/class/hwmon raw: ', Data::Dumper::Dumper \%hwmons if $dbg[18];
+ main::log_data('dump','/sys data raw: %hwmons',\%hwmons) if $b_log;
+ # $sensors_raw->{$type}{$adapter} = [@values];
+ foreach my $hwmon (sort keys %hwmons){
+ my $adapter = $hwmons{$hwmon}->{'name'};
+ $hwmons{$hwmon}->{'device'} =~ s/^0000://;
+ $adapter .= '-' . $hwmons{$hwmon}->{'device'};
+ @values = ();
+ foreach my $item (@{$hwmons{$hwmon}->{'sensors'}}){
+ my $name = ($item->{'label'}) ? $item->{'label'}: $item->{'id'};
+ if ($item->{'id'} =~ /^temp/){
+ $unit = 'C';
+ $value = sprintf('%0.1f',$item->{'value'}/1000);
+ }
+ elsif ($item->{'id'} =~ /^fan/){
+ $unit = 'RPM';
+ $value = $item->{'value'};
+ }
+ # note: many sensors require further math on value, so these will be wrong
+ # in many cases since this is not running the math on the results like
+ # lm-sensors will do if sensors are detected and loaded and configured.
+ elsif ($item->{'id'} =~ /^in\d/){
+ if ($item->{'value'} >= 1000){
+ $unit = 'V';
+ $value = sprintf('%0.2f',$item->{'value'}/1000) + 0;
+ if ($hwmons{$hwmon}->{'type'} eq 'main' && $name =~ /^in\d/){
+ if ($value >= 10 && $value <= 14){
+ $name = '12V';
+ }
+ elsif ($value >= 4 && $value <= 6){
+ $name = '5V';
+ }
+ # vbat can be 3, 3.3, but so can 3.3V board
+ }
+ }
+ else {
+ $unit = 'mV';
+ $value = $item->{'value'};
+ }
+ }
+ elsif ($item->{'id'} =~ /^power/){
+ $unit = 'W';
+ $value = sprintf('%0.1f',$item->{'value'}/1000);
+ }
+ my $string = $name . ':' . $value . " $unit";
+ push(@values,$string);
+ }
+# if ($hwmons{$hwmon}->{'type'} eq 'acpitz' && $hwmons{$hwmon}->{'device'}){
+# my $tz ='/sys/class/thermal/' . $hwmons{$hwmon}->{'device'} . '/type';
+# if (-e $tz){
+# my $tz_type = main::reader($tz,'strip',0),"\n";
+# }
+# }
+ if (@values){
+ $sensors_raw->{$hwmons{$hwmon}->{'type'}}{$adapter} = [@values];
+ }
+ }
+ print '/sys/class/hwmon processed: ' , Data::Dumper::Dumper $sensors_raw if $dbg[18];
+ main::log_data('dump','/sys data: %$sensors_raw',$sensors_raw) if $b_log;
+ eval $end if $b_log;
+}
# bsds sysctl may have hw.sensors data
sub sysctl_data {
@@ -23734,6 +24109,7 @@ sub sysctl_data {
my $sensors = {};
# assume always starts at 0, can't do dynamic because freebsd shows tz1 first
my $add = 1;
+ print Data::Dumper::Dumper $sysctl{'sensor'} if $dbg[18];;
foreach (@{$sysctl{'sensor'}}){
my ($sensor,$type,$number,$value);
if (/^hw\.sensors\.([a-z]+)([0-9]+)\.(cpu|temp|fan|volt)([0-9])/){
@@ -23776,7 +24152,7 @@ sub sysctl_data {
$sensors->{'temp' . $number} = $value;
}
elsif ($type eq 'fan' && !defined $sensors->{'fan-main'}->[$number]){
- $sensors->{'fan-main'}->[$number] = $value;
+ $sensors->{'fan-main'}->[$number] = $value if $value < $max_fan;
}
elsif ($type eq 'volt'){
if ($working =~ /\+3\.3V/i){
@@ -24184,8 +24560,8 @@ sub gpu_sensor_data {
elsif (/^[^:]+:([0-9\.]+)\s+W\s/i){
$gpu_data->[$j]{'watts'} = $1;
}
- elsif (/^[^:]+:([0-9\.]+)\s+mV\s/i){
- $gpu_data->[$j]{'mvolts'} = $1;
+ elsif (/^[^:]+:([0-9\.]+)\s+(m?V)\s/i){
+ $gpu_data->[$j]{'volts-gpu'} = [$1,$2];
}
}
}
@@ -26684,6 +27060,7 @@ sub set_xprop {
}
+## DeviceData
# creates arrays: $devices{'audio'}; $devices{'graphics'}; $devices{'hwraid'};
# $devices{'network'}; $devices{'timer'} and local @devices for logging/debugging
# 0 type
@@ -27442,6 +27819,24 @@ sub pci_class {
}
}
+# if > 1, returns first found, not going to be too granular with this yet.
+sub get_device_temp {
+ eval $start if $b_log;
+ my $bus_id = $_[0];
+ my $glob = "/sys/devices/pci*/*/*:$bus_id/hwmon/hwmon*/temp*_input";
+ my @files = main::globber($glob);
+ my $temp;
+ foreach my $file (@files){
+ $temp = main::reader($file,'strip',0);
+ if ($temp){
+ $temp = sprintf('%0.1f',$temp/1000);
+ last;
+ }
+ }
+ eval $end if $b_log;
+ return $temp;
+}
+
## DiskDataBSD
# handles disks and partition extra data for disks bsd, raid-zfs,
# partitions, swap, unmounted