aboutsummaryrefslogtreecommitdiffstats
path: root/inxi
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2022-02-24 23:57:12 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2022-02-24 23:57:12 -0500
commitf42f69813157b01202b94608e22e631ef8a46ff6 (patch)
tree3d67f6c98a4dafab52d26beaa56ccc233655a0e4 /inxi
parent81d27411acb309cebb1b6ea3b1ee928828827c81 (diff)
parentb8adc21d8a16323bc7f02e8cff78c2a85ac10585 (diff)
Update upstream source from tag 'upstream/3.3.13-1'
Update to upstream version '3.3.13-1' with Debian dir 4e1685610e3b8199855e4e599ed504e1fe871724
Diffstat (limited to 'inxi')
-rwxr-xr-xinxi4079
1 files changed, 3057 insertions, 1022 deletions
diff --git a/inxi b/inxi
index 41eadb3..a2f0db5 100755
--- a/inxi
+++ b/inxi
@@ -2,6 +2,7 @@
## infobash: Copyright (C) 2005-2007 Michiel de Boer aka locsmif
## inxi: Copyright (C) 2008-2021 Harald Hope
## Additional features (C) Scott Rogers - kde, cpu info
+## Parse::EDID (C): 2005-2010 by Mandriva SA, Pascal Rigaux, Anssi Hannula
## Further fixes (listed as known): Horst Tritremmel <hjt at sidux.com>
## Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch
## Jarett.Stevens - dmidecode -M patch for older systems without /sys machine
@@ -47,8 +48,8 @@ use POSIX qw(ceil uname strftime ttyname);
## INXI INFO ##
my $self_name='inxi';
-my $self_version='3.3.12';
-my $self_date='2022-01-18';
+my $self_version='3.3.13';
+my $self_date='2022-02-22';
my $self_patch='00';
## END INXI INFO ##
my ($b_pledge,@pledges);
@@ -103,7 +104,8 @@ if (eval {require Time::HiRes}){
my ($b_admin,$b_android,$b_busybox_ps,$b_cygwin,$b_display,$b_irc,$b_root);
## System
-my ($bsd_type,$device_vm,$language,$os,$pci_tool,$wan_url) = ('','','','','','');
+my ($bsd_type,$device_vm,$language,$os,$pci_tool) = ('','','','','');
+my ($wan_url,$wl_compositors) = ('','');
my ($bits_sys,$cpu_arch,$ppid);
my ($cpu_sleep,$dl_timeout,$limit,$ps_cols,$ps_count) = (0.35,4,10,0,5);
my $sensors_cpu_nu = 0;
@@ -514,6 +516,8 @@ sub set_os {
}
elsif ($cpu_arch =~ /(alpha|64|e2k|sparc_v9|sun4[uv]|ultrasparc)/){
$bits_sys = 64;
+ # force to string e2k, and also in case we need that ID changed
+ $cpu_arch = 'elbrus' if $cpu_arch =~ /e2k|elbrus/;
}
$b_cygwin = 1 if $os =~ /cygwin/;
$b_android = 1 if -e '/system/build.prop';
@@ -1845,7 +1849,7 @@ sub display_data {
push(@files, $system_files{'xorg-log'}) if $system_files{'xorg-log'};
push(@files, '/etc/X11/xorg.conf');
copy_files(\@files,'display-xorg');
- print "Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, wayland, weston...\n";
+ print "Collecting X, xprop, glxinfo, xrandr, xdpyinfo data, Wayland info...\n";
%data = (
'desktop-session' => $ENV{'DESKTOP_SESSION'},
'gdmsession' => $ENV{'GDMSESSION'},
@@ -1892,21 +1896,34 @@ sub display_data {
['kwin_x11','--version'],
# ['locate','/Xorg'], # for Xorg.wrap problem
['loginctl','--no-pager list-sessions'],
+ ['ls','/sys/class/drm'],
['nvidia-settings','-q screens'],
['nvidia-settings','-c :0.0 -q all'],
['nvidia-smi','-q'],
['nvidia-smi','-q -x'],
['plasmashell','--version'],
+ ['swaymsg','-t get_inputs -p'],
+ ['swaymsg','-t get_inputs -r'],
+ ['swaymsg','-t get_outputs -p'],
+ ['swaymsg','-t get_outputs -r'],
+ ['swaymsg','-t get_tree'],
+ ['swaymsg','-t get_workspaces -p'],
+ ['swaymsg','-t get_workspaces -r'],
['vainfo',''],
['vdpauinfo',''],
['vulkaninfo',''],
+ ['wayland-info',''], # not packaged as far as I know yet
['weston-info',''],
['wmctrl','-m'],
['weston','--version'],
+ ['wlr-randr',''],
['xdpyinfo',''],
['Xorg','-version'],
['xprop','-root'],
['xrandr',''],
+ ['Xvesa','-version'],
+ ['Xvesa','-listmodes'],
+ ['Xwayland','-version'],
);
run_commands(\@cmds,'display');
}
@@ -2143,13 +2160,14 @@ sub system_files {
sub run_self {
print "Creating $self_name output file now. This can take a few seconds...\n";
print "Starting $self_name from: $self_path\n";
+ my $a = ($debugger{'arg'}) ? ' ' . $debugger{'arg'} : '';
my $i = ($option eq 'main-full')? ' -i' : '';
my $z = ($debugger{'filter'}) ? ' -z' : '';
my $w = ($debugger{'width'}) ? $debugger{'width'} : 120;
- my $iz = "$i$z";
- $iz =~ s/[\s-]//g;
- my $self_file = "$data_dir/$self_name-FERfJLrploudma$iz-slots-y$w.txt";
- my $cmd = "$self_path/$self_name -FERfJLrploudma$i$z --slots --debug 10 -y $w > $self_file 2>&1";
+ my $aiz = "$i$z";
+ $aiz =~ s/[\s-]//g;
+ my $self_file = "$data_dir/$self_name-FERfJLrploudma$aiz-slots-y$w.txt";
+ my $cmd = "$self_path/$self_name -FERfJLrploudma$i$z$a --slots --debug 10 -y $w > $self_file 2>&1";
system($cmd);
copy($log_file, "$data_dir") or main::error_handler('copy-failed', "$log_file", "$!");
system("$self_path/$self_name --recommends -y 120 > $data_dir/$self_name-recommends-120.txt 2>&1");
@@ -2229,7 +2247,7 @@ sub get_glob {
else {
$item = main::message('root-required');
}
- $item = main::message('undefined') if ! defined $item;
+ $item = main::message('undefined') if !defined $item;
push(@result,$_ . '::' . $item);
}
# print Data::Dumper::Dumper \@result;
@@ -2899,9 +2917,9 @@ sub check_items {
$info_os = 'info-bsd';
}
else {
- @data = qw(blockdev bt-adapter dig dmidecode doas fdisk file hciconfig
- hddtemp ifconfig ip ipmitool ipmi-sensors lsblk lsusb lvs mdadm modinfo
- runlevel sensors smartctl strings sudo tree upower uptime);
+ @data = qw(blockdev bt-adapter dig dmidecode doas fdisk file fruid_print
+ hciconfig hddtemp ifconfig ip ipmitool ipmi-sensors lsblk lsusb lvs
+ mdadm modinfo runlevel sensors smartctl strings sudo tree upower uptime);
}
$b_program = 1;
$item = 'Program';
@@ -2939,16 +2957,20 @@ sub check_items {
}
elsif ($type eq 'recommended Perl modules'){
@data = qw(File::Copy File::Find File::Spec::Functions HTTP::Tiny IO::Socket::SSL
- Time::HiRes Cpanel::JSON::XS JSON::XS XML::Dumper Net::FTP);
- push(@data, qw(OpenBSD::Pledge OpenBSD::Unveil)) if $bsd_type && $bsd_type eq 'openbsd';
+ Time::HiRes JSON::PP Cpanel::JSON::XS JSON::XS XML::Dumper Net::FTP);
+ if ($bsd_type && $bsd_type eq 'openbsd'){
+ push(@data, qw(OpenBSD::Pledge OpenBSD::Unveil));
+ }
$b_perl_module = 1;
$item = 'Perl Module';
$extra = ' (Optional)';
- $extra2 = "None of these are strictly required, but if you have them all, you can
- eliminate some recommended non Perl programs from the install. ";
- $extra3 = "HTTP::Tiny and IO::Socket::SSL must both be present to use as a downloader option.
- For json export Cpanel::JSON::XS is preferred over JSON::XS. To run --debug 20-22 File::Copy,
- File::Find, and File::Spec::Functions must be present (most distros have these in Core Modules).
+ $extra2 = "None of these are strictly required, but if you have them all,
+ you can eliminate some recommended non Perl programs from the install. ";
+ $extra3 = "HTTP::Tiny and IO::Socket::SSL must both be present to use as a
+ downloader option. For json export Cpanel::JSON::XS is preferred over
+ JSON::XS, but JSON::PP is in core modules. To run --debug 20-22 File::Copy,
+ File::Find, and File::Spec::Functions must be present (most distros have
+ these in Core Modules).
";
}
elsif ($type eq 'recommended kernel modules'){
@@ -3006,9 +3028,9 @@ sub check_items {
%info = item_data($item);
$about = $info{$info_os};
if (($b_dir && -d $item) || ($b_file && -r $item) ||
- ($b_program && main::check_program($item)) ||
- ($b_perl_module && main::check_perl_module($item)) ||
- ($b_kernel_module && @modules && (grep {/^$item$/} @modules))){
+ ($b_program && main::check_program($item)) ||
+ ($b_perl_module && main::check_perl_module($item)) ||
+ ($b_kernel_module && @modules && (grep {/^$item$/} @modules))){
$result = 'Present';
}
elsif ($b_file && -f $item){
@@ -3210,6 +3232,13 @@ sub item_data {
'pacman' => '',
'rpm' => '',
},
+ 'fruid_print' => {
+ 'info' => '-M machine data, Elbrus only',
+ 'info-bsd' => '',
+ 'apt' => '',
+ 'pacman' => '',
+ 'rpm' => '',
+ },
'glabel' => {
'info' => '',
'info-bsd' => '-R; -D; -P. Get actual gptid /dev path',
@@ -3408,8 +3437,8 @@ sub item_data {
},
# Display Tools
'glxinfo' => {
- 'info' => '-G glx info',
- 'info-bsd' => '-G glx info',
+ 'info' => '-G (X) glx info',
+ 'info-bsd' => '-G (X) glx info',
'apt' => 'mesa-utils',
'pacman' => 'mesa-demos',
'rpm' => 'glx-utils (SUSE: Mesa-demo-x)',
@@ -3422,30 +3451,30 @@ sub item_data {
'rpm' => 'wmctrl',
},
'xdpyinfo' => {
- 'info' => '-G multi screen resolution',
- 'info-bsd' => '-G multi screen resolution',
+ 'info' => '-G (X) Screen resolution, dpi; -Ga Screen size',
+ 'info-bsd' => '-G (X) Screen resolution, dpi; -Ga Screen size',
'apt' => 'X11-utils',
'pacman' => 'xorg-xdpyinfo',
'rpm' => 'xorg-x11-utils (SUSE/Fedora?: xdpyinfo)',
},
'xprop' => {
- 'info' => '-S desktop data',
- 'info-bsd' => '-S desktop data',
+ 'info' => '-S (X) desktop data',
+ 'info-bsd' => '-S (X) desktop data',
'apt' => 'X11-utils',
'pacman' => 'xorg-xprop',
'rpm' => 'x11-utils',
},
'xrandr' => {
- 'info' => '-G single screen resolution',
- 'info-bsd' => '-G single screen resolution',
+ 'info' => '-G (X) monitors(s) resolution; -Ga monitor data',
+ 'info-bsd' => '-G (X) monitors(s) resolution; -Ga monitor data',
'apt' => 'x11-xserver-utils',
'pacman' => 'xrandr',
'rpm' => 'x11-server-utils (Fedora: xrandr)',
},
# Perl Modules
'Cpanel::JSON::XS' => {
- 'info' => '--output json - required for export.',
- 'info-bsd' => '--output json - required for export.',
+ 'info' => '--output json (faster than JSON::PP).',
+ 'info-bsd' => '--output json (faster than JSON::PP).',
'apt' => 'libcpanel-json-xs-perl',
'pacman' => 'perl-cpanel-json-xs',
'rpm' => 'perl-Cpanel-JSON-XS',
@@ -3485,9 +3514,16 @@ sub item_data {
'pacman' => 'perl-io-socket-ssl',
'rpm' => 'perl-IO-Socket-SSL',
},
+ 'JSON::PP' => {
+ 'info' => '--output json (in CoreModules, but slower).',
+ 'info-bsd' => '--output json (in CoreModules, but slower).',
+ 'apt' => 'libcpanel-json-xs-perl',
+ 'pacman' => 'perl-cpanel-json-xs',
+ 'rpm' => 'perl-Cpanel-JSON-XS',
+ },
'JSON::XS' => {
- 'info' => '--output json - required for export (legacy).',
- 'info-bsd' => '--output json - required for export (legacy).',
+ 'info' => '--output json (legacy).',
+ 'info-bsd' => '--output json (legacy).',
'apt' => 'libjson-xs-perl',
'pacman' => 'perl-json-xs',
'rpm' => 'perl-JSON-XS',
@@ -3751,6 +3787,34 @@ sub lister {
closedir $dir;
return @list;
}
+# checks for 1 of 3 perl json modules. All three have same encode_json,
+# decode_json() methods.
+sub load_json {
+ eval $start if $b_log;
+ $loaded{'json'} = 1;
+ # recommended, but not in core modules
+ if (check_perl_module('Cpanel::JSON::XS')){
+ Cpanel::JSON::XS->import;
+ $use{'json'} = {'type' => 'cpanel-json-xs',
+ 'encode' => \&Cpanel::JSON::XS::encode_json,
+ 'decode' => \&Cpanel::JSON::XS::decode_json};
+ }
+ # somewhat legacy, not in perl modules
+ elsif (check_perl_module('JSON::XS')){
+ JSON::XS->import;
+ $use{'json'} = {'type' => 'json-xs',
+ 'encode' => \&JSON::XS::encode_json,
+ 'decode' => \&JSON::XS::decode_json};
+ }
+ # perl, in core modules as of 5.14
+ elsif (check_perl_module('JSON::PP')){
+ JSON::PP->import;
+ $use{'json'} = {'type' => 'json-pp',
+ 'encode' => \&JSON::PP::encode_json,
+ 'decode' => \&JSON::PP::decode_json};
+ }
+ eval $end if $b_log;
+}
# returns array of: 0: program print name 1: program version
# args: 1: program values id 2: program version string
@@ -3813,17 +3877,22 @@ sub set_program_values {
'amiwm' => ['^amiwm',0,'0','AmiWM',0,1,0,'',''], # no version
'antiwm' => ['^antiwm',0,'0','AntiWM',0,1,0,'',''], # no version known
'asc' => ['^asc',0,'0','asc',0,1,0,'',''],
+ 'awc' => ['^awc',0,'0','awc',0,1,0,'',''], # unverified
'awesome' => ['^awesome',2,'--version','awesome',0,1,0,'',''],
'beryl' => ['^beryl',0,'0','Beryl',0,1,0,'',''], # unverified; legacy
'blackbox' => ['^Blackbox',2,'--version','Blackbox',0,1,0,'',''],
'bspwm' => ['^\S',1,'-v','bspwm',0,1,0,'',''],
'budgie-desktop' => ['^budgie-desktop',2,'--version','Budgie',0,1,0,'',''],
'budgie-wm' => ['^budgie',0,'0','budgie-wm',0,1,0,'',''],
+ 'cage' => ['^cage',0,'0','Cage',0,1,0,'',''], # unverified
'cagebreak' => ['^Cagebreak',3,'-v','Cagebreak',0,1,0,'',''],
'calmwm' => ['^calmwm',0,'0','CalmWM',0,1,0,'',''], # unverified
+ 'cardboard' => ['^cardboard',0,'0','Cardboard',0,1,0,'',''], # unverified
'catwm' => ['^catwm',0,'0','catwm',0,1,0,'',''], # unverified
+ 'chameleonwm' => ['^chameleon',0,'0','ChameleonWM',0,1,0,'',''], # unverified
'cinnamon' => ['^cinnamon',2,'--version','Cinnamon',0,1,0,'',''],
'clfswm' => ['^clsfwm',0,'0','clfswm',0,1,0,'',''], # no version
+ 'comfc' => ['^comfc',0,'0','comfc',0,1,0,'',''], # unverified
'compiz' => ['^compiz',2,'--version','Compiz',0,1,0,'',''],
'compton' => ['^\d',1,'--version','Compton',0,1,0,'',''],
'ctwm' => ['^\S',1,'-version','ctwm',0,1,0,'',''],
@@ -3834,11 +3903,15 @@ sub set_program_values {
'deepin-mutter' => ['^mutter',2,'--version','Deepin-Mutter',0,1,0,'',''],
'deepin-wm' => ['^gala',0,'0','DeepinWM',0,1,0,'',''], # no version
'dwc' => ['^dwc',0,'0','dwc',0,1,0,'',''], # unverified
+ 'dwl' => ['^dwl',0,'0','dwl',0,1,0,'',''], # unverified
'dwm' => ['^dwm',1,'-v','dwm',0,1,1,'^dwm-',''],
'echinus' => ['^echinus',1,'-v','echinus',0,1,1,'',''], # echinus-0.4.9 (c)...
# only listed here for compositor values, version data comes from xprop
'enlightenment' => ['^enlightenment',0,'0','enlightenment',0,1,0,'',''], # no version, yet?
+ 'epd-wm' => ['^epd-wm',0,'0','epd-wm',0,1,0,'',''], # unverified
'evilwm' => ['evilwm',3,'-V','evilwm',0,1,0,'',''],# might use full path in match
+ 'feathers' => ['^feathers',0,'0','feathers',0,1,0,'',''], # unverified
+ 'fenestra' => ['^fenestra',0,'0','fenestra',0,1,0,'',''], # unverified
'fireplace' => ['^fireplace',0,'0','fireplace',0,1,0,'',''], # unverified
'fluxbox' => ['^fluxbox',2,'-v','Fluxbox',0,1,0,'',''],
'flwm' => ['^flwm',0,'0','FLWM',0,0,1,'',''], # no version
@@ -3850,18 +3923,24 @@ sub set_program_values {
'fvwm95' => ['^fvwm',2,'--version','FVWM95',0,1,1,'',''],
'fvwm-crystal' => ['^fvwm',2,'--version','FVWM-Crystal',0,0,0,'',''], # for print name fvwm
'gala' => ['^gala',0,'0','gala',0,1,0,'',''], # pantheon wm: super slow result, 2, '--version' works?
+ 'gamescope' => ['^gamescope',0,'0','Gamescope',0,1,0,'',''], # unverified
'glass' => ['^glass',3,'-v','Glass',0,1,0,'',''],
'gnome' => ['^gnome',3,'--version','GNOME',0,1,0,'',''], # no version, print name
'gnome-about' => ['^gnome',3,'--version','GNOME',0,1,0,'',''],
'gnome-shell' => ['^gnome',3,'--version','gnome-shell',0,1,0,'',''],
- 'grefson' => ['^grefson',0,'0','grefson',0,1,0,'',''], # unverified
+ 'greenfield' => ['^greenfield',0,'0','Greenfield',0,1,0,'',''], # unverified
+ 'grefson' => ['^grefson',0,'0','Grefson',0,1,0,'',''], # unverified
'hackedbox' => ['^hackedbox',2,'-version','HackedBox',0,1,0,'',''], # unverified, assume blackbox
# note, herbstluftwm when launched with full path returns full path in version string
'herbstluftwm' => ['herbstluftwm',2,'--version','herbstluftwm',0,1,0,'',''],
+ 'hikari' => ['^hikari',0,'0','hikari',0,1,0,'',''], # unverified
+ 'hopalong' => ['^hopalong',0,'0','Hopalong',0,1,0,'',''], # unverified
'i3' => ['^i3',3,'--version','i3',0,1,0,'',''],
'icewm' => ['^icewm',2,'--version','IceWM',0,1,0,'',''],
+ 'inaban' => ['^inaban',0,'0','inaban',0,1,0,'',''], # unverified
'instantwm' => ['^instantwm',1,'-v','instantWM',0,1,1,'^instantwm-?(instantos-?)?',''],
'ion3' => ['^ion3',0,'--version','Ion3',0,1,0,'',''], # unverified; also shell called ion
+ 'japokwm' => ['^japokwm',0,'0','japokwm',0,1,0,'',''], # unverified
'jbwm' => ['jbwm',3,'-v','JBWM',0,1,0,'',''], # might use full path in match
'jwm' => ['^jwm',2,'--version','JWM',0,1,0,'',''],
'kded' => ['^KDE( Development Platform)?:',2,'--version','KDE',0,1,0,'\sDevelopment Platform',''],
@@ -3869,13 +3948,19 @@ sub set_program_values {
'kded2' => ['^KDE( Development Platform)?:',2,'--version','KDE',0,1,0,'\sDevelopment Platform',''],
'kded3' => ['^KDE( Development Platform)?:',2,'--version','KDE',0,1,0,'\sDevelopment Platform',''],
'kded4' => ['^KDE( Development Platform)?:',2,'--version','KDE',0,1,0,'\sDevelopment Platform',''],
+ 'kiwmi' => ['^kwimi',0,'0','kiwmi',0,1,0,'',''], # unverified
'ksmcon' => ['^ksmcon',0,'0','ksmcon',0,1,0,'',''],# no version
'kwin' => ['^kwin',0,'0','kwin',0,1,0,'',''],# no version
'kwin_wayland' => ['^kwin_wayland',0,'0','kwin_wayland',0,1,0,'',''],# no version
'kwin_x11' => ['^kwin_x11',0,'0','kwin_x11',0,1,0,'',''],# no version
+ 'kwinft' => ['^kwinft',0,'0','KWinFT',0,1,0,'',''], # unverified
+ 'labwc' => ['^labwc',0,'0','LabWC',0,1,0,'',''], # unverified
+ 'laikawm' => ['^laikawm',0,'0','LaikaWM',0,1,0,'',''], # unverified
'larswm' => ['^larswm',2,'-v','larswm',0,1,1,'',''],
'leftwm' => ['^leftwm',0,'0','LeftWM',0,1,0,'',''],# no version, in CHANGELOG
'liri' => ['^liri',0,'0','liri',0,1,0,'',''],
+ 'lipstick' => ['^lipstick',0,'0','Lipstick',0,1,0,'',''], # unverified
+ 'liri' => ['^liri',0,'0','liri',0,1,0,'',''], # unverified
'lumina-desktop' => ['^\S',1,'--version','Lumina',0,1,1,'',''],
'lwm' => ['^lwm',0,'0','lwm',0,1,0,'',''], # no version
'lxpanel' => ['^lxpanel',2,'--version','LXDE',0,1,0,'',''],
@@ -3883,13 +3968,16 @@ sub set_program_values {
'lxqt-panel' => ['^lxqt-panel',2,'--version','LXQt',0,1,0,'',''],
'lxqt-variant' => ['^lxqt-panel',0,'0','LXQt-Variant',0,1,0,'',''],
'lxsession' => ['^lxsession',0,'0','lxsession',0,1,0,'',''],
+ 'mahogany' => ['^mahogany',0,'0','Mahogany',0,1,0,'',''], # unverified
'manokwari' => ['^manokwari',0,'0','Manokwari',0,1,0,'',''],
+ 'marina' => ['^marina',0,'0','Marina',0,1,0,'',''], # unverified
'marco' => ['^marco',2,'--version','marco',0,1,0,'',''],
'matchbox' => ['^matchbox',0,'0','Matchbox',0,1,0,'',''],
'matchbox-window-manager' => ['^matchbox',2,'--help','Matchbox',0,0,0,'',''],
'mate-about' => ['^MATE[[:space:]]DESKTOP',-1,'--version','MATE',0,1,0,'',''],
# note, mate-session when launched with full path returns full path in version string
'mate-session' => ['mate-session',-1,'--version','MATE',0,1,0,'',''],
+ 'maze' => ['^maze',0,'0','Maze',0,1,0,'',''], # unverified
'mcwm' => ['^mcwm',0,'0','mcwm',0,1,0,'',''], # unverified/see 2bwm
'metacity' => ['^metacity',2,'--version','Metacity',0,1,0,'',''],
'metisse' => ['^metisse',0,'0','metisse',0,1,0,'',''],
@@ -3903,23 +3991,31 @@ sub set_program_values {
'mutter' => ['^mutter',2,'--version','Mutter',0,1,0,'',''],
'mwm' => ['^mwm',0,'0','MWM',0,1,0,'',''],# no version
'nawm' => ['^nawm',0,'0','nawm',0,1,0,'',''],# unverified
+ 'newm' => ['^newm',0,'0','newm',0,1,0,'',''], # unverified
'notion' => ['^.',1,'--version','Notion',0,1,0,'',''],
+ 'nucleus' => ['^nucleus',0,'0','Nucleus',0,1,0,'',''], # unverified
'openbox' => ['^openbox',2,'--version','Openbox',0,1,0,'',''],
- 'orbital' => ['^orbital',0,'0','orbital',0,1,0,'',''],# unverified
+ 'orbital' => ['^orbital',0,'0','Orbital',0,1,0,'',''],# unverified
'pantheon' => ['^pantheon',0,'0','Pantheon',0,1,0,'',''],# no version
'papyros' => ['^papyros',0,'0','papyros',0,1,0,'',''],# no version
'pekwm' => ['^pekwm',3,'--version','PekWM',0,1,0,'',''],
'penrose' => ['^penrose',0,'0','Penrose',0,1,0,'',''],# no version?
'perceptia' => ['^perceptia',0,'0','perceptia',0,1,0,'',''],
+ 'phoc' => ['^phoc',0,'0','phoc',0,1,0,'',''], # unverified
'picom' => ['^\S',1,'--version','Picom',0,1,0,'^v',''],
'plasmashell' => ['^plasmashell',2,'--version','KDE Plasma',0,1,0,'',''],
+ 'pywm' => ['^pywm',0,'0','pywm',0,1,0,'',''], # unverified
'qtile' => ['^',1,'--version','Qtile',0,1,0,'',''],
'qvwm' => ['^qvwm',0,'0','qvwm',0,1,0,'',''], # unverified
'razor-session' => ['^razor',0,'0','Razor-Qt',0,1,0,'',''],
'ratpoison' => ['^ratpoison',2,'--version','Ratpoison',0,1,0,'',''],
+ 'river' => ['^river',0,'0','River',0,1,0,'',''], # unverified
+ 'rootston' => ['^rootston',0,'0','rootston',0,1,0,'',''], # unverified, wlroot ref
'rustland' => ['^rustland',0,'0','rustland',0,1,0,'',''], # unverified
'sawfish' => ['^sawfish',3,'--version','Sawfish',0,1,0,'',''],
'scrotwm' => ['^scrotwm.*welcome.*',5,'-v','scrotwm',0,1,1,'',''],
+ 'simulavr' => ['simulavr^',0,'0','SimulaVR',0,1,0,'',''], # unverified
+ 'skylight' => ['^skylight',0,'0','Skylight',0,1,0,'',''], # unverified
'sommelier' => ['^sommelier',0,'0','sommelier',0,1,0,'',''], # unverified
'snapwm' => ['^snapwm',0,'0','snapwm',0,1,0,'',''], # unverified
'spectrwm' => ['^spectrwm.*welcome.*wm',5,'-v','spectrwm',0,1,1,'',''],
@@ -3927,7 +4023,13 @@ sub set_program_values {
'stumpwm' => ['^SBCL',0,'--version','StumpWM',0,1,0,'',''], # hangs when run in wm
'sway' => ['^sway',3,'-v','sway',0,1,0,'',''],
'swc' => ['^swc',0,'0','swc',0,1,0,'',''], # unverified
+ 'swvkc' => ['^swvkc',0,'0','swvkc',0,1,0,'',''], # unverified
+ 'tabby' => ['^tabby',0,'0','Tabby',0,1,0,'',''], # unverified
+ 'taiwins' => ['^taiwins',0,'0','taiwins',0,1,0,'',''], # unverified
+ 'tinybox' => ['^tinybox',0,'0','tinybox',0,1,0,'',''], # unverified
+ 'tinywl' => ['^tinywl',0,'0','TinyWL',0,1,0,'',''], # unverified
'tinywm' => ['^tinywm',0,'0','TinyWM',0,1,0,'',''], # no version
+ 'trinkster' => ['^trinkster',0,'0','Trinkster',0,1,0,'',''], # unverified
'tvtwm' => ['^tvtwm',0,'0','tvtwm',0,1,0,'',''], # unverified
'twin' => ['^Twin:',2,'--version','Twin',0,0,0,'',''],
'twm' => ['^twm',0,'0','TWM',0,1,0,'',''], # no version
@@ -3938,15 +4040,23 @@ sub set_program_values {
'unity-system-compositor' => ['^unity-system-compositor',2,'--version',
'unity-system-compositor (mir)',0,0,0,'',''],
'uwm' => ['^uwm',0,'0','UWM',0,1,0,'',''], # unverified
+ 'velox' => ['^velox',0,'0','Velox',0,1,0,'',''], # unverified
+ 'vimway' => ['^vimway',0,'0','vimway',0,1,0,'',''], # unverified
+ 'vivarium' => ['^vivarium',0,'0','Vivarium',0,1,0,'',''], # unverified
'wavy' => ['^wavy',0,'0','wavy',0,1,0,'',''], # unverified
+ 'waybox' => ['^way',0,'0','waybox',0,1,0,'',''], # unverified
'waycooler' => ['^way',3,'--version','way-cooler',0,1,0,'',''],
'way-cooler' => ['^way',3,'--version','way-cooler',0,1,0,'',''],
- 'wayfire' => ['^way',0,'0','wayfire',0,1,0,'',''], # unverified
+ 'wayfire' => ['^\d',1,'--version','wayfire',0,1,0,'',''], # -version/--version
'wayhouse' => ['^wayhouse',0,'0','wayhouse',0,1,0,'',''], # unverified
+ 'waymonad' => ['^waymonad',0,'0','waymonad',0,1,0,'',''], # unverified
+ 'westeros' => ['^westeros',0,'0','westeros',0,1,0,'',''], # unverified
'westford' => ['^westford',0,'0','westford',0,1,0,'',''], # unverified
- 'weston' => ['^weston',0,'0','weston',0,1,0,'',''], # unverified
+ 'weston' => ['^weston',0,'0','Weston',0,1,0,'',''], # unverified
'windowlab' => ['^windowlab',2,'-about','WindowLab',0,1,0,'',''],
'wingo' => ['^wingo',0,'0','Wingo',0,1,0,'',''], # unverified
+ 'wio' => ['^wio',0,'0','Wio',0,1,0,'',''], # unverified
+ 'wio' => ['^wio\+',0,'0','wio+',0,1,0,'',''], # unverified
'wm2' => ['^wm2',0,'0','wm2',0,1,0,'',''], # no version
'wmaker' => ['^Window[[:space:]]*Maker',-1,'--version','WindowMaker',0,1,0,'',''],
'wmfs' => ['^wmfs',0,'0','WMFS',0,1,0,'',''], # unverified
@@ -3954,6 +4064,8 @@ sub set_program_values {
'wmii' => ['^wmii',1,'-v','wmii',0,1,0,'^wmii[234]?-',''], # wmii is wmii3
'wmii2' => ['^wmii2',1,'--version','wmii2',0,1,0,'^wmii[234]?-',''],
'wmx' => ['^wmx',0,'0','wmx',0,1,0,'',''], # no version
+ 'wxrc' => ['^wx',0,'0','',0,1,0,'WXRC',''], # unverified
+ 'wxrd' => ['^wx',0,'0','',0,1,0,'WXRD',''], # unverified
'xcompmgr' => ['^xcompmgr',0,'0','xcompmgr',0,1,0,'',''], # no version
'xfce4-panel' => ['^xfce4-panel',2,'--version','Xfce',0,1,0,'',''],
'xfce5-panel' => ['^xfce5-panel',2,'--version','Xfce',0,1,0,'',''],
@@ -3965,6 +4077,7 @@ sub set_program_values {
'xfwm4' => ['xfwm4? version',5,'--version','xfwm',0,1,0,'^^\s+',''],
'xfwm5' => ['xfwm5? version',5,'--version','xfwm',0,1,0,'^^\s+',''], # unverified
'xmonad' => ['^xmonad',2,'--version','XMonad',0,1,0,'',''],
+ 'xuake' => ['^xuake',0,'0','xuake',0,1,0,'',''], # unverified
'yeahwm' => ['^yeahwm',0,'--version','YeahWM',0,1,0,'',''], # unverified
## Toolkits ##
'gtk-launch' => ['^\S',1,'--version','GTK',0,1,0,'',''],
@@ -3972,9 +4085,11 @@ sub set_program_values {
'qtdiag' => ['^qt',2,'--version','Qt',0,1,0,'',''],
## Display Managers (dm) ##
'cdm' => ['^cdm',0,'0','CDM',0,1,0,'',''],
+ 'emptty' => ['^emptty',0,'0','EMPTTY',0,1,0,'',''], # unverified
'entrance' => ['^entrance',0,'0','Entrance',0,1,0,'',''],
'gdm' => ['^gdm',2,'--version','GDM',0,1,0,'',''],
'gdm3' => ['^gdm',2,'--version','GDM3',0,1,0,'',''],
+ 'greetd' => ['^greetd',0,'0','greetd',0,1,0,'',''], # no version
'kdm' => ['^kdm',0,'0','KDM',0,1,0,'',''],
'kdm3' => ['^kdm',0,'0','KDM',0,1,0,'',''],
'ldm' => ['^ldm',0,'0','LDM',0,1,0,'',''],
@@ -3984,8 +4099,10 @@ sub set_program_values {
'mdm' => ['^mdm',0,'0','MDM',0,1,0,'',''],
'nodm' => ['^nodm',0,'0','nodm',0,1,0,'',''],
'pcdm' => ['^pcdm',0,'0','PCDM',0,1,0,'',''],
+ 'qingy' => ['^qingy',0,'0','qingy',0,1,0,'',''], # unverified
'sddm' => ['^sddm',0,'0','SDDM',0,1,0,'',''],
'slim' => ['slim version',3,'-v','SLiM',0,1,0,'',''],
+ 'tbsm' => ['^tbsm',0,'0','tbsm',0,1,0,'',''], # unverified
'tdm' => ['^tdm',0,'0','TDM',0,1,0,'',''],
'udm' => ['^udm',0,'0','udm',0,1,0,'',''],
'wdm' => ['^wdm',0,'0','WINGs DM',0,1,0,'',''],
@@ -4521,7 +4638,7 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
'C|cpu' => sub {
$show{'short'} = 0;
$show{'cpu'} = 1;},
@@ -4549,6 +4666,7 @@ sub get {
$show{'disk'} = 1;
$show{'graphic'} = 1;
$show{'graphic-basic'} = 1;
+ $show{'graphic-full'} = 1;
$show{'info'} = 1;
$show{'machine'} = 1;
$show{'network'} = 1;
@@ -4561,7 +4679,8 @@ sub get {
'G|graphics|graphic' => sub {
$show{'short'} = 0;
$show{'graphic'} = 1;
- $show{'graphic-basic'} = 1;},
+ $show{'graphic-basic'} = 1;
+ $show{'graphic-full'} = 1;},
'h|help|?' => sub {
$show{'help'} = 1;},
'i|ip' => sub {
@@ -4588,7 +4707,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'L|logical|lvm' => sub {
$show{'short'} = 0;
$show{'logical'} = 1;},
@@ -4630,7 +4749,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'r|repos|repo' => sub {
$show{'short'} = 0;
$show{'repo'} = 1;},
@@ -4649,7 +4768,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'slots|slot' => sub {
$show{'short'} = 0;
$show{'slot'} = 1;},
@@ -4674,7 +4793,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'u|uuid' => sub {
$show{'uuid'} = 1;},
'v|verbosity:i' => sub {
@@ -4711,11 +4830,11 @@ sub get {
if ($arg >= 5){
$show{'audio'} = 1;
$show{'bluetooth'} = 1;
- $show{'ram'} = 1;
+ $show{'graphic-full'} = 1;
$show{'label'} = 1;
$show{'optical-basic'} = 1;
- $show{'ram'} = 1;
$show{'raid'} = 1;
+ $show{'ram'} = 1;
$show{'sensor'} = 1;
$show{'swap'} = 1;
$show{'uuid'} = 1;
@@ -4750,7 +4869,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'V|version' => sub {
$show{'version'} = 1 },
'w|weather' => sub {
@@ -4762,7 +4881,7 @@ sub get {
}
else {
main::error_handler('distro-block', $opt);
- } },
+ }},
'W|weather-location:s' => sub {
my ($opt,$arg) = @_;
$arg ||= '';
@@ -4780,7 +4899,7 @@ sub get {
}
else {
main::error_handler('distro-block', $opt);
- } },
+ }},
'ws|weather-source:s' => sub {
my ($opt,$arg) = @_;
# let api processor handle checks if valid, this
@@ -4790,7 +4909,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'weather-unit:s' => sub {
my ($opt,$arg) = @_;
$arg ||= '';
@@ -4803,7 +4922,7 @@ sub get {
}
else {
main::error_handler('bad-arg',$opt,$arg);
- } },
+ }},
'x|extra:i' => sub {
my ($opt,$arg) = @_;
if ($arg > 0){
@@ -4811,7 +4930,7 @@ sub get {
}
else {
$extra++;
- } },
+ }},
'y|width:i' => sub {
my ($opt, $arg) = @_;
if (defined $arg && $arg == -1){
@@ -4908,7 +5027,7 @@ sub get {
}
},
'cygwin' => sub {
- $b_cygwin = 1 },
+ $b_cygwin = 1;},
'dbg:i' => sub {
my ($opt,$arg) = @_;
if ($arg > 0){
@@ -4924,7 +5043,15 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
+ 'debug-arg:s' => sub {
+ my ($opt,$arg) = @_;
+ if ($arg){
+ $debugger{'arg'} = $arg;
+ }
+ else {
+ main::error_handler('bad-arg', $opt, $arg);
+ }},
'debug-filter|debug-z|debug-zy' => sub {
$debugger{'filter'} = 1 },
'debug-id:s' => sub {
@@ -4934,7 +5061,7 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
'debug-no-eps' => sub {
$debugger{'no-exit'} = 1;
$debugger{'no-proc'} = 1;
@@ -4962,7 +5089,7 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
'dig' => sub {
$force{'no-dig'} = 0;},
'display:s' => sub {
@@ -4977,9 +5104,9 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
'dmi|dmidecode' => sub {
- $force{'dmidecode'} = 1 },
+ $force{'dmidecode'} = 1;},
'downloader:s' => sub {
my ($opt,$arg) = @_;
$arg = lc($arg);
@@ -5001,14 +5128,14 @@ sub get {
}
else {
main::error_handler('bad-arg', $opt, $arg);
- } },
+ }},
'fake:s' => sub {
my ($opt,$arg) = @_;
if ($arg){
- my $wl = 'bluetooth|compiler|cpu|dboot|dmidecode|ipmi|logical|lspci|';
+ 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|sysctl|uptime|usbconfig|';
- $wl .= 'usbdevs|vmstat|xorg-log';
+ $wl .= 'raid-md|raid-soft|raid-zfs|sensors|swaymsg|sysctl|';
+ $wl .= 'uptime|usbconfig|usbdevs|vmstat|wl-info|wlr-randr|xorg-log|xrandr';
for (split(',',$arg)){
if ($_ =~ /\b($wl)\b/){
$fake{lc($1)} = 1;
@@ -5025,7 +5152,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|usb-sys|vmstat|wmctrl';
+ $wl .= 'no-dig|no-doas|no-html-wan|no-sudo|pkg|usb-sys|vmstat|wayland|wmctrl';
for (split(',',$arg)){
if ($_ =~ /\b($wl)\b/){
$force{lc($1)} = 1;
@@ -5048,10 +5175,10 @@ sub get {
main::error_handler('bad-arg', $opt, $arg);
}},
'hddtemp' => sub {
- $force{'hddtemp'} = 1 },
+ $force{'hddtemp'} = 1;},
'host|hostname' => sub {
$show{'host'} = 1;
- $show{'no-host'} = 0},
+ $show{'no-host'} = 0;},
'html-wan' => sub {
$force{'no-html-wan'} = 0;},
'indent:i' => sub {
@@ -5099,14 +5226,14 @@ sub get {
'no-doas' => sub {
$force{'no-doas'} = 1;},
'no-host|no-hostname' => sub {
- $show{'host'} = 0 ;
- $show{'no-host'} = 1},
+ $show{'host'} = 0;
+ $show{'no-host'} = 1;},
'no-html-wan' => sub {
$force{'no-html-wan'}= 1;},
'no-man' => sub {
$use{'no-man'} = 0;},
'no-ssl' => sub {
- $dl{'no-ssl-opt'}=1 },
+ $dl{'no-ssl-opt'} = 1;},
'no-sudo' => sub {
$force{'no-sudo'} = 1;},
'output-file:s' => sub {
@@ -5123,7 +5250,7 @@ sub get {
main::error_handler('bad-arg', $opt, $arg);
}},
'pkg' => sub {
- $force{'pkg'} = 1 },
+ $force{'pkg'} = 1;},
'ppc' => sub {
undef %risc;
$risc{'id'} = 'ppc';
@@ -5164,9 +5291,9 @@ sub get {
my ($opt,$arg) = @_;
process_updater($opt,$arg);},
'usb-sys' => sub {
- $force{'usb-sys'} = 1 },
+ $force{'usb-sys'} = 1;},
'usb-tool' => sub {
- $force{'lsusb'} = 1 },
+ $force{'lsusb'} = 1;},
'wan-ip-url:s' => sub {
my ($opt,$arg) = @_;
if ($arg && $arg =~ /^(f|ht)tp[s]?:\/\//){
@@ -5176,8 +5303,10 @@ sub get {
else {
main::error_handler('bad-arg', $opt, $arg);
}},
- 'wm' => sub {
- $force{'wmctrl'} = 1 },
+ 'wayland|wl' => sub {
+ $force{'wayland'} = 1;},
+ 'wm|wmctrl' => sub {
+ $force{'wmctrl'} = 1;},
'<>' => sub {
my ($opt) = @_;
main::error_handler('unknown-option', "$opt", "");}
@@ -5226,14 +5355,15 @@ sub post_process {
!$show{'partition-full'} && !$show{'swap'} && !$show{'unmounted'}){
main::error_handler('bad-arg', '-l/-u', 'missing required option(s) -j, -o, -p, -P');
}
- $show{'graphic-basic'} = 0 if $b_admin;
+ $extra = 3 if $b_admin;
+ $show{'graphic-basic'} = 0 if $show{'graphic-full'} && $extra > 1;
if ($use{'sensors-default'}){
@sensors_exclude = ();
@sensors_use = ();
}
if ($show{'short'} || $show{'disk'} || $show{'disk-basic'} || $show{'disk-total'} ||
- $show{'logical'} || $show{'partition'} || $show{'partition-full'} || $show{'raid'} ||
- $show{'unmounted'}){
+ $show{'logical'} || $show{'partition'} || $show{'partition-full'} || $show{'raid'} ||
+ $show{'unmounted'}){
$use{'block-tool'} = 1;
}
if ($show{'short'} || $show{'raid'} || $show{'disk'} || $show{'disk-total'} ||
@@ -5246,11 +5376,10 @@ sub post_process {
}
# triggers may extend to -D, -pP
if ($show{'short'} || $show{'logical'} || $show{'raid'} || $show{'disk'} ||
- $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){
+ $show{'disk-total'} || $show{'disk-basic'} || $show{'unmounted'}){
$use{'logical'} = 1;
}
main::set_sudo() if ($show{'unmounted'} || ($extra > 0 && $show{'disk'}));
- $extra = 3 if $b_admin;
$use{'filter'} = 0 if $use{'filter-override'};
# override for things like -b or -v2 to -v3
$show{'cpu-basic'} = 0 if $show{'cpu'};
@@ -5404,8 +5533,8 @@ sub show_options {
(except -J, -W) plus --swap, -s and -n. Does not show extra verbose options
such as -d -f -i -J -l -m -o -p -r -t -u -x, unless specified."],
['1', '-G', '--graphics', "Graphics info (devices(s), drivers, display
- protocol (if available), display server/Wayland compositor, resolution,
- renderer, OpenGL version)."],
+ protocol (if available), display server/Wayland compositor, resolution, X.org:
+ renderer, OpenGL version; Xvesa: VBE info."],
['1', '-i', '--ip', "WAN IP address and local interfaces (requires ifconfig
or ip network tool). Triggers -n. Not shown with -F for user security reasons.
You shouldn't paste your local/WAN IP."],
@@ -5560,7 +5689,7 @@ sub show_options {
verbose or line output, not short form); check man page for explanations!;
also sets --extra=3:"],
['2', '-A', '', "If available: list of alternate kernel modules/drivers
- for device(s)."],
+ for device(s); PCIe lanes-max: gen, speed, lanes (if relevant)."],
['2', '-C', '', "If available: 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);
@@ -5570,10 +5699,9 @@ sub show_options {
family; maj:min, USB drive specifics; SMART report."],
['2', '-E', '', "If available: in Report:, adds Info: line: acl-mtu,
sco-mtu, link-policy, link-mode, service-classes."],
- ['2', '-G', '', "If available: Xorg Display ID, Screens total, default Screen,
- current Screen; per X Screen: resolution, dpi, size, diagonal; per Monitor:
- resolution; hz; dpi; size; diagonal; list of alternate kernel modules/drivers
- for device(s)."],
+ ['2', '-G', '', "PCIe lanes-max: gen, speed, lanes (if relevant); list of
+ alternate kernel modules/drivers for device(s) (if available); Monitor built
+ year, gamma, screen ratio (if available)."],
['2', '-I', '', "As well as per package manager counts, also adds total
number of lib files found for each package manager if not -r; adds init
service tool."],
@@ -5582,7 +5710,7 @@ sub show_options {
['2', '-L', '', "LV, Crypto, devices, components: add maj:min; show
full device/components report (speed, mapped names)."],
['2', '-n,-N', '', "If available: list of alternate kernel modules/drivers
- for device(s)."],
+ for device(s); PCIe lanes-max: gen, speed, lanes (if relevant)."],
['2', '-o', '', "If available: maj:min of device."],
['2', '-p,-P', '', "If available: raw size of ${partition_string}s, maj:min,
percent available for user, block size of file system (root required)."],
@@ -5611,9 +5739,9 @@ sub show_options {
Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp"],
['2', '-E', '', "PCI/USB Bus ID of device, driver version,
LMP version."],
- ['2', '-G', '', "Specific vendor/product information (if relevant);
- PCI/USB ID of device; Direct rendering status (in X); Screen
- number GPU is running on (Nvidia only)."],
+ ['2', '-G', '', "Specific vendor/product information (if relevant); PCI/USB ID
+ of device; Direct rendering status (in X); Screen number GPU is running on
+ (Nvidia only)."],
['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
@@ -5648,16 +5776,20 @@ sub show_options {
['0', '', '', ''],
['1', '-xx', '--extra 2', "Show extra, extra data (only works with verbose
or line output, not short form):"],
- ['2', '-A', '', "Chip vendor:product ID for each audio device."],
+ ['2', '-A', '', "Chip vendor:product ID for each audio device; PCIe speed,
+ lanes (if found)."],
['2', '-B', '', "Serial number."],
['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."],
- ['2', '-G', '', "Chip vendor:product ID for each video device; OpenGL
- compatibility version, if free drivers and available; Xorg compositor;
- alternate Xorg drivers (if available). Alternate means driver is on automatic
- driver check list of Xorg for the device vendor, but is not installed on
- system; Xorg dpi."],
+ ['2', '-E', '', "Chip vendor:product ID, LMP subversion; PCIe speed, lanes
+ (if found)."],
+ ['2', '-G', '', "Chip vendor:product ID for each video device; Output ports,
+ used and empty; PCIe speed, lanes (if found); Xorg: OpenGL compatibility
+ version, if free drivers and available; Xorg compositor; alternate Xorg
+ drivers (if available. Alternate means driver is on automatic driver check
+ list of Xorg for the device vendor, but is not installed on system); Xorg
+ Screen data: ID, s-res, dpi; Monitors: ID, position (if > 1), resolution,
+ dpi, model, diagonal."],
['2', '-I', '', "Other detected installed gcc versions (if present). System
default runlevel. Adds parent program (or pty/tty) for shell info if not in
IRC. Adds Init version number, RC (if found). Adds per package manager
@@ -5670,7 +5802,7 @@ sub show_options {
['2', '-m,--memory-modules', '', "Manufacturer, part number; single/double
bank (if found)."],
['2', '-M', '', "Chassis info, BIOS ROM size (dmidecode only), if available."],
- ['2', '-N', '', "Chip vendor:product ID."],
+ ['2', '-N', '', "Chip vendor:product ID; PCIe speed, lanes (if found)."],
['2', '-r', '', "Packages, see -Ixx."],
['2', '-R', '', "md-raid: Superblock (if present), algorithm. If resync,
shows progress bar. Hardware RAID Chip vendor:product ID."],
@@ -5697,7 +5829,8 @@ sub show_options {
['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases;
disk type, rotation rpm (if available)."],
['2', '-E', '', "Serial number, class ID, HCI version and revision."],
- ['2', '-G', '', "Serial number, class ID."],
+ ['2', '-G', '', "Device serial number, class ID; Xorg Screen size, diag;
+ Monitors: hz, size, modes, serial, scale, modes (max/min)."],
['2', '-I', '', "For 'Shell:' adds ([doas|su|sudo|login]) to shell name if
present; adds default shell+version if different; for 'running in:' adds (SSH)
if SSH session; adds wakeups: (from suspend) to Uptime."],
@@ -6088,10 +6221,10 @@ sub get_client_version {
# NOTE: these must be empirically determined, not all events that
# show no tty are actually IRC. tmux is not a vt, but runs inside one
if (!$client{'name-print'}){
- my $wl_terms = 'alacritty|altyo|black-screen|conhost|doas|evilvte|';
- $wl_terms .= 'germinal|guake|havoc|hyper|kate|kitty|kmscon|konsole|login|';
- $wl_terms .= 'macwise|minicom|putty|rxvt|sakura|securecrt|shellinabox|';
- $wl_terms .= '^st$|sudo|term|tilda|tilix|tmux|tym|wayst|xiki|';
+ my $wl_terms = 'alacritty|altyo|\bate\b|black-screen|conhost|doas|evilvte|';
+ $wl_terms .= 'foot|germinal|guake|havoc|hyper|kate|kitty|kmscon|konsole|';
+ $wl_terms .= 'login|macwise|minicom|putty|rxvt|sakura|securecrt|';
+ $wl_terms .= 'shellinabox|^st$|sudo|term|tilda|tilix|tmux|tym|wayst|xiki|';
$wl_terms .= 'yaft|yakuake|\bzoc\b';
my $wl_clients = 'ansible|chef|run-parts|sshd';
my $whitelist = "$wl_terms|$wl_clients";
@@ -6121,7 +6254,7 @@ sub get_cmdline {
}
local $\ = '';
open(my $fh, '<', "/proc/$ppid/cmdline") or
- print_line("Open /proc/$ppid/cmdline failed: $!");
+ print_line("Open /proc/$ppid/cmdline failed: $!");
my @rows = <$fh>;
close $fh;
foreach (@rows){
@@ -6282,7 +6415,7 @@ sub clean {
my ($item) = @_;
return $item if !$item;# handle cases where it was 0 or '' or undefined
# note: |nee trips engineering, but I don't know why nee was filtered
- $item =~ s/chipset|company|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|incorporation|industrial|international|\bnee\b|no\sstring|revision|semiconductor|software|technologies|technology|ltd\.|<ltd>|\bltd\b|inc\.|<inc>|\binc\b|intl\.|co\.|<co>|corp\.|<corp>|\(tm\)|\(r\)|®|\(rev ..\)|\'|\"|\sinc\s*$|\?//gi;
+ $item =~ s/chipset|company|components|computing|computer|corporation|communications|electronics?|electric(al)?|group|incorporation|industrial|international|limited|\bnee\b|<?no\sstring>?|revision|semiconductor|software|technolog(ies|y)|<?unknown>?|ltd\.|<ltd>|\bltd\b|inc\.|<inc>|\binc\b|intl\.|co\.|<co>|corp\.|<corp>|\(tm\)|\(r\)|®|\(rev ..\)|\'|\"|\?//gi;
$item =~ s/,|\*/ /g;
$item =~ s/^\s+|\s+$//g;
$item =~ s/\s\s+/ /g;
@@ -6515,24 +6648,25 @@ sub message {
'cpu-speeds' => 'No per core speed data found.',
'cpu-speeds-bsd' => 'No OS support for core speeds.',
'darwin-feature' => 'Feature not supported iu Darwin/OSX.',
+ 'dev' => 'Feature under development',
'disk-data' => 'No disk data found.',
'disk-data-bsd' => 'No disk data found.',
'disk-size-0' => 'Total N/A',
- 'display-console' => 'No advanced graphics data found on this system in console.',
- 'display-driver-na' => 'n/a (using device driver)',
- 'display-null' => 'No advanced graphics data found on this system.',
- 'display-root' => 'Advanced graphics data unavailable in console for root.',
- 'display-root-x' => 'Advanced graphics data unavailable for root.',
+ 'display-driver-na' => ' X driver n/a',
'display-server' => 'No display server data found. Headless machine?',
- 'glxinfo-missing' => 'Unable to show advanced data. Required tool glxinfo missing.',
- 'gl-empty' => 'Unset. Missing GL driver?',
- 'display-try' => 'Advanced graphics data unavailable in console. Try -G --display',
- 'dev' => 'Feature under development',
'dmesg-boot-permissions' => 'dmesg.boot permissions',
'dmesg-boot-missing' => 'dmesg.boot not found',
- 'IP' => "No $id found. Connected to web? SSL issues?",
'dmidecode-dev-mem' => 'dmidecode is not allowed to read /dev/mem',
'dmidecode-smbios' => 'No SMBIOS data for dmidecode to process',
+ 'gl-console' => 'No advanced graphics data found on this system in console.',
+ 'gl-empty' => 'Unset. Missing GL driver?',
+ 'gl-null' => 'No GL data found on this system.',
+ 'gl-root' => 'GL data unavailable in console for root.',
+ 'gl-root-display' => 'GL data unavailable for root.',
+ 'gl-try' => 'GL data unavailable in console. Try -G --display',
+ 'glxinfo-missing' => 'Unable to show GL data. Required tool glxinfo missing.',
+ 'interface-wayland' => 'Wayland GBM/EGL data currently not available.',
+ 'IP' => "No $id found. Connected to web? SSL issues?",
'IP-dig' => "No $id found. Connected to web? SSL issues? Try --no-dig",
'IP-no-dig' => "No $id found. Connected to web? SSL issues? Try enabling dig",
'logical-data' => 'No logical block device data found.',
@@ -6541,6 +6675,11 @@ sub message {
'machine-data-bsd' => 'No machine data: Is dmidecode installed? Try -M --dmidecode.',
'machine-data-dmidecode' => 'No machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.',
'machine-data-force-dmidecode' => 'No machine data: try newer kernel. Is dmidecode installed? Try -M --dmidecode.',
+ 'machine-data-fruid' => 'No machine data: Is fruid_print installed?',
+ 'monitor-console' => 'N/A in console',
+ 'monitor-id' => 'not-matched',
+ 'monitor-na' => 'N/A',
+ 'monitor-wayland' => 'no compositor data',
'note-check' => 'check',
'note-est' => 'est.',
'optical-data' => 'No optical or floppy data found.',
@@ -6569,6 +6708,8 @@ sub message {
'root-item-incomplete' => "Full $id report requires superuser permissions.",
'root-required' => '<superuser required>',
'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.',
@@ -6602,6 +6743,7 @@ sub message {
'unknown-shell' => 'ERR-100',
'weather-error' => "Error: $id",
'weather-null' => "No $id found. Internet connection working?",
+ 'xvesa-interface' => 'No Xvesa VBE/GOP data found.',
);
return $unfound{$type};
}
@@ -6619,16 +6761,16 @@ sub regex_range {
return join('|',@processed);
}
+# Handles duplicates occuring anywhere in string
sub remove_duplicates {
my ($string) = @_;
return if !$string;
- my $holder = '';
- my (@temp);
+ my (%holder,@temp);
foreach (split(/\s+/, $string)){
- if ($holder ne $_){
+ if (!$holder{lc($_)}){
push(@temp, $_);
+ $holder{lc($_)} = 1;
}
- $holder = $_;
}
$string = join(' ', @temp);
return $string;
@@ -6710,16 +6852,12 @@ sub generate_json {
my ($b_cpanel,$b_valid);
error_handler('not-in-irc', 'help') if $b_irc;
print Dumper $data if $b_debug;
- if (check_perl_module('Cpanel::JSON::XS')){
- Cpanel::JSON::XS->import;
- $json = Cpanel::JSON::XS::encode_json($data);
- }
- elsif (check_perl_module('JSON::XS')){
- JSON::XS->import;
- $json = JSON::XS::encode_json($data);
+ load_json() if !$loaded{'json'};
+ if ($use{'json'}){
+ $json = &{$use{'json'}->{'encode'}}($data);
}
else {
- error_handler('required-module', 'json', 'Cpanel::JSON::XS OR JSON::XS');
+ error_handler('required-module', 'json', 'JSON::PP, Cpanel::JSON::XS or JSON::XS');
}
if ($json){
#$json =~ s/"[0-9]+#/"/g;
@@ -7174,7 +7312,7 @@ sub get {
push(@rows,device_output());
}
if (((%risc && !$use{'soc-audio'} && !$use{'pci-tool'}) || !@rows) &&
- (my $file = $system_files{'asound-cards'})){
+ (my $file = $system_files{'asound-cards'})){
push(@rows,asound_output($file));
}
push(@rows,usb_output());
@@ -7228,7 +7366,11 @@ sub device_output {
$rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10];
}
if ($extra > 0){
- $rows[$j]->{main::key($num++,0,2,'bus-ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]";
+ my $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);
+ }
+ $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id;
}
if ($extra > 1){
my $chip_id = main::get_chip_id($row->[5],$row->[6]);
@@ -7466,7 +7608,7 @@ sub get {
@rows = ({main::key($num++,0,1,$key1) => $val1,});
}
}
- (@upower_items,$b_upower,$upower) = undef;
+ (@upower_items,$b_upower,$upower) = ();
eval $end if $b_log;
return @rows;
}
@@ -8013,7 +8155,11 @@ sub device_output {
$rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10];
}
if ($extra > 0){
- $rows[$j]->{main::key($num++,0,2,'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);
+ }
+ $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id;
}
if ($extra > 1){
my $chip_id = main::get_chip_id($row->[5],$row->[6]);
@@ -8191,7 +8337,7 @@ sub advanced_output {
# }
# this data only from hciconfig
if ($b_admin &&
- ($hci{$item}->{'acl-mtu'} || $hci{$item}->{'sco-mtu'} || $hci{$item}->{'link-policy'})){
+ ($hci{$item}->{'acl-mtu'} || $hci{$item}->{'sco-mtu'} || $hci{$item}->{'link-policy'})){
$j = scalar @rows;
push(@rows,{
main::key($num++,1,$l,'Info') => '',
@@ -8217,7 +8363,7 @@ sub advanced_output {
}
}
if (!@rows && !$b_hci_error && ($alerts{'hciconfig'}->{'action'} ne 'use' &&
- $alerts{'bt-adapter'}->{'action'} ne 'use')){
+ $alerts{'bt-adapter'}->{'action'} ne 'use')){
my $key = 'Report';
my $value = '';
if ($alerts{'hciconfig'}->{'action'} eq 'platform' ||
@@ -8883,7 +9029,7 @@ sub cpuinfo_data {
}
}
cpuinfo_data_grabber($file,\$cpu{'type'}) if !$loaded{'cpuinfo'};
- $cpu{'type'} = cpu_vendor($cpu_arch) if $cpu_arch =~ /e2k/; # already set to lower
+ $cpu{'type'} = cpu_vendor($cpu_arch) if $cpu_arch eq 'elbrus'; # already set to lower
my ($core_count,$proc_count,$speed) = (0,0,0);
my ($b_block_1) = (1);
# need to prime for arm cpus, which do not have physical/core ids usually
@@ -9504,7 +9650,7 @@ sub sysctl_data {
# darwin shows machine, like MacBook7,1, not cpu
# machdep.cpu.brand_string: Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
if (($bsd_type ne 'darwin' && $line[0] eq 'hw.model') ||
- $line[0] eq 'machdep.cpu.brand_string'){
+ $line[0] eq 'machdep.cpu.brand_string'){
# cut L2 cache/cpu max speed out of model string, if available
# openbsd 5.6: AMD Sempron(tm) Processor 3400+ ("AuthenticAMD" 686-class, 256KB L2 cache)
# openbsd 6.x has Lx cache data in dmesg.boot
@@ -9835,7 +9981,7 @@ sub dmidecode_data {
# Older dmidecode appear to have unreliable Upgrade outputs
elsif ($item->[0] == 4){
# skip first three row,s we don't need that data
- ($socket,$upgrade) = (undef,undef);
+ ($socket,$upgrade) = ();
$dmi_data{'phys-cnt'}++; # try to catch bsds without physical cpu count
foreach my $value (@$item[3 .. $#$item]){
next if $value =~ /^~/;
@@ -9872,11 +10018,11 @@ sub dmidecode_data {
# Seen older cases where Upgrade: Other value exists
if ($socket || $upgrade){
if ($socket && $upgrade){
- $upgrade = undef if $socket eq $upgrade;
+ undef $upgrade if $socket eq $upgrade;
}
elsif ($upgrade){
$socket = $upgrade;
- $upgrade = undef;
+ undef $upgrade;
}
$dmi_data{'socket'} = $socket;
$dmi_data{'upgrade'} = $upgrade;
@@ -10074,7 +10220,7 @@ sub cp_data_dmi {
}
# We have to undef all the sys stuff to get back to the true dmidecode results
# Too many variants to treat one by one, just clear it out if forced.
- undef %$caches if $force{'dmidecode'};
+ undef $caches if $force{'dmidecode'};
# We don't want to use dmi L1/L2/L3 at all for non BSD systems unless forced
# because have seen totally gibberish dmidecode data for caches. /sys cache
# data preferred, more granular and basically consistently right.
@@ -10409,7 +10555,7 @@ sub cp_cache_desc {
$desc .= $sep . $cache_desc->{$_} . 'x' . main::get_size($_,'string');
$sep = ', ';
}
- undef %{$cache_desc};
+ undef $cache_desc;
return $desc;
}
# $caches passed by reference
@@ -10758,8 +10904,10 @@ sub cp_cpu_arch {
$arch = 'Core Merom'}
elsif ($model =~ /^(15)$/){
$arch = 'M Tolapai'} # pentium M system on chip
- elsif ($model =~ /^(17|1D)$/){
+ elsif ($model =~ /^(1D)$/){
$arch = 'Core Penryn'}
+ elsif ($model =~ /^(17)$/){
+ $arch = 'Core Yorkfield'}
# had 25 also, but that's westmere, at least for stepping 2
elsif ($model =~ /^(1A|1E|1F|2C|2E|2F)$/){
$arch = 'Nehalem'}
@@ -11243,7 +11391,7 @@ sub cpu_vendor {
elsif ($string =~ /centaur/){
$vendor = "centaur"
}
- elsif ($string =~ /(e2k|elbrus)/){
+ elsif ($string eq 'elbrus'){
$vendor = "elbrus"
}
eval $end if $b_log;
@@ -11344,9 +11492,9 @@ sub hex_and_decimal {
## DriveItem
{
package DriveItem;
-my ($b_hddtemp,$b_nvme,$smartctl_missing);
+my ($b_hddtemp,$b_nvme,$smartctl_missing,$vendors);
my ($hddtemp,$nvme) = ('','');
-my (@by_id,@by_path,@vendors);
+my (@by_id,@by_path);
my ($debugger_dir);
# main::writer("$debugger_dir/system-repo-data-urpmq.txt",\@data2) if $debugger_dir;
sub get {
@@ -11396,8 +11544,8 @@ sub get {
if ($show{'optical'} || $show{'optical-basic'}){
push(@rows,OpticalItem::get());
}
- ($b_hddtemp,$b_nvme,$hddtemp,$nvme) = (undef,undef,undef,undef);
- (@by_id,@by_path) = (undef,undef);
+ ($b_hddtemp,$b_nvme,$hddtemp,$nvme,$vendors) = ();
+ (@by_id,@by_path) = ();
eval $end if $b_log;
return @rows;
}
@@ -11860,10 +12008,10 @@ sub proc_data_advanced {
$drives->[$i]{'drive-type'} = 'HDD';
}
elsif (($block_type && $block_type ne 'sdx') ||
- # note: this case could conceivabley be wrong for a spun down HDD
- (defined $data[2] && $data[2] eq '0') ||
- ($drives->[$i]{'model'} &&
- $drives->[$i]{'model'} =~ /(flash|mmc|msata|\bm[\.-]?2\b|nvme|ssd|solid\s?state)/i)){
+ # note: this case could conceivabley be wrong for a spun down HDD
+ (defined $data[2] && $data[2] eq '0') ||
+ ($drives->[$i]{'model'} &&
+ $drives->[$i]{'model'} =~ /(flash|mmc|msata|\bm[\.-]?2\b|nvme|ssd|solid\s?state)/i)){
$drives->[$i]{'drive-type'} = 'SSD';
}
}
@@ -12223,7 +12371,7 @@ sub smartctl_data {
# 'Airflow_Temperature_Cel' like: 29 (Min/Max 14/43) so can't use -1 index
# Temperature like 29 Celsisu
elsif ($split[$a] eq 'Temperature_Celsius' || $split[$a] eq 'Temperature' ||
- $split[$a] eq 'Airflow_Temperature_Cel'){
+ $split[$a] eq 'Airflow_Temperature_Cel'){
if (!$data->[$i]{'temp'} && $split[$r]){
$data->[$i]{'temp'} = $split[$r];
}
@@ -12600,9 +12748,10 @@ sub disk_data_by_id {
# 0 - match pattern; 1 - replace pattern; 2 - vendor print; 3 - serial pattern
sub set_vendors {
eval $start if $b_log;
- @vendors = (
+ my $vendors = $_[0];
+ @$vendors = (
## MOST LIKELY/COMMON MATCHES ##
- ['(Crucial|^(FC)?CT|-CT|^M4\b|Gizmo!|^((C300-)?CTF[\s-]?)?DDAC)','Crucial','Crucial',''],
+ ['(Crucial|^(FC)?CT|-CT|^M4(\b|SSD)|Gizmo!|^((C300-)?CTF[\s-]?)?DDAC)','Crucial','Crucial',''],
# H10 HBRPEKNX0202A NVMe INTEL 512GB
['(\bINTEL\b|^SSD(PAM|SA2))','\bINTEL\b','Intel',''],
# note: S[AV][1-9][0-9] can trigger false positives
@@ -12677,6 +12826,7 @@ sub set_vendors {
# must come before AP|Apacer
['^(APPLE|iPod)','^APPLE','Apple',''],
['^(AP|Apacer)','^Apacer','Apacer',''],
+ ['^(Apricom|SATAWire)','^Apricom','Apricom',''],
['^(A-?RAM|ARSSD)','^A-?RAM','A-RAM',''],
['^Arch','^Arch(\s*Memory)?','Arch Memory',''],
['^(Asenno|AS[1-9])','^Asenno','Asenno',''],
@@ -12686,6 +12836,7 @@ sub set_vendors {
['^Axiom','^Axiom','Axiom',''],
['^(Baititon|BT[0-9])','^Baititon','Baititon',''],
['^Bamba','^Bamba','Bamba',''],
+ ['^(Beckhoff)','^Beckhoff','Beckhoff',''],
['^Bell\b','^Bell','Packard Bell',''],
['^(BelovedkaiAE|GhostPen)','^BelovedkaiAE','BelovedkaiAE',''],
['^BHT','^BHT','BHT',''],
@@ -12693,6 +12844,7 @@ sub set_vendors {
['^BIOSTAR','^BIOSTAR','Biostar',''],
['^BIWIN','^BIWIN','BIWIN',''],
['^Blackpcs','^Blackpcs','Blackpcs',''],
+ ['^(BlitzWolf|BW-?PSSD)','^BlitzWolf','BlitzWolf',''],
['^(BlueRay|SDM[0-9])','^BlueRay','BlueRay',''],
['^Bory','^Bory','Bory',''],
['^Braveeagle','^Braveeagle','BraveEagle',''],
@@ -12725,6 +12877,7 @@ sub set_vendors {
['^Derler','^Derler','Derler',''],
['^detech','^detech','DETech',''],
['^DGM','^DGM\b','DGM',''],
+ ['^(DICOM|MAESTRO)','^DICOM','DICOM',''],
['^Digifast','^Digifast','Digifast',''],
['^DIGITAL\s?FILM','DIGITAL\s?FILM','Digital Film',''],
['^Dikom','^Dikom','Dikom',''],
@@ -12752,6 +12905,7 @@ sub set_vendors {
# NOTE: ESA3... may be IBM PCIe SAD card/drives
['^(EXCELSTOR|r technology)','^EXCELSTOR( TECHNO(LOGY)?)?','ExcelStor',''],
['^EYOTA','^EYOTA','EYOTA',''],
+ ['^EZCOOL','^EZCOOL','EZCOOL',''],
['^EZLINK','^EZLINK','EZLINK',''],
['^Fantom','^Fantom( Drive[s]?)?','Fantom Drives',''],
['^Fanxiang','^Fanxiang','Fanxiang',''],
@@ -12766,6 +12920,7 @@ sub set_vendors {
['^(FOXLINE|FLD)','^FOXLINE','Foxline',''], # russian vendor?
['^(GALAX\b|Gamer\s?L)','^GALAX','GALAX',''],
['^Galaxy\b','^Galaxy','Galaxy',''],
+ ['^Gamer[_\s-]?Black','^Gamer[_\s-]?Black','Gamer Black',''],
['^(Garmin|Fenix|Nuvi|Zumo)','^Garmin','Garmin',''],
['^Geil','^Geil','Geil',''],
['^GelL','^GelL','GelL',''], # typo for Geil? GelL ZENITH R3 120GB
@@ -12780,6 +12935,8 @@ sub set_vendors {
['^GLOWY','^GLOWY','Glowy',''],
['^Goldendisk','^Goldendisk','Goldendisk',''],
['^Goldenfir','^Goldenfir','Goldenfir',''],
+ ['^Golden[\s_-]?Memory','^Golden[\s_-]?Memory','Golden Memory',''],
+ ['^(Goldkey|GKP)','^Goldkey','GoldKey',''],
# Wilk Elektronik SA, poland
['^(Wilk\s*)?(GOODRAM|GOODDRIVE|IR[\s-]?SSD|IRP|SSDPR)','^GOODRAM','GOODRAM',''],
# supertalent also has FM: |FM
@@ -12791,6 +12948,7 @@ sub set_vendors {
['^HDC','^HDC\b','HDC',''],
['^Hectron','^Hectron','Hectron',''],
['^HEMA','^HEMA','HEMA',''],
+ ['(HEORIADY|^HX-0)','^HEORIADY','HEORIADY',''],
['^(Hikvision|HKVSN|HS-SSD)','^Hikvision','Hikvision',''],
['^Hoodisk','^Hoodisk','Hoodisk',''],
['^HUAWEI','^HUAWEI','Huawei',''],
@@ -12801,6 +12959,7 @@ sub set_vendors {
['^IEI Tech','^IEI Tech(\.|nology)?( Corp(\.|oration)?)?','IEI Technology',''],
['^(IGEL|UD Pocket)','^IGEL','IGEL',''],
['^(Imation|Nano\s?Pro|HQT)','^Imation(\sImation)?','Imation',''], # Imation_ImationFlashDrive; TF20 is imation/tdk
+ ['^(IMC|Kanguru)','^IMC\b','IMC',''],
['^(Inateck|FE20)','^Inateck','Inateck',''],
['^(Inca\b|Npenterprise)','^Inca','Inca',''],
['^(Indilinx|IND-)','^Indilinx','Indilinx',''],
@@ -12812,6 +12971,7 @@ sub set_vendors {
['(Innostor|1f75)','(Innostor|1f75)','Innostor',''],
['(^Innovation|Innovation\s?IT)','Innovation(\s*IT)?','Innovation IT',''],
['^Innovera','^Innovera','Innovera',''],
+ ['^(I\.?norys|INO-?IH])','^I\.?norys','I.norys',''],
['^Intaiel','^Intaiel','Intaiel',''],
['^(INM|Integral|V\s?Series)','^Integral(\s?Memory)?','Integral Memory',''],
['^(lntenso|Intenso|(Alu|Basic|Business|Micro|c?Mobile|Premium|Rainbow|Slim|Speed|Twister|Ultra) Line|Rainbow)','^Intenso','Intenso',''],
@@ -12819,6 +12979,7 @@ sub set_vendors {
['^(Integrated[\s-]?Technology|IT[0-9]+)','^Integrated[\s-]?Technology','Integrated Technology',''],
['^(Iomega|ZIP\b|Clik!)','^Iomega','Iomega',''],
['^ISOCOM','^ISOCOM','ISOCOM (Shenzhen Longsys Electronics)',''],
+ ['^(Jaster|JS\d)','^Jaster','Jaster',''],
['^JingX','^JingX','JingX',''], #JingX 120G SSD - not confirmed, but guessing
['^Jingyi','^Jingyi','Jingyi',''],
# NOTE: ITY2 120GB hard to find
@@ -12828,11 +12989,11 @@ sub set_vendors {
['^Kingbank','^Kingbank','Kingbank',''],
['^Kingchux[\s-]?ing','^Kingchux[\s-]?ing','Kingchuxing',''],
['(KingDian|^NGF)','KingDian','KingDian',''],
- ['^Kingfast','^Kingfast','Kingfast',''],
+ ['^(Kingfast|TYFS)','^Kingfast','Kingfast',''],
['^KingMAX','^KingMAX','KingMAX',''],
['^Kingrich','^Kingrich','KingrSU04Gich',''],
['KING\s?SHA\s?RE','KING\s?SHA\s?RE','KingShare',''],
- ['^(KingSpec|ACSC|KS[DQ]|N[ET]-[0-9]|P4\b|PA18|T-(3260|64|128))','^KingSpec','KingSpec',''],
+ ['^(KingSpec|ACSC|KS[DQ]|N[ET]-[0-9]|P4\b|PA[_-]?(18|25)|T-(3260|64|128))','^KingSpec','KingSpec',''],
['^KingSSD','^KingSSD','KingSSD',''],
# kingwin docking, not actual drive
['^(EZD|EZ-Dock)','','Kingwin Docking Station',''],
@@ -12858,9 +13019,11 @@ sub set_vendors {
['(LITE[-\s]?ON|^PH[1-9])','LITE[-]?ON','LITE-ON',''], # PH6-CE240-L; CL1-3D256-Q11 NVMe LITEON 256GB
['^LONDISK','^LONDISK','LONDISK',''],
['^Longline','^Longline','Longline',''],
+ ['^LuminouTek','^LuminouTek','LuminouTek',''],
['^(LSI|MegaRAID)','^LSI\b','LSI',''],
['^(M-Systems|DiskOnKey)','^M-Systems','M-Systems',''],
['^(Mach\s*Xtreme|MXSSD|MXU|MX[\s-])','^Mach\s*Xtreme','Mach Xtreme',''],
+ ['^Mainic','^Mainic','Mainic',''],
['^Maximus','^Maximus','Maximus',''],
['^Maxone','^Maxone','Maxone',''],
['^(MAXTOR|Atlas|L(250|500)|TM[0-9]{4}|[KL]0[1-9]|Y[0-9]{3}[A-Z]|STM[0-9]|F[0-9]{3}L)','^MAXTOR','Maxtor',''], # note M2 M3 is usually maxtor, but can be samsung
@@ -12921,6 +13084,7 @@ sub set_vendors {
['^(PQI|Intelligent\s?Stick|Cool\s?Drive)','^PQI','PQI',''],
['^(Premiertek|QSSD|Quaroni)','^Premiertek','Premiertek',''],
['^(Pretec|UltimateGuard)','Pretec','Pretec',''],
+ ['^(Prolific)','^Prolific( Technolgy Inc\.)?','Prolific',''],
# PS3109S9 is the result of an error condition with ssd drive
['QEMU','^[0-9]*QEMU( QEMU)?','QEMU',''], # 0QUEMU QEMU HARDDISK
['(^Quantum|Fireball)','^Quantum','Quantum',''],
@@ -12957,13 +13121,15 @@ sub set_vendors {
['^Skill','^Skill','Skill',''],
['^(SMART( Storage Systems)?|TX)','^(SMART( Storage Systems)?)','Smart Storage Systems',''],
['^Sobetter','^Sobetter','Sobetter',''],
- ['^(S[FR]-|Sony)','^Sony','Sony',''],
+ ['^(S[FR]-|Sony|IM9)','^Sony','Sony',''],
['^(SSSTC|CL1-)','^SSSTC','SSSTC',''],
['^STE[CK]','^STE[CK]','sTec',''], # wd bought this one
['^STmagic','^STmagic','STmagic',''],
['^STORFLY','^STORFLY','StorFly',''],
['\dSUN\d','^SUN(\sMicrosystems)?','Sun Microsystems',''],
+ ['^Sundisk','^Sundisk','Sundisk',''],
['^SUNEAST','^SUNEAST','SunEast',''],
+ ['^Supersonic','^Supersonic','Supersonic',''],
['^SuperSSpeed','^SuperSSpeed','SuperSSpeed',''],
# NOTE: F[MNETU] not reliable, g.skill starts with FM too:
# Seagate ST skips STT.
@@ -12985,12 +13151,12 @@ sub set_vendors {
['^TEUTONS','^TEUTONS','TEUTONS',''],
['^THU','^THU','THU',''],
['^Tigo','^Tigo','Tigo',''],
- ['^Timetec','^Timetec','Timetec',''],
+ ['^(Timetec|35TT)','^Timetec','Timetec',''],
['^TKD','^TKD','TKD',''],
['^TopSunligt','^TopSunligt','TopSunligt',''], # is this a typo? hard to know
['^TopSunlight','^TopSunlight','TopSunlight',''],
['^TOROSUS','^TOROSUS','Torosus',''],
- ['^([F]?TS|Transcend|JetDrive|JetFlash|USDU|EZEX|1307)','^(Transcend|1307)','Transcend',''],
+ ['(^[F]?TS|Transcend|JetDrive|JetFlash|^USDU|^EZEX|^1307)','^(Transcend|1307)','Transcend',''],
['^(TrekStor|DS (maxi|pocket)|DataStation)','^TrekStor','TrekStor',''],
['^Turbox','^Turbox','Turbox',''],
['^(TwinMOS|TW[0-9])','^TwinMOS','TwinMOS',''],
@@ -13012,6 +13178,7 @@ sub set_vendors {
['^VMware','^VMware','VMware',''],
['^(Vseky|Vaseky)','^Vaseky','Vaseky',''], # ata-Vseky_V880_350G_
['^(Walgreen|Infinitive)','^Walgreen','Walgreen',''],
+ ['^Walram','^Walram','WALRAM',''],
['^Walton','^Walton','Walton',''],
['^(Wearable|Air-?Stash)','^Wearable','Wearable',''],
['^Wellcomm','^Wellcomm','Wellcomm',''],
@@ -13030,6 +13197,7 @@ sub set_vendors {
['^(YingChu|YGC)','^YingChu','YingChu',''],
['^(YUCUN|R880)','^YUCUN','YUCUN',''],
['^(ZALMAN|ZM\b)','^ZALMAN','Zalman',''],
+ ['^ZXIC','^ZXIC','ZXIC',''],
['^ZEUSLAP','^ZEUSLAP','ZEUSLAP',''],
['^(Zheino|CHN[0-9]|CNM)','^Zheino','Zheino',''],
['^(Zotac|ZTSSD)','^Zotac','Zotac',''],
@@ -13048,12 +13216,15 @@ sub device_vendor {
my ($vendor) = ('');
my (@data);
return if !$model;
- set_vendors() if !@vendors;
# 0 - match pattern; 1 - replace pattern; 2 - vendor print; 3 - serial pattern
# Data URLs: inxi-resources.txt Section: DriveItem device_vendor()
# $model = 'H10 HBRPEKNX0202A NVMe INTEL 512GB';
# $model = 'Patriot Memory';
- foreach my $row (@vendors){
+ if (!$vendors){
+ $vendors = [];
+ set_vendors($vendors);
+ }
+ foreach my $row (@$vendors){
if ($model =~ /$row->[0]/i || ($row->[3] && $serial && $serial =~ /$row->[3]/)){
$vendor = $row->[2];
# Usually we want to assign N/A at output phase, maybe do this logic there?
@@ -13284,8 +13455,7 @@ sub device_speed {
## GraphicItem
{
package GraphicItem;
-my $driver = ''; # we need this as a fallback in case no xorg log found
-my %graphics;
+my ($b_wayland_data,%graphics,$monitor_ids,$monitor_map);
sub get {
eval $start if $b_log;
my (@rows);
@@ -13312,16 +13482,19 @@ sub get {
# note: not perfect, but we need usb gfx to show for all types, soc, pci, etc
push(@rows,usb_output());
push(@rows,display_output());
- push(@rows,gl_output());
+ push(@rows,interface_output());
+ (%graphics,$monitor_ids,$monitor_map) = ();
eval $end if $b_log;
return @rows;
}
+## DEVICE OUTPUT ##
sub device_output {
eval $start if $b_log;
return if !$devices{'graphics'};
my (@rows);
my ($j,$num) = (0,1);
+ set_monitors_sys() if !$monitor_ids && -e '/sys/class/drm';
foreach my $row (@{$devices{'graphics'}}){
$num = 1;
# print "$row->[0] $row->[3]\n";
@@ -13333,8 +13506,7 @@ sub device_output {
next if $row->[3] != 0;
# print "$row->[0] $row->[3]\n";
$j = scalar @rows;
- $driver = $row->[9];
- $driver ||= 'N/A';
+ push(@{$graphics{'gpu-drivers'}},$row->[9]) if $row->[9];
my $device = main::trimmer($row->[4]);
$device = ($device) ? main::clean_pci($device,'output') : 'N/A';
# have seen absurdly verbose card descriptions, with non related data etc
@@ -13348,6 +13520,7 @@ sub device_output {
my $item = main::get_pci_vendor($row->[4],$row->[12]);
$rows[$j]->{main::key($num++,0,2,'vendor')} = $item if $item;
}
+ my $driver = ($row->[9]) ? $row->[9]:'N/A';
$rows[$j]->{main::key($num++,1,2,'driver')} = $driver;
if ($row->[9] && !$bsd_type){
my $version = main::get_module_version($row->[9]);
@@ -13359,7 +13532,14 @@ sub device_output {
$rows[$j]->{main::key($num++,0,3,'alternate')} = $row->[10] if $row->[10];
}
if ($extra > 0){
- $rows[$j]->{main::key($num++,0,2,'bus-ID')} = (!$row->[2] && !$row->[3]) ? 'N/A' : "$row->[2].$row->[3]";
+ my $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');
+ }
+ if ($extra > 1 && $monitor_ids){
+ port_output($bus_id,$j,\@rows,\$num);
+ }
+ $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id;
}
if ($extra > 1){
my $chip_id = main::get_chip_id($row->[5],$row->[6]);
@@ -13403,7 +13583,11 @@ sub usb_output {
main::key($num++,0,2,'driver') => $driver,
},);
if ($extra > 0){
- $rows[$j]->{main::key($num++,0,2,'bus-ID')} = "$path_id:$row->[1]";
+ my $bus_id = "$path_id:$row->[1]";
+ if ($extra > 1 && $monitor_ids){
+ port_output($bus_id,$j,\@rows,\$num);
+ }
+ $rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id;
}
if ($extra > 1){
$row->[7] ||= 'N/A';
@@ -13419,53 +13603,94 @@ sub usb_output {
eval $end if $b_log;
return @rows;
}
+# $rows, $num by ref
+sub port_output {
+ my ($bus_id,$j,$rows,$num) = @_;
+ my (@connected,@disabled,@empty);
+ foreach my $id (keys %$monitor_ids){
+ next if !$monitor_ids->{$id}{'status'};
+ if ($monitor_ids->{$id}{'path'} =~ m|\Q$bus_id/drm/\E|){
+ # status can be: connected|disconnected|unknown
+ if ($monitor_ids->{$id}{'status'} eq 'connected'){
+ if ($monitor_ids->{$id}{'enabled'} eq 'enabled'){
+ push(@connected,$id);
+ }
+ else {
+ push(@disabled,$id);
+ }
+ }
+ else {
+ push(@empty,$id);
+ }
+ }
+ }
+ if (@connected || @empty || @disabled){
+ my ($off,$active,$unused);
+ my $split = ','; # add space if many to allow for wrapping
+ $$rows[$j]->{main::key($$num++,1,2,'ports')} = '';
+ $split = ', ' if scalar @connected > 3;
+ $active = (@connected) ? join($split,sort @connected) : 'none';
+ $$rows[$j]->{main::key($$num++,0,3,'active')} = $active;
+ if (@disabled){
+ $split = (scalar @disabled > 3) ? ', ' : ',';
+ $off = join($split,sort @disabled);
+ $$rows[$j]->{main::key($$num++,0,3,'off')} = $off;
+ }
+ $split = (scalar @empty > 3) ? ', ' : ',';
+ $unused = (@empty) ? join($split,sort @empty) : 'none';
+ $$rows[$j]->{main::key($$num++,0,3,'empty')} = $unused;
+ }
+}
+
+## DISPLAY OUTPUT ##
sub display_output(){
eval $start if $b_log;
my (@row);
- my ($num,$protocol) = (0,'');
+ my ($num,$j) = (0,0);
# note: these may not always be set, they won't be out of X, for example
- $protocol = get_protocol();
+ display_protocol();
+ $graphics{'protocol'} = 'wayland' if $force{'wayland'};
+ # get rid of all inactive or disabled monitor port ids
+ set_active_monitors() if $monitor_ids;
# note, since the compositor is the server with wayland, always show it
- if ($extra > 1 || $protocol eq 'wayland'){
- set_compositor($protocol);
+ if ($extra > 1 || $graphics{'protocol'} eq 'wayland'){
+ set_compositor_data();
}
if ($b_display){
- display_data_x();
- # currently barebones, wayland needs a lot more work
- if ($protocol && $protocol eq 'wayland' && !$graphics{'screens'}){
+ # Add compositors as data sources found
+ if ($graphics{'protocol'} eq 'wayland'){
display_data_wayland();
- # it worked! we got screen data
- $graphics{'no-xdpyinfo'} = undef if $graphics{'screens'};
+ }
+ if (!$b_wayland_data){
+ display_data_x() if !$force{'wayland'};
}
}
else {
$graphics{'tty'} = tty_data();
}
- # this gives better output than the failure last case, which would only show:
- # for example: X.org: 1.9 instead of: X.org: 1.9.0
- $graphics{'x-version'} = $graphics{'xorg-version'} if $graphics{'xorg-version'};;
- $graphics{'x-version'} = x_version() if !$graphics{'x-version'};
- $graphics{'x-version'} = $graphics{'x-version-id'} if !$graphics{'x-version'};
+ # no xdpyinfo installed
+ # undef $graphics{'x-server'};
+ if (!$graphics{'x-server'} || !$graphics{'x-server'}->[0][1] ||
+ !$b_display || $graphics{'protocol'} eq 'wayland'){
+ # fallback, will complete x-server/x-version, set flags, if found
+ display_server_data();
+ }
+ if (!defined $graphics{'display-id'} && defined $ENV{'DISPLAY'}){
+ $graphics{'display-id'} = $ENV{'DISPLAY'};
+ }
+ # print Data::Dumper::Dumper $graphics{'x-server'};
# print Data::Dumper::Dumper \%graphics;
if (%graphics){
- my ($driver_missing,$resolution,$server_string) = ('','','');
- # print "$graphics{'x-vendor'} $graphics{'x-version'} $graphics{'x-vendor-release'}","\n";
- if ($graphics{'x-vendor'}){
- my $version = ($graphics{'x-version'}) ? " $graphics{'x-version'}" : '';
- # $version = (!$version && $graphics{'x-vendor-release'}) ? " $graphics{'x-vendor-release'}" : '';
- $server_string = "$graphics{'x-vendor'}$version";
+ my ($driver_note,$resolution,$server_string) = ('','','');
+ my ($b_screen_monitors,$x_drivers);
+ $x_drivers = display_drivers_x() if !$force{'wayland'};
+ # print "$graphics{'x-server'} $graphics{'x-version'} $graphics{'x-vendor-release'}","\n";
+ if ($graphics{'x-server'}){
+ $server_string = $graphics{'x-server'}->[0][0];
# print "$server_string\n";
}
- elsif ($graphics{'x-version'}){
- if ($graphics{'x-version'} =~ /^Xvesa/){
- $server_string = $graphics{'x-version'};
- }
- else {
- $server_string = "X.org $graphics{'x-version'}";
- }
- }
- my @drivers = x_drivers();
- if (!$protocol && !$server_string && !$graphics{'x-vendor'} && !@drivers){
+ if (!$graphics{'protocol'} && !$server_string && !$graphics{'x-server'} &&
+ !$x_drivers){
$server_string = main::message('display-server');
@row = ({
main::key($num++,1,1,'Display') => '',
@@ -13475,55 +13700,99 @@ sub display_output(){
else {
$server_string ||= 'N/A';
@row = ({
- main::key($num++,1,1,'Display') => $protocol,
- main::key($num++,0,2,'server') => $server_string,
+ main::key($num++,1,1,'Display') => $graphics{'protocol'},
+ main::key($num++,1,2,'server') => $server_string,
});
- if ($graphics{'compositor'}){
- $row[0]->{main::key($num++,0,2,'compositor')} = $graphics{'compositor'};
- if ($graphics{'compositor-version'}){
- $row[0]->{main::key($num++,0,3,'v')} = $graphics{'compositor-version'};
+ if ($graphics{'x-server'} && $graphics{'x-server'}->[0][1]){
+ $row[0]->{main::key($num++,0,3,'v')} = $graphics{'x-server'}->[0][1];
+ }
+ if ($graphics{'x-server'} && $graphics{'x-server'}->[1][0]){
+ $row[0]->{main::key($num++,1,3,'with')} = $graphics{'x-server'}->[1][0];
+ if ($graphics{'x-server'}->[1][1]){
+ $row[0]->{main::key($num++,0,4,'v')} = $graphics{'x-server'}->[1][1];
+ }
+ }
+ if ($graphics{'compositors'}){
+ if (scalar @{$graphics{'compositors'}} == 1){
+ $row[0]->{main::key($num++,1,2,'compositor')} = $graphics{'compositors'}->[0][0];
+ if ($graphics{'compositors'}->[0][1]){
+ $row[0]->{main::key($num++,0,3,'v')} = $graphics{'compositors'}->[0][1];
+ }
+ }
+ else {
+ my $i =1;
+ $row[0]->{main::key($num++,1,2,'compositors')} = '';
+ foreach (@{$graphics{'compositors'}}){
+ $row[0]->{main::key($num++,1,3,$i)} = $_->[0];
+ if ($_->[1]){
+ $row[0]->{main::key($num++,0,4,'v')} = $_->[1];
+ }
+ $i++;
+ }
}
}
# note: if no xorg log, and if wayland, there will be no xorg drivers,
# obviously, so we use the last driver found on the card section in that case.
# those come from lscpi kernel drivers so there should be no xorg/wayland issues.
- if (!$drivers[0]){
+ if (!$x_drivers || !$x_drivers->[0]){
# Fallback: specific case: in Arch/Manjaro gdm run systems, their Xorg.0.log is
# located inside this directory, which is not readable unless you are root
# Normally Arch gdm log is here: ~/.local/share/xorg/Xorg.1.log
# $driver comes from the Device lines, and is just last fallback.
- if ($driver && $driver ne 'N/A'){
- if (-e '/var/lib/gdm' && !$b_root){
- $driver_missing = main::message('display-driver-na') . ' - ' . main::message('root-suggested');
+ if (!$graphics{'protocol'} || $graphics{'protocol'} ne 'wayland'){
+ if ($graphics{'gpu-drivers'}){
+ if (-e '/var/lib/gdm' && !$b_root){
+ $driver_note = main::message('display-driver-na');
+ $driver_note .= ' - ' . main::message('root-suggested');
+ }
+ else {
+ $driver_note = main::message('display-driver-na');
+ }
}
- else {
- $driver_missing = main::message('display-driver-na');
+ elsif (-e '/var/lib/gdm' && !$b_root) {
+ $driver_note = main::message('root-suggested');
}
}
- else {
- $driver_missing = main::message('root-suggested') if -e '/var/lib/gdm' && !$b_root;
- }
- }
- else {
- $driver = $drivers[0];
}
- $row[0]->{main::key($num++,1,2,'driver')} = '';
- $driver ||= 'N/A';
- $row[0]->{main::key($num++,1,3,'loaded')} = $driver;
- if ($driver_missing){
- $row[0]->{main::key($num++,0,4,'note')} = $driver_missing;
- }
- if ($drivers[1]){
- $row[0]->{main::key($num++,0,3,'unloaded')} = $drivers[1];
- }
- if ($drivers[2]){
- $row[0]->{main::key($num++,0,3,'failed')} = $drivers[2];
+ # if xvesa, will always have display-driver set
+ if ($graphics{'xvesa'} && $graphics{'display-driver'}){
+ $row[0]->{main::key($num++,1,2,'driver')} = join(',',@{$graphics{'display-driver'}});;
}
- if ($extra > 1 && $drivers[3]){
- $row[0]->{main::key($num++,0,3,'alternate')} = $drivers[3];
+ else {
+ $row[0]->{main::key($num++,1,2,'driver')} = '';
+ # The only wayland setups with x drivers have xorg, transitional that is.
+ if ($x_drivers){
+ $row[0]->{main::key($num++,1,3,'X')} = '';
+ my $driver = ($x_drivers->[0]) ? $x_drivers->[0] : 'N/A';
+ $row[0]->{main::key($num++,1,4,'loaded')} = $driver;
+ if ($x_drivers->[1]){
+ $row[0]->{main::key($num++,0,4,'unloaded')} = $x_drivers->[1];
+ }
+ if ($x_drivers->[2]){
+ $row[0]->{main::key($num++,0,4,'failed')} = $x_drivers->[2];
+ }
+ if ($extra > 1 && $x_drivers->[3]){
+ $row[0]->{main::key($num++,0,4,'alternate')} = $x_drivers->[3];
+ }
+ }
+ my $gpu_drivers = gpu_drivers_sys('all');
+ my $drivers;
+ if ($gpu_drivers ){
+ $drivers = join(',',@{$gpu_drivers});
+ }
+ else {
+ $drivers = ($graphics{'gpu-drivers'}) ? join(',',@{$graphics{'gpu-drivers'}}): 'N/A';
+ }
+ $row[0]->{main::key($num++,1,3,'gpu')} = $drivers;
+ if ($driver_note){
+ $row[0]->{main::key($num++,0,4,'note')} = $driver_note;
+ }
}
}
- if ($b_admin){
+ if (!$show{'graphic-basic'} && $extra > 1 && $graphics{'display-rect'}){
+ $row[0]->{main::key($num++,0,2,'d-rect')} = $graphics{'display-rect'};
+ }
+ if (!$show{'graphic-basic'} && $extra > 1){
if (defined $graphics{'display-id'}){
$row[0]->{main::key($num++,0,2,'display-ID')} = $graphics{'display-id'};
}
@@ -13535,504 +13804,1234 @@ sub display_output(){
$row[0]->{main::key($num++,0,2,'default screen')} = $graphics{'display-default-screen'};
}
}
- if ($graphics{'no-xdpyinfo'}){
- $row[0]->{main::key($num++,0,2,'resolution')} = $graphics{'no-xdpyinfo'};
+ if ($graphics{'no-screens'}){
+ my $res = (!$show{'graphic-basic'} && $extra > 1 && !$graphics{'xvesa'}) ? 'note' : 'resolution';
+ $row[0]->{main::key($num++,0,2,$res)} = $graphics{'no-screens'};
}
elsif ($graphics{'screens'}){
my ($diag,$dpi,$hz,$size);
- my ($m_count,$basic_count,$row_key,$screen_count) = (0,0,0,0);
+ my ($m_count,$basic_count,$screen_count) = (0,0,0);
my $s_count = ($graphics{'screens'}) ? scalar @{$graphics{'screens'}}: 0;
foreach my $main (@{$graphics{'screens'}}){
- $m_count = scalar @{$main->{'monitors'}} if $main->{'monitors'};
+ $m_count = scalar keys %{$main->{'monitors'}} if $main->{'monitors'};
$screen_count++;
- ($diag,$dpi,$hz,$resolution,$size) = (undef);
- $row_key++ if !$show{'graphic-basic'};
+ ($diag,$dpi,$hz,$resolution,$size) = ();
+ $j++ if !$show{'graphic-basic'};
if (!$show{'graphic-basic'} || $m_count == 0){
if (!$show{'graphic-basic'} && defined $main->{'screen'}){
- $row[$row_key]->{main::key($num++,1,2,'Screen')} = $main->{'screen'};
+ $row[$j]->{main::key($num++,1,2,'Screen')} = $main->{'screen'};
+ }
+ if ($main->{'res-x'} && $main->{'res-y'}){
+ $resolution = $main->{'res-x'} . 'x' . $main->{'res-y'};
+ $resolution .= '~' . $main->{'hz'} . 'Hz' if $show{'graphic-basic'};
}
- $resolution = $main->{'res-x'} . 'x' . $main->{'res-y'} if $main->{'res-x'} && $main->{'res-y'};
- $resolution .= '~' . $main->{'hz'} . 'Hz' if $show{'graphic-basic'} && $main->{'hz'} && $resolution;
$resolution ||= 'N/A';
if ($s_count == 1 || !$show{'graphic-basic'}){
- $row[$row_key]->{main::key($num++,0,3,'s-res')} = $resolution;
+ $row[$j]->{main::key($num++,0,3,'s-res')} = $resolution;
}
elsif ($show{'graphic-basic'}){
- $row[$row_key]->{main::key($num++,0,3,'s-res')} = '' if $screen_count == 1;
- $row[$row_key]->{main::key($num++,0,3,$screen_count)} = $resolution;
+ $row[$j]->{main::key($num++,0,3,'s-res')} = '' if $screen_count == 1;
+ $row[$j]->{main::key($num++,0,3,$screen_count)} = $resolution;
}
- $resolution = '';
- if ($main->{'s-dpi'} && (!$show{'graphic-basic'} || $extra > 1)){
- $row[$row_key]->{main::key($num++,0,3,'s-dpi')} = $main->{'s-dpi'};
+ if ($main->{'s-dpi'} && (!$show{'graphic-basic'} && $extra > 1)){
+ $row[$j]->{main::key($num++,0,3,'s-dpi')} = $main->{'s-dpi'};
}
- if (!$show{'graphic-basic'}){
- if ($main->{'size-x'} && $main->{'size-y'}){
- $size = $main->{'size-x'} . 'x' . $main->{'size-y'} .
- 'mm ('. $main->{'size-x-i'} . 'x' . $main->{'size-y-i'} . '")';
+ if (!$show{'graphic-basic'} && $extra > 2){
+ if ($main->{'size-missing'}){
+ $row[$j]->{main::key($num++,0,3,'s-size')} = $main->{'size-missing'};
}
- $size ||= '';
- $row[$row_key]->{main::key($num++,0,3,'s-size')} = $size if $size;
- if ($main->{'diagonal'}){
- $diag = $main->{'diagonal-m'} . 'mm ('. $main->{'diagonal'} . '")';
+ else {
+ if ($main->{'size-x'} && $main->{'size-y'}){
+ $size = $main->{'size-x'} . 'x' . $main->{'size-y'} .
+ 'mm ('. $main->{'size-x-i'} . 'x' . $main->{'size-y-i'} . '")';
+ $row[$j]->{main::key($num++,0,3,'s-size')} = $size;
+ }
+ if ($main->{'diagonal'}){
+ $diag = $main->{'diagonal-m'} . 'mm ('. $main->{'diagonal'} . '")';
+ $row[$j]->{main::key($num++,0,3,'s-diag')} = $diag;
+ }
}
- $diag ||= '';
- $row[$row_key]->{main::key($num++,0,3,'s-diag')} = $diag if $diag;
}
}
if ($main->{'monitors'}){
# print $basic_count . '::' . $m_count, "\n";
- foreach my $monitor (@{$main->{'monitors'}}){
- ($diag,$dpi,$hz,$resolution,$size) = (undef);
- if ($show{'graphic-basic'}){
- $basic_count++;
- if ($monitor->{'res-x'} && $monitor->{'res-y'}){
- $resolution = $monitor->{'res-x'} . 'x' . $monitor->{'res-y'};
- }
- # using main, noit monitor, dpi because we want xorg dpi, not physical screen dpi
- $dpi = $main->{'s-dpi'} if $resolution && $extra > 1 && $main->{'s-dpi'};
- $resolution .= '~' . $monitor->{'hz'} . 'Hz' if $monitor->{'hz'} && $resolution;
- $resolution ||= 'N/A';
- if ($basic_count == 1 && $m_count == 1){
- $row[$row_key]->{main::key($num++,0,2,'resolution')} = $resolution;
- }
- else {
- $row[$row_key]->{main::key($num++,1,2,'resolution')} = '' if $basic_count == 1;
- $row[$row_key]->{main::key($num++,0,3,$basic_count)} = $resolution;
- }
- if ($m_count == $basic_count){
- $row[$row_key]->{main::key($num++,0,2,'s-dpi')} = $dpi if $dpi;
- }
- next;
- }
- $row_key++;
- $row[$row_key]->{main::key($num++,0,3,'Monitor')} = $monitor->{'monitor'};
- if ($monitor->{'res-x'} && $monitor->{'res-y'}){
- $resolution = $monitor->{'res-x'} . 'x' . $monitor->{'res-y'};
- }
- $resolution ||= 'N/A';
- $row[$row_key]->{main::key($num++,0,4,'res')} = $resolution;
- $hz = ($monitor->{'hz'}) ? $monitor->{'hz'} : '';
- $row[$row_key]->{main::key($num++,0,4,'hz')} = $hz if $hz;
- $dpi = ($monitor->{'dpi'}) ? $monitor->{'dpi'} : '';
- $row[$row_key]->{main::key($num++,0,4,'dpi')} = $dpi if $dpi;
- # print "$dpi :: $main->{'s-dpi'}\n";
- if ($monitor->{'size-x'} && $monitor->{'size-y'}){
- $size = $monitor->{'size-x'} . 'x' . $monitor->{'size-y'} .
- 'mm ('. $monitor->{'size-x-i'} . 'x' . $monitor->{'size-y-i'} . '")';
- }
- $size ||= '';
- $row[$row_key]->{main::key($num++,0,4,'size')} = $size if $size;
- if ($monitor->{'diagonal'}){
- $diag = $monitor->{'diagonal-m'} . 'mm ('. $monitor->{'diagonal'} . '")';
- }
- $diag ||= '';
- $row[$row_key]->{main::key($num++,0,4,'diag')} = $diag if $diag;
+ $b_screen_monitors = 1;
+ if ($show{'graphic-basic'}){
+ monitors_output_basic('screen',$main->{'monitors'},
+ $main->{'s-dpi'},$j,\@row,\$num);
}
+ else {
+ monitors_output_full('screen',$main->{'monitors'},
+ $j,\@row,\$num);
+ }
+ }
+ elsif (!$show{'graphic-basic'} && $graphics{'no-monitors'}){
+ $row[$j]->{main::key($num++,0,4,'monitors')} = $graphics{'no-monitors'};
}
}
}
- else {
+ elsif (!$b_display){
$graphics{'tty'} ||= 'N/A';
$row[0]->{main::key($num++,0,2,'tty')} = $graphics{'tty'};
}
+ # fallback, if no xrandr/xdpyinfo, if wayland, if console. Note we've
+ # deleted each key used in advanced_monitor_data() so those won't show again
+ if (!$b_screen_monitors && $monitor_ids && %$monitor_ids){
+ if ($show{'graphic-basic'}){
+ monitors_output_basic('monitor',$monitor_ids,'',$j,\@row,\$num);
+ }
+ else {
+ monitors_output_full('monitor',$monitor_ids,$j,\@row,\$num);
+ }
+ }
}
eval $end if $b_log;
return @row;
}
+sub monitors_output_basic {
+ eval $start if $b_log;
+ my ($type,$monitors,$s_dpi,$j,$row,$num) = @_;
+ my ($dpi,$resolution);
+ my ($basic_count,$m_count) = (0,scalar keys %{$monitors});
+ foreach my $key (sort keys %{$monitors}){
+ if ($type eq 'monitor' && (!$monitors->{$key}{'res-x'} ||
+ !$monitors->{$key}{'res-y'})){
+ next;
+ }
+ ($dpi,$resolution) = ();
+ $basic_count++;
+ if ($monitors->{$key}{'res-x'} && $monitors->{$key}{'res-y'}){
+ $resolution = $monitors->{$key}{'res-x'} . 'x' . $monitors->{$key}{'res-y'};
+ }
+ # using main, not monitor, dpi because we want xorg dpi, not physical screen dpi
+ $dpi = $s_dpi if $resolution && $extra > 1 && $s_dpi;
+ if ($monitors->{$key}{'hz'} && $resolution){
+ $resolution .= '~' . $monitors->{$key}{'hz'} . 'Hz';
+ }
+ $resolution ||= 'N/A';
+ if ($basic_count == 1 && $m_count == 1){
+ $row->[$j]{main::key($$num++,0,2,'resolution')} = $resolution;
+ }
+ else {
+ if ($basic_count == 1){
+ $row->[$j]{main::key($$num++,1,2,'resolution')} = '';
+ }
+ $row->[$j]{main::key($$num++,0,3,$basic_count)} = $resolution;
+ }
+ if (!$show{'graphic-basic'} && $m_count == $basic_count && $dpi){
+ $row->[$j]{main::key($$num++,0,2,'s-dpi')} = $dpi;
+ }
+ }
+ eval $end if $b_log;
+}
+# row, num passed by ref
+sub monitors_output_full {
+ eval $start if $b_log;
+ my ($type,$monitors,$j,$row,$num) = @_;
+ my ($b_no_size,$resolution);
+ my ($m1,$m2,$m3) = ($type eq 'screen') ? (3,4,5) : (2,3,4);
+ foreach my $key (sort keys %{$monitors}){
+ $j++;
+ $$row[$j]->{main::key($$num++,1,$m1,'Monitor')} = $monitors->{$key}{'monitor'};
+ if ($monitors->{$key}{'monitor-mapped'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'mapped')} = $monitors->{$key}{'monitor-mapped'};
+ }
+ if ($monitors->{$key}{'position'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'pos')} = $monitors->{$key}{'position'};
+ }
+ if ($monitors->{$key}{'model'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'model')} = $monitors->{$key}{'model'};
+ }
+ if ($extra > 2 && $monitors->{$key}{'serial'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'serial')} = main::filter($monitors->{$key}{'serial'});
+ }
+ if ($b_admin && $monitors->{$key}{'build-date'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'built')} = $monitors->{$key}{'build-date'};
+ }
+ if ($monitors->{$key}{'res-x'} || $monitors->{$key}{'res-y'} ||
+ $monitors->{$key}{'hz'} || $monitors->{$key}{'size-x'} ||
+ $monitors->{$key}{'size-y'}){
+ if ($monitors->{$key}{'res-x'} && $monitors->{$key}{'res-y'}){
+ $resolution = $monitors->{$key}{'res-x'} . 'x' . $monitors->{$key}{'res-y'};
+ }
+ $resolution ||= 'N/A';
+ $$row[$j]->{main::key($$num++,0,$m2,'res')} = $resolution;
+ }
+ else {
+ if ($b_display){
+ $resolution = main::message('monitor-na');
+ }
+ else {
+ $resolution = main::message('monitor-console');
+ }
+ $b_no_size = 1;
+ $$row[$j]->{main::key($$num++,0,$m2,'size-res')} = $resolution;
+ }
+ if ($extra > 2 && $monitors->{$key}{'hz'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'hz')} = $monitors->{$key}{'hz'};
+ }
+ if ($monitors->{$key}{'dpi'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'dpi')} = $monitors->{$key}{'dpi'};
+ }
+ if ($b_admin && $monitors->{$key}{'gamma'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'gamma')} = $monitors->{$key}{'gamma'};
+ }
+ if ($extra > 2 && $monitors->{$key}{'scale'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'scale')} = $monitors->{$key}{'scale'};
+ }
+ if ($extra > 2 && $monitors->{$key}{'size-x'} && $monitors->{$key}{'size-y'}){
+ my $size = $monitors->{$key}{'size-x'} . 'x' . $monitors->{$key}{'size-y'} .
+ 'mm ('. $monitors->{$key}{'size-x-i'} . 'x' . $monitors->{$key}{'size-y-i'} . '")';
+ $$row[$j]->{main::key($$num++,0,$m2,'size')} = $size;
+ }
+ if ($monitors->{$key}{'diagonal'}){
+ my $diag = $monitors->{$key}{'diagonal-m'} . 'mm ('. $monitors->{$key}{'diagonal'} . '")';
+ $$row[$j]->{main::key($$num++,0,$m2,'diag')} = $diag;
+ }
+ elsif ($b_display && !$b_no_size && !$monitors->{$key}{'size-x'} &&
+ !$monitors->{$key}{'size-y'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'size')} = main::message('monitor-na');;
+ }
+ if ($b_admin && $monitors->{$key}{'ratio'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'ratio')} = $monitors->{$key}{'ratio'};
+ }
+ if ($extra > 2){
+ if ($monitors->{$key}{'modes-min-max'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'modes')} = $monitors->{$key}{'modes-min-max'};
+ }
+ elsif ($monitors->{$key}{'modes-min'} && $monitors->{$key}{'modes-max'}){
+ $$row[$j]->{main::key($$num++,1,$m2,'modes')} = '';
+ $$row[$j]->{main::key($$num++,0,$m3,'max')} = $monitors->{$key}{'modes-max'};
+ $$row[$j]->{main::key($$num++,0,$m3,'min')} = $monitors->{$key}{'modes-min'};
+ }
+ }
+ }
+ # we only want to see gpu drivers for wayland since otherwise it's x drivers.
+# if ($b_display && $b_admin && $graphics{'protocol'} &&
+# $graphics{'protocol'} eq 'wayland' && $monitors->{$key}{'drivers'}){
+# $driver = join(',',@{$monitors->{$key}{'drivers'}});
+# $$row[$j]->{main::key($$num++,0,$m2,'driver')} = $driver;
+# }
+ eval $end if $b_log;
+}
-sub display_data_x {
+## INTERFACE OUTPUT ##
+# as soon as EGL for Wayland appears add it!
+sub interface_output {
eval $start if $b_log;
- # X vendor and version detection.
- # new method added since radeon and X.org and the disappearance of
- # <X server name> version : ...etc. Later on, the normal textual version string
- # returned, e.g. like: X.Org version: 6.8.2
- # A failover mechanism is in place: if $version empty, release number parsed instead
- if (my $program = main::check_program('xdpyinfo')){
- my ($diagonal,$diagonal_m,$dpi) = ('','','');
- my ($screen_id,$screen,@working);
- my ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i);
- my @xdpyinfo = main::grabber("$program $display_opt 2>/dev/null","\n",'strip');
- # @xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo;
- # print join("\n",@xdpyinfo), "\n";
- foreach (@xdpyinfo){
- @working = split(/:\s+/, $_);
- next if (($graphics{'screens'} && $working[0] !~ /^(dimensions$|screen\s#)/) || !$working[0]);
- # print "$_\n";
- if ($working[0] eq 'vendor string'){
- $working[1] =~ s/The\s|\sFoundation//g;
- # some distros, like fedora, report themselves as the xorg vendor,
- # so quick check here to make sure the vendor string includes Xorg in string
- if ($working[1] !~ /x/i){
- $working[1] .= ' X.org';
- }
- $graphics{'x-vendor'} = $working[1];
- }
- elsif ($working[0] eq 'name of display'){
- $graphics{'display-id'} = $working[1];
- }
- elsif ($working[0] eq 'version number'){
- $graphics{'x-version-id'} = $working[1];
- }
- # note used, fix that
- elsif ($working[0] eq 'vendor release number'){
- $graphics{'x-vendor-release'} = $working[1];
- }
- elsif ($working[0] eq 'X.Org version'){
- $graphics{'xorg-version'} = $working[1];
- }
- elsif ($working[0] eq 'default screen number'){
- $graphics{'display-default-screen'} = $working[1];
- }
- elsif ($working[0] eq 'number of screens'){
- $graphics{'display-screens'} = $working[1];
- }
- elsif ($working[0] =~ /^screen #([0-9]+):/){
- $screen_id = $1;
- $graphics{'screens'} = () if !$graphics{'screens'};
- }
- elsif ($working[0] eq 'resolution'){
- $working[1] =~ s/^([0-9]+)x/$1/;
- $graphics{'s-dpi'} = $working[1];
- }
- elsif ($working[0] eq 'dimensions'){
- ($dpi,$res_x,$res_y,$size_x,$size_y) = (undef,undef,undef,undef,undef);
- if ($working[1] =~ /([0-9]+)\s*x\s*([0-9]+)\s+pixels\s+\(([0-9]+)\s*x\s*([0-9]+)\s*millimeters\)/){
- $res_x = $1;
- $res_y = $2;
- $size_x = $3;
- $size_y = $4;
- $res_x_i = ($1) ? sprintf("%.1f", ($1/25.4)) : 0;
- $res_y_i = ($2) ? sprintf("%.1f", ($2/25.4)) : 0;
- $size_x_i = ($3) ? sprintf("%.1f", ($3/25.4)) : 0;
- $size_y_i = ($4) ? sprintf("%.1f", ($4/25.4)) : 0;
- $dpi = ($res_x && $size_x) ? sprintf("%.0f", ($res_x*25.4/$size_x)) : '';
- $diagonal = ($res_x && $size_x) ? sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4)) : '';
- $diagonal += 0 if $diagonal;# trick to get rid of decimal 0
- $diagonal_m = ($res_x && $size_x) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
- }
- $screen = {
- 'screen' => $screen_id,
- 'res-x' => $res_x,
- 'res-x-i' => $res_x_i,
- 'res-y' => $res_y,
- 'res-y-i' => $res_y_i,
- 'size-x' => $size_x,
- 'size-x-i' => $size_x_i,
- 'size-y' => $size_y,
- 'size-y-i' => $size_y_i,
- 's-dpi' => $dpi,
- 'diagonal' => $diagonal,
- 'diagonal-m' => $diagonal_m,
- };
- push(@{$graphics{'screens'}}, $screen);
- }
- }
- # print Data::Dumper::Dumper $graphics{'screens'};
- if (my $program = main::check_program('xrandr')){
- ($diagonal,$diagonal_m,$dpi) = (undef);
- ($screen_id,$screen,@working) = (undef);
- ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i) = (undef);
- my (@monitors,$monitor_id,$screen,$screen_id,@xrandr_screens);
- my @xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip');
- # $graphics{'dimensions'} = (\@dimensions);
- # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
- # multiple screens from different video cards
- foreach (@xrandr){
- if (/^Screen ([0-9]+):/){
- $screen_id = $1;
- push(@xrandr_screens, \@monitors) if @monitors;
- @monitors = ();
- }
- if (/^([^\s]+)\s+connected\s(primary\s)?([0-9]+)\s*x\s*([0-9]+)\+[0-9+]+(\s\([^)]+\))?(\s([0-9]+)mm\sx\s([0-9]+)mm)?/){
- $monitor_id = $1;
- $res_x = $3;
- $res_y = $4;
- $size_x = $7;
- $size_y = $8;
- $res_x_i = ($3) ? sprintf("%.1f", ($3/25.4)) : 0;
- $res_y_i = ($4) ? sprintf("%.1f", ($4/25.4)) : 0;
- $size_x_i = ($7) ? sprintf("%.1f", ($7/25.4)) : 0;
- $size_y_i = ($8) ? sprintf("%.1f", ($8/25.4)) : 0;
- $dpi = ($res_x && $size_x) ? sprintf("%.0f", $res_x * 25.4 / $size_x) : '';
- $diagonal = ($res_x && $size_x) ? sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4)) : '';
- $diagonal += 0 if $diagonal; # trick to get rid of decimal 0
- $diagonal_m = ($res_x && $size_x) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
- push(@monitors, {
- 'screen' => $screen_id,
- 'monitor' => $monitor_id,
- 'res-x' => $res_x,
- 'res-x-i' => $res_x_i,
- 'res-y' => $res_y,
- 'res-y-i' => $res_y_i,
- 'size-x' => $size_x,
- 'size-x-i' => $size_x_i,
- 'size-y' => $size_y,
- 'size-y-i' => $size_y_i,
- 'dpi' => $dpi,
- 'diagonal' => $diagonal,
- 'diagonal-m' => $diagonal_m,
- });
- # print "x:$size_x y:$size_y rx:$res_x ry:$res_y dpi:$dpi\n";
- ($res_x,$res_x_i,$res_y,$res_y_i,$size_x,$size_x_i,$size_y,$size_y_i) = (0,0,0,0,0,0,0,0);
-
- }
- my @working = split(/\s+/,$_);
- if ($working[1] =~ /\*/){
- $working[1] =~ s/\*|\+//g;
- $working[1] = sprintf("%.0f",$working[1]);
- $monitors[scalar @monitors - 1]->{'hz'} = $working[1] if @monitors;
- ($diagonal,$dpi) = ('','');
- # print Data::Dumper::Dumper \@monitors;
- }
+ my $num = 0;
+ my (@row,$program,$type);
+ # print ("$b_display : $b_root\n");
+ if ($b_display){
+ if (!$force{'wayland'} && ($program = main::check_program('glxinfo'))){
+ interface_glx_output($program,\@row,\$num);
+ }
+ elsif ($graphics{'xvesa'}){
+ interface_vesa_output(\@row,\$num);
+ }
+ # handles no data until we find one for wayland egl data
+ elsif ($graphics{'protocol'} eq 'wayland'){
+ interface_egl_output(\@row,\$num);
+ }
+ else {
+ @row = ({
+ main::key($num++,0,1,'Message') => main::message('glxinfo-missing'),
+ });
+ }
+ }
+ else {
+ $type = 'gl-console';
+ if ($graphics{'xvesa'}){
+ interface_vesa_output(\@row,\$num);
+ }
+ elsif (!main::check_program('glxinfo')){
+ if ($graphics{'protocol'} eq 'wayland'){
+ $type = 'interface-wayland';
}
- push(@xrandr_screens, \@monitors) if @monitors;
- # print "xrand: " . Data::Dumper::Dumper \@xrandr_screens;
- my ($i) = (0);
- foreach my $main (@{$graphics{'screens'}}){
- # print "h: " . Data::Dumper::Dumper $main;
- # print $main->{'screen'}, "\n";
- foreach my $screens (@xrandr_screens){
- # print "d: " . Data::Dumper::Dumper $screens;
- if ($screens->[0]{'screen'} eq $main->{'screen'}){
- $graphics{'screens'}->[$i]{'monitors'} = $screens;
- last;
- }
- }
- $i++;
+ else {
+ $type = 'glxinfo-missing';
}
- if (!$graphics{'screens'}){
- $graphics{'tty'} = tty_data();
+ }
+ else {
+ if ($graphics{'protocol'} eq 'wayland'){
+ $type = 'interface-wayland';
+ }
+ elsif ($b_root){
+ $type = 'gl-root';
+ }
+ else {
+ $type = 'gl-try';
+ }
+ }
+ @row = ({
+ main::key($num++,0,1,'Message') => main::message($type),
+ });
+ }
+ eval $end if $b_log;
+ return @row;
+}
+sub interface_egl_output {
+ eval $start if $b_log;
+ my ($row,$num) = @_;
+ @$row = ({
+ main::key($num++,0,1,'Message') => main::message('interface-wayland'),
+ });
+ eval $end if $b_log;
+}
+sub interface_glx_output {
+ eval $start if $b_log;
+ my ($program,$row,$num) = @_;
+ # NOTE: glxinfo -B is not always available, unfortunately
+ my @glxinfo = main::grabber("$program $display_opt 2>/dev/null");
+ # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/graphics/glxinfo/glxinfo-ssh-centos.txt";
+ # my @glxinfo = main::reader($file);
+ if (!@glxinfo){
+ my $type = 'gl-console';
+ if ($b_root){
+ $type = 'gl-root-display';
+ }
+ else {
+ $type = 'gl-null';
+ }
+ @$row = ({
+ main::key($$num++,0,1,'Message') => main::message($type),
+ });
+ return;
+ }
+ # print join("\n", @glxinfo),"\n";
+ my $compat_version = '';
+ my ($b_compat,$b_nogl,@core_profile_version,@direct_render,@renderer,
+ @opengl_version,@working);
+ foreach (@glxinfo){
+ next if /^\s/;
+ if (/^opengl renderer/i){
+ @working = split(/:\s*/, $_, 2);
+ if ($working[1]){
+ $working[1] = main::clean($working[1]);
+ }
+ # note: there are cases where gl drivers are missing and empty
+ # field value occurs.
+ else {
+ $b_nogl = 1;
+ $working[1] = main::message('gl-empty');
+ }
+ push(@renderer, $working[1]);
+ }
+ # dropping all conditions from this test to just show full mesa information
+ # there is a user case where not f and mesa apply, atom mobo
+ # /opengl version/ && ( f || $2 !~ /mesa/){
+ elsif (/^opengl version/i){
+ @working = split(/:\s*/, $_, 2);
+ if ($working[1]){
+ # fglrx started appearing with this extra string, does not appear
+ # to communicate anything of value
+ $working[1] =~ s/(Compatibility Profile Context|\(Compatibility Profile\))//;
+ $working[1] =~ s/\s\s/ /g;
+ $working[1] =~ s/^\s+|\s+$//;
+ push(@opengl_version, $working[1]);
+ # note: this is going to be off if ever multi opengl versions appear,
+ # never seen one
+ @working = split(/\s+/, $working[1]);
+ $compat_version = $working[0];
+ }
+ elsif (!$b_nogl){
+ push(@opengl_version, main::message('gl-empty'));
+ }
+ }
+ elsif (/^opengl core profile version/i){
+ @working = split(/:\s*/, $_, 2);
+ # note: no need to apply empty message here since we don't have the data
+ # anyway
+ if ($working[1]){
+ # fglrx started appearing with this extra string, does not appear
+ # to communicate anything of value
+ $working[1] =~ s/(Compatibility Profile Context|\((Compatibility|Core) Profile\))//;
+ $working[1] =~ s/\s\s/ /g;
+ $working[1] =~ s/^\s+|\s+$//;
+ push(@core_profile_version, $working[1]);
}
}
+ elsif (/direct rendering/){
+ @working = split(/:\s*/, $_, 2);
+ push(@direct_render, $working[1]);
+ }
+ # if -B was always available, we could skip this, but it is not
+ elsif (/GLX Visuals/){
+ last;
+ }
+ }
+ my ($direct_render,$renderer,$version) = ('N/A','N/A','N/A');
+ $direct_render = join(', ', @direct_render) if @direct_render;
+ # non free drivers once filtered and cleaned show the same for core and compat
+ # but this stopped for some reason at 4.5/4.6 nvidia
+ if (@core_profile_version && @opengl_version &&
+ join('', @core_profile_version) ne join('', @opengl_version) &&
+ !(grep {/nvidia/i} @opengl_version)){
+ @opengl_version = @core_profile_version;
+ $b_compat = 1;
+ }
+ $version = join(', ', @opengl_version) if @opengl_version;
+ $renderer = join(', ', @renderer) if @renderer;
+ @$row = ({
+ main::key($$num++,1,1,'OpenGL') => '',
+ main::key($$num++,1,2,'renderer') => ($renderer) ? $renderer : 'N/A',
+ main::key($$num++,0,2,'v') => ($version) ? $version : 'N/A',
+ });
+ if ($b_compat && $extra > 1 && $compat_version){
+ $row->[0]{main::key($$num++,0,2,'compat-v')} = $compat_version;
+ }
+ if ($extra > 0){
+ $row->[0]{main::key($$num++,0,2,'direct render')} = $direct_render;
+ }
+ eval $end if $b_log;
+}
+# WARNING! Never seen a GOP type UEFI, needs more data
+sub interface_vesa_output {
+ eval $start if $b_log;
+ my ($row,$num) = @_;
+ my ($controller,$dac,$interface,$ram,$source,$version);
+ # note: goes to stderr, not stdout
+ my @data = main::grabber($graphics{'xvesa'} . ' -listmodes 2>&1');
+ if ($data[0] && $data[0] =~ /^(VBE|GOP)\s+version\s+(\S+)\s\(([^)]+)\)/i){
+ $interface = $1;
+ $version = $2;
+ $source = $3;
+ }
+ if ($data[1] && $data[1] =~ /^DAC is ([^,]+), controller is ([^,]+)/i){
+ $dac = $1;
+ $controller = $2;
+ }
+ if ($data[2] && $data[2] =~ /^Total memory:\s+(\d+)\s/i){
+ $ram = $1;
+ $ram = main::get_size($ram,'string');
+ }
+ if (!$interface){
+ $row->[0]{main::key($$num++,0,1,'Message')} = main::message('xvesa-interface');
}
else {
- $graphics{'no-xdpyinfo'} = main::message('tool-missing-basic','xdpyinfo');
+ $row->[0]{main::key($$num++,1,1,'Interface')} = $interface;
+ $row->[0]{main::key($$num++,0,2,'v')} = ($version) ? $version : 'N/A';
+ $row->[0]{main::key($$num++,0,2,'source')} = ($source) ? $source : 'N/A';
+ if ($dac){
+ $row->[0]{main::key($$num++,0,2,'dac')} = $dac;
+ $row->[0]{main::key($$num++,0,2,'controller')} = $controller;
+ }
+ if ($ram){
+ $row->[0]{main::key($$num++,0,2,'ram')} = $ram;
+ }
}
- print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17];
- main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log;
eval $end if $b_log;
}
+
+## DISPLAY DATA WAYLAND ##
sub display_data_wayland {
eval $start if $b_log;
+ my ($b_skip_pos,$program);
if ($ENV{'WAYLAND_DISPLAY'}){
$graphics{'display-id'} = $ENV{'WAYLAND_DISPLAY'};
# return as wayland-0 or 0?
$graphics{'display-id'} =~ s/wayland-?//i;
}
- # print 'last: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17];
- # main::log_data('dump','@graphics{screens}',$graphics{'screens'}) if $b_log;
+ if ($fake{'swaymsg'} || ($program = main::check_program('swaymsg'))){
+ swaymsg_data($program);
+ }
+ # until we get data proving otherwise, assuming these have same output
+ elsif ($fake{'wl-info'} || (($program = main::check_program('wayland-info')) ||
+ ($program = main::check_program('weston-info')))){
+ wlinfo_data($program);
+ }
+ elsif ($fake{'wlr-randr'} || ($program = main::check_program('wlr-randr'))){
+ wlrrandr_data($program);
+ }
+ # make sure we got enough for advanced position data, might be from /sys
+ if ($extra > 1 && $monitor_ids){
+ $b_skip_pos = check_wayland_data();
+ }
+ if ($extra > 1 && $monitor_ids && $b_wayland_data){
+ # map_monitor_ids([keys %$monitors]); # not required, but leave in case.
+ wayland_data_advanced($b_skip_pos);
+ }
+ print 'Wayland monitors: ', Data::Dumper::Dumper $monitor_ids if $dbg[17];
+ main::log_data('dump','$monitor_ids',$monitor_ids) if $b_log;
eval $end if $b_log;
}
-sub set_compositor {
+# if we didn't get explicit tool for wayland data, check to see if we got most
+# of the data from /sys/class/drm edid and then skip xrandr to avoid gunking up
+# the data, in that case, all we get from xrandr would be the position, which is
+# nice but not a must-have. We've already cleared out all disabled ports.
+sub check_wayland_data {
eval $start if $b_log;
- my ($protocol) = @_;
- # initial tests, if wayland, it is certainly a compositor
- $protocol = lc($protocol) if $protocol;
- $graphics{'compositor'} = display_compositor($protocol);
- # gnome-shell is incredibly slow to return version
- if (($extra > 2 || $protocol eq 'wayland') && $graphics{'compositor'} &&
- (!$show{'system'} || $graphics{'compositor'} ne 'gnome-shell')){
- $graphics{'compositor-version'} = (main::program_data($graphics{'compositor'},$graphics{'compositor'},3))[1];
+ my ($b_skip_pos,$b_invalid);
+ foreach my $key (keys %$monitor_ids){
+ # we need these 4 items to construct the grid rectangle
+ if (!defined $monitor_ids->{$key}{'pos-x'} ||
+ !defined $monitor_ids->{$key}{'pos-y'} ||
+ !$monitor_ids->{$key}{'res-x'} || !$monitor_ids->{$key}{'res-y'}){
+ $b_skip_pos = 1;
+ }
+ if (!$monitor_ids->{$key}{'res-x'} || !$monitor_ids->{$key}{'res-y'}){
+ $b_invalid = 1;
+ }
}
+ # ok, we have enough, we don't need to do fallback xrandr checks
+ $b_wayland_data = 1 if !$b_invalid;
eval $end if $b_log;
+ return $b_skip_pos;
}
-sub get_protocol {
+# Set Display rect size for > 1 monitors, monitor positions, size-i, diag
+sub wayland_data_advanced {
eval $start if $b_log;
- my ($protocol) = ('');
- $protocol = $ENV{'XDG_SESSION_TYPE'} if $ENV{'XDG_SESSION_TYPE'};
- $protocol = $ENV{'WAYLAND_DISPLAY'} if (!$protocol && $ENV{'WAYLAND_DISPLAY'});
- # can show as wayland-0
- $protocol = 'wayland' if $protocol && $protocol =~ /wayland/i;
- # yes, I've seen this in 2019 distros, sigh
- $protocol = '' if $protocol eq 'tty';
- # need to confirm that there's a point to this test, I believe no, fails out of x
- # loginctl also results in the session id
- if (!$protocol && $b_display && $force{'display'}){
- if (my $program = main::check_program('loginctl')){
- my $id = '';
- # $id = $ENV{'XDG_SESSION_ID'}; # returns tty session in console
- my @data = main::grabber("$program --no-pager --no-legend 2>/dev/null",'','strip');
- foreach (@data){
- next if /tty[v]?[0-6]$/; # freebsd: ttyv3
- $id = (split(/\s+/, $_))[0];
- last; # multiuser? too bad, we'll go for the first one
+ my ($b_skip_pos) = @_;
+ my (%x_pos,%y_pos);
+ my ($x_max,$y_max) = (0,0);
+ my @keys = keys %$monitor_ids;
+ foreach my $key (@keys){
+ if (!$b_skip_pos){
+ if ($monitor_ids->{$key}{'res-x'} && $monitor_ids->{$key}{'res-x'} > $x_max){
+ $x_max = $monitor_ids->{$key}{'res-x'};
}
- if ($id){
- my $temp = (main::grabber("$program show-session $id -p Type --no-pager --no-legend 2>/dev/null"))[0];
- $temp =~ s/Type=// if $temp;
- # ssh will not show /dev/ttyx so would have passed the first test
- $protocol = $temp if $temp && $temp ne 'tty';
+ if ($monitor_ids->{$key}{'res-y'} && $monitor_ids->{$key}{'res-y'} > $y_max){
+ $y_max = $monitor_ids->{$key}{'res-y'};
}
+ # Now we'll add the detected x, y res to the trackers
+ if (!defined $x_pos{$monitor_ids->{$key}{'pos-x'}}){
+ $x_pos{$monitor_ids->{$key}{'pos-x'}} = $monitor_ids->{$key}{'res-x'};
+ }
+ if (!defined $y_pos{$monitor_ids->{$key}{'pos-y'}}){
+ $y_pos{$monitor_ids->{$key}{'pos-y'}} += $monitor_ids->{$key}{'res-y'};
+ }
+ }
+ # this means we failed to get EDID real data, and are using just the wayland
+ # tool to get this info, eg. with BSD without compositor data.
+ if ($monitor_ids->{$key}{'size-x'} && $monitor_ids->{$key}{'size-y'} &&
+ (!$monitor_ids->{$key}{'size-x-i'} || !$monitor_ids->{$key}{'size-y-i'} ||
+ !$monitor_ids->{$key}{'dpi'} || !$monitor_ids->{$key}{'diagonal'})){
+ my $size_x = $monitor_ids->{$key}{'size-x'};
+ my $size_y = $monitor_ids->{$key}{'size-y'};
+ $monitor_ids->{$key}{'size-x-i'} = sprintf("%.1f", ($size_x/25.4));
+ $monitor_ids->{$key}{'size-y-i'} = sprintf("%.1f", ($size_y/25.4));
+ $monitor_ids->{$key}{'diagonal'} = sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4)) + 0;
+ $monitor_ids->{$key}{'diagonal-m'} = sprintf("%.0f", (sqrt($size_x**2 + $size_y**2)));
+ if ($monitor_ids->{$key}{'res-x'}){
+ my $res_x = $monitor_ids->{$key}{'res-x'};
+ $monitor_ids->{$key}{'dpi'} = sprintf("%.0f", $res_x * 25.4 / $size_x);
+ }
+ }
+ }
+ if (!$b_skip_pos){
+ if (scalar @keys > 1 && %x_pos && %y_pos){
+ my ($x,$y) = (0,0);
+ foreach (keys %x_pos){$x += $x_pos{$_}}
+ foreach (keys %y_pos){$y += $y_pos{$_}}
+ # handle cases with one tall portrait mode > 2 short landscapes, etc.
+ $x = $x_max if $x_max > $x;
+ $y = $y_max if $y_max > $y;
+ $graphics{'display-rect'} = $x . 'x' . $y;
}
+ my $layouts = [];
+ set_monitor_layouts($layouts);
+ # only update position, we already have all the rest of the data
+ advanced_monitor_data($monitor_ids,$layouts);
+ undef $layouts;
}
eval $end if $b_log;
- return $protocol;
}
-sub gl_output(){
+
+## WAYLAND COMPOSITOR DATA TOOLS ##
+
+# NOTE: These patterns are VERY fragile, and depend on no changes at all to
+# the data structure, and more important, the order. Something I would put
+# almost no money on being able to count on.
+sub wlinfo_data {
eval $start if $b_log;
- my $num = 0;
- my (@row,$arg);
- # print ("$b_display : $b_root\n");
- if ($b_display){
- if (my $program = main::check_program('glxinfo')){
- # NOTE: glxinfo -B is not always available, unfortunately
- my @glxinfo = main::grabber("$program $display_opt 2>/dev/null");
- # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/graphics/glxinfo/glxinfo-ssh-centos.txt";
- # my @glxinfo = main::reader($file);
- if (!@glxinfo){
- my $type = 'display-console';
- if ($b_root){
- $type = 'display-root-x';
+ my ($program) = @_;
+ my (@data,%mon,@temp,$ref);
+ my ($b_iwlo,$b_izxdg,$file,$hz,$id,$pos_x,$pos_y,$res_x,$res_y,$scale);
+ if (!$fake{'wl-info'}){
+ undef $monitor_ids;
+ @data = main::grabber("$program 2>/dev/null",'','strip');
+ }
+ else {
+ $file = "$ENV{'HOME'}/bin/scripts/inxi/data/wayland/weston-info-2-mon-1.txt";
+ @data = main::reader($file,'strip');
+ }
+ print 'wayland/weston-info raw: ', Data::Dumper::Dumper \@data if $dbg[46];
+ main::log_data('dump','@data', \@data) if $b_log;
+ foreach (@data){
+ # print 'l: ', $_,"\n";
+ if (/^interface: 'wl_output', version: \d+, name: (\d+)$/){
+ $b_iwlo = 1;
+ $id = $1;
+ }
+ elsif (/^interface: 'zxdg_output/){
+ $b_izxdg = 1;
+ $b_iwlo = 0;
+ }
+ if ($b_iwlo){
+ if (/^x: (\d+), y: (\d+), scale: ([\d\.]+)/){
+ $mon{$id}->{'pos-x'} = $1;
+ $mon{$id}->{'pos-y'} = $2;
+ $mon{$id}->{'scale'} = $3;
+ }
+ elsif (/^physical_width: (\d+) mm, physical_height: (\d+) mm/){
+ $mon{$id}->{'size-x'} = $1 if $1; # can be 0 if edid data n/a
+ $mon{$id}->{'size-y'} = $2 if $2; # can be 0 if edid data n/a
+ }
+ elsif (/^make: '([^']+)', model: '([^']+)'/){
+ my $make = main::clean($1);
+ my $model = main::clean($2);
+ $mon{$id}->{'model'} = $make;
+ if ($make && $model){
+ $mon{$id}->{'model'} = $make . ' ' . $model;
}
- else {
- $type = 'display-null';
+ elsif ($model) {
+ $mon{$id}->{'model'} = $model;
}
- @row = ({
- main::key($num++,0,1,'Message') => main::message($type),
- });
- return @row;
- }
- # print join("\n", @glxinfo),"\n";
- my $compat_version = '';
- my ($b_compat,$b_nogl,@core_profile_version,@direct_render,@renderer,
- @opengl_version,@working);
- foreach (@glxinfo){
- next if /^\s/;
- if (/^opengl renderer/i){
- @working = split(/:\s*/, $_, 2);
- if ($working[1]){
- $working[1] = main::clean($working[1]);
- # Allow all mesas
- # if ($working[1] =~ /mesa/i){
- #
- # }
- }
- # note: there are cases where gl drivers are missing and empty
- # field value occurs.
- else {
- $b_nogl = 1;
- $working[1] = main::message('gl-empty');
- }
- push(@renderer, $working[1]);
- }
- # dropping all conditions from this test to just show full mesa information
- # there is a user case where not f and mesa apply, atom mobo
- # /opengl version/ && ( f || $2 !~ /mesa/){
- elsif (/^opengl version/i){
- @working = split(/:\s*/, $_, 2);
- if ($working[1]){
- # fglrx started appearing with this extra string, does not appear
- # to communicate anything of value
- $working[1] =~ s/(Compatibility Profile Context|\(Compatibility Profile\))//;
- $working[1] =~ s/\s\s/ /g;
- $working[1] =~ s/^\s+|\s+$//;
- push(@opengl_version, $working[1]);
- # note: this is going to be off if ever multi opengl versions appear,
- # never seen one
- @working = split(/\s+/, $working[1]);
- $compat_version = $working[0];
- }
- elsif (!$b_nogl){
- push(@opengl_version, main::message('gl-empty'));
+ elsif ($make) {
+ $mon{$id}->{'model'} = $make;
+ }
+ # includes remove duplicates and remove unset
+ if ($mon{$id}->{'model'}){
+ $mon{$id}->{'model'} = main::clean_dmi($mon{$id}->{'model'});
+ }
+ }
+ elsif (/^width: (\d+) px, height: (\d+) px, refresh: ([\d\.]+) Hz,/){
+ $mon{$id}->{'res-x'} = $1;
+ $mon{$id}->{'res-y'} = $2;
+ $mon{$id}->{'hz'} = sprintf('%.0f',$3);
+ }
+ }
+ # note: we don't want to use the 'description' field because that doesn't
+ # always contain make/model data, sometimes it's: Built-in/Unknown Display
+ elsif ($b_izxdg){
+ if (/^output: (\d+)/){
+ $id = $1;
+ }
+ elsif (/^name: '([^']+)'$/){
+ $mon{$id}->{'monitor'} = $1;
+ }
+ elsif (/^logical_x: (\d+), logical_y: (\d+)/){
+ $mon{$id}->{'log-pos-x'} = $1;
+ $mon{$id}->{'log-pos-y'} = $2;
+ }
+ elsif (/^logical_width: (\d+), logical_height: (\d+)/){
+ $mon{$id}->{'log-x'} = $1;
+ $mon{$id}->{'log-y'} = $2;
+ }
+ }
+ if ($b_izxdg && /^interface: '(?!zxdg_output)/){
+ last;
+ }
+ }
+ # now we need to map %mon back to $monitor_ids
+ if (%mon){
+ $b_wayland_data = 1;
+ foreach my $key (keys %mon){
+ next if !$mon{$key}->{'monitor'}; # no way to know what it is, sorry
+ $id = $mon{$key}->{'monitor'};
+ $monitor_ids->{$id}{'monitor'} = $id;
+ $monitor_ids->{$id}{'log-x'} = $mon{$key}->{'log-x'} if defined $mon{$key}->{'log-x'};
+ $monitor_ids->{$id}{'log-y'} = $mon{$key}->{'log-y'} if defined $mon{$key}->{'log-y'};
+ $monitor_ids->{$id}{'pos-x'} = $mon{$key}->{'pos-x'} if defined $mon{$key}->{'pos-x'};
+ $monitor_ids->{$id}{'pos-y'} = $mon{$key}->{'pos-y'} if defined $mon{$key}->{'pos-y'};
+ $monitor_ids->{$id}{'res-x'} = $mon{$key}->{'res-x'} if defined $mon{$key}->{'res-x'};
+ $monitor_ids->{$id}{'res-y'} = $mon{$key}->{'res-y'} if defined $mon{$key}->{'res-y'};
+ $monitor_ids->{$id}{'size-x'} = $mon{$key}->{'size-x'} if defined $mon{$key}->{'size-x'};
+ $monitor_ids->{$id}{'size-y'} = $mon{$key}->{'size-y'} if defined $mon{$key}->{'size-y'};
+ $monitor_ids->{$id}{'hz'} = $mon{$key}->{'hz'} if defined $mon{$key}->{'hz'};
+ if (defined $mon{$key}->{'model'} && !$monitor_ids->{$id}{'model'}){
+ $monitor_ids->{$id}{'model'} = $mon{$key}->{'model'};
+ }
+ $monitor_ids->{$id}{'scale'} = $mon{$key}->{'scale'} if defined $mon{$key}->{'scale'};
+ # fallbacks in case wl_output block is not present, which happens
+ if (!defined $mon{$key}->{'pos-x'} && defined $mon{$key}->{'log-pos-x'}){
+ $monitor_ids->{$id}{'pos-x'} = $mon{$key}->{'log-pos-x'};
+ }
+ if (!defined $mon{$key}->{'pos-y'} && defined $mon{$key}->{'log-pos-y'}){
+ $monitor_ids->{$id}{'pos-y'} = $mon{$key}->{'log-pos-y'};
+ }
+ if (!defined $mon{$key}->{'res-x'} && defined $mon{$key}->{'log-x'}){
+ $monitor_ids->{$id}{'res-x'} = $mon{$key}->{'log-x'};
+ }
+ if (!defined $mon{$key}->{'res-y'} && defined $mon{$key}->{'log-y'}){
+ $monitor_ids->{$id}{'res-y'} = $mon{$key}->{'log-y'};
+ }
+ }
+ }
+ print '%mon: ', Data::Dumper::Dumper \%mon if $dbg[46];
+ main::log_data('dump','%mon', \%mon) if $b_log;
+ print 'wayland/weston-info: monitor_ids: ', Data::Dumper::Dumper $monitor_ids if $dbg[46];
+ eval $end if $b_log;
+}
+# note; since not all systems will have /sys data, we'll repack it if it's
+# missing here.
+sub swaymsg_data {
+ eval $start if $b_log;
+ my ($program) = @_;
+ my (@data,%json,@temp,$ref);
+ my ($b_json,$file,$hz,$id,$model,$pos_x,$pos_y,$res_x,$res_y,$scale,$serial);
+ if (!$fake{'swaymsg'}){
+ main::load_json() if !$loaded{'json'};
+ if ($use{'json'}){
+ my $result = qx($program -t get_outputs -r 2>/dev/null);
+ # returns array of monitors found
+ @data = &{$use{'json'}->{'decode'}}($result) if $result;
+ $b_json = 1;
+ print "$use{'json'}->{'type'}: " if $dbg[46];
+ # print "using: $use{'json'}->{'type'}\n";
+ }
+ else {
+ @data = main::grabber("$program -t get_outputs -p 2>/dev/null",'','strip');
+ }
+ }
+ else {
+ undef $monitor_ids;
+ $file = "$ENV{'HOME'}/bin/scripts/inxi/data/wayland/swaymsg-2-monitor-1.txt";
+ @data = main::reader($file,'strip');
+ }
+ print 'swaymsg: ', Data::Dumper::Dumper \@data if $dbg[46];
+ main::log_data('dump','@data', \@data) if $b_log;
+ # print Data::Dumper::Dumper \@data;
+ if ($b_json){
+ $b_wayland_data = 1 if scalar @data > 0;
+ foreach my $display (@data){
+ foreach my $mon (@$display){
+ ($hz,$pos_x,$pos_y,$res_x,$res_y,$scale) = ();
+ $id = $mon->{'name'};
+ if (!$monitor_ids->{$id}{'monitor'}){
+ $monitor_ids->{$id}{'monitor'} = $mon->{'name'};
+ }
+ # we don't want to overwrite good edid model data if we already got it
+ if (!$monitor_ids->{$id}{'model'} && $mon->{'make'}){
+ $monitor_ids->{$id}{'model'} = main::clean($mon->{'make'});
+ if ($mon->{'model'}){
+ $monitor_ids->{$id}{'model'} .= ' ' . main::clean($mon->{'model'});
+
}
+ $monitor_ids->{$id}{'model'} = main::remove_duplicates($monitor_ids->{$id}{'model'});
+ }
+ if ($monitor_ids->{$id}{'primary'} &&
+ $monitor_ids->{$id}{'primary'} ne 'false'){
+ $monitor_ids->{$id}{'primary'} = $id;
}
- elsif (/^opengl core profile version/i){
- @working = split(/:\s*/, $_, 2);
- # note: no need to apply empty message here since we don't have the data
- # anyway
- if ($working[1]){
- # fglrx started appearing with this extra string, does not appear
- # to communicate anything of value
- $working[1] =~ s/(Compatibility Profile Context|\((Compatibility|Core) Profile\))//;
- $working[1] =~ s/\s\s/ /g;
- $working[1] =~ s/^\s+|\s+$//;
- push(@core_profile_version, $working[1]);
+ if (!$monitor_ids->{$id}{'serial'}){
+ $monitor_ids->{$id}{'serial'} = main::clean_dmi($mon->{'serial'});
+ }
+ # sys data will only have edid type info, not active state res/pos/hz
+ if ($mon->{'current_mode'}){
+ if ($hz = $mon->{'current_mode'}{'refresh'}){
+ $hz = sprintf('%.0f',($mon->{'current_mode'}{'refresh'}/1000));
+ $monitor_ids->{$id}{'hz'} = $hz;
}
+ $monitor_ids->{$id}{'res-x'} = $mon->{'current_mode'}{'width'};
+ $monitor_ids->{$id}{'res-y'} = $mon->{'current_mode'}{'height'};
}
- elsif (/direct rendering/){
- @working = split(/:\s*/, $_, 2);
- push(@direct_render, $working[1]);
+ if ($mon->{'rect'}){
+ $monitor_ids->{$id}{'pos-x'} = $mon->{'rect'}{'x'};
+ $monitor_ids->{$id}{'pos-y'} = $mon->{'rect'}{'y'};
}
- # if -B was always available, we could skip this, but it is not
- elsif (/GLX Visuals/){
- last;
+ if ($mon->{'scale'}){
+ $monitor_ids->{$id}{'scale'} =$mon->{'scale'};
+ }
+ }
+ }
+ }
+ else {
+ foreach (@data){
+ push(@temp,'~~') if /^Output/i;
+ push(@temp,$_);
+ }
+ push(@temp,'~~') if @temp;
+ @data = @temp;
+ $b_wayland_data = 1 if scalar @data > 8;
+ foreach (@data){
+ if ($_ eq '~~' && $id){
+ $monitor_ids->{$id}{'hz'} = $hz;
+ $monitor_ids->{$id}{'model'} = $model if $model;
+ $monitor_ids->{$id}{'monitor'} = $id;
+ $monitor_ids->{$id}{'pos-x'} = $pos_x;
+ $monitor_ids->{$id}{'pos-y'} = $pos_y;
+ $monitor_ids->{$id}{'res-x'} = $res_x;
+ $monitor_ids->{$id}{'res-y'} = $res_y;
+ $monitor_ids->{$id}{'scale'} = $scale;
+ $monitor_ids->{$id}{'serial'} = $serial if $serial;
+ ($hz,$model,$pos_x,$pos_y,$res_x,$res_y,$scale,$serial) = ();
+ $b_wayland_data = 1;
+ }
+ # Output VGA-1 '<Unknown> <Unknown> ' (focused)
+ # unknown how 'primary' is shown, if it shows in this output
+ if (/^Output (\S+) '([^']+)'/i){
+ $id = $1;
+ if ($2 && !$monitor_ids->{$id}{'model'}){
+ ($model,$serial) = get_model_serial($2);
}
}
- my ($direct_render,$renderer,$version) = ('N/A','N/A','N/A');
- $direct_render = join(', ', @direct_render) if @direct_render;
- # non free drivers once filtered and cleaned show the same for core and compat
- # but this stopped for some reason at 4.5/4.6 nvidia
- if (@core_profile_version && @opengl_version &&
- join('', @core_profile_version) ne join('', @opengl_version) &&
- !(grep {/nvidia/i} @opengl_version)){
- @opengl_version = @core_profile_version;
- $b_compat = 1;
+ elsif (/^Current mode:\s+(\d+)x(\d+)\s+\@\s+([\d\.]+)\s+Hz/i){
+ $res_x = $1;
+ $res_y = $2;
+ $hz = (sprintf('%.0f',($3/1000)) + 0) if $3;
}
- $version = join(', ', @opengl_version) if @opengl_version;
- $renderer = join(', ', @renderer) if @renderer;
- @row = ({
- main::key($num++,1,1,'OpenGL') => '',
- main::key($num++,1,2,'renderer') => ($renderer) ? $renderer : 'N/A',
- main::key($num++,0,2,'v') => ($version) ? $version : 'N/A',
- });
- if ($b_compat && $extra > 1 && $compat_version){
- $row[0]->{main::key($num++,0,2,'compat-v')} = $compat_version;
+ elsif (/^Position:\s+(\d+),(\d+)/i){
+ $pos_x = $1;
+ $pos_y = $2;
}
- if ($extra > 0){
- $row[0]->{main::key($num++,0,2,'direct render')} = $direct_render;
+ elsif (/^Scale factor:\s+([\d\.]+)/i){
+ $scale = $1 + 0;
}
}
- else {
- @row = ({
- main::key($num++,0,1,'Message') => main::message('glxinfo-missing'),
- });
- }
+ }
+ print 'swaymsg: ', Data::Dumper::Dumper $monitor_ids if $dbg[46];
+ eval $end if $b_log;
+}
+# like a basic stripped down swaymsg -t get_outputs -p, less data though
+# This is EXTREMELY LIKELY TO FAIL! Any tiny syntax change will break this.
+sub wlrrandr_data {
+ eval $start if $b_log;
+ my ($program) = @_;
+ my ($file,$hz,$id,$info,$model,$pos_x,$pos_y,$res_x,$res_y,$scale,$serial);
+ my (@data,@temp);
+ if (!$fake{'wlr-randr'}){
+ @data = main::grabber("$program 2>/dev/null",'','strip');
}
else {
- my $type = 'display-console';
- if (!main::check_program('glxinfo')){
- $type = 'glxinfo-missing';
+ undef $monitor_ids;
+ $file = "$ENV{'HOME'}/bin/scripts/inxi/data/wayland/wlr-randr-2-monitor-1.txt";
+ @data = main::reader($file,'strip');
+ }
+ foreach (@data){
+ push(@temp,'~~') if /^([A-Z]+-[ABID\d-]+)\s['"]/i;
+ push(@temp,$_);
+ }
+ push(@temp,'~~') if @temp;
+ @data = @temp;
+ $b_wayland_data = 1 if scalar @data > 4;
+ print 'wlr-randr: ', Data::Dumper::Dumper \@data if $dbg[46];
+ main::log_data('dump','@data', \@data) if $b_log;
+ foreach (@data){
+ if ($_ eq '~~' && $id){
+ $monitor_ids->{$id}{'hz'} = $hz;
+ $monitor_ids->{$id}{'model'} = $model if $model && !$monitor_ids->{$id}{'model'};
+ $monitor_ids->{$id}{'monitor'} = $id;
+ $monitor_ids->{$id}{'pos-x'} = $pos_x;
+ $monitor_ids->{$id}{'pos-y'} = $pos_y;
+ $monitor_ids->{$id}{'res-x'} = $res_x;
+ $monitor_ids->{$id}{'res-y'} = $res_y;
+ $monitor_ids->{$id}{'scale'} = $scale;
+ $monitor_ids->{$id}{'serial'} = $serial if $serial && !$monitor_ids->{$id}{'serial'};
+ ($hz,$info,$model,$pos_x,$pos_y,$res_x,$res_y,$scale,$serial) = ();
+ $b_wayland_data = 1;
+ }
+ # Output: VGA-1 '<Unknown> <Unknown> ' (focused)
+ # DVI-I-1 'Samsung Electric Company SyncMaster H9NX843762' (focused)
+ # unknown how 'primary' is shown, if it shows in this output
+ if (/^([A-Z]+-[ABID\d-]+)\s([']([^']+)['])?/i){
+ $id = $1;
+ # if model is set, we got edid data
+ if ($3 && !$monitor_ids->{$id}{'model'}){
+ ($model,$serial) = get_model_serial($3);
+ }
}
- else {
- if ($b_root){
- $type = 'display-root';
+ elsif (/^(\d+)x(\d+)\s+px,\s+([\d\.]+)\s+Hz \([^\)]*?current\)/i){
+ $res_x = $1;
+ $res_y = $2;
+ $hz = sprintf('%.0f',$3) if $3;
+ }
+ elsif (/^Position:\s+(\d+),(\d+)/i){
+ $pos_x = $1;
+ $pos_y = $2;
+ }
+ elsif (/^Scale:\s+([\d\.]+)/i){
+ $scale = $1 + 0;
+ }
+ }
+ print 'wlr-randr: ', Data::Dumper::Dumper $monitor_ids if $dbg[46];
+ eval $end if $b_log;
+}
+# return model/serial for those horrible string type values we have to process
+# in swaymsg -t get_outputs -p and wlr-randr default output
+sub get_model_serial {
+ eval $start if $b_log;
+ my $info = $_[0];
+ my ($model,$serial);
+ $info = main::clean($info);
+ return if !$info;
+ my @parts = split(/\s+/, $info);
+ # Perl Madness, lol: the last just checks how many integers in string
+ if (scalar @parts > 1 && (length($parts[-1]) > 7) &&
+ (($parts[-1] =~ tr/[0-9]//) > 4)){
+ $serial = pop @parts;
+ $serial = main::clean_dmi($serial); # clears out 0x00000 type non data
+ }
+ # we're assuming that we'll never get a serial without make/model data too.
+ $model = join(' ',@parts) if @parts;
+ $model = main::remove_duplicates($model) if $model && scalar @parts > 1;
+ eval $end if $b_log;
+ return ($model,$serial);
+}
+
+# DISPLAY DATA X.org ##
+sub display_data_x {
+ eval $start if $b_log;
+ my ($prog_xdpyinfo,$prog_xrandr);
+ if ($prog_xdpyinfo = main::check_program('xdpyinfo')){
+ xdpyinfo_data($prog_xdpyinfo);
+ }
+ # print Data::Dumper::Dumper $graphics{'screens'};
+ if ($prog_xrandr = main::check_program('xrandr')){
+ xrandr_data($prog_xrandr);
+ }
+ if (!$graphics{'screens'}){
+ $graphics{'tty'} = tty_data();
+ }
+ if (!$prog_xrandr){
+ $graphics{'no-monitors'} = main::message('tool-missing-basic','xrandr');
+ if (!$prog_xdpyinfo){
+ if ($graphics{'protocol'} eq 'wayland'){
+ $graphics{'no-screens'} = main::message('screen-wayland');
}
else {
- $type = 'display-try';
+ $graphics{'no-screens'} = main::message('tool-missing-basic','xdpyinfo/xrandr');
}
}
- @row = ({
- main::key($num++,0,1,'Message') => main::message($type),
- });
}
+ print 'Final display x: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17];
+ main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log;
eval $end if $b_log;
- return @row;
}
-sub tty_data(){
+sub xdpyinfo_data {
eval $start if $b_log;
- my ($tty);
- if ($size{'term-cols'}){
- $tty = "$size{'term-cols'}x$size{'term-lines'}";
+ my ($program) = @_;
+ my ($diagonal,$diagonal_m,$dpi) = ('','','');
+ my ($screen_id,$screen,@working);
+ my ($res_x,$res_y,$size_x,$size_x_i,$size_y,$size_y_i);
+ my @xdpyinfo = main::grabber("$program $display_opt 2>/dev/null","\n",'strip');
+ # @xdpyinfo = map {s/^\s+//;$_} @xdpyinfo if @xdpyinfo;
+ # print join("\n",@xdpyinfo), "\n";
+ # X vendor and version detection.
+ # new method added since radeon and X.org and the disappearance of
+ # <X server name> version : ...etc. Later on, the normal textual version string
+ # returned, e.g. like: X.Org version: 6.8.2
+ # A failover mechanism is in place: if $version empty, release number parsed instead
+ foreach (@xdpyinfo){
+ @working = split(/:\s+/, $_);
+ next if (($graphics{'screens'} && $working[0] !~ /^(dimensions$|screen\s#)/) || !$working[0]);
+ # print "$_\n";
+ if ($working[0] eq 'vendor string'){
+ $working[1] =~ s/The\s|\sFoundation//g;
+ # some distros, like fedora, report themselves as the xorg vendor,
+ # so quick check here to make sure the vendor string includes Xorg in string
+ if ($working[1] !~ /x/i){
+ $working[1] .= ' X.org';
+ }
+ $graphics{'x-server'} = [[$working[1]]];
+ }
+ elsif ($working[0] eq 'name of display'){
+ $graphics{'display-id'} = $working[1];
+ }
+ # this is the x protocol version
+ elsif ($working[0] eq 'version number'){
+ $graphics{'x-protocol-version'} = $working[1];
+ }
+ # not used, but might be good for something?
+ elsif ($working[0] eq 'vendor release number'){
+ $graphics{'x-vendor-release'} = $working[1];
+ }
+ # the real X.org version string
+ elsif ($working[0] eq 'X.Org version'){
+ push(@{$graphics{'x-server'}->[0]},$working[1]);
+ }
+ elsif ($working[0] eq 'default screen number'){
+ $graphics{'display-default-screen'} = $working[1];
+ }
+ elsif ($working[0] eq 'number of screens'){
+ $graphics{'display-screens'} = $working[1];
+ }
+ elsif ($working[0] =~ /^screen #([0-9]+):/){
+ $screen_id = $1;
+ }
+ elsif ($working[0] eq 'resolution'){
+ $working[1] =~ s/^([0-9]+)x/$1/;
+ $graphics{'s-dpi'} = $working[1];
+ }
+ # This is Screen, not monitor: dimensions: 2560x1024 pixels (677x270 millimeters)
+ elsif ($working[0] eq 'dimensions'){
+ ($dpi,$res_x,$res_y,$size_x,$size_y) = ();
+ if ($working[1] =~ /([0-9]+)\s*x\s*([0-9]+)\s+pixels\s+\(([0-9]+)\s*x\s*([0-9]+)\s*millimeters\)/){
+ $res_x = $1;
+ $res_y = $2;
+ $size_x = $3;
+ $size_y = $4;
+ # flip size x,y if don't roughly match res x/y ratio
+ if ($size_x && $size_y && $res_y){
+ flip_size_x_y(\$size_x,\$size_y,\$res_x,\$res_y);
+ }
+ $size_x_i = ($size_x) ? sprintf("%.1f", ($size_x/25.4)) : 0;
+ $size_y_i = ($size_y) ? sprintf("%.1f", ($size_y/25.4)) : 0;
+ $dpi = ($res_x && $size_x) ? sprintf("%.0f", ($res_x*25.4/$size_x)) : '';
+ $diagonal = ($size_x && $size_y) ? sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4)) : '';
+ $diagonal += 0 if $diagonal;# trick to get rid of decimal 0
+ $diagonal_m = ($size_x && $size_y) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
+ }
+ $screen = {
+ 'screen' => $screen_id,
+ 'res-x' => $res_x,
+ 'res-y' => $res_y,
+ 'size-x' => $size_x,
+ 'size-x-i' => $size_x_i,
+ 'size-y' => $size_y,
+ 'size-y-i' => $size_y_i,
+ 's-dpi' => $dpi,
+ 'diagonal' => $diagonal,
+ 'diagonal-m' => $diagonal_m,
+ };
+ push(@{$graphics{'screens'}}, $screen);
+ }
}
- # this is broken
- elsif ($b_irc && $client{'console-irc'}){
- ShellData::console_irc_tty() if !$loaded{'con-irc-tty'};
- my $tty_working = $client{'con-irc-tty'};
- if ($tty_working ne '' && (my $program = main::check_program('stty'))){
- my $tty_arg = ($bsd_type) ? '-f' : '-F';
- # handle vtnr integers, and tty ID with letters etc.
- $tty_working = "tty$tty_working" if -e "/dev/tty$tty_working";
- $tty = (main::grabber("$program $tty_arg /dev/$tty_working size 2>/dev/null"))[0];
- if ($tty){
- my @temp = split(/\s+/, $tty);
- $tty = "$temp[1]x$temp[0]";
+ print 'Data: xdpyinfo: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17];
+ main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log;
+ eval $end if $b_log;
+}
+sub xrandr_data {
+ eval $end if $b_log;
+ my ($program) = @_;
+ my ($diagonal,$diagonal_m,$dpi,$monitor_id,$pos_x,$pos_y,$primary);
+ my ($res_x,$res_x_max,$res_y,$res_y_max);
+ my ($screen_id,$set_as,$size_x,$size_x_i,$size_y,$size_y_i,$x_screen);
+ my (@ids,%monitors,@xrandr_screens,@xrandr);
+ if (!$fake{'xrandr'}){
+ @xrandr = main::grabber("$program $display_opt 2>/dev/null",'','strip');
+ }
+ else {
+ @xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/svn/branches/inxi-perl/xrandr.txt",'strip');
+ }
+ # $graphics{'dimensions'} = (\@dimensions);
+ # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
+ # multiple screens from different video cards
+ foreach (@xrandr){
+ # note: no mm as with xdpyinfo
+ # Screen 0: minimum 320 x 200, current 2560 x 1024, maximum 8192 x 8192
+ if (/^Screen ([0-9]+):/){
+ $screen_id = $1;
+ # handle no xdpyinfo Screen data
+ if ((!$graphics{'screens'} ||
+ scalar @{$graphics{'screens'}} != (scalar @xrandr_screens + 1)) &&
+ /:\s.*?current\s+(\d+)\s*x\s*(\d+),\smaximum\s+(\d+)\s*x\s*(\d+)/){
+ $res_x = $1;
+ $res_y = $2;
+ $res_x_max = $3;
+ $res_y_max = $4;
+ $x_screen = {
+ 'screen' => $screen_id,
+ 'res-x' => $res_x,
+ 'res-y' => $res_y,
+ 'size-x' => undef,
+ 'size-x-i' => undef,
+ 'size-y' => undef,
+ 'size-y-i' => undef,
+ 's-dpi' => undef,
+ 'diagonal' => undef,
+ 'diagonal-m' => undef,
+ };
+ push(@{$graphics{'screens'}}, $x_screen);
+ }
+ if (%monitors){
+ push(@xrandr_screens,\%monitors);
+ %monitors = ();
+ }
+ }
+ # HDMI-2 connected 1920x1200+1080+0 (normal left inverted right x axis y axis) 519mm x 324mm
+ # DP-1 connected primary 2560x1440+1080+1200 (normal left inverted right x axis y axis) 598mm x 336mm
+ # HDMI-1 connected 1080x1920+0+0 left (normal left inverted right x axis y axis) 160mm x 90mm
+ elsif (/^([^\s]+)\s+connected\s(primary\s)?([0-9]+)\s*x\s*([0-9]+)\+([0-9]+)\+([0-9]+)(\s[^(]*\([^)]+\))?(\s([0-9]+)mm\sx\s([0-9]+)mm)?/){
+ $monitor_id = $1;
+ $set_as = $2;
+ $res_x = $3;
+ $res_y = $4;
+ $pos_x = $5;
+ $pos_y = $6;
+ $size_x = $9;
+ $size_y = $10;
+ # flip size x,y if don't roughly match res x/y ratio
+ if ($size_x && $size_y && $res_y){
+ flip_size_x_y(\$size_x,\$size_y,\$res_x,\$res_y);
+ }
+ $size_x_i = ($size_x) ? sprintf("%.1f", ($size_x/25.4)) : 0;
+ $size_y_i = ($size_y) ? sprintf("%.1f", ($size_y/25.4)) : 0;
+ $dpi = ($res_x && $size_x) ? sprintf("%.0f", $res_x * 25.4 / $size_x) : '';
+ $diagonal = ($res_x && $size_x) ? sprintf("%.1f", (sqrt($size_x**2 + $size_y**2)/25.4)) : '';
+ $diagonal += 0 if $diagonal; # trick to get rid of decimal 0
+ $diagonal_m = ($res_x && $size_x) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
+ undef $primary;
+ push(@ids,$monitor_id);
+ if ($set_as){
+ $primary = $monitor_id;
+ $set_as =~ s/\s$//;
+ }
+ $monitors{$monitor_id} = {
+ 'screen' => $screen_id,
+ 'monitor' => $monitor_id,
+ 'pos-x' => $pos_x,
+ 'pos-y' => $pos_y,
+ 'primary' => $primary,
+ 'res-x' => $res_x,
+ 'res-y' => $res_y,
+ 'size-x' => $size_x,
+ 'size-x-i' => $size_x_i,
+ 'size-y' => $size_y,
+ 'size-y-i' => $size_y_i,
+ 'dpi' => $dpi,
+ 'diagonal' => $diagonal,
+ 'diagonal-m' => $diagonal_m,
+ 'position' => $set_as,
+ };
+ # print "x:$size_x y:$size_y rx:$res_x ry:$res_y dpi:$dpi\n";
+ ($res_x,$res_y,$size_x,$size_x_i,$size_y,$size_y_i,$set_as) = (0,0,0,0,0,0,0,0,undef);
+ }
+ my @working = split(/\s+/,$_);
+ # this is the monitor current dimensions
+ if ($working[1] =~ /\*/){
+ $working[1] =~ s/\*|\+//g;
+ $working[1] = sprintf("%.0f",$working[1]);
+ if ($monitor_id && %monitors){
+ $monitors{$monitor_id}->{'hz'} = $working[1];
+ }
+ ($diagonal,$dpi) = ('','');
+ # print Data::Dumper::Dumper \@monitors;
+ }
+ }
+ if (%monitors){
+ push(@xrandr_screens,\%monitors);
+ }
+ my $i = 0;
+ my $layouts;
+ if (!defined $graphics{'display-screens'} && $graphics{'screens'}){
+ $graphics{'display-screens'} = scalar @{$graphics{'screens'}};
+ }
+ map_monitor_ids(\@ids) if @ids;
+ foreach my $main (@{$graphics{'screens'}}){
+ # print "h: " . Data::Dumper::Dumper $main;
+ # print "h: " . Data::Dumper::Dumper @xrandr_screens;
+ # print $main->{'screen'}, "\n";
+ foreach my $x_screen (@xrandr_screens){
+ # print "d: " . Data::Dumper::Dumper $x_screen;
+ my @keys = sort keys %$x_screen;
+ if ($x_screen->{$keys[0]}{'screen'} eq $main->{'screen'} &&
+ !defined $graphics{'screens'}->[$i]{'monitors'}){
+ $graphics{'screens'}->[$i]{'monitors'} = $x_screen;
+ }
+ if ($extra > 1){
+ if (!$layouts){
+ $layouts = [];
+ set_monitor_layouts($layouts);
+ }
+ advanced_monitor_data($x_screen,$layouts);
+ }
+ if (!defined $main->{'size-x'}){
+ $graphics{'screens'}->[$i]{'size-missing'} = main::message('tool-missing-basic','xdpyinfo');
}
}
+ $i++;
}
+ undef $layouts;
+ # print "xrand: " . Data::Dumper::Dumper \@xrandr_screens;
+ print 'Data: xrandr: ', Data::Dumper::Dumper $graphics{'screens'} if $dbg[17];
+ main::log_data('dump','$graphics{screens}',$graphics{'screens'}) if $b_log;
eval $end if $b_log;
- return $tty;
}
-sub x_drivers {
+# case where no xpdyinfo display server/version data exists, or to set Wayland
+# Xwayland version, or Xvesa data.
+sub display_server_data {
+ eval $start if $b_log;
+ my ($program);
+ # load the extra X paths, it's important that these are first, because
+ # later Xorg versions show error if run in console or ssh if the true path
+ # is not used.
+ @paths = (qw(/usr/lib /usr/lib/xorg /usr/lib/xorg-server /usr/libexec /usr/X11R6/bin), @paths);
+ my (@data,$server,$version);
+ if (!$graphics{'x-server'} || !$graphics{'x-server'}->[0][1]){
+ # IMPORTANT: both commands send version data to stderr!
+ if ($program = main::check_program('Xorg')){
+ @data = main::grabber("$program -version 2>&1",'','strip');
+ $server = 'X.org';
+ }
+ elsif ($program = main::check_program('X')){
+ @data = main::grabber("$program -version 2>&1",'','strip');
+ $server = 'X.org';
+ }
+ elsif ($program = main::check_program('Xvesa')){
+ @data = main::grabber("$program -version 2>&1",'','strip');
+ $server = 'Xvesa';
+ $graphics{'display-driver'} = ['vesa'];
+ $graphics{'xvesa'} = $program;
+ if (!$graphics{'screens'}){
+ $graphics{'no-screens'} = main::message('screen-xvesa');
+ }
+ }
+ # print join('^ ', @paths), " :: $program\n";
+ # print Data::Dumper::Dumper \@data;
+ if ($data[0]){
+ if ($data[0] =~ /X.org X server (\S+)/i){
+ $version = $1;
+ }
+ elsif ($data[0] =~ /XFree86 Version (\S+)/i){
+ $version = $1;
+ $server = 'XFree86';
+ }
+ elsif ($data[0] =~ /X Window System Version (\S+)/i){
+ $version = $1;
+ }
+ elsif ($data[0] =~ /Xvesa from tinyx (\S+)/i){
+ $version = $1;
+ $server = 'TinyX Xvesa';
+ }
+ }
+ $graphics{'x-server'} = [[$server,$version]] if $server;
+ }
+ if ((!$b_display || $graphics{'protocol'} eq 'wayland') &&
+ ($program = main::check_program('Xwayland'))){
+ undef $version;
+ @data = main::grabber("$program -version 2>&1",'','strip');
+ # Slackware Linux Project Xwayland Version 21.1.4 (12101004)
+ # The X.Org Foundation Xwayland Version 21.1.4 (12101004)
+ if (@data){
+ $data[0] =~ /Xwayland Version (\S+)/;
+ $version = $1;
+ }
+ $graphics{'x-server'} = [] if !$graphics{'x-server'};
+ push(@{$graphics{'x-server'}},['Xwayland',$version]);
+ }
+ # remove extra X paths from global @paths
+ @paths = grep { !/^\/usr\/lib|xorg|X11R6|libexec/ } @paths;
+ eval $end if $b_log;
+}
+# for wayland display/monitor drivers, or if no display drivers found for x
+sub gpu_drivers_sys {
+ eval $start if $b_log;
+ my ($id) = @_;
+ my ($driver,@drivers);
+ # we only want list of drivers for cards with a connected monitor, and inactive
+ # ports are already removed by the 'all' stage.
+ foreach my $port (keys %{$monitor_ids}){
+ if (!$monitor_ids->{$port}{'drivers'} ||
+ ($id ne 'all' && $id ne $port) ||
+ !$monitor_ids->{$port}{'status'} ||
+ $monitor_ids->{$port}{'status'} ne 'connected'){
+ next;
+ }
+ else {
+ foreach $driver (@{$monitor_ids->{$port}{'drivers'}}){
+ push(@drivers,$driver);
+ }
+ }
+ }
+ if (@drivers){
+ @drivers = sort(@drivers);
+ main::uniq(\@drivers);
+ }
+ eval $end if $b_log;
+ @drivers ? return \@drivers : return;
+}
+sub display_drivers_x {
eval $start if $b_log;
my ($driver,@driver_data,,%drivers);
my ($alternate,$failed,$loaded,$sep,$unloaded) = ('','','','','');
@@ -14048,13 +15047,12 @@ sub x_drivers {
# list is from sgfxi plus non-free drivers, plus ARM drivers
my $list = join('|', qw(amdgpu apm ark armsoc atimisc ati
chips cirrus cyrix fbdev fbturbo fglrx geode glide glint
- i128 i740 i810-dec100 i810e i810 i815 i830 i845 i855 i865 i915 i945
- i965 iftv imstt intel ivtv mach64 mesa mga modesetting neomagic newport
- nouveau nsc nvidia nv openchrome r128 radeonhd radeon
- rendition s3virge s3 savage siliconmotion sisimedia sisusb sis
- sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx
- tdfx tga trident tseng unichrome v4l vboxvideo vesa vga via vmware vmwgfx
- voodoo));
+ i128 i740 i810-dec100 i810e i810 i815 i830 i845 i855 i865 i915 i945 i965
+ iftv imstt intel ivtv mach64 mesa mga modesetting neomagic newport
+ nouveau nsc nvidia nv openchrome r128 radeonhd radeon rendition
+ s3virge s3 savage siliconmotion sisimedia sisusb sis
+ sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx tdfx tga trident tseng
+ unichrome v4l vboxvideo vesa vga via vmware vmwgfx voodoo));
# 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;
@@ -14124,123 +15122,433 @@ sub x_drivers {
$alternate .= $sep . $_;
}
}
- @driver_data = ($loaded,$unloaded,$failed,$alternate);
+ if ($loaded || $unloaded || $failed || $alternate){
+ @driver_data = ($loaded,$unloaded,$failed,$alternate);
+ }
}
eval $end if $b_log;
- return @driver_data;
+ @driver_data ? return \@driver_data : return;
}
-# fallback if no glx x version data found
-sub x_version {
+sub display_protocol {
eval $start if $b_log;
- my ($version,@data,$program);
- # load the extra X paths, it's important that these are first, because
- # later Xorg versions show error if run in console or ssh if the true path
- # is not used.
- @paths = (qw(/usr/lib /usr/lib/xorg /usr/lib/xorg-server /usr/libexec /usr/X11R6/bin), @paths);
- # IMPORTANT: both commands send version data to stderr!
- if ($program = main::check_program('Xorg')){
- @data = main::grabber("$program -version 2>&1");
+ $graphics{'protocol'} = '';
+ if ($ENV{'XDG_SESSION_TYPE'}){
+ $graphics{'protocol'} = $ENV{'XDG_SESSION_TYPE'};
}
- elsif ($program = main::check_program('X')){
- @data = main::grabber("$program -version 2>&1");
+ if (!$graphics{'protocol'} && $ENV{'WAYLAND_DISPLAY'}){
+ $graphics{'protocol'} = $ENV{'WAYLAND_DISPLAY'};
}
- elsif ($program = main::check_program('Xvesa')){
- @data = main::grabber("$program -version 2>&1");
+ # can show as wayland-0
+ if ($graphics{'protocol'} && $graphics{'protocol'} =~ /wayland/i){
+ $graphics{'protocol'} = 'wayland';
}
- # print join('^ ', @paths), " :: $program\n";
- # print Data::Dumper::Dumper \@data;
- if (@data){
- foreach (@data){
- if (/^X.org X server/i){
- $version = (split(/\s+/, $_))[3];
- last;
+ # yes, I've seen this in 2019 distros, sigh
+ elsif ($graphics{'protocol'} eq 'tty'){
+ $graphics{'protocol'} = '';
+ }
+ # need to confirm that there's a point to this test, I believe no, fails out of x
+ # loginctl also results in the session id
+ if (!$graphics{'protocol'} && $b_display && $force{'display'}){
+ if (my $program = main::check_program('loginctl')){
+ my $id = '';
+ # $id = $ENV{'XDG_SESSION_ID'}; # returns tty session in console
+ my @data = main::grabber("$program --no-pager --no-legend 2>/dev/null",'','strip');
+ foreach (@data){
+ next if /tty[v]?[0-6]$/; # freebsd: ttyv3
+ $id = (split(/\s+/, $_))[0];
+ last; # multiuser? too bad, we'll go for the first one
}
- elsif (/^X Window System Version/i){
- $version = (split(/\s+/, $_))[4];
- last;
+ if ($id){
+ my $temp = (main::grabber("$program show-session $id -p Type --no-pager --no-legend 2>/dev/null"))[0];
+ $temp =~ s/Type=// if $temp;
+ # ssh will not show /dev/ttyx so would have passed the first test
+ $graphics{'protocol'} = $temp if $temp && $temp ne 'tty';
}
- elsif (/^Xvesa from/i){
- $version = (split(/\s+/, $_))[3];
- $version = "Xvesa $version" if $version;
- last;
+ }
+ }
+ $graphics{'protocol'} = lc($graphics{'protocol'}) if $graphics{'protocol'};
+ eval $end if $b_log;
+}
+
+## MONITOR DATA ##
+sub set_monitors_sys {
+ eval $start if $b_log;
+ my $pattern = '/sys/class/drm/card[0-9]/device/driver/module/drivers/*';
+ my @cards_glob = main::globber($pattern);
+ $pattern = '/sys/class/drm/card*-*/{edid,enabled,status,modes}';
+ my @ports_glob = main::globber($pattern);
+ # print Data::Dumper::Dumper \@cards_glob;
+ # print Data::Dumper::Dumper \@ports_glob;
+ my ($card,%cards,@data,$file,$item,$path,$port);
+ foreach $file (@cards_glob){
+ next if ! -e $file;
+ if ($file =~ m|^/sys/class/drm/(card\d+)/.+?/drivers/(\S+):(\S+)$|){
+ push(@{$cards{$1}},[$2,$3]);
+ }
+ }
+ # print Data::Dumper::Dumper \%cards;
+ foreach $file (sort @ports_glob){
+ next if ! -r $file;
+ $item = $file;
+ $item =~ s|(/.*/(card\d+)-([^/]+))/(.+)||;
+ $path = $1;
+ $card = $2;
+ $port = $3;
+ $item = $4;
+ next if !$1;
+ $monitor_ids = {} if !$monitor_ids;
+ $monitor_ids->{$port}{'monitor'} = $port;
+ if (!$monitor_ids->{$port}{'drivers'} && $cards{$card}){
+ foreach my $info (@{$cards{$card}}){
+ push(@{$monitor_ids->{$port}{'drivers'}},$info->[1]);
+ }
+ }
+ $monitor_ids->{$port}{'path'} = readlink($path);
+ $monitor_ids->{$port}{'path'} =~ s|^\.\./\.\.|/sys|;
+ if ($item eq 'status' || $item eq 'enabled'){
+ # print "$file\n";
+ $monitor_ids->{$port}{$item} = main::reader($file,'strip',0);
+ }
+ # arm: U:1680x1050p-0
+ elsif ($item eq 'modes'){
+ @data = main::reader($file,'strip');
+ next if !@data;
+ if (scalar @data == 1 || $data[-1] eq $data[0]){
+ $monitor_ids->{$port}{'modes-min-max'} = $data[0];
+ }
+ else {
+ $monitor_ids->{$port}{'modes-min'} = $data[-1];
+ $monitor_ids->{$port}{'modes-max'} = $data[0];
+ }
+ }
+ elsif ($item eq 'edid'){
+ next if -s $file;
+ monitor_edid_data($file,$port);
+ }
+ }
+ main::log_data('dump','$ports ref',$monitor_ids) if $b_log;
+ print Data::Dumper::Dumper $monitor_ids if $dbg[44];
+ eval $end if $b_log;
+}
+sub monitor_edid_data {
+ eval $start if $b_log;
+ my ($file,$port) = @_;
+ my (@data);
+ open my $fh, '<:raw', $file or return; # it failed, give up, we don't care why
+ my $edid_raw = do { local $/; <$fh> };
+ return if !$edid_raw;
+ my $edid = ParseEDID::parse_edid($edid_raw,$dbg[47]);
+ main::log_data('dump','Parse::EDID',$edid) if $b_log;
+ print Data::Dumper::Dumper $edid if $dbg[44];
+ return if !$edid || ref $edid ne 'HASH' || !%$edid;
+ $monitor_ids->{$port}{'build-date'} = $edid->{'year'};
+ if ($edid->{'gamma'}){
+ $monitor_ids->{$port}{'gamma'} = ($edid->{'gamma'}/100 + 0);
+ }
+ if ($edid->{'monitor_name'} || $edid->{'manufacturer_name_nice'}){
+ my $model = '';
+ if ($edid->{'manufacturer_name_nice'}){
+ $model = $edid->{'manufacturer_name_nice'};
+ }
+ if ($edid->{'monitor_name'}){
+ $model .= ' ' if $model;
+ $model .= $edid->{'monitor_name'};
+ }
+ $monitor_ids->{$port}{'model'} = main::remove_duplicates(main::clean($model));
+ }
+ if ($edid->{'diagonal_size'}){
+ $monitor_ids->{$port}{'diagonal-m'} = sprintf('%.0f',($edid->{'diagonal_size'}*25.4)) + 0;
+ $monitor_ids->{$port}{'diagonal'} = sprintf('%.1f',$edid->{'diagonal_size'}) + 0;
+ }
+ if ($edid->{'ratio_name'}){
+ $edid->{'ratio_name'} =~ s|/|:|; # this should be changed in ParseEDID
+ $monitor_ids->{$port}{'ratio'} = $edid->{'ratio_name'};
+ }
+ if ($edid->{'detailed_timings'}){
+ $monitor_ids->{$port}{'res-x'} = $edid->{'detailed_timings'}[0]{'horizontal_active'};
+ $monitor_ids->{$port}{'res-y'} = $edid->{'detailed_timings'}[0]{'vertical_active'};
+ if ($edid->{'detailed_timings'}[0]{'horizontal_image_size'}){
+ $monitor_ids->{$port}{'size-x'} = $edid->{'detailed_timings'}[0]{'horizontal_image_size'};
+ $monitor_ids->{$port}{'size-x-i'} = sprintf('%.1f',($edid->{'detailed_timings'}[0]{'horizontal_image_size'}/25.4)) + 0;
+ }
+ if ($edid->{'detailed_timings'}[0]{'vertical_image_size'}){
+ $monitor_ids->{$port}{'size-y'} = $edid->{'detailed_timings'}[0]{'vertical_image_size'};
+ $monitor_ids->{$port}{'size-y-i'} = sprintf('%.1f',($edid->{'detailed_timings'}[0]{'vertical_image_size'}/25.4)) + 0;
+ }
+ if ($edid->{'detailed_timings'}[0]{'horizontal_dpi'}){
+ $monitor_ids->{$port}{'dpi'} = sprintf('%.0f',$edid->{'detailed_timings'}[0]{'horizontal_dpi'}) + 0;
+ }
+ }
+ if ($edid->{'serial_number'} || $edid->{'serial_number2'}){
+ # this looks much more like a real serial than the default: serial_number
+ if ($edid->{'serial_number2'} && @{$edid->{'serial_number2'}}){
+ $monitor_ids->{$port}{'serial'} = main::clean_dmi($edid->{'serial_number2'}[0]);
+ }
+ elsif ($edid->{'serial_number'}){
+ $monitor_ids->{$port}{'serial'} = main::clean_dmi($edid->{'serial_number'});
+ }
+ }
+ eval $end if $b_log;
+}
+sub advanced_monitor_data {
+ eval $start if $b_log;
+ my ($monitors,$layouts) = @_;
+ my (@horiz,@vert);
+ my $position = '';
+ # then see if we can locate a default position primary monitor
+ foreach my $key (keys %$monitors){
+ next if !defined $monitors->{$key}{'pos-x'};
+ # this is the only scenario we can guess at if no primary detected
+ if (!$monitors->{$key}{'primary'} &&
+ $monitors->{$key}{'pos-x'} == 0 && $monitors->{$key}{'pos-y'} == 0){
+ $monitors->{$key}{'position'} = 'primary';
+ $monitors->{$key}{'primary'} = $monitors->{$key}{'monitor'};
+ }
+ if (!grep {$monitors->{$key}{'pos-x'} == $_} @horiz){
+ push(@horiz,$monitors->{$key}{'pos-x'});
+ }
+ if (!grep {$monitors->{$key}{'pos-y'} == $_} @vert){
+ push(@vert,$monitors->{$key}{'pos-y'});
+ }
+ }
+ @horiz = sort(@horiz);
+ @vert = sort(@vert);
+ my ($h,$v) = (scalar(@horiz),scalar(@vert));
+ # print Data::Dumper::Dumper \@horiz;
+ # print Data::Dumper::Dumper \@vert;
+ # print Data::Dumper::Dumper $layouts;
+ # print Data::Dumper::Dumper $monitor_map;
+ foreach my $key (keys %$monitors){
+ if (@horiz && @vert){
+ $monitors->{$key}{'position'} ||= '';
+ $position = '';
+ $position = get_monitor_position($monitors->{$key},\@horiz,\@vert);
+ $position = $layouts->[$v][$h]{$position} if $layouts->[$v][$h]{$position};
+ $monitors->{$key}{'position'} .= ',' if $monitors->{$key}{'position'};
+ $monitors->{$key}{'position'} .= $position;
+ }
+ my $mon_mapped = ($monitor_map) ? $monitor_map->{$monitors->{$key}{'monitor'}} : undef;
+ # these are already set for monitor_ids, only need this for Xorg data.
+ if ($mon_mapped && $monitor_ids->{$mon_mapped}){
+ # note: xorg drivers can be different than gpu drivers
+ $monitors->{$key}{'drivers'} = gpu_drivers_sys($mon_mapped);
+ $monitors->{$key}{'build-date'} = $monitor_ids->{$mon_mapped}{'build-date'};
+ $monitors->{$key}{'diagonal'} = $monitor_ids->{$mon_mapped}{'diagonal'};
+ $monitors->{$key}{'diagonal-m'} = $monitor_ids->{$mon_mapped}{'diagonal-m'};
+ $monitors->{$key}{'gamma'} = $monitor_ids->{$mon_mapped}{'gamma'};
+ $monitors->{$key}{'modes-min-max'} = $monitor_ids->{$mon_mapped}{'modes-min-max'};
+ $monitors->{$key}{'modes-max'} = $monitor_ids->{$mon_mapped}{'modes-max'};
+ $monitors->{$key}{'modes-min'} = $monitor_ids->{$mon_mapped}{'modes-min'};
+ $monitors->{$key}{'model'} = $monitor_ids->{$mon_mapped}{'model'};
+ $monitors->{$key}{'ratio'} = $monitor_ids->{$mon_mapped}{'ratio'};
+ $monitors->{$key}{'serial'} = $monitor_ids->{$mon_mapped}{'serial'};
+ if ($mon_mapped ne $monitors->{$key}{'monitor'}){
+ $monitors->{$key}{'monitor-mapped'} = $mon_mapped;
+ }
+ }
+ }
+ # not printing out primary if Screen has only 1 Monitor
+ if (scalar keys %$monitors == 1){
+ my @keys = keys %$monitors;
+ $monitors->{$keys[0]}{'position'} = undef;
+ }
+ print Data::Dumper::Dumper $monitors if $dbg[45];
+ eval $end if $b_log;
+}
+# clear out all disabled or not connected monitor ports
+sub set_active_monitors {
+ eval $start if $b_log;
+ foreach my $key (keys %$monitor_ids){
+ if (!$monitor_ids->{$key}{'enabled'} ||
+ $monitor_ids->{$key}{'enabled'} ne 'enabled' ||
+ !$monitor_ids->{$key}{'status'} ||
+ $monitor_ids->{$key}{'status'} ne 'connected'){
+ delete $monitor_ids->{$key};
+ }
+ }
+ # print 'active monitors: ', Data::Dumper::Dumper $monitor_ids;
+ eval $end if $b_log;
+}
+sub get_monitor_position {
+ eval $start if $b_log;
+ my ($monitor,$horiz,$vert) = @_;
+ my ($i,$position) = (1,'');
+ foreach (@$vert){
+ if ($_ == $monitor->{'pos-y'}){
+ $position = $i . '-';
+ last;
+ }
+ $i++;
+ }
+ $i = 1;
+ foreach (@$horiz){
+ if ($_ == $monitor->{'pos-x'}){
+ $position .= $i;
+ last;
+ }
+ $i++;
+ }
+ main::log_data('data','pos-raw: ' . $position) if $b_log;
+ eval $end if $b_log;
+ return $position;
+}
+sub set_monitor_layouts {
+ my ($layouts) = @_;
+ $layouts->[1][2] = {'1-1' => 'left','1-2' => 'right'};
+ $layouts->[1][3] = {'1-1' => 'left','1-2' => 'center','1-3' => 'right'};
+ $layouts->[1][4] = {'1-1' => 'left','1-2' => 'center-l','1-3' => 'center-r',
+ '1-4' => 'right'};
+ $layouts->[2][1] = {'1-1' => 'top','2-1' => 'bottom'};
+ $layouts->[2][2] = {'1-1' => 'top-left','1-2' => 'top-right',
+ '2-1' => 'bottom-l','2-2' => 'bottom-r'};
+ $layouts->[2][3] = {'1-1' => 'top-left','1-2' => 'top-center','1-3' => 'top-right',
+ '2-1' => 'bottom-l','2-2' => 'bottom-c','2-3' => 'bottom-r'};
+ $layouts->[3][1] = {'1-1' => 'top','2-1' => 'middle','3-1' => 'bottom'};
+ $layouts->[3][2] = {'1-1' => 'top-left','1-2' => 'top-right',
+ '2-1' => 'middle-l','2-2' => 'middle-r',
+ '3-1' => 'bottom-l','3-2' => 'bottom-r'};
+ $layouts->[3][3] = {'1-1' => 'top-left','1-2' => 'top-center',,'1-3' => 'top-right',
+ '2-1' => 'middle-l','2-2' => 'middle-c','2-3' => 'middle-r',
+ '3-1' => 'bottom-l','3-2' => 'bottom-c','3-3' => 'bottom-r'};
+}
+# this is required to resolve the insane situation where some xorg drivers change
+# the kernel ID for the port to something slightly different, amdgpu in particular.
+sub map_monitor_ids {
+ eval $start if $b_log;
+ my ($display_ids) = @_;
+ return if !$monitor_ids;
+ @$display_ids = sort { lc($a) cmp lc($b) } @$display_ids;
+ my @sys_ids;
+ foreach my $key (keys %$monitor_ids){
+ if ($monitor_ids->{$key}{'status'} eq 'connected' &&
+ $monitor_ids->{$key}{'enabled'} eq 'enabled'){
+ push(@sys_ids,$key);
+ }
+ }
+ @sys_ids = sort { lc($a) cmp lc($b) } @sys_ids;
+ # @sys_ids = ('DP-1-1','DVI-I-1','VGA-1');
+ main::log_data('dump','@sys_ids',\@sys_ids) if $b_log;
+ main::log_data('dump','$xrandr_ids ref',$display_ids) if $b_log;
+ print 'sys: ', Data::Dumper::Dumper \@sys_ids if $dbg[45];
+ print 'display: ', Data::Dumper::Dumper $display_ids if $dbg[45];
+ return if scalar @sys_ids != scalar @$display_ids;
+ $monitor_map = {};
+ # known patterns: s: DP-1, d: DisplayPort-0; s: HDMI-A-2, d: HDMI-A-1
+ # s: HDMI-A-2, d: HDMI-2; s: DVI-1 d: DVI1; s: HDMI-1, d: HDMI1
+ # s: DVI-I-1, d: DVI0; s: VGA-1, d: VGA1; s: DP-1-1; d: DP-1-1
+ my ($d_1,$d_2,$d_3,$d_4,$s_1,$s_2,$s_3,$s_4);
+ for (my $i=0; $i < scalar @$display_ids; $i++){
+ print "s: $sys_ids[$i] x: $display_ids->[$i]\n" if $dbg[45];
+ if ($display_ids->[$i] =~ /^([A-Z]+)(-[AB]|-[ADI]|-[ADI]-\d+?|-\d+?)?(-)?(\d+)$/i){
+ $d_1 = $1;
+ $d_2 = ($2) ? $2 : '';
+ $d_3 = ($3) ? $3 : '';
+ $d_4 = $4;
+ $d_1 =~ s/^DisplayPort/DP/i; # amdgpu...
+ print " d1: $d_1 d2: $d_2 d3: $d_3 d4: $d_4\n" if $dbg[45];
+ if ($sys_ids[$i] =~ /^([A-Z]+?)(-[AB]|-[ADI]|-[ADI]-\d+?|-\d+?)?(-)?(\d+)$/i){
+ $s_1 = $1;
+ $s_2 = ($2) ? $2 : '';
+ $s_3 = ($3) ? $3 : '';
+ $s_4 = $4;
+ $d_1 = $s_1 if uc($d_1) eq 'XWAYLAND';
+ print " d1: $d_1 s1: $s_1 s2: $s_2 s3: $s_3 s4: $s_4\n" if $dbg[45];
+ if ($d_1 eq $s_1 && ($d_4 == $s_4 || $d_4 == ($s_4 - 1))){
+ $monitor_map->{$display_ids->[$i]} = $sys_ids[$i];
+ }
+ }
+ }
+ if (!$monitor_map->{$display_ids->[$i]}){
+ $monitor_map->{$display_ids->[$i]} = main::message('monitor-id');
+ }
+ }
+ main::log_data('dump','$monitor_map ref',$monitor_map) if $b_log;
+ print Data::Dumper::Dumper $monitor_map if $dbg[45];
+ eval $end if $b_log;
+}
+# handle case of monitor on left or right edge, vertical that is.
+# mm dimensiions are based on the default position of monitor as sold.
+# very old systems may not have non 0 value for size x or y
+# size, res x,y by reference
+sub flip_size_x_y {
+ eval $start if $b_log;
+ my ($size_x,$size_y,$res_x,$res_y) = @_;
+ if ((($$res_x/$$res_y > 1 && $$size_x/$$size_y < 1) ||
+ ($$res_x/$$res_y < 1 && $$size_x/$$size_y > 1))){
+ ($$size_x,$$size_y) = ($$size_y,$$size_x);
+ }
+ eval $end if $b_log;
+}
+## COMPOSITOR DATA ##
+sub set_compositor_data {
+ eval $start if $b_log;
+ if (my $compositors = get_compositors()){
+ my @data;
+ foreach my $compositor (@$compositors){
+ # gnome-shell is incredibly slow to return version
+ if (($extra > 1 || $graphics{'protocol'} eq 'wayland') &&
+ (!$show{'system'} || $compositor ne 'gnome-shell')){
+ $graphics{'compositors'} = [] if !$graphics{'compositors'};
+ push(@{$graphics{'compositors'}},[main::program_data($compositor,$compositor)]);
+ }
+ else {
+ $graphics{'compositors'} = [] if !$graphics{'compositors'};
+ push(@{$graphics{'compositors'}},[(main::program_values($compositor))[3]]);
}
}
}
- # remove extra X paths
- @paths = grep { !/^\/usr\/lib|xorg|X11R6|libexec/ } @paths;
eval $end if $b_log;
- return $version;
}
-# $1 - protocol: wayland|x11
-sub display_compositor {
+sub get_compositors {
eval $start if $b_log;
- my ($protocol) = @_;
- my ($compositor) = ('');
+ my @found;
main::set_ps_gui() if !$loaded{'ps-gui'};
if (@ps_gui){
- # 1 check program; 2 search; 3 unused version; 4 print
- my @compositors = (
- ['asc','asc','','asc'],
- ['budgie-wm','budgie-wm','','budgie-wm'],
- # owned by: compiz-core in debian
- ['compiz','compiz','','compiz'],
- ['compton','compton','','compton'],
- # as of version 20 is wayland compositor
- ['enlightenment','enlightenment','','enlightenment'],
- ['gnome-shell','gnome-shell','','gnome-shell'],
- ['kwin_wayland','kwin_wayland','','kwin_wayland'],
- ['kwin_x11','kwin_x11','','kwin_x11'],
- # ['kwin','kwin','','kwin'],
- ['marco','marco','','marco'],
- ['muffin','muffin','','muffin'],
- ['mutter','mutter','','mutter'],
- ['weston','weston','','weston'],
- # these are more obscure, so check for them last
- ['3dwm','3dwm','','3dwm'],
- ['dcompmgr','dcompmgr','','dcompmgr'],
- ['dwc','dwc','','dwc'],
- ['fireplace','fireplace','','fireplace'],
- ['grefson','grefson','','grefson'],
- ['kmscon','kmscon','','kmscon'],
- ['liri','liri','','liri'],
- ['metisse','metisse','','metisse'],
- ['mir','mir','','mir'],
- ['moblin','moblin','','moblin'],
- ['motorcar','motorcar','','motorcar'],
- ['monsterwm','monsterwm','','monsterwm'],
- ['orbital','orbital','','orbital'],
- ['papyros','papyros','','papyros'],
- ['perceptia','perceptia','','perceptia'],
- ['picom','picom','','picom'],
- ['rustland','rustland','','rustland'],
- ['sommelier','sommelier','','sommelier'],
- ['sway','sway','','sway'],
- ['swc','swc','','swc'],
- ['ukwm','ukwm','','ukwm'],
- ['unagi','unagi','','unagi'],
- ['unity-system-compositor','unity-system-compositor','','unity-system-compositor'],
- ['way-cooler','way-cooler','','way-cooler'],
- ['wavy','wavy','','wavy'],
- ['wayfire','wayfire','','wayfire'],
- ['wayhouse','wayhouse','','wayhouse'],
- ['westford','westford','','westford'],
- ['xcompmgr','xcompmgr','','xcompmgr'],
- ['xfwm4','xfwm4','','xfwm4'],
- ['xfwm5','xfwm5','','xfwm5'],
- ['xfwm','xfwm','','xfwm'],
- );
- foreach my $item (@compositors){
- # no need to use check program with short list of ps_gui
- # if (main::check_program($item[0]) && (grep {/^$item[1]$/} @ps_gui)){
- if (grep {/^$item->[1]$/} @ps_gui){
- $compositor = $item->[3];
- last;
+ # ORDER MATTES!
+ # notes: compiz: debian package compiz-core;
+ # enlightenment: as of version 20 wayland compositor
+ my @compositors = qw(budgie-wm compiz compton enlightenment gnome-shell
+ kwin_wayland kwin_x11 kwinft marco muffin mutter);
+ # these are more obscure, so check for them after primary common ones
+ push (@compositors,qw(3dwm dcompmgr gala kmscon metisse mir moblin
+ monsterwm picom ukwm unagi unity-system-compositor xcompmgr xfwm4
+ xfwm5 xfwm));
+ my $matches = join('|',@compositors) . $wl_compositors;
+ foreach my $psg (@ps_gui){
+ if ($psg =~ /^($matches)$/){
+ push(@found,$1);
+ }
+ }
+ }
+ main::log_data('dump','compositors:', \@found) if $b_log;
+ eval $end if $b_log;
+ (@found) ? return \@found : return;
+}
+
+## UTILITIES ##
+sub tty_data(){
+ eval $start if $b_log;
+ my ($tty);
+ if ($size{'term-cols'}){
+ $tty = "$size{'term-cols'}x$size{'term-lines'}";
+ }
+ # this is broken
+ elsif ($b_irc && $client{'console-irc'}){
+ ShellData::console_irc_tty() if !$loaded{'con-irc-tty'};
+ my $tty_working = $client{'con-irc-tty'};
+ if ($tty_working ne '' && (my $program = main::check_program('stty'))){
+ my $tty_arg = ($bsd_type) ? '-f' : '-F';
+ # handle vtnr integers, and tty ID with letters etc.
+ $tty_working = "tty$tty_working" if -e "/dev/tty$tty_working";
+ $tty = (main::grabber("$program $tty_arg /dev/$tty_working size 2>/dev/null"))[0];
+ if ($tty){
+ my @temp = split(/\s+/, $tty);
+ $tty = "$temp[1]x$temp[0]";
}
}
}
- main::log_data('data',"compositor: $compositor") if $b_log;
eval $end if $b_log;
- return $compositor;
+ return $tty;
}
}
@@ -14281,7 +15589,7 @@ sub get {
},);
}
elsif (@lsblk && !$use{'logical-lvm'} && ($alerts{'lvs'}->{'action'} eq 'permissions' ||
- $alerts{'lvs'}->{'action'} eq 'missing')){
+ $alerts{'lvs'}->{'action'} eq 'missing')){
my $key = 'Message';
push(@rows, {
main::key($num++,0,1,$key) => main::message('logical-data',''),
@@ -14445,9 +15753,9 @@ sub general_data {
%parent = LsblkData::get($row->{'parent'});
next if !$parent{'fs'};
if ($row->{'type'} && (($row->{'type'} eq 'crypt' ||
- $row->{'type'} eq 'mpath' || $row->{'type'} eq 'multipath') ||
- ($row->{'type'} eq 'dm' && $row->{'name'} =~ /veracrypt/i) ||
- ($parent{'fs'} eq 'bcache'))){
+ $row->{'type'} eq 'mpath' || $row->{'type'} eq 'multipath') ||
+ ($row->{'type'} eq 'dm' && $row->{'name'} =~ /veracrypt/i) ||
+ ($parent{'fs'} eq 'bcache'))){
my (@full_components,$mapped,$type);
$mapped = $mapper{$row->{'name'}} if %mapper;
next if grep(/^$row->{'name'}$/, @found);
@@ -14656,6 +15964,18 @@ sub get {
}
}
}
+ elsif ($fake{'elbrus'} || $cpu_arch eq 'elbrus'){
+ if ($fake{'elbrus'} || (my $program = main::check_program('fruid_print'))){
+ %data = machine_data_fruid($program);
+ }
+ if (%data){
+ @rows = machine_output(\%data);
+ }
+ elsif (!$key1){
+ $key1 = 'Message';
+ $val1 = main::message('machine-data-fruid');
+ }
+ }
elsif (!$bsd_type){
# this uses /proc/cpuinfo so only GNU/Linux
if (%risc){
@@ -14696,8 +16016,9 @@ sub machine_output {
# print "$key: $data->{$key}\n";
# }
if (!$data->{'sys_vendor'} ||
- ($data->{'board_vendor'} && $data->{'sys_vendor'} eq $data->{'board_vendor'} &&
- !$data->{'product_name'} && !$data->{'product_version'} && !$data->{'product_serial'})){
+ ($data->{'board_vendor'} && $data->{'sys_vendor'} eq $data->{'board_vendor'} &&
+ !$data->{'product_name'} && !$data->{'product_version'} &&
+ !$data->{'product_serial'})){
$b_skip_system = 1;
}
# The goal here is to not show laptop/mobile devices
@@ -14708,11 +16029,11 @@ sub machine_output {
# in case where the vendor is the same and the version is the same and not null,
# otherwise the version information is going to be different in all cases I think
if (($data->{'sys_vendor'} && $data->{'board_vendor'} &&
- $data->{'sys_vendor'} eq $data->{'board_vendor'}) &&
- (($data->{'product_version'} && $data->{'board_version'} &&
- $data->{'product_version'} eq $data->{'board_version'}) ||
- (!$data->{'product_version'} && $data->{'product_name'} && $data->{'board_name'} &&
- $data->{'product_name'} eq $data->{'board_name'}))){
+ $data->{'sys_vendor'} eq $data->{'board_vendor'}) &&
+ (($data->{'product_version'} && $data->{'board_version'} &&
+ $data->{'product_version'} eq $data->{'board_version'}) ||
+ (!$data->{'product_version'} && $data->{'product_name'} && $data->{'board_name'} &&
+ $data->{'product_name'} eq $data->{'board_name'}))){
$b_skip_system = 1;
}
}
@@ -14797,6 +16118,9 @@ sub machine_output {
if ($extra > 2 && $data->{'board_uuid'}){
$rows[$j]->{main::key($num++,0,3,'uuid')} = $data->{'board_uuid'};
}
+ if ($extra > 1 && $data->{'board_mfg_date'}){
+ $rows[$j]->{main::key($num++,0,3,'mfg-date')} = $data->{'board_mfg_date'};
+ }
$rows[$j]->{main::key($num++,1,1,$firmware)} = $bios_vendor;
$rows[$j]->{main::key($num++,0,2,'v')} = $bios_version;
if ($bios_rev){
@@ -14846,7 +16170,48 @@ sub machine_soc_output {
eval $end if $b_log;
return @rows;
}
-
+sub machine_data_fruid {
+ eval $start if $b_log;
+ my ($program) = @_;
+ my ($b_start,%data,@fruid);
+ if (!$fake{'elbrus'}){
+ @fruid = main::grabber("$program 2>/dev/null",'','strip');
+ }
+ else {
+ # my $file;
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/fruid/fruid-e904-1_full.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/fruid/fruid-e804-1_full.txt";
+ # @fruid = main::reader($file,'strip');
+ }
+ # print Data::Dumper::Dumper \@fruid;
+ foreach (@fruid){
+ $b_start = 1 if /^Board info/;
+ next if !$b_start;
+ my @split = split(/\s*:\s+/,$_,2);
+ if ($split[0] eq 'Mfg. Date/Time'){
+ $data{'board_mfg_date'} = $split[1];
+ $data{'board_mfg_date'} =~ s/^(\d+:\d+)\s//;
+ }
+ elsif ($split[0] eq 'Board manufacturer'){
+ $data{'board_vendor'} = $split[1];
+ }
+ elsif ($split[0] eq 'Board part number'){
+ $data{'board_part_nu'} = $split[1];
+ }
+ elsif ($split[0] eq 'Board product name'){
+ $data{'board_name'} = $split[1];
+ }
+ elsif ($split[0] eq 'Board serial number'){
+ $data{'board_serial'} = $split[1];
+ }
+ elsif ($split[0] eq 'Board product version'){
+ $data{'board_version'} = $split[1];
+ }
+ }
+ print Data::Dumper::Dumper \%data if $dbg[28];
+ main::log_data('dump','%data',\%data) if $b_log;
+ return %data;
+}
sub machine_data_sys {
eval $start if $b_log;
my (%data,$path,$vm);
@@ -15454,6 +16819,9 @@ sub device_output {
$rows[$j]->{main::key($num++,0,3,'modules')} = $row->[10] if $row->[10];
}
$row->[8] ||= 'N/A';
+ if ($extra > 1 && $bus_id ne 'N/A'){
+ 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'));
$rows[$j]->{main::key($num++,0,2,'bus-ID')} = $bus_id;
@@ -16749,7 +18117,7 @@ sub swap_data {
}
sub swap_advanced_data {
eval $start if $b_log;
- my ($swappiness,$cache_pressure) = (undef,undef);
+ my ($swappiness,$cache_pressure) = ();
if (-r '/proc/sys/vm/swappiness'){
$swappiness = main::reader('/proc/sys/vm/swappiness','',0);
if (defined $swappiness){
@@ -18394,7 +19762,7 @@ sub check_zfs_status {
## RamItem
{
package RamItem;
-my (@vendors,%vendor_ids);
+my ($vendors,$vendor_ids);
sub get {
my (@data,@rows,$key1,@ram,$val1);
my $num = 0;
@@ -18436,6 +19804,7 @@ sub get {
});
}
push(@rows,@data);
+ ($vendors,$vendor_ids) = ();
eval $end if $b_log;
return @rows;
}
@@ -18511,7 +19880,7 @@ sub ram_output {
$rows[$j]->{main::key($num++,0,3,'info')} = $mod->{'type'};
}
if ($mod->{'speed'} && $mod->{'configured-clock-speed'} &&
- $mod->{'speed'} ne $mod->{'configured-clock-speed'}){
+ $mod->{'speed'} ne $mod->{'configured-clock-speed'}){
$rows[$j]->{main::key($num++,1,3,'speed')} = '';
$rows[$j]->{main::key($num++,0,4,'spec')} = $mod->{'speed'};
$rows[$j]->{main::key($num++,0,4,'note')} = $mod->{'speed-note'} if $mod->{'speed-note'};
@@ -18801,9 +20170,9 @@ sub dmidecode_data {
$part_number = $result[1] if $result[1];
}
if ($vendor_id && !$manufacturer){
- set_vendor_ids() if !%vendor_ids;
- if ($vendor_ids{$vendor_id}){
- $manufacturer = $vendor_ids{$vendor_id};
+ set_vendor_ids() if !$vendor_ids;
+ if ($vendor_ids->{$vendor_id}){
+ $manufacturer = $vendor_ids->{$vendor_id};
}
}
$ram[$handle]->{'derived-module-size'} = $derived_module_size;
@@ -18959,7 +20328,7 @@ sub process_data {
}
# 2: now check to see if actually found module sizes are > than listed max module, replace if >
if ($item->{'max-module-size'} && $item->{'derived-module-size'} &&
- $item->{'derived-module-size'} > $item->{'max-module-size'}){
+ $item->{'derived-module-size'} > $item->{'max-module-size'}){
$item->{'max-module-size'} = $item->{'derived-module-size'};
$est_mod = $est;
}
@@ -18974,13 +20343,13 @@ sub process_data {
if ($item->{'used-capacity'} && $item->{'max-capacity-16'}){
if ($item->{'used-capacity'} > $max_cap){
if ($item->{'max-module-size'} &&
- $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'max-module-size'})){
+ $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'max-module-size'})){
$max_cap = $item->{'slots-16'} * $item->{'max-module-size'};
$est_cap = $est;
print "A\n" if $b_debug;
}
elsif ($item->{'derived-module-size'} &&
- $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'derived-module-size'})){
+ $item->{'used-capacity'} < ($item->{'slots-16'} * $item->{'derived-module-size'})){
$max_cap = $item->{'slots-16'} * $item->{'derived-module-size'};
$est_cap = $est;
print "B\n" if $b_debug;
@@ -18997,7 +20366,7 @@ sub process_data {
if (!$est_cap){
# do not do this for only single modules found, max mod size can be equal to the array size
if ($item->{'slots-16'} > 1 && $item->{'device-count-found'} > 1 &&
- $max_cap < ($item->{'derived-module-size'} * $item->{'slots-16'})){
+ $max_cap < ($item->{'derived-module-size'} * $item->{'slots-16'})){
$max_cap = $item->{'derived-module-size'} * $item->{'slots-16'};
$est_cap = $est;
print "D\n" if $b_debug;
@@ -19010,9 +20379,9 @@ sub process_data {
## handle cases where we have type 5 data: mms x device count equals type 5 max cap
# however do not use it if cap / devices equals the derived module size
elsif ($item->{'max-module-size'} > 0 &&
- ($item->{'max-module-size'} * $item->{'slots-16'}) == $item->{'max-capacity-5'} &&
- $item->{'max-capacity-5'} != $item->{'max-capacity-16'} &&
- $item->{'derived-module-size'} != ($item->{'max-capacity-16'}/$item->{'slots-16'})){
+ ($item->{'max-module-size'} * $item->{'slots-16'}) == $item->{'max-capacity-5'} &&
+ $item->{'max-capacity-5'} != $item->{'max-capacity-16'} &&
+ $item->{'derived-module-size'} != ($item->{'max-capacity-16'}/$item->{'slots-16'})){
$max_cap = $item->{'max-capacity-5'};
$est_cap = $est;
print "F\n" if $b_debug;
@@ -19192,7 +20561,7 @@ sub speed_mapper {
return ($speeds{$type}) ? $speeds{$type} . ' MT/s' : $type;
}
sub set_vendors {
- @vendors = (
+ $vendors = [
# A-Data xpg: AX4U; AX\d{4} for axiom
['^(A[DX]\dU|AVD|A[\s-]?Data)','A[\s-]?Data','A-Data',''],
['^(A[\s-]?Tech)','A[\s-]?Tech','A-Tech',''], # don't know part nu
@@ -19216,6 +20585,7 @@ sub set_vendors {
# ['^(HYS]|Qimonda)','Qimonda','Qimonda',''],
['^(HY|Infineon)','Infineon','Infineon',''],#HY[A-Z]\d
['^(KSM|KVR|Kingston)','Kingston','Kingston',''],
+ ['^(LuminouTek)','LuminouTek','LuminouTek',''],
['^(MT|Micron)','Micron','Micron',''],
# seen: 992069 991434 997110S
['^(M[BLERS][A-Z][1-7]|99[0-9]{3}|Mushkin)','Mushkin','Mushkin',''],
@@ -19235,11 +20605,11 @@ sub set_vendors {
['^(TR\d|JM\d|Transcend)','Transcend','Transcend',''],
['^(VK\d|Vaseky)','Vaseky','Vaseky',''],
['^(Yangtze|Zhitai)','Yangtze(\s*Memory)?','Yangtze Memory',''],
- );
+ ];
}
# note: many of these are pci ids, not confirmed valid for ram
sub set_vendor_ids {
- %vendor_ids = {
+ $vendor_ids = {
'01f4' => 'Transcend',# confirmed
'02fe' => 'Elpida',# confirmed
'0314' => 'Mushkin',# confirmed
@@ -19274,9 +20644,9 @@ sub set_vendor_ids {
sub ram_vendor {
eval $end if $b_log;
my ($id) = $_[0];
- set_vendors() if !@vendors;
+ set_vendors() if !$vendors;
my ($vendor,@data);
- foreach my $row (@vendors){
+ foreach my $row (@$vendors){
if ($id =~ /$row->[0]/i){
$vendor = $row->[2];
# Usually we want to assign N/A at output phase, maybe do this logic there?
@@ -20145,8 +21515,8 @@ sub get {
# we're allowing 1 or 2 ipmi tools, first the gnu one, then the
# almost certain to be present in BSDs
if ($fake{'ipmi'} || (main::globber('/dev/ipmi**') &&
- (($program = main::check_program('ipmi-sensors')) ||
- ($program = main::check_program('ipmitool'))))){
+ (($program = main::check_program('ipmi-sensors')) ||
+ ($program = main::check_program('ipmitool'))))){
if ($fake{'ipmi'} || $b_root){
%sensors = ipmi_data($program);
@data = sensors_output('ipmi',\%sensors);
@@ -20315,7 +21685,7 @@ sub sensors_output {
my $gpu_unit = (defined $gpu[0]->{'temp-unit'}) ? " $gpu[0]->{'temp-unit'}" : ' C';
foreach my $info (@gpu){
# speed unit is either '' or %
- my $gpu_fan = (defined $info->{'fan-speed'}) ? $info->{'fan-speed'} . $info->{'speed-unit'}: undef ;
+ 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;
@@ -20338,7 +21708,8 @@ sub sensors_output {
}
}
if ($extra > 0 && ($source eq 'ipmi' ||
- ($sensors->{'volts-12'} || $sensors->{'volts-5'} || $sensors->{'volts-3.3'} || $sensors->{'volts-vbat'}))){
+ ($sensors->{'volts-12'} || $sensors->{'volts-5'} || $sensors->{'volts-3.3'} ||
+ $sensors->{'volts-vbat'}))){
$j = scalar @rows;
$sensors->{'volts-12'} ||= 'N/A';
$sensors->{'volts-5'} ||= 'N/A';
@@ -20377,6 +21748,7 @@ sub ipmi_data {
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-crazy-epyc-1.txt";$program='ipmitool';
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-RK016013.txt";$program='ipmitool';
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensors-freebsd-offsite-backup.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmitool-sensor-tyan-1.txt";
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-crazy-epyc-1.txt";
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-lathander.txt";
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ipmitool/ipmi-sensors-zwerg.txt";
@@ -20413,7 +21785,7 @@ sub ipmi_data {
$working_unit =~ s/degrees\s// if $b_ipmitool;
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
}
- elsif ($row[$i_key] =~ /^(Ambient)([\s_]Temp)?$/i){
+ elsif ($row[$i_key] =~ /^(System\s)?(Ambient)([\s_]Temp)?$/i){
$sensors{'ambient-temp'} = int($row[$i_value]);
$working_unit = $row[$i_unit];
$working_unit =~ s/degrees\s// if $b_ipmitool;
@@ -20422,14 +21794,14 @@ sub ipmi_data {
# Platform Control Hub (PCH), it is the X370 chip on the Crosshair VI Hero.
# VRM: voltage regulator module
# NOTE: CPU0_TEMP CPU1_TEMP is possible, unfortunately; CPU Temp Interf
- elsif (!$sensors{'cpu-temp'} && $row[$i_key] =~ /^CPU([01])?([\s_]Temp)?$/i){
+ elsif (!$sensors{'cpu-temp'} && $row[$i_key] =~ /^CPU([01])?([\s_](below[\s_]Tmax|Temp))?$/i){
$b_cpu_0 = 1 if defined $1 && $1 == 0;
$sensors{'cpu-temp'} = int($row[$i_value]);
$working_unit = $row[$i_unit];
$working_unit =~ s/degrees\s// if $b_ipmitool;
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
}
- elsif ($row[$i_key] =~ /^CPU([1-4])([\s_]Temp)?$/i){
+ elsif ($row[$i_key] =~ /^CPU([1-4])([\s_](below[\s_]Tmax|Temp))?$/i){
$temp_working = $1;
$temp_working++ if $b_cpu_0;
$sensors{"cpu${temp_working}-temp"} = int($row[$i_value]);
@@ -20466,19 +21838,23 @@ sub ipmi_data {
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
}
- elsif (!$sensors{'sodimm-temp'} && $row[$i_key] =~ /^(DIMM[-_]([A-Z][0-9][-_])?[A-Z]?[0-9][A-Z]?)$/i){
+ elsif (!$sensors{'sodimm-temp'} && ($row[$i_key] =~ /^(DIMM[-_]([A-Z][0-9][-_])?[A-Z]?[0-9][A-Z]?)$/i ||
+ $row[$i_key] =~ /^DIMM[0-9] Area.*/)){
$sensors{'sodimm-temp'} = int($row[$i_value]);
$working_unit = $row[$i_unit];
$working_unit =~ s/degrees\s// if $b_ipmitool;
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
}
# note: can be cpu fan:, cpu fan speed:, etc.
- elsif ($row[$i_key] =~ /^(CPU|Processor)[\s_]Fan/i){
+ 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]);
}
# 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 are 1/2/3
+ # SYS.3(Front 2)
+ # $row[$i_key] =~ /^(SYS[\.])([0-9])\s?\((Front|Rear).+\)$/i
elsif ($row[$i_key] =~ /^(SYS[\s_])?FAN[\s_]?([0-9A-F]+)/i){
$sys_fan_nu = hex($2);
$fan_working = int($row[$i_value]);
@@ -20505,13 +21881,13 @@ sub ipmi_data {
$sensors{'fan-psu-2'} = int($row[$i_value]);
}
if ($extra > 0){
- if ($row[$i_key] =~ /^((MAIN\s|P[_]?)?12V|PSU[12]_VOUT)$/i){
+ if ($row[$i_key] =~ /^((MAIN\s|P[_]?)?\+?12V|PSU[12]_VOUT)$/i){
$sensors{'volts-12'} = $row[$i_value];
}
- elsif ($row[$i_key] =~ /^(MAIN\s5V|P5V|5VCC|5V PG|5V_SB)$/i){
+ elsif ($row[$i_key] =~ /^(MAIN\s5V|P5V|5VCC|5V( PG)?|5V_SB)$/i){
$sensors{'volts-5'} = $row[$i_value];
}
- elsif ($row[$i_key] =~ /^(MAIN\s3\.3V|P3V3|3\.3VCC|3\.3V PG|3V3_SB)$/i){
+ elsif ($row[$i_key] =~ /^(MAIN\s3\.3V|P3V3|3\.3VCC|3\.3V( PG)?|3V3_SB)$/i){
$sensors{'volts-3.3'} = $row[$i_value];
}
elsif ($row[$i_key] =~ /^((P_)?VBAT|CMOS Battery|BATT 3.0V)$/i){
@@ -21616,11 +22992,11 @@ sub proc_data {
# In arm/android seen /dev/block/mmcblk0p12
# print "mount: $row->[-1]\n";
if ($row->[-1] !~ /^(nvme[0-9]+n|mmcblk|mtdblk|mtdblock)[0-9]+$/ &&
- $row->[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ &&
- $row->[-1] !~ /\bloop/ &&
- !(grep {$row->[-1] =~ /$_$/} (@filters,@mounted)) &&
- !(grep {$_ =~ /(block\/)?$row->[-1]$/} @mounted) &&
- !(grep {$_ =~ /^sd[a-z]+$/ && $row->[-1] =~ /^$_[0-9]+/} @mounted)){
+ $row->[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ &&
+ $row->[-1] !~ /\bloop/ &&
+ !(grep {$row->[-1] =~ /$_$/} (@filters,@mounted)) &&
+ !(grep {$_ =~ /(block\/)?$row->[-1]$/} @mounted) &&
+ !(grep {$_ =~ /^sd[a-z]+$/ && $row->[-1] =~ /^$_[0-9]+/} @mounted)){
$dev_mapped = $dmmapper{$row->[-1]} if $dmmapper{$row->[-1]};
if (@lsblk){
my $id = ($dev_mapped) ? $dev_mapped: $row->[-1];
@@ -22897,7 +24273,7 @@ sub get {
set_gtk_data() if $b_gtk && $extra > 1;
set_qt_data() if $b_qt && $extra > 1;
main::log_data('dump','@desktop', \@desktop) if $b_log;
- # ($b_xprop,$kde_session_version,$xdg_desktop,@data,@xprop) = undef;
+ # ($b_xprop,$kde_session_version,$xdg_desktop,@data,@xprop) = ();
eval $end if $b_log;
return @desktop;
}
@@ -23047,8 +24423,8 @@ sub get_env_de_data {
foreach my $item (@desktops){
# Check if in xdg_desktop OR desktop_session OR if in $item->[6] and in ps_gui
if ((($item->[0] && ($xdg_desktop eq $item->[1] || $desktop_session eq $item->[1])) ||
- (!$item->[0] && ($xdg_desktop =~ /$item->[1]/ || $desktop_session =~ /$item->[1]/))) ||
- ($item->[5] && @ps_gui && (grep {/$item->[5]/} @ps_gui))){
+ (!$item->[0] && ($xdg_desktop =~ /$item->[1]/ || $desktop_session =~ /$item->[1]/))) ||
+ ($item->[5] && @ps_gui && (grep {/$item->[5]/} @ps_gui))){
($desktop[0],$desktop[1]) = main::program_data($item->[2]);
$b_gtk = $item->[3];
$b_qt = $item->[4];
@@ -23250,101 +24626,58 @@ sub get_ps_de_data {
if (@ps_gui){
# the sequence here matters, some desktops like icewm, razor, let you set different
# wm, so we want to get the main controlling desktop first
- # 1 check program; 2 ps_gui search; 3 data; 4: trigger alternate values/version
- my @desktops =(
- ['icewm','icewm','icewm'],
- ['WindowMaker','WindowMaker','wmaker',''],
- ['2bwm','2bwm','2bwm',''],# unverified
- ['9wm','9wm','9wm',''],
- ['afterstep','afterstep','afterstep',''],
- ['aewm++','aewm\+\+','aewm++',''],
- ['aewm','aewm','aewm',''],
- ['amiwm','amiwm','amiwm',''],
- ['antiwm','antiwm','antiwm',''],
- ['awesome','awesome','awesome',''],
- ['blackbox','blackbox','blackbox',''],
- ['bspwm','bspwm','bspwm',''],
- ['cagebreak','cagebreak','cagebreak',''],
- ['calmwm','calmwm','calmwm',''],
- ['catwm','catwm','catwm',''],# unverified
- ['clfswm','.*(sh|c?lisp)?.*clfswm','clfswm',''],
- ['ctwm','ctwm','ctwm',''],
- ['cwm','(openbsd-)?cwm','cwm',''],
- ['dwm','dwm','dwm',''],
- ['echinus','echinus','echinus',''],
- ['evilwm','evilwm','evilwm',''],
- ['fireplace','fireplace','fireplace',''],
- ['fluxbox','fluxbox','fluxbox',''],
- ['flwm','flwm','flwm',''],
- ['flwm','flwm_topside','flwm',''],
- ['fvwm-crystal','fvwm.*-crystal','fvwm-crystal','fvwm'],
- ['fvwm1','fvwm1','fvwm1',''],
- ['fvwm2','fvwm2','fvwm2',''],
- ['fvwm3','fvwm3','fvwm3',''],
- ['fvwm95','fvwm95','fvwm95',''],
- ['fvwm','fvwm','fvwm',''],
- ['glass','glass','glass',''],
- ['hackedbox','hackedbox','hackedbox',''],
- ['herbstluftwm','herbstluftwm','herbstluftwm'],
- ['instantwm','instantwm','instantwm',''],
- ['i3','i3','i3',''],
- ['ion3','ion3','ion3',''],
- ['jbwm','jbwm','jbwm',''],
- ['jwm','jwm','jwm',''],
- ['larswm','larswm','larswm',''],
- ['leftwm','leftwm','leftwm',''],
- ['lwm','lwm','lwm',''],
- ['mcwm','mcwm','mcwm',''],# unverified
- ['mini','mini','mini',''],
- ['musca','musca','musca',''],
- ['mvwm','mvwm','mvwm',''],
- ['mwm','mwm','mwm',''],
- ['nawm','nawm','nawm',''],
- ['notion','notion','notion',''],
- ['openbox','openbox','openbox',''],
- ['orbital','orbital','orbital',''],
- ['pekwm','pekwm','pekwm',''],
- ['perceptia','perceptia','perceptia',''],
- ['penrose','penrose','penrose',''],# unverified
- ['qtile','.*(python.*)?qtile','qtile',''],
- ['qvwm','qvwm','qvwm',''],
- ['ratpoison','ratpoison','ratpoison',''],
- ['sawfish','sawfish','sawfish',''],
- ['scrotwm','scrotwm','scrotwm',''],
- ['snapwm','snapwm','snapwm',''],# unverified
- ['spectrwm','spectrwm','spectrwm',''],
- ['stumpwm','(sh|c?lisp)?.*stumpwm','stumpwm',''],
- ['sway','sway','sway',''],
- ['matchbox-window-manager','matchbox-window-manager','matchbox-window-manager',''],
- ['tinywm','tinywm','tinywm',''],
- ['tvtwm','tvtwm','tvtwm',''],
- ['twm','twm','twm',''],
- ['uwm','uwm','uwm',''],# unverified
- ['waycooler','waycooler','way-cooler',''],
- ['way-cooler','way-cooler','way-cooler',''],
- ['windowlab','windowlab','windowlab',''],
- ['wmfs','wmfs','wmfs',''],# unverified
- ['wmfs2','wmfs2','wmfs2',''],# unverified
- ['wingo','wingo','wingo',''],# unverified
- # not in debian apt, current is wmii, version 3
- ['wmii2','wmii2','wmii2',''],
- ['wmii','wmii','wmii',''],
- ['wmx','wmx','wmx',''],
- ['xmonad','xmonad','xmonad',''],
- ## fallback for xfce in case no xprop
- ['xfdesktop','xfdesktop','xfdesktop',''],
- ['yeahwm','yeahwm','yeahwm',''],
- );
- foreach my $item (@desktops){
+ # icewm and any other that permits alternate wm to be used need to go first
+ # in this list.
+ # unverfied: 2bwm catwm mcwm penrose snapwm uwm wmfs wmfs2 wingo wmii2
+ # xfdesktoo is fallback in case not in xprop
+ my @wms = qw(icewm 2bwm 9wm aewm aewm\+\+ afterstep amiwm antiwm awesome
+ blackbox bspwm calmwm catwm ctwm dwm echinus evilwm fluxbox fvwm
+ hackedbox herbstluftwm instantwm i3 ion3 jbwm jwm larswm leftwm lwm
+ matchbox-window-manager mcwm mini musca mvwm mwm nawm notion
+ openbox pekwm penrose qvwm ratpoison
+ sawfish scrotwm snapwm spectrwm tinywm tvtwm twm uwm
+ windowlab wmfs wmfs2 wingo wmii2 wmii wmx xmonad yeahwm);
+ my $matches = join('|',@wms) . $wl_compositors;
+ # note: use my $psg to avoid bizarre return from program_data to ps_gui write
+ foreach my $psg (@ps_gui){
# no need to use check program with short list of ps_gui
- if (grep {/^$item->[1]$/} @ps_gui){
- ($desktop[0],$desktop[1]) = main::program_data($item->[2],$item->[3]);
- if ($extra > 1 && $item->[0] eq 'xfdesktop'){
- ($desktop[2],$desktop[3]) = main::program_data('xfdesktop-toolkit',$item->[0],1);
+ if ($psg =~ /^($matches)$/){
+ my $item = $1;
+ ($desktop[0],$desktop[1]) = main::program_data($item);
+ if ($extra > 1 && $item eq 'xfdesktop'){
+ ($desktop[2],$desktop[3]) = main::program_data('xfdesktop-toolkit',$item,1);
}
last;
}
}
+ if (!$desktop[0]){
+ # order matters, these have alternate search patterns from default name
+ # 1 check program; 2 ps_gui search; 3 data; 4: trigger alternate values/version
+ @wms =(
+ ['WindowMaker','WindowMaker','wmaker',''],
+ ['clfswm','.*(sh|c?lisp)?.*clfswm','clfswm',''],
+ ['cwm','(openbsd-)?cwm','cwm',''],
+ ['flwm','flwm','flwm',''],
+ ['flwm','flwm_topside','flwm',''],
+ ['fvwm-crystal','fvwm.*-crystal','fvwm-crystal','fvwm'],
+ ['fvwm1','fvwm1','fvwm1',''],
+ ['fvwm2','fvwm2','fvwm2',''],
+ ['fvwm3','fvwm3','fvwm3',''],
+ ['fvwm95','fvwm95','fvwm95',''],
+ ['qtile','.*(python.*)?qtile','qtile',''],
+ ['stumpwm','(sh|c?lisp)?.*stumpwm','stumpwm',''],
+ );
+ foreach my $item (@wms){
+ # no need to use check program with short list of ps_gui
+ if (grep {/^$item->[1]$/} @ps_gui){
+ ($desktop[0],$desktop[1]) = main::program_data($item->[2],$item->[3]);
+ if ($extra > 1 && $item->[0] eq 'xfdesktop'){
+ ($desktop[2],$desktop[3]) = main::program_data('xfdesktop-toolkit',$item->[0],1);
+ }
+ last;
+ }
+ }
+ }
}
eval $end if $b_log;
}
@@ -23407,7 +24740,7 @@ sub get_wm_main {
# xprop is set only if not kde/gnome/cinnamon/mate/budgie/lx..
if ($b_xprop){
#KWIN_RUNNING
- $wms = 'amiwm|blackbox|bspwm|compiz|kwin_wayland|kwin_x11|kwin|marco|';
+ $wms = 'amiwm|blackbox|bspwm|compiz|kwin_wayland|kwin_x11|kwinft|kwin|marco|';
$wms .= 'motif|muffin|openbox|herbstluftwm|twin|ukwm|wm2|windowmaker|i3';
foreach (@xprop){
if (/($wms)/){
@@ -23421,21 +24754,18 @@ sub get_wm_main {
main::set_ps_gui() if !$loaded{'ps-gui'};
# order matters, see above logic
# due to lisp/python starters, clfswm/stumpwm/qtile will not detect here
- $wms = '2bwm|9wm|aewm\+\+|aewm|afterstep|amiwm|antiwm|awesome|blackbox|';
- $wms .= 'cagebreak|calmwm|catwm|clfswm|compiz|ctwm|(openbsd-)?cwm|fluxbox';
- $wms .= '|bspwm|budgie-wm|deepin-wm|dwm|echinus|evilwm|';
- $wms .= 'fireplace|flwm|fvwm-crystal|fvwm1|fvwm2|fvwm3|fvwm95|fvwm|';
- $wms .= 'gala|glass|gnome-shell|hackedbox|i3|instantwm|ion3|jbwm|jwm|';
- $wms .= 'twin|kwin_wayland|kwin_x11|kwin|larswm|leftwm|lwm|';
- $wms .= 'matchbox-window-manager|marco|mcwm|mini|muffin|';
- $wms .= 'musca|deepin-mutter|mutter|deepin-metacity|metacity|mvwm|mwm|';
- $wms .= 'nawm|notion|openbox|orbital|perceptia|qtile|qvwm|';
- $wms .= 'penrose|ratpoison|sawfish|scrotwm|snapwm|spectrwm|';
- $wms .= 'stumpwm|sway|tinywm|tvtwm|twm|ukwm|';
- $wms .= 'way-?cooler|windowlab|WindowMaker|wingo|wm2|wmfs2?|wmii2?|wmx|';
- $wms .= 'xfwm[45]?|xmonad|yeahwm';
- foreach (@ps_gui){
- if (/^($wms)$/){
+ my @wms = qw(2bwm 9wm aewm aewm\+\+ afterstep amiwm antiwm awesome blackbox
+ calmwm catwm clfswm compiz ctwm (openbsd-)?cwm fluxbox bspwm budgie-wm
+ deepin-wm dwm echinus evilwm flwm fvwm-crystal fvwm1 fvwm2 fvwm3 fvwm95
+ fvwm gala gnome-shell hackedbox i3 instantwm ion3 jbwm jwm twin kwin_wayland
+ kwin_x11 kwinft kwin larswm leftwm lwm matchbox-window-manager marco mcwm mini
+ muffin musca deepin-mutter mutter deepin-metacity metacity mvwm mwm
+ nawm notion openbox qtile qvwm penrose ratpoison sawfish scrotwm snapwm
+ spectrwm stumpwm tinywm tvtwm twm ukwm windowlab WindowMaker wingo wmfs2?
+ wmii2? wmx xfwm[45]? xmonad yeahwm);
+ my $wms = join('|',@wms) . $wl_compositors;
+ foreach my $psg (@ps_gui){
+ if ($psg =~ /^($wms)$/){
$working = $1;
last;
}
@@ -23493,14 +24823,16 @@ sub set_info_data {
my (@data,@info,$item);
my $pattern = 'alltray|awn|bar|bmpanel|bmpanel2|budgie-panel|cairo-dock|';
$pattern .= 'dde-dock|dmenu|dockbarx|docker|docky|dzen|dzen2|';
- $pattern .= 'fancybar|fbpanel|fspanel|glx-dock|gnome-panel|hpanel|i3bar|i3status|icewmtray|';
+ $pattern .= 'fancybar|fbpanel|fspanel|glx-dock|gnome-panel|hpanel|';
+ $pattern .= 'i3bar|i3status|i3-status-rs|icewmtray|';
$pattern .= 'kdocker|kicker|';
- $pattern .= 'latte|latte-dock|lemonbar|ltpanel|lxpanel|lxqt-panel|';
- $pattern .= 'matchbox-panel|mate-panel|ourico|';
+ $pattern .= 'latte|latte-dock|lemonbar|ltpanel|luastatus|lxpanel|lxqt-panel|';
+ $pattern .= 'matchbox-panel|mate-panel|nwg-bar|nwg-dock|nwg-panel|ourico|';
$pattern .= 'perlpanel|plank|plasma-desktop|plasma-netbook|polybar|pypanel|';
- $pattern .= 'razor-panel|razorqt-panel|stalonetray|swaybar|taskbar|tint2|trayer|';
- $pattern .= 'ukui-panel|vala-panel|wbar|wharf|wingpanel|witray|';
- $pattern .= 'xfce4-panel|xfce5-panel|xmobar|yabar';
+ $pattern .= 'razor-panel|razorqt-panel|rootbar|sfwbar|stalonetray|swaybar|';
+ $pattern .= 'taskbar|tint2|trayer|';
+ $pattern .= 'ukui-panel|vala-panel|wapanel|waybar|wbar|wharf|wingpanel|witray|';
+ $pattern .= 'xfce4-panel|xfce5-panel|xmobar|yabar|yambar';
if (@data = grep {/^($pattern)$/} @ps_gui){
# only one entry per type, can be multiple
foreach $item (@data){
@@ -23611,7 +24943,7 @@ sub set {
main::log_data('dump','$devices{timer}',$devices{'timer'});
}
}
- @devices = undef;
+ undef @devices;
eval $end if $b_log;
}
@@ -23623,7 +24955,7 @@ sub lspci_data {
foreach (@data){
# print "$_\n";
if ($device){
- if ($_ =~ /^~$/){
+ if ($_ eq '~'){
@temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,
$rev,$port,$driver,$modules,$driver_nu,$subsystem,$subsystem_id);
assign_data('pci',\@temp);
@@ -23756,7 +25088,7 @@ sub pciconf_data {
my @data = pci_grabber('pciconf');
foreach (@data){
if ($driver){
- if ($_ =~ /^~$/){
+ if ($_ eq '~'){
$vendor = main::clean($vendor);
$device = main::clean($device);
# handle possible regex in device name, like [ConnectX-3]
@@ -23829,12 +25161,12 @@ sub pcidump_data {
my @data = pci_grabber('pcidump');
main::set_dboot_data() if !$loaded{'dboot'};
foreach (@data){
- if ($_ =~ /^~$/ && $busid && $device){
+ if ($_ eq '~' && $busid && $device){
@temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,
$rev,$port,$driver,$modules,$driver_nu,'','','',$serial);
assign_data('pci',\@temp);
($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,
- $rev,$port,$driver,$modules,$driver_nu,$serial) = undef;
+ $rev,$port,$driver,$modules,$driver_nu,$serial) = ();
next;
}
if ($_ =~ /^([0-9a-f:]+):([0-9]+):\s([^:]+)$/i){
@@ -23878,12 +25210,12 @@ sub pcictl_data {
my @data = pci_grabber('pcictl');
my @data2 = pci_grabber('pcictl-n');
foreach (@data){
- if ($_ =~ /^~$/ && $busid && $device){
+ if ($_ eq '~' && $busid && $device){
@temp = ($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,
$rev,$port,$driver,$modules,$driver_nu);
assign_data('pci',\@temp);
($type,$type_id,$busid,$busid_nu,$device,$vendor_id,$chip_id,
- $rev,$port,$driver,$modules,$driver_nu) = undef;
+ $rev,$port,$driver,$modules,$driver_nu) = ();
next;
}
# it's too fragile to get these in one matching so match, trim, next match
@@ -23954,6 +25286,7 @@ sub pci_grabber {
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/kot--book-lspci-nnv.txt";
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/steve-mint-topaz-lspci-nnkv.txt";
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/ben81-hwraid-lspci-nnv.txt";
+ # my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/lspci/gx78b-lspci-nnv.txt";
# @data = main::reader($file,'strip');
}
else {
@@ -24033,7 +25366,7 @@ sub soc_devices_files {
push(@files,@temp2) if @temp2;
@temp2 = main::globber('/sys/devices/*/*/uevent'); # see case 10
push(@files,@temp2) if @temp2;
- @temp2 = undef;
+ undef @temp2;
# not sure why, but even as root/sudo, /subsystem|driver/uevent are unreadable with -r test true
@files = grep {!/\/(subsystem|driver)\//} @files if @files;
main::uniq(\@files);
@@ -24054,7 +25387,7 @@ sub soc_devices {
$chip_id = $5;
$temp = $7;
@working = main::reader($file, 'strip') if -r $file;
- ($device,$driver,$handle,$type,$vendor_id) = (undef,undef,undef,undef,undef);
+ ($device,$driver,$handle,$type,$vendor_id) = ();
foreach my $data (@working){
@temp2 = split('=', $data);
if ($temp2[0] eq 'DRIVER'){
@@ -24453,7 +25786,7 @@ sub set_disklabel_data {
last;
}
else {
- my ($b_part,$duid,$part_id,$bytes_sector) = undef;
+ my ($b_part,$duid,$part_id,$bytes_sector) = ();
if ($extra > 2 && $show{'disk'} && $alerts{'fdisk'}->{'action'} eq 'use'){
$disks_bsd{$id}->{'partition-table'} = fdisk_data($id);
}
@@ -24606,43 +25939,65 @@ sub set_gpart_data {
sub get_display_manager {
eval $start if $b_log;
- my (@data,@found,$path,$working,$b_run,$b_vrun,$b_vrunrc);
+ my (@data,@found,@glob,$link,$path,@temp);
# ldm - LTSP display manager. Note that sddm does not appear to have a .pid
- # extension in Arch note: to avoid positives with directories, test for -f
- # explicitly, not -e. Guessing on cdm.pid. pcdm uses vt, PCDM-vt9.pid
- my @dms = qw(cdm.pid entranced.pid gdm.pid gdm3.pid kdm.pid kdm3.pid ldm.pid
- lightdm.pid lxdm.pid mdm.pid nodm.pid pcdm.pid sddm.pid slim.lock
- slim.pid tdm.pid udm.pid wdm.pid xdm.pid xenodm.pid);
+ # extension in Arch. Guessing on cdm, qingy. pcdm uses vt, PCDM-vt9.pid
+ # Not verified: qingy emptty; greetd.run verified, but alternate:
+ # greetd-684.sock if no .run seen. Add Ly in case they add run file/directory.
+ # greetd frontends: agreety dlm gtkgreet qtgreet tuigreet wlgreet
+ my @dms = qw(cdm emptty entranced gdm gdm3 greetd kdm kdm3 ldm lightdm lxdm ly
+ mdm nodm pcdm qingy sddm slim tbsm tdm udm wdm xdm xenodm);
# these are the only one I know of so far that have version info
- my @dms_version = qw(gdm gdm3 lightdm slim);
- $b_run = 1 if -d "/run";
+ my @dms_version = qw(gdm gdm3 lightdm ly slim);
+ my $pattern = '';
+ if (-d '/run'){
+ $pattern .= '/run';
+ }
# in most linux, /var/run is a sym link to /run, so no need to check it twice
- if (-d "/var/run"){
- my $rdlink = readlink('/var/run');
- $b_vrun = 1 if !$rdlink || ($rdlink && $rdlink ne '/run');
- $b_vrunrc = 1 if -d "/var/run/rc.d";
- }
- foreach my $id (@dms){
- # note: $working will create a dir name out of the dm $id, then
- # test if pid is in that note: sddm, in an effort to be unique and special,
- # do not use a pid/lock file, but rather a random string inside a directory
- # called /run/sddm/ so assuming the existence of the pid inside a directory named
- # from the dm. Hopefully this change will not have negative results.
- $working = $id;
- $working =~ s/\.\S+$//;
- # note: there were issues with duplicated dm's in inxi, checking @found corrects it
- if ((($b_run && (-f "/run/$id" || -d "/run/$working")) ||
- ($b_vrun && (-f "/var/run/$id" || -d "/var/run/$working")) ||
- ($b_vrunrc && (-f "/var/run/rc.d/$working" || -d "/var/run/rc.d/$id"))) &&
- !grep {/$working/i} @found){
- if ($extra > 2 && awk(\@dms_version, $working) && ($path = check_program($working))){}
- else {$path = $working;}
- # print "$path $extra\n";
- @data = program_data($working,$path,3);
- $working = $data[0];
- $working .= ' ' . $data[1] if $data[1];
- push(@found, $working);
- }
+ if (-d '/var/run' && ! -l '/var/run'){
+ $pattern .= ',' if $pattern;
+ $pattern .= '/var/run';
+ }
+ if (-d '/var/run/rc.d'){
+ $pattern .= ',' if $pattern;
+ $pattern .= '/var/run/rc.d';
+ }
+ if ($pattern){
+ $pattern = '{' . $pattern . '/*}' if $pattern;
+ # for dm.pid type file or dm directory names, like greetd-684.sock
+ @glob = globber($pattern) if $pattern;
+ }
+ # print Data::Dumper::Dumper \@glob;
+ # used to test for .pid/lock type file or directory, now just see if the
+ # search name exists in run and call it good since test would always be true
+ # if directory existed previously anyway.
+ if (@glob){
+ my $search = join('|',@dms);
+ @glob = grep {/\/($search)\b/} @glob;
+ # $search = join('|',@glob);
+ if (@glob){
+ uniq(\@glob);
+ foreach my $item (@glob){
+ my @id = grep {$item =~ /\/$_\b/} @dms;
+ push(@temp,@id) if @id;
+ }
+ # note: there were issues with duplicated dm's, using uniq will handle those
+ uniq(\@temp) if @temp;
+ }
+ }
+ @dms = @temp;
+ # print Data::Dumper::Dumper \@dms;
+ # we know the files or directories exist so no need for further checks here
+ foreach my $dm (@dms){
+ # do nothing, we just wanted the path
+ if ($extra > 2 && (grep {$dm eq $_} @dms_version) &&
+ ($path = check_program($dm))){}
+ else {$path = $dm}
+ # print "$path $extra\n";
+ @data = program_data($dm,$path,3);
+ $dm = $data[0];
+ $dm .= ' ' . $data[1] if $data[1];
+ push(@found,$dm);
}
if (!@found){
# ly does not have a run/pid file
@@ -24719,8 +26074,8 @@ sub get_bsd_os {
$distro_id = lc($uname[0]);
}
if ($distro &&
- (-e '/etc/pkg/GhostBSD.conf' || -e '/usr/local/etc/pkg/repos/GhostBSD.conf') &&
- $distro =~ /freebsd/i){
+ (-e '/etc/pkg/GhostBSD.conf' || -e '/usr/local/etc/pkg/repos/GhostBSD.conf') &&
+ $distro =~ /freebsd/i){
my $version = (main::grabber("pkg query '%v' os-generic-userland-base 2>/dev/null"))[0];
# only swap if we get result from the query
if ($version){
@@ -25010,10 +26365,10 @@ sub system_base_bsd {
sub system_base {
eval $start if $b_log;
- my $base_arch_distro = 'anarchy|antergos|archbang|archlabs|archman|archstrike|arco|artix';
+ my $base_arch_distro = 'anarchy|antergos|arch(bang|craft|labs|man|strike)|arco|artix';
# note: arch linux derived distro page claims kaos as arch derived but it is NOT
$base_arch_distro .= '|blackarch|bluestar|chakra|ctios|endeavour|garuda|hyperbola|linhes';
- $base_arch_distro .= '|manjaro|mysys2|netrunner\s?rolling|ninja|obarun|parabola';
+ $base_arch_distro .= '|mabox|manjaro|mysys2|netrunner\s?rolling|ninja|obarun|parabola';
$base_arch_distro .= '|puppyrus-?a|reborn|snal|talkingarch|ubos';
my $base_debian_version_distro = 'sidux';
my $base_debian_version_osr = '\belive|lmde|neptune|parrot|pureos|rescatux|septor|sparky|tails';
@@ -25045,7 +26400,7 @@ sub system_base {
@osr = @osr_working;
$system_base = get_os_release();
@osr = @osr_temp if !$system_base;
- (@osr_temp,@osr_working) = (undef,undef);
+ (@osr_temp,@osr_working) = ();
}
}
elsif (-r $base_upstream_lsb){
@@ -25224,7 +26579,7 @@ sub get_os_release {
}
# note: mint has varying formats here, some have ubuntu as name, 17 and earlier
else {
- # mint 17 used ubuntu os-release, so won't have $base_version
+ # mint 17 used ubuntu os-release, so won't have $base_version
if ($base_name && $base_version){
$base_id = ubuntu_id($base_version) if $base_type eq 'ubuntu' && $base_version;
$base_id = '' if $base_id && "$base_name$base_version" =~ /$base_id/;
@@ -25282,8 +26637,9 @@ sub debian_id {
return $id;
}
-# note, these are only for matching derived names, no need to go
-# all the way back here, update as new names are known. This is because
+# note, these are only for matching distro/mint derived names.
+# Update list as new names become available. While first Mint was 2006-08,
+# this method depends on /etc/os-release which was introduced 2012-02.
# Mint is using UBUNTU_CODENAME without ID data.
sub ubuntu_id {
eval $start if $b_log;
@@ -25291,25 +26647,25 @@ sub ubuntu_id {
$codename = lc($codename);
my ($id) = ('');
my %codenames = (
- 'hirsute' => '21.04',
- 'groovy' => '20.10',
- 'focal' => '20.04 LTS',
- 'eoan' => '19.10',
- 'disco' => '19.04',
- 'cosmic' => '18.10',
- 'bionic' => '18.04 LTS',
- 'artful' => '17.10',
- 'zesty' => '17.04',
- 'yakkety' => '16.10',
- 'xenial' => '16.04 LTS',
- 'wily' => '15.10',
- 'vivid' => '15.04',
- 'utopic' => '14.10',
- 'trusty' => '14.04 LTS ',
- 'saucy' => '13.10',
- 'raring' => '13.04',
- 'quantal' => '12.10',
- 'precise' => '12.04 LTS ',
+ 'jammy' => '22.04 LTS',
+ 'impish' => '21.10','hirsute' => '21.04',
+ 'groovy' => '20.10','focal' => '20.04 LTS',
+ 'eoan' => '19.10','disco' => '19.04',
+ 'cosmic' => '18.10','bionic' => '18.04 LTS',
+ 'artful' => '17.10','zesty' => '17.04',
+ 'yakkety' => '16.10','xenial' => '16.04 LTS',
+ 'wily' => '15.10','vivid' => '15.04',
+ 'utopic' => '14.10','trusty' => '14.04 LTS ',
+ 'saucy' => '13.10','raring' => '13.04',
+ 'quantal' => '12.10','precise' => '12.04 LTS ',
+ # 'oneiric' => '11.10','natty' => '11.04',
+ # 'maverick' => '10.10','lucid' => '10.04',
+ # 'karmic' => '9.10','jaunty' => '9.04',
+ # 'intrepid' => '8.10','hardy' => '8.04',
+ # 'gutsy' => '7.10','feisty' => '7.04',
+ # 'edgy' => '6.10', 'dapper' => '6.06',
+ # 'breezy' => '5.10', 'hoary' => '5.04',
+ # 'warty' => '4.10',
);
$id = $codenames{$codename} if defined $codenames{$codename};
eval $end if $b_log;
@@ -25916,9 +27272,10 @@ sub set {
# note: for bcache and luks, the device that has that fs is the parent!!
if ($show{'logical'}){
$use{'logical-lvm'} = 1 if !$use{'logical-lvm'} && $2 && $2 eq 'lvm';
- if (!$use{'logical-general'} && (($4 && ($4 eq 'crypto_LUKS' || $4 eq 'bcache'))
- || ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) ||
- $2 eq 'crypto' || $2 eq 'mpath' || $2 eq 'multipath'))){
+ if (!$use{'logical-general'} && (($4 &&
+ ($4 eq 'crypto_LUKS' || $4 eq 'bcache')) ||
+ ($2 && ($2 eq 'dm' && $1 =~ /veracrypt/i) || $2 eq 'crypto' ||
+ $2 eq 'mpath' || $2 eq 'multipath'))){
$use{'logical-general'} = 1;
}
}
@@ -26342,10 +27699,10 @@ sub package_counts {
@list = main::globber($_->[3]);
}
else {
- @list = undef;
+ undef @list;
$error = main::message('pm-disabled');
}
- $libs = undef;
+ undef $libs;
# print Data::Dumper::Dumper \@list;
if (!$error){
$count = scalar @list;
@@ -26388,6 +27745,603 @@ sub count_libs {
}
}
+## ParseEDID
+{
+package ParseEDID;
+# CVT_ratios:
+my @known_ratios = qw(5/4 4/3 3/2 16/10 15/9 16/9);
+my @edid_info = (
+ ['a8', '_header'],
+ ['a2', 'manufacturer_name'],
+
+ ['v', 'product_code'],
+ ['V', 'serial_number'],
+ ['C', 'week'],
+ ['C', 'year'],
+ ['C', 'edid_version'],
+ ['C', 'edid_revision'],
+ ['a', 'video_input_definition'],
+
+ ['C', 'max_size_horizontal'], # in cm, 0 on projectors
+ ['C', 'max_size_vertical'], # in cm, 0 on projectors
+ ['C', 'gamma'],
+ ['a', 'feature_support'],
+ ['a10', '_color_characteristics'],
+ ['a3' , 'established_timings'],
+ ['a16', 'standard_timings'],
+ ['a72', 'monitor_details'],
+
+ ['C', 'extension_flag'],
+ ['C', 'checksum'],
+);
+my %subfields = (
+ manufacturer_name => [
+ [1, ''],
+ [5, '1'],
+ [5, '2'],
+ [5, '3'],
+ ],
+ video_input_definition => [
+ [1, 'digital'],
+ [1, 'separate_sync'],
+ [1, 'composite_sync'],
+ [1, 'sync_on_green'],
+ [2, ''],
+ [2, 'voltage_level'],
+ ],
+ feature_support => [
+ [1, 'DPMS_standby'],
+ [1, 'DPMS_suspend'],
+ [1, 'DPMS_active_off'],
+ [1, 'rgb'],
+
+ [1, ''],
+ [1, 'sRGB_compliance'],
+ [1, 'has_preferred_timing'],
+ [1, 'GTF_compliance'],
+ ],
+ # these are VESA timings, basically: VESA-EEDID-A2.pdf
+ established_timings => [
+ # byte 1, 23h
+ [1, '720x400_70'],
+ [1, '720x400_88'],
+ [1, '640x480_60'],
+ [1, '640x480_67'],
+ [1, '640x480_72'],
+ [1, '640x480_75'],
+ [1, '800x600_56'],
+ [1, '800x600_60'],
+ # byte 2, 24h
+ [1, '800x600_72'],
+ [1, '800x600_75'],
+ [1, '832x624_75'],
+ [1, '1024x768_87i'],
+ [1, '1024x768_60'],
+ [1, '1024x768_70'],
+ [1, '1024x768_75'],
+ [1, '1280x1024_75'],
+ # byte 3, 25h
+ # 7: [1, '1152x870_75'], # apple macII
+ # 6-0: manufacturer's timings
+ ],
+ detailed_timing => [
+ [8, 'horizontal_active'],
+ [8, 'horizontal_blanking'],
+ [4, 'horizontal_active_hi'],
+ [4, 'horizontal_blanking_hi'],
+ [8, 'vertical_active'],
+ [8, 'vertical_blanking'],
+ [4, 'vertical_active_hi'],
+ [4, 'vertical_blanking_hi'],
+ [8, 'horizontal_sync_offset'],
+ [8, 'horizontal_sync_pulse_width'],
+ [4, 'vertical_sync_offset'],
+ [4, 'vertical_sync_pulse_width'],
+ [2, 'horizontal_sync_offset_hi'],
+ [2, 'horizontal_sync_pulse_width_hi'],
+ [2, 'vertical_sync_offset_hi'],
+ [2, 'vertical_sync_pulse_width_hi'],
+ [8, 'horizontal_image_size'], # in mm
+ [8, 'vertical_image_size'], # in mm
+ [4, 'horizontal_image_size_hi'],
+ [4, 'vertical_image_size_hi'],
+ [8, 'horizontal_border'],
+ [8, 'vertical_border'],
+
+ [1, 'interlaced'],
+ [2, 'stereo'],
+ [2, 'digital_composite'],
+ [1, 'horizontal_sync_positive'],
+ [1, 'vertical_sync_positive'],
+ [1, ''],
+ ],
+ # 16 bytes, up to 8 additional timings, each identified by a unique 2 byte
+ # code derived from the horizontal active pixel count, the image aspect ratio
+ # and field refresh rate as described in Table 3.19
+ standard_timing => [
+ [8, 'X'],
+ [2, 'aspect'],
+ [6, 'vfreq'],
+ ],
+ monitor_range => [
+ [8, 'vertical_min'],
+ [8, 'vertical_max'],
+ [8, 'horizontal_min'],
+ [8, 'horizontal_max'],
+ [8, 'pixel_clock_max'],
+ ],
+ manufacturer_specified_range_timing => [
+ # http://www.spwg.org/salisbury_march_19_2002.pdf
+ # for the glossary: http://www.vesa.org/Public/PSWG/PSWG15v1.pdf
+ [8, 'horizontal_sync_pulse_width_min'], # HSPW (Horizontal Sync Pulse Width)
+ [8, 'horizontal_sync_pulse_width_max'],
+ [8, 'horizontal_back_porch_min'], # t_hbp
+ [8, 'horizontal_back_porch_max'],
+ [8, 'vertical_sync_pulse_width_min'], # VSPW (Vertical Sync Pulse Width)
+ [8, 'vertical_sync_pulse_width_max'],
+ [8, 'vertical_back_porch_min'], # t_vbp (Vertical Back Porch)
+ [8, 'vertical_back_porch_max'],
+ [8, 'horizontal_blanking_min'], # t_hp (Horizontal Period)
+ [8, 'horizontal_blanking_max'],
+ [8, 'vertical_blanking_min'], # t_vp
+ [8, 'vertical_blanking_max'],
+ [8, 'module_revision'],
+ ],
+ cea_data_block_collection => [
+ [3, 'type'],
+ [5, 'size'],
+ ],
+ cea_video_data_block => [
+ [1, 'native'],
+ [7, 'mode'],
+ ],
+);
+my @cea_video_mode_to_detailed_timing = (
+ 'pixel_clock',
+ 'horizontal_active',
+ 'vertical_active',
+ 'aspect',
+ 'horizontal_blanking',
+ 'horizontal_sync_offset',
+ 'horizontal_sync_pulse_width',
+ 'vertical_blanking',
+ 'vertical_sync_offset',
+ 'vertical_sync_pulse_width',
+ 'horizontal_sync_positive',
+ 'vertical_sync_positive',
+ 'interlaced'
+);
+my @cea_video_modes = (
+# [0] pixel clock, [1] X, [2] Y, [3] aspect, [4] Hblank, [5] Hsync_offset, [6] Hsync_pulse_width,
+# [7] Vblank, [8] Vsync_offset, [9] Vsync_pulse_width, [10] Hsync+, [11] Vsync+, [12] interlaced
+# 59.94/29.97 and similar modes also have a 60.00/30.00 counterpart by raising the pixel clock
+ [ 25.175, 640, 480, "4/3", 160, 16, 96, 45, 10, 2, 0, 0, 0 ], # 1: 640x 480@59.94
+ [ 27.000, 720, 480, "4/3", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 2: 720x 480@59.94
+ [ 27.000, 720, 480, "16/9", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 3: 720x 480@59.94
+ [ 74.250, 1280, 720, "16/9", 370, 110, 40, 30, 5, 5, 1, 1, 0 ], # 4: 1280x 720@60.00
+ [ 74.250, 1920, 1080, "16/9", 280, 88, 44, 45, 4, 10, 1, 1, 1 ], # 5: 1920x1080@30.00
+ [ 27.000, 1440, 480, "4/3", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 6: 1440x 480@29.97
+ [ 27.000, 1440, 480, "16/9", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 7: 1440x 480@29.97
+ [ 27.000, 1440, 240, "4/3", 276, 38, 124, 22, 4, 3, 0, 0, 0 ], # 8: 1440x 240@60.05
+ [ 27.000, 1440, 240, "16/9", 276, 38, 124, 22, 4, 3, 0, 0, 0 ], # 9: 1440x 240@60.05
+ [ 54.000, 2880, 480, "4/3", 552, 76, 248, 45, 8, 6, 0, 0, 1 ], # 10: 2880x 480@29.97
+ [ 54.000, 2880, 480, "16/9", 552, 76, 248, 45, 8, 6, 0, 0, 1 ], # 11: 2880x 480@29.97
+ [ 54.000, 2880, 240, "4/3", 552, 76, 248, 22, 4, 3, 0, 0, 0 ], # 12: 2880x 240@60.05
+ [ 54.000, 2880, 240, "16/9", 552, 76, 248, 22, 4, 3, 0, 0, 0 ], # 13: 2880x 240@60.05
+ [ 54.000, 1440, 480, "4/3", 276, 32, 124, 45, 9, 6, 0, 0, 0 ], # 14: 1440x 480@59.94
+ [ 54.000, 1440, 480, "16/9", 276, 32, 124, 45, 9, 6, 0, 0, 0 ], # 15: 1440x 480@59.94
+ [ 148.500, 1920, 1080, "16/9", 280, 88, 44, 45, 4, 5, 1, 1, 0 ], # 16: 1920x1080@60.00
+ [ 27.000, 720, 576, "4/3", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 17: 720x 576@50.00
+ [ 27.000, 720, 576, "16/9", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 18: 720x 576@50.00
+ [ 74.250, 1280, 720, "16/9", 700, 440, 40, 30, 5, 5, 1, 1, 0 ], # 19: 1280x 720@50.00
+ [ 74.250, 1920, 1080, "16/9", 720, 528, 44, 45, 4, 10, 1, 1, 1 ], # 20: 1920x1080@25.00
+ [ 27.000, 1440, 576, "4/3", 288, 24, 126, 49, 4, 6, 0, 0, 1 ], # 21: 1440x 576@25.00
+ [ 27.000, 1440, 576, "16/9", 288, 24, 126, 49, 4, 6, 0, 0, 1 ], # 22: 1440x 576@25.00
+ [ 27.000, 1440, 288, "4/3", 288, 24, 126, 24, 2, 3, 0, 0, 0 ], # 23: 1440x 288@50.08
+ [ 27.000, 1440, 288, "16/9", 288, 24, 126, 24, 2, 3, 0, 0, 0 ], # 24: 1440x 288@50.08
+ [ 54.000, 2880, 576, "4/3", 576, 48, 252, 49, 4, 6, 0, 0, 1 ], # 25: 2880x 576@25.00
+ [ 54.000, 2880, 576, "16/9", 576, 48, 252, 49, 4, 6, 0, 0, 1 ], # 26: 2880x 576@25.00
+ [ 54.000, 2880, 288, "4/3", 576, 48, 252, 24, 2, 3, 0, 0, 0 ], # 27: 2880x 288@50.08
+ [ 54.000, 2880, 288, "16/9", 576, 48, 252, 24, 2, 3, 0, 0, 0 ], # 28: 2880x 288@50.08
+ [ 54.000, 1440, 576, "4/3", 288, 24, 128, 49, 5, 5, 0, 0, 0 ], # 29: 1440x 576@50.00
+ [ 54.000, 1440, 576, "16/9", 288, 24, 128, 49, 5, 5, 0, 0, 0 ], # 30: 1440x 576@50.00
+ [ 148.500, 1920, 1080, "16/9", 720, 528, 44, 45, 4, 5, 1, 1, 0 ], # 31: 1920x1080@50.00
+ [ 74.250, 1920, 1080, "16/9", 830, 638, 44, 45, 4, 5, 1, 1, 0 ], # 32: 1920x1080@24.00
+ [ 74.250, 1920, 1080, "16/9", 720, 528, 44, 45, 4, 5, 1, 1, 0 ], # 33: 1920x1080@25.00
+ [ 74.250, 1920, 1080, "16/9", 280, 88, 44, 45, 4, 5, 1, 1, 0 ], # 34: 1920x1080@30.00
+ [ 108.000, 2880, 480, "4/3", 552, 64, 248, 45, 9, 6, 0, 0, 0 ], # 35: 2880x 480@59.94
+ [ 108.000, 2880, 480, "16/9", 552, 64, 248, 45, 9, 6, 0, 0, 0 ], # 36: 2880x 480@59.94
+ [ 108.000, 2880, 576, "4/3", 576, 48, 256, 49, 5, 5, 0, 0, 0 ], # 37: 2880x 576@50.00
+ [ 108.000, 2880, 576, "16/9", 576, 48, 256, 49, 5, 5, 0, 0, 0 ], # 38: 2880x 576@50.00
+ [ 72.000, 1920, 1080, "16/9", 384, 32, 168, 170, 46, 10, 1, 0, 1 ], # 39: 1920x1080@25.00
+ [ 148.500, 1920, 1080, "16/9", 720, 528, 44, 45, 4, 10, 1, 1, 1 ], # 40: 1920x1080@50.00
+ [ 148.500, 1280, 720, "16/9", 700, 440, 40, 30, 5, 5, 1, 1, 0 ], # 41: 1280x 720@100.00
+ [ 54.000, 720, 576, "4/3", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 42: 720x 576@100.00
+ [ 54.000, 720, 576, "16/9", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 43: 720x 576@100.00
+ [ 54.000, 1440, 576, "4/3", 288, 24, 126, 49, 4, 6, 0, 0, 0 ], # 44: 1440x 576@50.00
+ [ 54.000, 1440, 576, "16/9", 288, 24, 126, 49, 4, 6, 0, 0, 0 ], # 45: 1440x 576@50.00
+ [ 148.500, 1920, 1080, "16/9", 280, 88, 44, 45, 4, 10, 1, 1, 1 ], # 46: 1920x1080@60.00
+ [ 148.500, 1280, 720, "16/9", 370, 110, 40, 30, 5, 5, 1, 1, 0 ], # 47: 1280x 720@120.00
+ [ 54.000, 720, 480, "4/3", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 48: 720x 480@119.88
+ [ 54.000, 720, 480, "16/9", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 49: 720x 480@119.88
+ [ 54.000, 1440, 480, "4/3", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 50: 1440x 480@59.94
+ [ 54.000, 1440, 480, "16/9", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 51: 1440x 480@59.94
+ [ 108.000, 720, 576, "4/3", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 52: 720x 576@200.00
+ [ 108.000, 720, 576, "16/9", 144, 12, 64, 49, 5, 5, 0, 0, 0 ], # 53: 720x 576@200.00
+ [ 108.000, 1440, 576, "4/3", 288, 24, 126, 49, 4, 6, 0, 0, 1 ], # 54: 1440x 576@100.00
+ [ 108.000, 1440, 576, "16/9", 288, 24, 126, 49, 4, 6, 0, 0, 1 ], # 55: 1440x 576@100.00
+ [ 108.000, 720, 480, "4/3", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 56: 720x 480@239.76
+ [ 108.000, 720, 480, "16/9", 138, 16, 62, 45, 9, 6, 0, 0, 0 ], # 57: 720x 480@239.76
+ [ 108.000, 1440, 480, "4/3", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 58: 1440x 480@119.88
+ [ 108.000, 1440, 480, "16/9", 276, 38, 124, 45, 8, 6, 0, 0, 1 ], # 59: 1440x 480@119.88
+ [ 59.400, 1280, 720, "16/9", 2020, 1760, 40, 30, 5, 5, 1, 1, 0 ], # 60: 1280x 720@24.00
+ [ 74.250, 1280, 720, "16/9", 2680, 2420, 40, 30, 5, 5, 1, 1, 0 ], # 61: 1280x 720@25.00
+ [ 74.250, 1280, 720, "16/9", 2020, 1760, 40, 30, 5, 5, 1, 1, 0 ], # 62: 1280x 720@30.00
+ [ 297.000, 1920, 1080, "16/9", 280, 88, 44, 45, 4, 5, 1, 1, 0 ], # 63: 1920x1080@120.00
+ [ 297.000, 1920, 1080, "16/9", 720, 528, 44, 45, 4, 10, 1, 1, 0 ], # 64: 1920x1080@100.00
+);
+# Exist but IDs Unknown: Pixio, AOpen (AON?), AORUS [probably GBT], Deco Gear,
+# Eyoyo, GAEMS, GeChic, KOORUI, Lilliput, Mobile Pixels, Nexanic,
+# SunFounder, TECNII, TPEKKA, V7/VSEVEN,
+# Guesses: KYY=KYY, MSI=MSI,
+# PGS: Princeton Graphic Systems; SDC: Samsung Display Co;
+# SIS: Silicon Integrated Systems; STN: Samsung Electronics America;
+# TAI: Toshiba America
+my %vendors = (
+'ACI' => 'Asus', 'ACR' => 'Acer', 'ACT' => 'Targa', 'ADI' => 'ADI',
+'AMW' => 'AMW', 'ANX' => 'Acer Netxix', 'AOC' => 'AOC', 'API' => 'Acer',
+'APP' => 'Apple', 'ART' => 'ArtMedia', 'AST' => 'AST Research', 'AUO' => 'AU Optronics',
+'BEL' => 'Beltronic', 'BMM' => 'BMM', 'BNQ' => 'BenQ', 'BOE' => 'BOE Display',
+'CMN' => 'Chi Mei Innolux', 'CPL' => 'Compal/ALFA', 'CPQ' => 'Compaq',
+'CPT' => 'Asus', 'CTX' => 'CTX (Chuntex)', 'CVT' => 'DGM',
+'DEC' => 'DEC', 'DEL' => 'Dell', 'DPC' => 'Delta', 'DPL' => 'Digital Projection', 'DWE' => 'Daewoo',
+'ECS' => 'Elitegroup', 'EIZ' => 'EIZO', 'EPI' => 'Envision', 'ETR' => 'Rotel',
+'FCM' => 'Funai', 'FUS' => 'Fujitsu Siemens',
+'GBT' => 'Gigabyte', 'GSM' => 'LG (GoldStar)', 'GWY' => 'Gateway 2000',
+'HEI' => 'Hyundai.', 'HIQ' => 'Hyundai ImageQuest', 'HIT' => 'Hitachi', 'HPN' => 'HP',
+'HSD' => 'Hannspree', 'HSL' => 'Hansol', 'HTC' => 'Hitachi', 'HVR' => 'Hitache', 'HWP' => 'HP',
+'IBM' => 'IBM', 'ICL' => 'Fujitsu ICL', 'IFS' => 'InFocus', 'IQT' => 'Hyundai',
+'IVM' => 'Idek Iiyama',
+'KDS' => 'KDS', 'KFC' => 'KFC Computek', 'KYY' => 'KYY',
+'LEN' => 'Lenovo', 'LGD' => 'LG', 'LKM' => 'Adlas/Azalea', 'LNK' => 'LINK',
+'LPL' => 'LG Philips', 'LTN' => 'Lite-On',
+'MAG' => 'MAG InnoVision', 'MAX' => 'Maxdata', 'MED' => 'Medion',
+'MEI' => 'Panasonic', 'MEL' => 'Mitsubishi', 'MIR' => 'Miro', 'MSI' => 'MSI', 'MTC' => 'MITAC',
+'NAN' => 'NANAO', 'NEC' => 'NEC', 'NOK' => 'Nokia', 'NVD' => 'Nvidia',
+'OQI' => 'ViewSonic Optiquest', 'ORN' => 'Orion',
+'PBN' => 'Packard Bell', 'PCK' => 'Daewoo', 'PDC' => 'Polaroid', 'PGS' => 'Princeton',
+'PHL' => 'Philips', 'PIO' => 'Pioneer', 'PNR' => 'Planar', 'PRT' => 'Princeton',
+'QDI' => 'Quahtum Data', 'QDS' => 'Quanta Display', 'REL' => 'Relisys',
+'SAM' => 'Samsung', 'SAN' => 'Sanyo', 'SDC' => 'Samsung', 'SEC' => 'Seiko Epson',
+'SEN' => 'Sensics', 'SHP' => 'Sharp', 'SII' => 'Silicon Image', 'SIS' => 'SIS',
+'SMC' => 'Samtron', 'SMI' => 'Smile', 'SNI' => 'Siemens Nixdorf', 'SNY' => 'Sony',
+'SPT' => 'Sceptre', 'SRC' => 'Shamrock', 'STN' => 'Samsung', 'STP' => 'Sceptre',
+'TAI' => 'Toshiba', 'TAT' => 'Tatung', 'TOS' => 'Toshiba', 'TRL' => 'Royal Information',
+'TSB' => 'Toshiba', 'UEG' => 'EliteGroup', 'UNM' => 'Unisys',
+'VIT' => 'Visitech', 'VLV' => 'Valve', 'VSC' => 'ViewSonic', 'VTK' => 'Viewteck',
+'WTC' => 'Wen Technology', 'ZCM' => 'Zenith',
+);
+sub _within_limit {
+ my ($value, $type, $limit) = @_;
+ $type eq 'min' ? $value >= $limit : $value <= $limit;
+}
+sub _get_many_bits {
+ my ($s, $field_name) = @_;
+ my @bits = split('', unpack('B*', $s));
+ my %h;
+ foreach (@{$subfields{$field_name}}) {
+ my ($size, $field) = @$_;
+ my @l = ('0' x (8 - $size), splice(@bits, 0, $size));
+ $h{$field} = unpack("C", pack('B*', join('', @l))) if $field && $field !~ /^_/;
+ }
+ \%h;
+}
+sub check_parsed_edid {
+ my ($edid) = @_;
+ $edid->{edid_version} >= 1 && $edid->{edid_version} <= 2 or return 'bad edid_version';
+ $edid->{edid_revision} != 0xff or return 'bad edid_revision';
+ if ($edid->{monitor_range}) {
+ $edid->{monitor_range}{horizontal_min} &&
+ $edid->{monitor_range}{horizontal_min} <= $edid->{monitor_range}{horizontal_max}
+ or return 'bad HorizSync';
+ $edid->{monitor_range}{vertical_min} &&
+ $edid->{monitor_range}{vertical_min} <= $edid->{monitor_range}{vertical_max}
+ or return 'bad VertRefresh';
+ }
+ '';
+}
+sub _build_detailed_timing {
+ my ($pixel_clock, $vv) = @_;
+ my $h = _get_many_bits($vv, 'detailed_timing');
+ $h->{pixel_clock} = $pixel_clock / 100; # to have it in MHz
+ my %detailed_timing_field_size = map { $_->[1], $_->[0] } @{$subfields{detailed_timing}};
+ foreach my $field (keys %detailed_timing_field_size) {
+ $field =~ s/_hi$// or next;
+ my $hi = delete($h->{$field . '_hi'});
+ $h->{$field} += $hi << $detailed_timing_field_size{$field};
+ }
+ $h;
+}
+sub _add_standard_timing_modes {
+ my ($edid, $v) = @_;
+ my @aspect2ratio = (
+ $edid->{edid_version} > 1 || $edid->{edid_revision} > 2 ? '16/10' : '1/1',
+ '4/3', '5/4', '16/9',
+ );
+ $v = [ map {
+ my $h = _get_many_bits($_, 'standard_timing');
+ $h->{X} = ($h->{X} + 31) * 8;
+ if ($_ ne "\x20\x20" && $h->{X} > 256) { # cf VALID_TIMING in Xorg edid.h
+ $h->{vfreq} += 60;
+ if ($h->{ratio} = $aspect2ratio[$h->{aspect}]) {
+ delete $h->{aspect};
+ $h->{Y} = $h->{X} / eval($h->{ratio});
+ }
+ $h;
+ } else { () }
+ } unpack('a2' x (length($v) / 2), $v) ];
+ $v;
+}
+sub parse_edid {
+ my ($raw_edid, $verbose) = @_;
+ my %edid;
+ my ($main_edid, @eedid_blocks) = unpack("a128" x (length($raw_edid) / 128), $raw_edid);
+ my @vals = unpack(join('', map { $_->[0] } @edid_info), $main_edid);
+ my $i;
+ foreach (@edid_info) {
+ my ($field, $v) = ($_->[1], $vals[$i++]);
+ if ($field eq 'year') {
+ $v += 1990;
+ } elsif ($field eq 'manufacturer_name') {
+ my $h = _get_many_bits($v, 'manufacturer_name');
+ $v = join('', map { chr(ord('A') + $h->{$_} - 1) } 1 .. 3);
+ $v = "" if $v eq "@@@";
+ $edid{'manufacturer_name_nice'} = ($v && $vendors{$v}) ? $vendors{$v} : '';
+ } elsif ($field eq 'video_input_definition') {
+ $v = _get_many_bits($v, 'video_input_definition');
+ } elsif ($field eq 'feature_support') {
+ $v = _get_many_bits($v, 'feature_support');
+ } elsif ($field eq 'established_timings') {
+ my $h = _get_many_bits($v, 'established_timings');
+ $v = [
+ sort { $a->{X} <=> $b->{X} || $a->{vfreq} <=> $b->{vfreq} }
+ map { /(\d+)x(\d+)_(\d+)(i?)/ ? { X => $1, Y => $2, vfreq => $3, $4 ? (interlace => 1) : () } : () }
+ grep { $h->{$_} } keys %$h ];
+ } elsif ($field eq 'standard_timings') {
+ $v = _add_standard_timing_modes(\%edid, $v);
+ } elsif ($field eq 'monitor_details') {
+ while ($v) {
+ (my $pixel_clock, my $vv, $v) = unpack("v a16 a*", $v);
+ if ($pixel_clock) {
+ # detailed timing
+ my $h = _build_detailed_timing($pixel_clock, $vv);
+ push @{$edid{detailed_timings}}, $h
+ if $h->{horizontal_active} > 1 && $h->{vertical_active} > 1;
+ } else {
+ (my $flag, $vv) = unpack("n x a*", $vv);
+ if ($flag == 0xfd) {
+ # range
+ $edid{monitor_range} = _get_many_bits($vv, 'monitor_range');
+ if ($edid{monitor_range}{pixel_clock_max} == 0xff) {
+ delete $edid{monitor_range}{pixel_clock_max};
+ } else {
+ $edid{monitor_range}{pixel_clock_max} *= 10; #- to have it in MHz
+ }
+ } elsif ($flag == 0xf) {
+ my $range = _get_many_bits($vv, 'manufacturer_specified_range_timing');
+ my $e = $edid{detailed_timings}[0];
+ my $valid = 1;
+ foreach my $m ('min', 'max') {
+ my %total;
+ foreach my $dir ('horizontal', 'vertical') {
+ $range->{$dir . '_sync_pulse_width_' . $m} *= 2;
+ $range->{$dir . '_back_porch_' . $m} *= 2;
+ $range->{$dir . '_blanking_' . $m} *= 2;
+ if ($e && $e->{$dir . '_active'}
+ && _within_limit($e->{$dir . '_blanking'}, $m, $range->{$dir . '_blanking_' . $m})
+ && _within_limit($e->{$dir . '_sync_pulse_width'}, $m, $range->{$dir . '_sync_pulse_width_' . $m})
+ && _within_limit($e->{$dir . '_blanking'} - $e->{$dir . '_sync_offset'} - $e->{$dir . '_sync_pulse_width'},
+ $m, $range->{$dir . '_back_porch_' . $m})) {
+ $total{$dir} = $e->{$dir . '_active'} + $range->{$dir . '_blanking_' . $m};
+ }
+ }
+ if ($total{horizontal} && $total{vertical}) {
+ my $hfreq = $e->{pixel_clock} * 1000 / $total{horizontal};
+ my $vfreq = $hfreq * 1000 / $total{vertical};
+ $range->{'horizontal_' . ($m eq 'min' ? 'max' : 'min')} = _round($hfreq);
+ $range->{'vertical_' . ($m eq 'min' ? 'max' : 'min')} = _round($vfreq);
+ } else {
+ $valid = 0;
+ }
+ }
+ $edid{$valid ? 'monitor_range' : 'manufacturer_specified_range_timing'} = $range;
+ } elsif ($flag == 0xfa) {
+ push @{$edid{standard_timings}}, _add_standard_timing_modes(\%edid, unpack('a12', $vv));
+ } elsif ($flag == 0xfc) {
+ my $prev = $edid{monitor_name};
+ $edid{monitor_name} = ($prev ? "$prev " : '') . unpack('A13', $vv);
+ } elsif ($flag == 0xfe) {
+ push @{$edid{monitor_text}}, unpack('A13', $vv);
+ } elsif ($flag == 0xff) {
+ push @{$edid{serial_number2}}, unpack('A13', $vv);
+ } else {
+ $verbose && $vv ne "\0" x 13 && $vv ne " " x 13 and
+ warn "parse_edid: unknown flag $flag\n";
+ }
+ }
+ }
+ }
+ $edid{$field} = $v if $field && $field !~ /^_/;
+ }
+ foreach (@eedid_blocks) {
+ my ($tag, $v) = unpack("C a*", $_);
+ if ($tag == 0x02) { # CEA EDID
+ my $dtd_offset;
+ ($dtd_offset, $v) = unpack("x C x a*", $v);
+ next if $dtd_offset < 4;
+ $dtd_offset -= 4;
+ while ($dtd_offset > 0) {
+ if (!$v) {
+ warn "parse_edid: DTD offset outside of available data\n" if $verbose;
+ last;
+ }
+ my $h = _get_many_bits($v, 'cea_data_block_collection');
+ $dtd_offset -= $h->{size} + 1;
+ my $vv;
+ ($vv, $v) = unpack("x a$h->{size} a*", $v);
+ if ($h->{type} == 0x02) { # Video Data Block
+ my @vmodes = unpack("a" x $h->{size}, $vv);
+ foreach my $vmode (@vmodes) {
+ $h = _get_many_bits($vmode, 'cea_video_data_block');
+ my $cea_mode = $cea_video_modes[$h->{mode} - 1];
+ if (!$cea_mode) {
+ warn "parse_edid: unhandled CEA mode $h->{mode}\n" if $verbose;
+ next;
+ }
+ my %det_mode = (source => 'cea_vdb');
+ @det_mode{@cea_video_mode_to_detailed_timing} = @$cea_mode;
+ push @{$edid{detailed_timings}}, \%det_mode;
+ }
+ }
+ }
+ while (length($v) >= 18) {
+ (my $pixel_clock, my $vv, $v) = unpack("v a16 a*", $v);
+ last if !$pixel_clock;
+ my $h = _build_detailed_timing($pixel_clock, $vv);
+ push @{$edid{detailed_timings}}, $h
+ if $h->{horizontal_active} > 1 && $h->{vertical_active} > 1;
+ }
+ } else {
+ $verbose && warn "parse_edid: unknown tag $tag\n";
+ }
+ }
+ $edid{max_size_precision} = 'cm';
+ $edid{EISA_ID} = $edid{manufacturer_name} . sprintf('%04x', $edid{product_code}) if $edid{product_code} && $edid{manufacturer_name};
+ if ($edid{monitor_range}) {
+ $edid{HorizSync} = $edid{monitor_range}{horizontal_min} . '-' . $edid{monitor_range}{horizontal_max};
+ $edid{VertRefresh} = $edid{monitor_range}{vertical_min} . '-' . $edid{monitor_range}{vertical_max};
+ }
+ if ($edid{max_size_vertical}) {
+ $edid{ratio} = $edid{max_size_horizontal} / $edid{max_size_vertical};
+ $edid{ratio_name} = _ratio_name($edid{max_size_horizontal}, $edid{max_size_vertical}, 'cm');
+ $edid{ratio_precision} = 'cm';
+ }
+ if ($edid{feature_support}{has_preferred_timing} && $edid{detailed_timings}[0]) {
+ $edid{detailed_timings}[0]{preferred} = 1;
+ }
+ foreach my $h (@{$edid{detailed_timings}}) {
+ # EDID standard is ambiguous on how interlaced modes should be
+ # specified; workaround clearly broken modes:
+ if ($h->{interlaced}) {
+ foreach ("720x480", "1440x480", "2880x480", "720x576", "1440x576", "2880x576", "1920x1080") {
+ if ($_ eq $h->{horizontal_active} . 'x' . $h->{vertical_active} * 2) {
+ $h->{vertical_active} *= 2;
+ $h->{vertical_blanking} *= 2;
+ $h->{vertical_sync_offset} *= 2;
+ $h->{vertical_sync_pulse_width} *= 2;
+ $h->{vertical_blanking} |= 1;
+ }
+ }
+ }
+ # if the mm size given in the detailed_timing is not far from the cm size
+ # put it as a more precise cm size
+ my %in_cm = (
+ horizontal => _define($h->{horizontal_image_size}) / 10,
+ vertical => _define($h->{vertical_image_size}) / 10,
+ );
+ my ($error) = sort { $b <=> $a } map { abs($edid{'max_size_' . $_} - $in_cm{$_}) } keys %in_cm;
+ if ($error <= 0.5) {
+ $edid{'max_size_' . $_} = $in_cm{$_} foreach keys %in_cm;
+ $edid{max_size_precision} = 'mm';
+ }
+ if ($error < 1 && $in_cm{vertical}) {
+ # using it for the ratio
+ $edid{ratio} = $in_cm{horizontal} / $in_cm{vertical};
+ $edid{ratio_name} = _ratio_name($in_cm{horizontal}, $in_cm{vertical}, 'mm');
+ $edid{ratio_precision} = 'mm';
+ }
+ $h->{bad_ratio} = 1 if
+ $edid{ratio_precision} &&
+ abs($edid{ratio} - $h->{horizontal_active} / $h->{vertical_active}) > ($edid{ratio_precision} eq 'mm' ? 0.02 : 0.2);
+
+ if ($edid{max_size_vertical}) {
+ $h->{vertical_dpi} = $h->{vertical_active} / $edid{max_size_vertical} * 2.54;
+ }
+ if ($edid{max_size_horizontal}) {
+ $h->{horizontal_dpi} = $h->{horizontal_active} / $edid{max_size_horizontal} * 2.54;
+ }
+ my $dpi_string = '';
+ if ($h->{vertical_dpi} && $h->{horizontal_dpi}) {
+ $dpi_string =
+ abs($h->{vertical_dpi} / $h->{horizontal_dpi} - 1) < 0.05 ?
+ sprintf("%d dpi", $h->{horizontal_dpi}) :
+ sprintf("%dx%d dpi", $h->{horizontal_dpi}, $h->{vertical_dpi});
+ }
+ my $horizontal_total = $h->{horizontal_active} + $h->{horizontal_blanking};
+ my $vertical_total = $h->{vertical_active} + $h->{vertical_blanking};
+ no warnings 'uninitialized';
+ $h->{ModeLine_comment} = sprintf qq(# Monitor %s%s modeline (%.1f Hz vsync, %.1f kHz hsync, %sratio %s%s)),
+ $h->{preferred} ? "preferred" : "supported",
+ $h->{source} eq 'cea_vdb' ? " CEA" : '',
+ $h->{pixel_clock} / $horizontal_total / $vertical_total * 1000 * 1000 * ($h->{interlaced} ? 2 : 1),
+ $h->{pixel_clock} / $horizontal_total * 1000,
+ $h->{interlaced} ? "interlaced, " : '',
+ _nearest_ratio($h->{horizontal_active} / $h->{vertical_active}, 0.01) || sprintf("%.2f", $h->{horizontal_active} / $h->{vertical_active}),
+ $dpi_string ? ", $dpi_string" : '';
+
+ $h->{ModeLine} = sprintf qq("%dx%d" $h->{pixel_clock} %d %d %d %d %d %d %d %d %shsync %svsync%s),
+ $h->{horizontal_active}, $h->{vertical_active},
+
+ $h->{horizontal_active},
+ $h->{horizontal_active} + $h->{horizontal_sync_offset},
+ $h->{horizontal_active} + $h->{horizontal_sync_offset} + $h->{horizontal_sync_pulse_width},
+ $horizontal_total,
+
+ $h->{vertical_active},
+ $h->{vertical_active} + $h->{vertical_sync_offset},
+ $h->{vertical_active} + $h->{vertical_sync_offset} + $h->{vertical_sync_pulse_width},
+ $vertical_total,
+
+ $h->{horizontal_sync_positive} ? '+' : '-',
+ $h->{vertical_sync_positive} ? '+' : '-',
+ $h->{interlaced} ? ' Interlace' : '';
+ }
+ $edid{diagonal_size} = sqrt(_sqr($edid{max_size_horizontal}) + _sqr($edid{max_size_vertical})) / 2.54;
+
+ \%edid;
+}
+sub _nearest_ratio {
+ my ($ratio, $max_error) = @_;
+ my @sorted =
+ sort { $a->[1] <=> $b->[1] }
+ map {
+ my $error = abs($ratio - eval($_));
+ $error > $max_error ? () : [ $_, $error ];
+ } @known_ratios;
+ $sorted[0][0];
+}
+sub _ratio_name {
+ my ($horizontal, $vertical, $precision) = @_;
+ if ($precision eq 'mm') {
+ _nearest_ratio($horizontal / $vertical, 0.1);
+ } else {
+ my $error = 0.5;
+ my $ratio1 = _nearest_ratio(($horizontal + $error) / ($vertical - $error), 0.2);
+ my $ratio2 = _nearest_ratio(($horizontal - $error) / ($vertical + $error), 0.2);
+ $ratio1 && $ratio2 or return;
+ if ($ratio1 eq $ratio2) {
+ $ratio1;
+ } else {
+ my $ratio = _nearest_ratio($horizontal / $vertical, 0.2);
+ join(' or ', $ratio, $ratio eq $ratio1 ? $ratio2 : $ratio1);
+ }
+ }
+}
+sub _define { defined $_[0] ? $_[0] : 0 }
+sub _sqr { $_[0] * $_[0] }
+sub _round { int($_[0] + 0.5) }
+}
+
## PartitionData - set/get
# for /proc/partitions only, see DiskDataBSD for BSD partition data.
{
@@ -26459,6 +28413,79 @@ sub get_pci_vendor {
return $vendor;
}
+# $rows, $num by ref.
+sub get_pcie_data {
+ eval $start if $b_log;
+ my ($bus_id,$j,$rows,$num,$type) = @_;
+ $type ||= '';
+ # see also /sys/class/drm/
+ my $path_start = '/sys/bus/pci/devices/0000:';
+ return if !$bus_id || ! -d $path_start . $bus_id;
+ $path_start .= $bus_id;
+ my $path = $path_start . '/{max_link_width,current_link_width,max_link_speed';
+ $path .= ',current_link_speed}';
+ my @files = globber($path);
+ if ($type eq 'gpu'){
+ $path = $path_start . '/0000*/0000*/{mem_info_vram_used,mem_info_vram_total}';
+ push(@files,globber($path));
+ }
+ # print @files,"\n";
+ return if !@files;
+ my (%data,$name);
+ my %gen = (
+ '2.5 GT/s' => 1,
+ '5 GT/s' => 2,
+ '8 GT/s' => 3,
+ '16 GT/s' => 4,
+ '32 GT/s' => 5,
+ '64 GT/s' => 6,
+ );
+ foreach (@files){
+ if (-r $_){
+ $name = $_;
+ $name =~ s|^/.*/||;
+ $data{$name} = reader($_,'strip',0);
+ if ($name eq 'max_link_speed' || $name eq 'current_link_speed'){
+ $data{$name} =~ s/\.0\b| PCIe$//g; # trim .0 off in 5.0, 8.0
+ }
+ }
+ }
+ # print Data::Dumper::Dumper \%data;
+ # Maximum PCIe Bandwidth = SPEED * WIDTH * (1 - ENCODING) - 1Gb/s.
+ if ($data{'current_link_speed'} && $data{'current_link_width'}){
+ $$rows[$j]->{key($$num++,1,2,'pcie')} = '';
+ if ($b_admin && $gen{$data{'current_link_speed'}}){
+ $$rows[$j]{key($$num++,0,3,'gen')} = $gen{$data{'current_link_speed'}};
+ }
+ $$rows[$j]{key($$num++,0,3,'speed')} = $data{'current_link_speed'};
+ $$rows[$j]->{key($$num++,0,3,'lanes')} = $data{'current_link_width'};
+ if ($b_admin && (($data{'max_link_speed'} &&
+ $data{'max_link_speed'} ne $data{'current_link_speed'}) ||
+ ($data{'max_link_width'} &&
+ $data{'max_link_width'} > $data{'current_link_width'}))){
+ $$rows[$j]->{key($$num++,1,3,'link-max')} = '';
+ if ($data{'max_link_speed'} &&
+ $data{'max_link_speed'} ne $data{'current_link_speed'}){
+ $$rows[$j]{key($$num++,0,4,'gen')} = $gen{$data{'max_link_speed'}};
+ $$rows[$j]->{key($$num++,0,4,'speed')} = $data{'max_link_speed'};
+ }
+ if ($data{'max_link_width'} &&
+ $data{'max_link_width'} > $data{'current_link_width'}){
+ $$rows[$j]->{key($$num++,0,4,'lanes')} = $data{'max_link_width'};
+ }
+ }
+ }
+ if ($type eq 'gpu' && $data{'mem_info_vram_used'} && $data{'mem_info_vram_total'}){
+ $$rows[$j]->{key($$num++,1,2,'vram')} = '';
+ $$rows[$j]->{key($$num++,0,3,'total')} = get_size($data{'mem_info_vram_total'}/1024,'string');
+ my $used = get_size($data{'mem_info_vram_used'}/1024,'string');
+ $used .= ' (' . sprintf('%0.1f',($data{'mem_info_vram_used'}/$data{'mem_info_vram_total'}*100)) . '%)';
+ $$rows[$j]->{key($$num++,0,3,'used')} = $used;
+
+ }
+ eval $end if $b_log;
+}
+
sub set_ps_aux {
eval $start if $b_log;
my ($header,@ps,@temp);
@@ -26503,30 +28530,29 @@ sub set_ps_aux {
sub set_ps_gui {
eval $start if $b_log;
$loaded{'ps-gui'} = 1;
- my ($working,@match,@temp);
+ my ($b_wl,$working,@match,@temp);
# desktops / wm (some wm also compositors)
if ($show{'system'}){
@temp=qw(razor-desktop razor-session lxsession lxqt-session
tdelauncher tdeinit_phase1);
push(@match,@temp);
@temp=qw(2bwm 3dwm 9wm afterstep aewm aewm\+\+ amiwm antiwm awesome
- blackbox bspwm
- cagebreak calmwm catwm (sh|c?lisp).*clfswm ctwm (openbsd-)?cwm dwm evilwm
+ blackbox bspwm calmwm catwm (sh|c?lisp).*clfswm ctwm (openbsd-)?cwm dwm evilwm
fluxbox flwm flwm_topside fvwm.*-crystal fvwm1 fvwm2 fvwm3 fvwm95 fvwm
herbstluftwm i3 icewm instantwm ion3 jbwm jwm larswm leftwm lwm
matchbox-window-manager mcwm mini monsterwm musca mwm nawm notion
- openbox orbital pekwm penrose perceptia python.*qtile qtile qvwm ratpoison
- sawfish scrotwm snapwm spectrwm (sh|c?lisp).*stumpwm sway
- tinywm tvtwm twm uwm
- waycooler way-cooler windowlab WindowMaker wingo wm2 wmfs wmfs2 wmii2 wmii
- wmx
- xfdesktop xmonad yeahwm);
+ openbox pekwm penrose python.*qtile qvwm ratpoison
+ sawfish scrotwm snapwm spectrwm (sh|c?lisp).*stumpwm
+ tinywm tvtwm twm uwm windowlab WindowMaker wingo wm2 wmfs wmfs2 wmii2 wmii
+ wmx xfdesktop xmonad yeahwm);
push(@match,@temp);
+ $b_wl = 1;
}
- # wm:
+ # wm: note that for all but the listed wm, the wm and desktop would be the
+ # same, particularly with all smaller wayland wm/compositors.
if ($show{'system'} && $extra > 1){
@temp=qw(budgie-wm compiz deepin-wm gala gnome-shell
- twin kwin_wayland kwin_x11 kwin marco
+ twin kwin_wayland kwin_x11 kwinft kwin marco
deepin-metacity metacity metisse mir muffin deepin-mutter mutter
ukwm xfwm[45]?);
push(@match,@temp);
@@ -26538,29 +28564,42 @@ sub set_ps_gui {
if ($show{'system'} && $extra > 2){
@temp=qw(alltray awn bar bmpanel bmpanel2 budgie-panel
cairo-dock dde-dock dmenu dockbarx docker docky dzen dzen2
- fbpanel fspanel glx-dock gnome-panel hpanel i3bar icewmtray
- kdocker kicker latte latte-dock lemonbar ltpanel lxpanel lxqt-panel
- matchbox-panel mate-panel ourico
+ fbpanel fspanel glx-dock gnome-panel hpanel i3bar i3-status(-rs)? icewmtray
+ kdocker kicker latte latte-dock lemonbar ltpanel luastatus lxpanel lxqt-panel
+ matchbox-panel mate-panel nwg-bar nwg-dock nwg-panel ourico
perlpanel plank plasma-desktop plasma-netbook polybar pypanel
- razor-panel razorqt-panel stalonetray swaybar taskbar tint2 trayer
- ukui-panel vala-panel wbar wharf wingpanel witray
- xfce[45]?-panel xmobar yabar);
+ razor-panel razorqt-panel rootbar
+ sfwbar stalonetray swaybar taskbar tint2 trayer
+ ukui-panel vala-panel wapanel waybar wbar wharf wingpanel witray
+ xfce[45]?-panel xmobar yambar yabar);
push(@match,@temp);
}
# compositors (for wayland these are also the server, note.
# for wayland always show, so always load these
- if ($show{'graphic'} && $extra > 0){
- @temp=qw(3dwm asc budgie-wm compiz compton deepin-wm dwc dcompmgr
- enlightenment fireplace gnome-shell grefson kmscon kwin_wayland kwin_x11
- liri marco metisse mir moblin motorcar muffin mutter
- orbital papyros perceptia picom rustland sommelier sway swc
- ukwm unagi unity-system-compositor
- wavy waycooler way-cooler wayfire wayhouse westford weston xcompmgr
- xfwm[45]?);
+ if ($show{'graphic'}){
+ @temp=qw(3dwm budgie-wm cairo compiz compton deepin-wm dcompmgr enlightenment
+ gala gnome-shell kmscon kwin_wayland kwin_x11 kwinft kwin
+ marco metisse mir moblin muffin mutter picom steamcompmgr
+ ukwm unagi unity-system-compositor wayland xcompmgr xfwm[45]?);
push(@match,@temp);
+ $b_wl = 1;
}
uniq(\@match);
my $matches = join('|', @match);
+ if ($b_wl){
+ # wayland compositors generally are compositors and wm.
+ # These will be used globally to avoid having to redo it over and over.
+ $wl_compositors = '|' . join('|',qw(asc awc
+ cage cagebreak cardboard chameleonwm clayland comfc
+ dwc dwl epd-wm fireplace feathers fenestra glass gamescope greenfield grefson
+ hikari hopalong inaban japokwm kiwmi labwc laikawm lipstick liri
+ mahogany marina maze motorcar newm nucleus orbital perceptia phoc pywm qtile
+ river rootston rustland simulavr skylight sommelier sway swc swvkc
+ tabby taiwins tinybox tinywl trinkster velox vimway vivarium
+ wavy waybox way-?cooler wayfire wayhouse waymonad westeros westford
+ weston wio\+? wxr[cd] xuake));
+ $matches .= $wl_compositors;
+ }
foreach (@ps_cmd){
if (/^(|[\S]*\/)($matches)(\/|\s|$)/){
$working = $2;
@@ -26953,8 +28992,8 @@ sub shell_launcher {
}
# in case sudo starts inxi, parent is shell (or perl inxi if run by debugger)
# so: perl (2) started pinxi with sudo (3) in sh (4) in terminal
- my $shells = 'ash|bash|busybox|cicada|csh|dash|doas|elvish|fish|fizsh|ksh|ksh93|';
- $shells .= 'lksh|login|loksh|mksh|nash|oh|oil|osh|pdksh|perl|posh|';
+ my $shells = 'ash|bash|busybox|cicada|csh|dash|doas|elvish|fish|fizsh|ksh|';
+ $shells .= 'ksh93|lksh|login|loksh|mksh|nash|oh|oil|osh|pdksh|perl|posh|';
$shells .= 'su|sudo|tcsh|xonsh|yash|zsh';
$shells .= shell_test('return');
my $i = 0;
@@ -27416,7 +29455,7 @@ sub usbconfig_data {
undef @working;
}
elsif (/^([a-z_-]+)([0-9]+)\.([0-9]+):\s+<[^>]+>\s+at usbus([0-9]+)\b/){
- ($class_id,$cfg,$power,$speed,$subclass_id,$type) = undef;
+ ($class_id,$cfg,$power,$speed,$subclass_id,$type) = ();
($product,$product_id,$vendor,$vendor_id) = ('','','','');
$hub_id = $2;
$addr_id = $3;
@@ -27925,9 +29964,8 @@ sub assign_usb_type {
# nested hubs of course can be > 1 too. No need to build these if none of
# lines are showing.
if (($row->[4] && $row->[4] eq '09') ||
- ($row->[14] && $row->[14] eq 'Hub') ||
- $row->[1] <= 1 ||
- (!$show{'audio'} && !$show{'bluetooth'} && !$show{'graphic'} && !$show{'network'})){
+ ($row->[14] && $row->[14] eq 'Hub') || $row->[1] <= 1 ||
+ (!$show{'audio'} && !$show{'bluetooth'} && !$show{'graphic'} && !$show{'network'})){
return;
}
$row->[13] = '' if !defined $row->[13]; # product
@@ -27937,27 +29975,24 @@ sub assign_usb_type {
set_network_regex() if $show{'network'} && !$network_regex;
# NOTE: a device, like camera, can be audio+graphic
if ($show{'audio'} && (
- (@asound_ids && $row->[7] && (grep {$row->[7] eq $_} @asound_ids)) ||
- ($row->[14] =~ /Audio/) ||
- ($row->[15] && $row->[15] =~ /audio/) ||
- ($row->[13] && lc($row->[13]) =~ /(audio|\bdac[0-9]*\b|headphone|\bmic(rophone)?\b)/))){
+ (@asound_ids && $row->[7] && (grep {$row->[7] eq $_} @asound_ids)) ||
+ ($row->[14] =~ /Audio/) || ($row->[15] && $row->[15] =~ /audio/) ||
+ ($row->[13] && lc($row->[13]) =~ /(audio|\bdac[0-9]*\b|headphone|\bmic(rophone)?\b)/))){
push(@{$usb{'audio'}},$row);
}
- if ($show{'graphic'} && (
- $row->[14] && ($row->[14] =~ /Video/) ||
- ($row->[15] && $row->[15] =~ /video/) ||
- ($row->[13] && lc($row->[13]) =~ /(camera|\bdvb-t|\b(pc)?tv\b|video|webcam)/))){
+ if ($show{'graphic'} && ($row->[14] && ($row->[14] =~ /Video/) ||
+ ($row->[15] && $row->[15] =~ /video/) ||
+ ($row->[13] && lc($row->[13]) =~ /(camera|\bdvb-t|\b(pc)?tv\b|video|webcam)/))){
push(@{$usb{'graphics'}},$row);
}
- elsif ($show{'bluetooth'} && (
- $row->[14] && $row->[14] =~ /Bluetooth/ ||
- ($row->[15] && $row->[15] =~ /\b(btusb|ubt)\b/))){
+ elsif ($show{'bluetooth'} && ($row->[14] && $row->[14] =~ /Bluetooth/ ||
+ ($row->[15] && $row->[15] =~ /\b(btusb|ubt)\b/))){
push(@{$usb{'bluetooth'}},$row);
}
elsif ($show{'network'} && (
- ($row->[14] && $row->[14] =~ /(Ethernet|Network|WiFi)/i) ||
- ($row->[15] && $row->[15] =~ /(^ipw|^iwl|wifi)/) ||
- ($row->[13] && $row->[13] =~ /($network_regex)/i))){
+ ($row->[14] && $row->[14] =~ /(Ethernet|Network|WiFi)/i) ||
+ ($row->[15] && $row->[15] =~ /(^ipw|^iwl|wifi)/) ||
+ ($row->[13] && $row->[13] =~ /($network_regex)/i))){
# print "$1\n";
push(@{$usb{'network'}},$row);
}
@@ -28038,7 +30073,7 @@ sub check_type {
$type = 'Bluetooth'
}
elsif (($driver && $driver =~ /video/) ||
- $name =~ /(camera|display|\bdvb-t|\b(pc)?tv\bvideo|webcam)/){
+ $name =~ /(camera|display|\bdvb-t|\b(pc)?tv\bvideo|webcam)/){
$type = 'Video';
}
elsif ($name =~ /(wlan|wi-?fi|802\.1[15]|(11|54|108|240|300|450|1300)\s?mbps|(11|54|108|240)g\b|wireless[\s-][gn]\b|wireless.*adapter)/){
@@ -28054,7 +30089,7 @@ sub check_type {
$type = 'HID';
}
elsif (($driver && $driver =~ /^(umass)$/) ||
- $name =~ /\b(disk|drive|flash)\b/){
+ $name =~ /\b(disk|drive|flash)\b/){
$type = 'Mass Storage';
}
return $type;
@@ -28600,8 +30635,8 @@ sub system_item {
}
# don't print the desktop if it's a wm and the same
if ($extra > 1 && $desktop_data[5] &&
- (!$desktop_data[0] || $desktop_data[5] =~ /^(deepin.+|gnome[\s_-]shell|budgie.+)$/i ||
- index(lc($desktop_data[5]),lc($desktop_data[0])) == -1)){
+ (!$desktop_data[0] || $desktop_data[5] =~ /^(deepin.+|gnome[\s_-]shell|budgie.+)$/i ||
+ index(lc($desktop_data[5]),lc($desktop_data[0])) == -1)){
$wm = $desktop_data[5];
$wm .= ' ' . $desktop_data[6] if $extra > 2 && $desktop_data[6];
}