aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2022-04-04 23:24:38 -0400
committerLibravatarUnit 193 <unit193@unit193.net>2022-04-04 23:24:38 -0400
commitb300f90fb530a235408019a71f68cc6903ed3dfc (patch)
tree890e39c906786f377cf97fa857071db3a210e912
parent4aa30d7cf0b462da4105834fff99dccc610d4049 (diff)
parent53fa8a4c9c192af8ed408892828f77dd09679e7f (diff)
Update upstream source from tag 'upstream/3.3.14-1'
Update to upstream version '3.3.14-1' with Debian dir d4ae3fc1776e5bf7dbd6a33cca46589ed1dacc2c
-rw-r--r--README.txt95
-rwxr-xr-xinxi882
-rw-r--r--inxi.133
-rw-r--r--inxi.changelog190
4 files changed, 897 insertions, 303 deletions
diff --git a/README.txt b/README.txt
index 94a41b2..7b2a529 100644
--- a/README.txt
+++ b/README.txt
@@ -35,13 +35,11 @@ data for non trivial issue reports.
Note that the following options are present:
1. Generate local gz'ed debugger dataset. Leaves gz on your system:
- inxi version 3: inxi --debug 20
- inxi version <= 2.3: inxi -@14
+ inxi version >= 3: inxi --debug 20
2. Generate, upload gz'ed debugger dataset. Leaves gz on your system:
- inxi version 3: inxi --debug 21
- inxi version <= 2.3: inxi -xx@14
+ inxi version >= 3: inxi --debug 21
3. Generate, upload, delete gz'ed debugger dataset:
- inxi version 3 only: inxi --debug 22
+ inxi version >= 3: inxi --debug 22
You can run these as regular user, or root/sudo, which will gather a bit more
data, like from dmidecode, and other tools that need superuser permissions to
@@ -206,7 +204,7 @@ version, pre 2.9.
IRC
--------------------------------------------------------------------------------
-You can go to: irc.oftc.net channel #smxi
+You can go to: irc.oftc.net or irc.libera.chat channel #smxi
but be prepared to wait around for a while to get a response. Generally it's
better to use github issues.
@@ -262,8 +260,8 @@ The primary purpose of inxi is for support, and sys admin use. inxi is used
widely for forum and IRC support, which is I believe it's most common function.
If you are piping output to paste or post (or writing to file), inxi now
-automatically turns off color codes, so the old suggestion to use -c 0 to turn
-off colors is no longer required.
+automatically turns off color codes, so the inxi 2.3.xx and older suggestion to
+use -c 0 to turn off colors is no longer required.
inxi strives to be as accurate as possible, but some things, like memory/ram
data, depend on radically unreliable system self reporting based on OEM filling
@@ -356,13 +354,13 @@ just to keep it clean, would cause a change.
The second digit(s), "2", means a new real feature has been added. Not a tweaked
existing feature, an actual new feature, which usually also has a new argument
option letter attached. The second number goes from 0 to 9, and then rolls over
-the first after 9. It could also be adding a very complicated expansion of
-existing features, like Wayland. It depends.
+the first after 9.
-The third, "28", is for everything small, can cover bug fixes, tweaks to
-existing features to add support for something, pretty much anything where you
-want the end user to know that they are not up to date. The third goes from 0 to
-99, then rolls over the second.
+The third, "28", is for everything not covered by 1 and 2, can cover bug fixes,
+tweaks to existing features to add support for something, full on refactors of
+existing features, pretty much anything where you want the end user to know that
+they are not up to date. The third goes from 0 to 99, then rolls over the
+second.
The fourth, "6", is extra information about certain types of inxi updates. I
don't usually use this last one in master branch, but you will see it in
@@ -379,10 +377,11 @@ confusing.
inxi does not use the fiction of date based versioning because that imparts no
useful information to the end user, when you look at say, 2.2.28, and you last
had 2.2.11, you can know with some certainty that inxi has no major new
-features, just fine tunings and bug fixes. And if you see one with 2.3.2, you
-will know that there is a new feature, almost, but not always, linked to one or
-more new line output items. Sometimes a fine tuning can be quite significant,
-sometimes it's a one line code fix.
+features, just refactors or expansion of existing logic, enhancements, fine
+tunings, and bug fixes. And if you see one with 2.3.2, you will know that there
+is a new feature, almost, but not always, linked to one or more new line output
+items. Sometimes a the changes in the third number can be quite significant,
+sometimes it's a one line code or bug fix.
A move to a new full version number, like the rewrite of inxi to Perl, would
reflect in first version say, 2.9.01, then after a period of testing, where most
@@ -398,14 +397,33 @@ BSD / UNIX
BSD support is not as complete as GNU/Linux support due to the fact some of the
data simply is not available, or is structured in a way that makes it unique to
each BSD, or is difficult to process. This fragmentation makes supporting BSDs
-far more difficult than it should be in the 21st century. The BSD support in
-inxi is an ongoing process, with more features being added as new data sources
-and types are discovered.
+far more difficult than it should be in the 21st century.
+
+The BSD support in inxi is a slowly evolving process. Evolving in the strict
+technical sense of evolutionary fitness, following fitness for purpose, that is
+(like OpenBSD's focus on security and high quality code, for instance), not as
+in progressing forwards. Features are being added as new data sources and types
+are discovered, and others are being dropped, as prior data sources degenerate
+or mutate to a point where trying to deal with them stops being interesting.
+
+Once it starts growing evident that a particular branch has hit a dead end and
+no longer warrants the time required to follow it to its extinction, support
+will be reduced to basically maintenance mode. In other words, inxi follows this
+evolutionary process, and does not try to revive dead or dying branches, since
+that's a waste of time.
Note that due to time/practicality constraints, in general, only the original
-BSD branches will be actively supported: FreeBSD+derived; OpenBSD+derived;
-NetBSD+derived. Other UNIX variants will generally only get the work required to
-make internal BSD flags get set and to remove visible output errors.
+BSD branches will be supported: OpenBSD+derived; FreeBSD+derived; NetBSD+derived
+(in that order of priority, with a steep curve down from first to last). With
+the caveat that since it's my time being volunteered here, if the BSD in
+question has basically no users, or has bad tools, or no usable tools, or
+inconsistent or unreliable tools, or bad / weak data, or, worst, no actual clear
+reason to exist, I'm not willing to spend time on it as a general rule.
+
+Other UNIX variants will generally only get the work required to make internal
+BSD flags get set and to remove visible output errors. I am not interested in
+them at all, zero. They are at this point basically historical artifacts, of
+interest only to computer museums as far as I'm concerned.
--------------------------------------------------------------------------------
TRUE BSDs
@@ -425,11 +443,11 @@ similar one.
Option 2 is far preferred because in terms of my finite time on this planet of
ours, the fact is, if I don't have direct (or SSH) access, I can't get much
done, and the little I can get done will take 10 to 1000x longer than it should.
-That's my time spent (and sadly, with BSDs, largely lost), not yours.
+That's my time spent (and sadly, with BSDs, largely wasted), not yours.
I decided I have to adopt this much more strict policy with BSDs after wasting
untold hours on trying to get good BSD support, only to see that support break a
-few years down the road as the data inxi relied in changed structure or syntax,
+few years down the road as the data inxi relied on changed structure or syntax,
or the tools changed, or whatever else makes the BSDs such a challenge to
support. In the end, I realized, the only BSDs that are well supported are ones
that I have had direct access to for debugging and testing.
@@ -453,6 +471,29 @@ system as a 'Unix'.
If you want me to use my time on OSX features or issues, you have to pay me,
because Apple is all about money, not freedom (that's what the 'free' in 'free
software' is referring to, not cost), and I'm not donating my finite time in
-support of non-free operating systems.
+support of non-free operating systems, particularly not one with a market
+capitalization hovering around 1 trillion dollars, with usually well north of
+100 billion dollars in liquid assetts.
+
+================================================================================
+MICROSOFT CORPORATION WINDOWS
+--------------------------------------------------------------------------------
+
+To be quite clear, support for Windows will never happen, I don't care about
+Windows, and don't want to waste a second of my time on it. I also don't care
+about cygwin issues, beyond maybe hyper basic issues that can be handled with a
+line or two of code. inxi isn't going to ruin itself by trying to handle the
+silly Microsoft path separator \, and obviously there's zero chance of my trying
+to support PowerShell or whatever else they come up with.
+
+While I would consider doing Apple stuff if you paid my hourly full market
+rates, in advance, I would not consider touching Windows for any amount of
+money. My best advice there is, fork inxi, and do it yourself if you want it.
+You'll soon run screaming from the project however, once you realize what a
+nightmare you've stepped into.
+
+If you are interested in something like inxi for Windows, I suggest, rather than
+forking inxi, you just start out from scratch, and build the features up one by
+one, that will lead to much better code.
### EOF ###
diff --git a/inxi b/inxi
index a2f0db5..1f983d1 100755
--- a/inxi
+++ b/inxi
@@ -48,8 +48,8 @@ use POSIX qw(ceil uname strftime ttyname);
## INXI INFO ##
my $self_name='inxi';
-my $self_version='3.3.13';
-my $self_date='2022-02-22';
+my $self_version='3.3.14';
+my $self_date='2022-03-24';
my $self_patch='00';
## END INXI INFO ##
my ($b_pledge,@pledges);
@@ -4653,6 +4653,12 @@ sub get {
$show{'short'} = 0;
$show{'bluetooth'} = 1;
$show{'bluetooth-forced'} = 1;},
+ 'edid' => sub {
+ $b_admin = 1;
+ $show{'short'} = 0;
+ $show{'edid'} = 1;
+ $show{'graphic'} = 1;
+ $show{'graphic-full'} = 1;},
'f|flags|flag' => sub {
$show{'short'} = 0;
$show{'cpu'} = 1;
@@ -4858,13 +4864,14 @@ sub get {
}
if ($arg >= 8){
$b_admin = 1;
- $use{'downloader'} = 1;
+ # $use{'downloader'} = 1; # only if weather
+ $show{'edid'} = 1;
$show{'process'} = 1;
$show{'ps-cpu'} = 1;
$show{'ps-mem'} = 1;
$show{'repo'} = 1;
$show{'slot'} = 1;
- #$show{'weather'} = 1;
+ # $show{'weather'} = 1;
}
}
else {
@@ -5527,6 +5534,8 @@ sub show_options {
size(s)."],
['1', '-E', '--bluetooth', "Show bluetooth device data and report, if
available. Shows state, address, IDs, version info."],
+ ['1', '', '--edid', "Full graphics data, triggers -a, -G. Add monitor chroma,
+ full modelines (if > 2), EDID errors and warnings, if present."],
['1', '-f', '--flags', "All CPU $flags. Triggers -C. Not shown with -F to
avoid spamming."],
['1', '-F', '--full', "Full output. Includes all Upper Case line letters
@@ -5609,7 +5618,7 @@ sub show_options {
full RAID; triggers -xx."],
['2', '7', '', "Network IP data (-i), bluetooth, logical (-L),
RAID forced, full CPU $flags; triggers -xxx."],
- ['2', '8', '', "Everything available, including repos (-r),
+ ['2', '8', '', "Everything available, including EDID (--edid), repos (-r),
processes (-tcm), PCI slots (--slots); triggers admin (-a)."],
);
# if distro maintainers don't want the weather feature disable it
@@ -6659,6 +6668,9 @@ sub message {
'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.',
+ 'edid-revision' => "invalid EDID revision: $id",
+ 'edid-sync' => "bad sync value: $id",
+ 'edid-version' => "invalid EDID version: $id",
'gl-empty' => 'Unset. Missing GL driver?',
'gl-null' => 'No GL data found on this system.',
'gl-root' => 'GL data unavailable in console for root.',
@@ -6719,6 +6731,7 @@ sub message {
'smartctl-open' => 'Unable to open device. Wrong device ID given?',
'smartctl-udma-crc' => 'Bad cable/connection?',
'smartctl-usb' => 'Unknown USB bridge. Flash drive/Unsupported enclosure?',
+ 'stopped' => 'stopped',
'swap-admin' => 'No admin swap data available.',
'swap-data' => 'No swap data was found.',
'tool-missing-basic' => "<missing: $id>",
@@ -7848,7 +7861,9 @@ sub battery_data_sys {
# Valid values: Unknown,Charging,Discharging,Not charging,Full
# don't use clean_unset because Not charging is a valid value.
elsif ($file eq 'status'){
- $value =~ s/unknown//i;
+ $value = lc($value);
+ $value =~ s/unknown//;
+
}
}
elsif ($b_root && -e $path && ! -r $path){
@@ -13506,7 +13521,6 @@ sub device_output {
next if $row->[3] != 0;
# print "$row->[0] $row->[3]\n";
$j = scalar @rows;
- 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
@@ -13520,6 +13534,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;
}
+ push(@{$graphics{'gpu-drivers'}},$row->[9]) if $row->[9];
my $driver = ($row->[9]) ? $row->[9]:'N/A';
$rows[$j]->{main::key($num++,1,2,'driver')} = $driver;
if ($row->[9] && !$bsd_type){
@@ -13649,9 +13664,9 @@ sub display_output(){
my ($num,$j) = (0,0);
# note: these may not always be set, they won't be out of X, for example
display_protocol();
- $graphics{'protocol'} = 'wayland' if $force{'wayland'};
# get rid of all inactive or disabled monitor port ids
set_active_monitors() if $monitor_ids;
+ $graphics{'protocol'} = 'wayland' if $force{'wayland'};
# note, since the compositor is the server with wayland, always show it
if ($extra > 1 || $graphics{'protocol'} eq 'wayland'){
set_compositor_data();
@@ -13777,7 +13792,7 @@ sub display_output(){
}
my $gpu_drivers = gpu_drivers_sys('all');
my $drivers;
- if ($gpu_drivers ){
+ if ($gpu_drivers){
$drivers = join(',',@{$gpu_drivers});
}
else {
@@ -13924,24 +13939,31 @@ sub monitors_output_basic {
}
eval $end if $b_log;
}
-# row, num passed by ref
+# $j, $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);
+ my ($m1,$m2,$m3,$m4) = ($type eq 'screen') ? (3,4,5,6) : (2,3,4,5);
+ # note: in case where mapped id != sys id, the key will not match 'monitor'
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}{'disabled'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'note')} = $monitors->{$key}{'disabled'};
+ }
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'};
}
+ elsif ($monitors->{$key}{'model-id'}){
+ $$row[$j]->{main::key($$num++,0,$m2,'model-id')} = $monitors->{$key}{'model-id'};
+ }
if ($extra > 2 && $monitors->{$key}{'serial'}){
$$row[$j]->{main::key($$num++,0,$m2,'serial')} = main::filter($monitors->{$key}{'serial'});
}
@@ -13976,6 +13998,21 @@ sub monitors_output_full {
if ($b_admin && $monitors->{$key}{'gamma'}){
$$row[$j]->{main::key($$num++,0,$m2,'gamma')} = $monitors->{$key}{'gamma'};
}
+ if ($show{'edid'} && $monitors->{$key}{'colors'}){
+ $$row[$j]->{main::key($$num++,1,$m2,'chroma')} = '';
+ $$row[$j]->{main::key($$num++,1,$m3,'red')} = '';
+ $$row[$j]->{main::key($$num++,0,$m4,'x')} = $monitors->{$key}{'colors'}{'red_x'};
+ $$row[$j]->{main::key($$num++,0,$m4,'y')} = $monitors->{$key}{'colors'}{'red_y'};
+ $$row[$j]->{main::key($$num++,1,$m3,'green')} = '';
+ $$row[$j]->{main::key($$num++,0,$m4,'x')} = $monitors->{$key}{'colors'}{'green_x'};
+ $$row[$j]->{main::key($$num++,0,$m4,'y')} = $monitors->{$key}{'colors'}{'green_y'};
+ $$row[$j]->{main::key($$num++,1,$m3,'blue')} = '';
+ $$row[$j]->{main::key($$num++,0,$m4,'x')} = $monitors->{$key}{'colors'}{'blue_x'};
+ $$row[$j]->{main::key($$num++,0,$m4,'y')} = $monitors->{$key}{'colors'}{'blue_y'};
+ $$row[$j]->{main::key($$num++,1,$m3,'white')} = '';
+ $$row[$j]->{main::key($$num++,0,$m4,'x')} = $monitors->{$key}{'colors'}{'white_x'};
+ $$row[$j]->{main::key($$num++,0,$m4,'y')} = $monitors->{$key}{'colors'}{'white_y'};
+ }
if ($extra > 2 && $monitors->{$key}{'scale'}){
$$row[$j]->{main::key($$num++,0,$m2,'scale')} = $monitors->{$key}{'scale'};
}
@@ -13996,13 +14033,27 @@ sub monitors_output_full {
$$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'};
+ if (!$monitors->{$key}{'modes'} || !@{$monitors->{$key}{'modes'}}){
+ $monitors->{$key}{'modes'} = ['N/A'];
+ }
+ my $cnt = scalar @{$monitors->{$key}{'modes'}};
+ if ($cnt == 1 || ($cnt > 2 && $show{'edid'})){
+ $$row[$j]->{main::key($$num++,0,$m2,'modes')} = join(', ', @{$monitors->{$key}{'modes'}});
}
- elsif ($monitors->{$key}{'modes-min'} && $monitors->{$key}{'modes-max'}){
+ else {
$$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'};
+ $$row[$j]->{main::key($$num++,0,$m3,'max')} = ${$monitors->{$key}{'modes'}}[0];
+ $$row[$j]->{main::key($$num++,0,$m3,'min')} = ${$monitors->{$key}{'modes'}}[-1];
+ }
+ }
+ if ($show{'edid'} && ($monitors->{$key}{'errors'} || $monitors->{$key}{'warnings'})){
+ $j++;
+ $$row[$j]->{main::key($$num++,1,$m2,'EDID')} = '';
+ if ($monitors->{$key}{'errors'}){
+ $$row[$j]->{main::key($$num++,0,$m3,'errors')} = join('; ', @{$monitors->{$key}{'errors'}});
+ }
+ if ($monitors->{$key}{'warnings'}){
+ $$row[$j]->{main::key($$num++,0,$m3,'warnings')} = join('; ', @{$monitors->{$key}{'warnings'}});
}
}
}
@@ -14308,9 +14359,9 @@ sub wayland_data_advanced {
!$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}{'size-x-i'} = sprintf("%.2f", ($size_x/25.4)) + 0;
+ $monitor_ids->{$key}{'size-y-i'} = sprintf("%.2f", ($size_y/25.4)) + 0;
+ $monitor_ids->{$key}{'diagonal'} = sprintf("%.2f", (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'};
@@ -14506,7 +14557,6 @@ sub swaymsg_data {
$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'});
}
@@ -14765,11 +14815,10 @@ sub xdpyinfo_data {
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;
+ $size_x_i = ($size_x) ? sprintf("%.2f", ($size_x/25.4)) : 0;
+ $size_y_i = ($size_y) ? sprintf("%.2f", ($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 = ($size_x && $size_y) ? sprintf("%.2f", (sqrt($size_x**2 + $size_y**2)/25.4)) + 0 : '';
$diagonal_m = ($size_x && $size_y) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
}
$screen = {
@@ -14802,7 +14851,7 @@ sub xrandr_data {
@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');
+ @xrandr = main::reader("$ENV{HOME}/bin/scripts/inxi/data/xrandr/xrandr-test-1.txt",'strip');
}
# $graphics{'dimensions'} = (\@dimensions);
# we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
@@ -14842,25 +14891,30 @@ sub xrandr_data {
# 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)?/){
+ # disabled but connected: VGA-1 connected (normal left inverted right x axis y axis)
+ elsif (/^([^\s]+)\s+connected\s(primary\s)?/){
$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))) : '';
+ if (/^[^\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)?/){
+ $res_x = $2;
+ $res_y = $3;
+ $pos_x = $4;
+ $pos_y = $5;
+ $size_x = $8;
+ $size_y = $9;
+ # 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("%.2f", ($size_x/25.4)) + 0 : 0;
+ $size_y_i = ($size_y) ? sprintf("%.2f", ($size_y/25.4)) + 0 : 0;
+ $dpi = ($res_x && $size_x) ? sprintf("%.0f", $res_x * 25.4 / $size_x) : '';
+ $diagonal = ($res_x && $size_x) ? sprintf("%.2f", (sqrt($size_x**2 + $size_y**2)/25.4)) + 0 : '';
+ $diagonal_m = ($res_x && $size_x) ? sprintf("%.0f", (sqrt($size_x**2 + $size_y**2))) : '';
+ }
+ else {
+ ($res_x,$res_y,$pos_x,$pos_y,$size_x,$size_x_i,$size_y,$size_y_i,$dpi,$diagonal,$diagonal_m) = ()
+ }
undef $primary;
push(@ids,$monitor_id);
if ($set_as){
@@ -15044,9 +15098,10 @@ sub display_drivers_x {
# $log = "$ENV{HOME}/bin/scripts/inxi/data/xorg-logs/xorg-multi-driver-1.log";
}
my @xorg = main::reader($log);
- # 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
+ # list is from sgfxi plus non-free drivers, plus ARM drivers.
+ # Don't use ati. It's just a wrapper for: r128, mach64, radeon
+ my $list = join('|', qw(amdgpu apm ark armsoc atimisc
+ chips cirrus cyrix etnaviv 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
@@ -15213,13 +15268,9 @@ sub set_monitors_sys {
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];
- }
+ # modes has repeat values, probably because kernel doesn't show hz
+ main::uniq(\@data);
+ $monitor_ids->{$port}{'modes'} = [@data];
}
elsif ($item eq 'edid'){
next if -s $file;
@@ -15227,7 +15278,7 @@ sub set_monitors_sys {
}
}
main::log_data('dump','$ports ref',$monitor_ids) if $b_log;
- print Data::Dumper::Dumper $monitor_ids if $dbg[44];
+ print 'monitor_sys_data(): ', Data::Dumper::Dumper $monitor_ids if $dbg[44];
eval $end if $b_log;
}
sub monitor_edid_data {
@@ -15239,9 +15290,12 @@ sub monitor_edid_data {
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];
+ print 'parse_edid(): ', Data::Dumper::Dumper $edid if $dbg[44];
return if !$edid || ref $edid ne 'HASH' || !%$edid;
$monitor_ids->{$port}{'build-date'} = $edid->{'year'};
+ if ($edid->{'color_characteristics'}){
+ $monitor_ids->{$port}{'colors'} = $edid->{'color_characteristics'};
+ }
if ($edid->{'gamma'}){
$monitor_ids->{$port}{'gamma'} = ($edid->{'gamma'}/100 + 0);
}
@@ -15254,26 +15308,37 @@ sub monitor_edid_data {
$model .= ' ' if $model;
$model .= $edid->{'monitor_name'};
}
+ elsif ($model && $edid->{'product_code_h'}){
+ $model .= ' ' . $edid->{'product_code_h'};
+ }
$monitor_ids->{$port}{'model'} = main::remove_duplicates(main::clean($model));
}
+ elsif ($edid->{'manufacturer_name'} && $edid->{'product_code_h'}){
+ $monitor_ids->{$port}{'model-id'} = $edid->{'manufacturer_name'} . ' ';
+ $monitor_ids->{$port}{'model-id'} .= $edid->{'product_code_h'};
+ }
+ # construct to match xorg values
+ if ($edid->{'manufacturer_name'} && $edid->{'product_code'}){
+ my $id = $edid->{'manufacturer_name'} . sprintf('%x',$edid->{'product_code'});
+ $monitor_ids->{$port}{$id} = ($edid->{'serial_number'}) ? $edid->{'serial_number'}: '';
+ }
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->{'ratios'}){
+ $monitor_ids->{$port}{'ratio'} = join(', ', @{$edid->{'ratios'}});
}
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;
+ $monitor_ids->{$port}{'size-x-i'} = $edid->{'detailed_timings'}[0]{'horizontal_image_size_i'};
}
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;
+ $monitor_ids->{$port}{'size-y-i'} = $edid->{'detailed_timings'}[0]{'vertical_image_size_i'};
}
if ($edid->{'detailed_timings'}[0]{'horizontal_dpi'}){
$monitor_ids->{$port}{'dpi'} = sprintf('%.0f',$edid->{'detailed_timings'}[0]{'horizontal_dpi'}) + 0;
@@ -15288,6 +15353,14 @@ sub monitor_edid_data {
$monitor_ids->{$port}{'serial'} = main::clean_dmi($edid->{'serial_number'});
}
}
+ # this will be an array reference of one or more edid errors
+ if ($edid->{'edid_errors'}){
+ $monitor_ids->{$port}{'edid-errors'} = $edid->{'edid_errors'};
+ }
+ # this will be an array reference of one or more edid warnings
+ if ($edid->{'edid_warnings'}){
+ $monitor_ids->{$port}{'edid-warnings'} = $edid->{'edid_warnings'};
+ }
eval $end if $b_log;
}
sub advanced_monitor_data {
@@ -15297,7 +15370,7 @@ sub advanced_monitor_data {
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'};
+ next if !defined $monitors->{$key}{'pos-x'} || !defined $monitors->{$key}{'pos-y'};
# 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){
@@ -15317,9 +15390,9 @@ sub advanced_monitor_data {
# print Data::Dumper::Dumper \@horiz;
# print Data::Dumper::Dumper \@vert;
# print Data::Dumper::Dumper $layouts;
- # print Data::Dumper::Dumper $monitor_map;
+ # print 'mon advanced monitor_map: ', Data::Dumper::Dumper $monitor_map;
foreach my $key (keys %$monitors){
- if (@horiz && @vert){
+ if (@horiz && @vert && (scalar @horiz > 1 || scalar @vert > 1)){
$monitors->{$key}{'position'} ||= '';
$position = '';
$position = get_monitor_position($monitors->{$key},\@horiz,\@vert);
@@ -15333,18 +15406,44 @@ sub advanced_monitor_data {
# 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}{'colors'} = $monitor_ids->{$mon_mapped}{'colors'};
$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}{'modes'} = $monitor_ids->{$mon_mapped}{'modes'};
$monitors->{$key}{'model'} = $monitor_ids->{$mon_mapped}{'model'};
+ $monitors->{$key}{'color-characteristics'} = $monitor_ids->{$mon_mapped}{'color-characteristics'};
+ if (!defined $monitors->{$key}{'size-x'} && $monitor_ids->{$mon_mapped}{'size-x'}){
+ $monitors->{$key}{'size-x'} = $monitor_ids->{$mon_mapped}{'size-x'};
+ $monitors->{$key}{'size-x-i'} = $monitor_ids->{$mon_mapped}{'size-x-i'};
+ }
+ if (!defined $monitors->{$key}{'size-y'} && $monitor_ids->{$mon_mapped}{'size-y'}){
+ $monitors->{$key}{'size-y'} = $monitor_ids->{$mon_mapped}{'size-y'};
+ $monitors->{$key}{'size-y-i'} = $monitor_ids->{$mon_mapped}{'size-y-i'};
+ }
+ if (!defined $monitors->{$key}{'dpi'} && $monitor_ids->{$mon_mapped}{'dpi'}){
+ $monitors->{$key}{'dpi'} = $monitor_ids->{$mon_mapped}{'dpi'};
+ }
+ if ($monitor_ids->{$mon_mapped}{'model-id'}){
+ $monitors->{$key}{'model-id'} = $monitor_ids->{$mon_mapped}{'model-id'};
+ }
+ if ($monitor_ids->{$mon_mapped}{'edid-errors'}){
+ $monitors->{$key}{'edid-errors'} = $monitor_ids->{$mon_mapped}{'edid-errors'};
+ }
+ if ($monitor_ids->{$mon_mapped}{'edid-warnings'}){
+ $monitors->{$key}{'edid-warnings'} = $monitor_ids->{$mon_mapped}{'edid-warnings'};
+ }
+ if ($monitor_ids->{$mon_mapped}{'enabled'} &&
+ $monitor_ids->{$mon_mapped}{'enabled'} eq 'disabled'){
+ $monitors->{$key}{'disabled'} = $monitor_ids->{$mon_mapped}{'enabled'};
+ }
$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;
- }
+ }
+ # now swap the drm id for the display server id if they don't match
+ if ($mon_mapped && $mon_mapped ne $monitors->{$key}{'monitor'}){
+ $monitors->{$key}{'monitor-mapped'} = $monitors->{$key}{'monitor'};
+ $monitors->{$key}{'monitor'} = $mon_mapped;
}
}
# not printing out primary if Screen has only 1 Monitor
@@ -15359,9 +15458,7 @@ sub advanced_monitor_data {
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'} ||
+ if (!$monitor_ids->{$key}{'status'} ||
$monitor_ids->{$key}{'status'} ne 'connected'){
delete $monitor_ids->{$key};
}
@@ -15411,7 +15508,7 @@ sub set_monitor_layouts {
'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
+# this is required to resolve the 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;
@@ -15420,13 +15517,12 @@ sub map_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'){
+ if ($monitor_ids->{$key}{'status'} eq 'connected'){
push(@sys_ids,$key);
}
}
@sys_ids = sort { lc($a) cmp lc($b) } @sys_ids;
- # @sys_ids = ('DP-1-1','DVI-I-1','VGA-1');
+ # @sys_ids = ('DVI-I-1','eDP-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];
@@ -15435,31 +15531,37 @@ sub map_monitor_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);
+ # s: DVI-I-1, d: DVI0; s: VGA-1, d: VGA1; s: DP-1-1; d: DP-1-1;
+ # s: eDP-1, d: eDP-1-1 (yes, reversed from normal deviation!); s: eDP-1, d: eDP
+ # worst: s: DP-6, d: DP-2-3 (2 banks of 3 according to X); s: eDP-1, d: DP-4;
+ my ($d_1,$d_2,$d_m,$s_1,$s_2,$s_m);
+ my $b_single = (scalar @sys_ids == 1) ? 1 : 0;
+ my $pattern = '([A-Z]+)(-[A-Z]-\d+-\d+|-[A-Z]-\d+|-\d+-\d+|-?\d+|)';
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){
+ print "s: $sys_ids[$i] d: $display_ids->[$i]\n" if $dbg[45];
+ # try 1: /^([A-Z]+)(-[AB]|-[ADI]|-[ADI]-\d+?|-\d+?)?(-)?(\d+)$/i
+ if ($display_ids->[$i] =~ /^$pattern$/i){
$d_1 = $1;
$d_2 = ($2) ? $2 : '';
- $d_3 = ($3) ? $3 : '';
- $d_4 = $4;
+ $d_2 =~ /(\d+)?$/;
+ $d_m = ($1) ? $1 : 0;
$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){
+ print " d1: $d_1 d2: $d_2 d3: $d_m\n" if $dbg[45];
+ if ($sys_ids[$i] =~ /^$pattern$/i){
$s_1 = $1;
$s_2 = ($2) ? $2 : '';
- $s_3 = ($3) ? $3 : '';
- $s_4 = $4;
+ $s_2 =~ /(\d+)?$/;
+ $s_m = ($1) ? $1 : 0;
$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))){
+ print " d1: $d_1 s1: $s_1 dm: $d_m sm: $s_m \n" if $dbg[45];
+ if ($d_1 eq $s_1 && ($d_m == $s_m || $d_m == ($s_m - 1))){
$monitor_map->{$display_ids->[$i]} = $sys_ids[$i];
}
}
}
if (!$monitor_map->{$display_ids->[$i]}){
- $monitor_map->{$display_ids->[$i]} = main::message('monitor-id');
+ # we're not even going to try, if there's 1 sys and 1 display, just use it!
+ $monitor_map->{$display_ids->[$i]} = ($b_single) ? $sys_ids[$i] : main::message('monitor-id');
}
}
main::log_data('dump','$monitor_map ref',$monitor_map) if $b_log;
@@ -22130,7 +22232,8 @@ sub process_lm_sensors {
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-zenpower-nvme-2.txt";
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-pch-intel-1.txt";
# my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-ppc-sr71.txt";
- # @sensors_data = main::reader($file);
+ my $file = "$ENV{'HOME'}/bin/scripts/inxi/data/sensors/sensors-applesmc-1.txt";
+ @sensors_data = main::reader($file);
}
else {
# only way to get sensor array data? Unless using sensors -j, but can't assume json
@@ -22151,6 +22254,9 @@ sub process_lm_sensors {
if ($adapter =~ /^(drive|nvme)/){
$type = 'disk';
}
+ elsif ($adapter =~ /^(BAT)/){
+ $type = 'bat';
+ }
# intel on die io controller, like southbridge/northbridge used to be
elsif ($adapter =~ /^(pch[_-])/){
$type = 'pch';
@@ -22666,11 +22772,18 @@ sub gpu_data {
package SlotItem;
sub get {
eval $start if $b_log;
- my (@rows,$key1,$val1);
+ my ($data,@rows,$key1,$val1);
my $num = 0;
if ($fake{'dmidecode'} || ($alerts{'dmidecode'}->{'action'} eq 'use' &&
(!%risc || $use{'slot-tool'}))){
- @rows = slot_output();
+ $data = slot_data_dmi();
+ @rows = slot_output($data) if $data;
+ if (!@rows){
+ my $key = 'Message';
+ push(@rows, {
+ main::key($num++,0,1,$key) => main::message('pci-slot-data',''),
+ },);
+ }
}
elsif (%risc && !$use{'slot-tool'}){
$key1 = 'Message';
@@ -22688,62 +22801,161 @@ sub get {
}
sub slot_output {
eval $start if $b_log;
+ my $data = $_[0];
my (@rows);
- my $num = 0;
- foreach my $entry (@dmi){
+ my $num = 1;
+ foreach my $slot_data (@$data){
+ next if !$slot_data || ref $slot_data ne 'HASH';
$num = 1;
- if ($entry->[0] == 9){
- my ($designation,$id,$length,$type,$usage) = ('','','','','');
- # skip first two row, we don't need that data
- my $j = scalar @rows;
- foreach my $item (@$entry[2 .. $#$entry]){
- if ($item !~ /^~/){ # skip the indented rows
- my @value = split(/:\s+/, $item);
- if ($value[0] eq 'Type'){
- $type = $value[1];
- }
- if ($value[0] eq 'Designation'){
- $designation = $value[1];
- }
- if ($value[0] eq 'Current Usage'){
- $usage = $value[1];
-
- }
- if ($value[0] eq 'ID'){
- $id = $value[1];
- }
- if ($extra > 1 && $value[0] eq 'Length'){
- $length = $value[1];
- }
- }
+ my $j = scalar @rows;
+ $slot_data->{'id'} = 'N/A' if !defined $slot_data->{'id'}; # can be 0
+ $slot_data->{'pci'} ||= 'N/A';
+ push(@rows, {
+ main::key($num++,1,1,'Slot') => $slot_data->{'id'},
+ main::key($num++,0,2,'type') => $slot_data->{'pci'},
+ },);
+ # PCIe only
+ if ($extra > 1 && $slot_data->{'gen'}){
+ $rows[$j]->{main::key($num++,0,2,'gen')} = $slot_data->{'gen'};
+ }
+ if ($slot_data->{'lanes-phys'} && $slot_data->{'lanes-active'} &&
+ $slot_data->{'lanes-phys'} ne $slot_data->{'lanes-active'}){
+ $rows[$j]->{main::key($num++,1,2,'lanes')} = '';
+ $rows[$j]->{main::key($num++,0,3,'phys')} = $slot_data->{'lanes-phys'};
+ $rows[$j]->{main::key($num++,0,3,'active')} = $slot_data->{'lanes-active'};
+ }
+ elsif ($slot_data->{'lanes-phys'}){
+ $rows[$j]->{main::key($num++,0,2,'lanes')} = $slot_data->{'lanes-phys'};
+ }
+ # Non PCIe only
+ if ($extra > 1 && $slot_data->{'bits'}){
+ $rows[$j]->{main::key($num++,0,2,'bits')} = $slot_data->{'bits'};
+ }
+ # PCI-X and PCI only
+ if ($extra > 1 && $slot_data->{'mhz'}){
+ $rows[$j]->{main::key($num++,0,2,'MHz')} = $slot_data->{'mhz'};
+ }
+ $rows[$j]->{main::key($num++,0,2,'status')} = $slot_data->{'usage'};
+ if ($slot_data->{'j'} || $slot_data->{'m2'}){
+ my $info = ($slot_data->{'m2'}) ? $slot_data->{'m2'} : '';
+ if ($slot_data->{'j'}){
+ $info .= ' ' if $info;
+ $info .= $slot_data->{'j'};
}
- if ($type){
- $id = 'N/A' if ($id eq '');
- if ($type eq 'Other' && $designation){
- $type = $designation;
+ $rows[$j]->{main::key($num++,0,2,'info')} = $info;
+ }
+ if ($extra > 1){
+ $slot_data->{'length'} ||= 'N/A';
+ $rows[$j]->{main::key($num++,0,2,'length')} = $slot_data->{'length'};
+ if ($slot_data->{'cpu'}){
+ $rows[$j]->{main::key($num++,0,2,'cpu')} = $slot_data->{'cpu'};
+ }
+ }
+ if ($extra > 0){
+ $slot_data->{'bus_address'} ||= 'N/A';
+ $rows[$j]->{main::key($num++,0,2,'bus-ID')} =$slot_data->{'bus_address'};
+ }
+ }
+ eval $end if $b_log;
+ return @rows;
+}
+sub slot_children {
+ eval $start if $b_log;
+
+ eval $end if $b_log;
+}
+sub slot_data_dmi {
+ eval $start if $b_log;
+ my $i = 0;
+ my @slots;
+ foreach my $slot_data (@dmi){
+ next if $slot_data->[0] != 9;
+ my %data;
+ # skip first two row, we don't need that data
+ foreach my $item (@$slot_data[2 .. $#$slot_data]){
+ if ($item !~ /^~/){ # skip the indented rows
+ my @value = split(/:\s+/, $item, 2);
+ if ($value[0] eq 'Type'){
+ $data{'type'} = $value[1];
}
- elsif ($type && $designation){
- $type = "$type $designation";
+ if ($value[0] eq 'Designation'){
+ $data{'designation'} = $value[1];
}
- push(@rows, {
- main::key($num++,1,1,'Slot') => $id,
- main::key($num++,0,2,'type') => $type,
- main::key($num++,0,2,'status') => $usage,
- },);
- if ($extra > 1){
- $rows[$j]->{main::key($num++,0,2,'length')} = $length;
+ if ($value[0] eq 'Current Usage'){
+ $data{'usage'} = lc($value[1]);
+ }
+ if ($value[0] eq 'ID'){
+ $data{'id'} = $value[1];
+ }
+ if ($extra > 1 && $value[0] eq 'Length'){
+ $data{'length'} = lc($value[1]);
+ }
+ if ($extra > 1 && $value[0] eq 'Bus Address'){
+ $value[1] =~ s/^0000://;
+ $data{'bus_address'} = $value[1];
}
}
}
+ if ($data{'type'} eq 'Other' && $data{'designation'}){
+ $data{'type'} = $data{'designation'};
+ undef $data{'designation'};
+ }
+ foreach my $string (($data{'type'},$data{'designation'})){
+ next if !$string;
+ print "st: $string\n" if $dbg[48];
+ $string =~ s/(PCI[\s_-]?Express|Pci[_-]?e)/PCIe /ig;
+ $string =~ s/PCI[\s_-]?X/PCIX /ig;
+ $string =~ s/Mini[\s_-]?PCI/MiniPCI /ig;
+ $string =~ s/PCMCIA/PCMCIA /ig;
+ if (!$data{'pci'} && $string =~ /(AGP|ISA|MiniPCI|PCIe|PCIX|PCMCIA|PCI)/){
+ $data{'pci'} = $1;
+ # print "pci: $data{'pci'}\n";
+ }
+ if ($string =~ /(MiniPCI|PCMCIA)/){
+ $data{'pci'} = $1;
+ # print "pci: $data{'pci'}\n";
+ }
+ # legacy format: PCIE#3-x8
+ if (!$data{'lanes-phys'} && $string =~ /(^x|#\d+-x)(\d+)/){
+ $data{'lanes-phys'} = $2;
+ }
+ if (!$data{'lanes-active'} && $string =~ /^x\d+ .*? x(\d+)/){
+ $data{'lanes-active'} = $1;
+ }
+ if (!defined $data{'slot'} && $string =~ s/SLOT-?(\d+)?\b//){
+ $data{'slot'} = $1 if defined $1;
+ }
+ # legacy format, seens with PCI-X/PCIe mobos: PCIX#2-100MHz, PCIE#3-x8
+ if (!defined $data{'id'} && $string =~ /(#|PCI)(\d+)\b/){
+ $data{'id'} = $2;
+ }
+ if (!$data{'j'} && $string =~ s/\bJ-?(\S+)\b//){
+ $data{'j'} = 'J' . $1;
+ }
+ if (!$data{'m2'} && $string =~ s/\bM\.?2\b//){
+ $data{'m2'} = 'M.2';
+ }
+ if (!$data{'cpu'} && $string =~ s/CPU-?(\d+)\b//){
+ $data{'cpu'} = $1;
+ }
+ if (!$data{'gen'} && $data{'pci'} && $data{'pci'} eq 'PCIe' &&
+ $string =~ /PCIe[\s_-]*([\d.]+)/){
+ $data{'gen'} = $1 + 0;
+ }
+ if (!$data{'mhz'} && $data{'pci'} && $string =~ /(\d+)[\s_-]?MHz/){
+ $data{'mhz'} = $1;
+ }
+ if (!$data{'bits'} && $data{'pci'} && $string =~ /\b(\d+)[\s_-]?bit/){
+ $data{'bits'} = $1;
+ }
+ $i++;
+ }
+ push(@slots,{%data}) if %data;
}
- if (!@rows){
- my $key = 'Message';
- push(@rows, {
- main::key($num++,0,1,$key) => main::message('pci-slot-data',''),
- },);
- }
+ print '@slots: ', Data::Dumper::Dumper \@slots if $dbg[48];
+ main::log_data('dump','@slots final',\@slots) if $b_log;
eval $end if $b_log;
- return @rows;
+ return \@slots if @slots;
}
}
@@ -25620,6 +25832,7 @@ sub pci_class {
'11' => 'signal-processing',
'12' => 'processing-accelerators',
'13' => 'non-essential-instrumentation',
+ # 14 - fe reserved
'40' => 'coprocessor',
'ff' => 'unassigned',
);
@@ -25986,6 +26199,7 @@ sub get_display_manager {
}
}
@dms = @temp;
+ my (@dm_info);
# print Data::Dumper::Dumper \@dms;
# we know the files or directories exist so no need for further checks here
foreach my $dm (@dms){
@@ -25994,30 +26208,36 @@ sub get_display_manager {
($path = check_program($dm))){}
else {$path = $dm}
# print "$path $extra\n";
+ @dm_info = ();
@data = program_data($dm,$path,3);
- $dm = $data[0];
- $dm .= ' ' . $data[1] if $data[1];
- push(@found,$dm);
+ $dm_info[0] = $data[0];
+ $dm_info[1] = $data[1];
+ if (scalar @dms > 1 && (my $temp = ServiceData::get('status',$dm))){
+ $dm_info[2] = message('stopped') if $temp && $temp =~ /stopped|disabled/;
+ }
+ push(@found,[@dm_info]);
}
if (!@found){
# ly does not have a run/pid file
if (grep {$_ eq 'ly'} @ps_gui){
@data = program_data('ly','ly',3);
- $found[0] = $data[0];
- $found[0] .= ' ' . $data[1] if $data[1];
+ $dm_info[0] = $data[0];
+ $dm_info[1] = $data[1];
+ $found[0] = [@dm_info];
}
elsif (grep {/startx$/} @ps_gui){
- $found[0] = 'startx';
+ $found[0] = ['startx'];
}
elsif (grep {$_ eq 'xinit'} @ps_gui){
- $found[0] = 'xinit';
+ $found[0] = ['xinit'];
}
}
# might add this in, but the rate of new dm's makes it more likely it's an
# unknown dm, so we'll keep output to N/A
+ # print Data::Dumper::Dumper \@found;
log_data('dump','display manager: @found',\@found) if $b_log;
eval $end if $b_log;
- return join(', ', @found) if @found;
+ return \@found if @found;
}
## DistroData
@@ -26102,12 +26322,12 @@ sub get_linux_distro {
# note, pclinuxos has all these mandrake/mandriva files, careful!
my $lsb_good_s = 'mandrake-release|mandriva-release|mandrakelinux-release|';
$lsb_good_s .= 'manjaro-release';
- my $os_release_good_s = 'altlinux-release|arch-release|pclinuxos-release|';
- $os_release_good_s .= 'rpi-issue|SuSE-release';
+ my $os_release_good_s = 'altlinux-release|arch-release|mageia-release|';
+ $os_release_good_s .= 'pclinuxos-release|rpi-issue|SuSE-release';
# we need these empirically verified one by one as they appear, but always remember
# that stuff changes, legacy, deprecated, but these ideally are going to be right
- my $osr_good = 'manjaro|antergos|chakra|guix|pclinuxos|raspberry pi os|slint|';
- $osr_good .= 'zorin';
+ my $osr_good = 'manjaro|antergos|chakra|guix|mageia|pclinuxos|raspberry pi os|';
+ $osr_good .= 'slint|zorin';
my ($b_issue,$b_lsb,$b_skip_issue,$b_skip_osr);
my ($issue,$lsb_release) = ('/etc/issue','/etc/lsb-release');
$b_issue = 1 if -f $issue;
@@ -26169,13 +26389,15 @@ sub get_linux_distro {
@working = (@derived,@primary);
foreach my $file (@working){
if ("/etc/$file" =~ /($distro_files_s)$/){
- # Now lets see if the distro file is in the known-good working-lsb-list
- # if so, use lsb-release, if not, then just use the found file
- # this is for only those distro's with self named release/version files
+ # These is for only those distro's with self named release/version files
# because Mint does not use such, it must be done as below
+ # Force use of os-release file in cases where there might be conflict
+ # between lsb-release rules and os-release priorities.
if (@osr && $file =~ /($os_release_good_s)$/){
$distro_file = $os_release;
}
+ # Now lets see if the distro file is in the known-good working-lsb-list
+ # if so, use lsb-release, if not, then just use the found file
elsif ($b_lsb && $file =~ /$lsb_good_s/){
$distro_file = $lsb_release;
}
@@ -26504,8 +26726,12 @@ sub get_lsb_release {
else {
# avoid duplicates
$distro = $id;
- $distro .= " $release" if $distro !~ /$release/;
- $distro .= " $codename" if $distro !~ /$codename/;
+ $distro .= " $release" if $release && $distro !~ /$release/;
+ # eg: release: 9 codename: mga9
+ if ($codename && $distro !~ /$codename/i &&
+ (!$release || $codename !~ /$release/)){
+ $distro .= " $codename";
+ }
$distro =~ s/^\s+|\s\s+|\s+$//g; # get rid of double and trailing spaces
}
eval $end if $b_log;
@@ -26701,6 +26927,7 @@ sub generate_data {
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-1.txt";
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/dmidecode-speed-configured-2.txt";
# $file = "$ENV{'HOME'}/bin/scripts/inxi/data/ram/00srv-dmidecode-mushkin-1.txt";
+ # $file = "$ENV{'HOME'}/bin/scripts/inxi/data/dmidecode/dmidecode-slots-pcix-pcie-1.txt";
# open(my $fh, '<', $file) or die "can't open $file: $!";
# chomp(@data = <$fh>);
}
@@ -27161,24 +27388,26 @@ sub get_kernel_bits {
sub get_kernel_data {
eval $start if $b_log;
- my ($kernel,$ksplice) = ('','');
+ my ($ksplice) = ('');
+ my @kernel;
# Linux; yawn; 4.9.0-3.1-liquorix-686-pae; #1 ZEN SMP PREEMPT liquorix 4.9-4 (2017-01-14); i686
# FreeBSD; siwi.pair.com; 8.2-STABLE; FreeBSD 8.2-STABLE #0: Tue May 31 14:36:14 EDT 2016 erik5@iddhi.pair.com:/usr/obj/usr/src/sys/82PAIRx-AMD64; amd64
if (@uname){
- $kernel = $uname[2];
- if ((my $program = check_program('uptrack-uname')) && $kernel){
+ $kernel[0] = $uname[2];
+ if ((my $program = check_program('uptrack-uname')) && $kernel[0]){
$ksplice = qx($program -rm);
$ksplice = trimmer($ksplice);
- $kernel = ($ksplice) ? $ksplice . ' (ksplice)' : $kernel;
+ $kernel[0] = $ksplice . ' (ksplice)' if $ksplice;
}
- $kernel .= ' ' . $uname[-1];
- $kernel = ($bsd_type) ? $uname[0] . ' ' . $kernel : $kernel;
+ $kernel[1] = $uname[-1];
}
- $kernel ||= 'N/A';
- log_data('data',"kernel: $kernel ksplice: $ksplice") if $b_log;
+ # we want these to have values to save validation checks for output
+ $kernel[0] ||= 'N/A';
+ $kernel[1] ||= 'N/A';
+ log_data('data',"kernel: " . join('; ', @kernel) . " ksplice: $ksplice") if $b_log;
log_data('dump','perl @uname', \@uname) if $b_log;
eval $end if $b_log;
- return $kernel;
+ return \@kernel;
}
## KernelParameters
@@ -27766,7 +27995,7 @@ my @edid_info = (
['C', 'max_size_vertical'], # in cm, 0 on projectors
['C', 'gamma'],
['a', 'feature_support'],
- ['a10', '_color_characteristics'],
+ ['a10', 'color_characteristics'],
['a3' , 'established_timings'],
['a16', 'standard_timings'],
['a72', 'monitor_details'],
@@ -27895,6 +28124,21 @@ my %subfields = (
[1, 'native'],
[7, 'mode'],
],
+ # Section 3.7 in VESA-EEDID-A2.pdf specs
+ color_characteristics => [
+ # Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1 Gy0
+ [8, 'white_point_red_green'],
+ # Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0
+ [8, 'white_point_blue_white'],
+ [8, 'red_x'],
+ [8, 'red_y'],
+ [8, 'green_x'],
+ [8, 'green_y'],
+ [8, 'blue_x'],
+ [8, 'blue_y'],
+ [8, 'white_x'],
+ [8, 'white_y'],
+ ],
);
my @cea_video_mode_to_detailed_timing = (
'pixel_clock',
@@ -27981,50 +28225,58 @@ my @cea_video_modes = (
[ 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,
+# Eyoyo, GAEMS, GeChic, KOORUI, Lilliput, Mobile Pixels, Nexanic, SunFounder,
+# TECNII, TPEKKA, V7/VSEVEN,
+# Guesses: KYY=KYY, MSI=MSI, KOE=Kaohsiung Opto Electronics
# PGS: Princeton Graphic Systems; SDC: Samsung Display Co;
# SIS: Silicon Integrated Systems; STN: Samsung Electronics America;
+# BDS: Barco Display Systems
# TAI: Toshiba America
+# HIQ: Hitachi ImageQuest or Kaohsiung Opto Electronics? or does Imagequest make hitachi:
+# NVD: Nvidia or NewVisionDisplay?
my %vendors = (
-'ACI' => 'Asus', 'ACR' => 'Acer', 'ACT' => 'Targa', 'ADI' => 'ADI',
-'AMW' => 'AMW', 'ANX' => 'Acer Netxix', 'AOC' => 'AOC', 'API' => 'Acer',
+'AAC' => 'AcerView', 'ACI' => 'Asus', 'ACR' => 'Acer', 'ACT' => 'Targa', 'ADI' => 'ADI',
+'AIC' => 'AG Neovo', 'AMW' => 'AMW', 'ANX' => 'Acer Netxix', 'AOC' => 'AOC', 'API' => 'A Plus Info',
'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',
+'BEL' => 'Beltronic', 'BMM' => 'BMM', 'BNQ' => 'BenQ', 'BOE' => 'BOE Display', 'BDS' => 'Barco',
+'CHO' => 'Sichuang Changhong', 'CMN' => 'ChiMei InnoLux', 'CMO' => 'Chi Mei Optoelectronics',
+'CPL' => 'Compal/ALFA', 'CPQ' => 'Compaq', 'CPT' => 'Chungwa Picture Tubes', 'CTX' => 'CTX (Chuntex)', 'CVT' => 'DGM',
+'DEC' => 'DEC', 'DEL' => 'Dell', 'DON' => 'Denon', 'DPC' => 'Delta', 'DPL' => 'Digital Projection', 'DWE' => 'Daewoo',
+'ECS' => 'Elitegroup', 'EIZ' => 'EIZO', 'ELS' => 'ELSA', 'ENC' => 'EIZO NANAO', 'EPI' => 'Envision', 'ETR' => 'Rotel',
+'FCM' => 'Funai', 'FUJ' => 'Fujitsu', 'FUS' => 'Fujitsu Siemens',
+'GBT' => 'Gigabyte', 'GFN' => 'Gefen', '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',
+'HSD' => 'HannSpree/HannStar', 'HSL' => 'Hansol', 'HTC' => 'Hitachi/Nissei', 'HVR' => 'Hitachi',
+'HWP' => 'HP', 'HWV' => 'Huawei',
+'IBM' => 'IBM', 'ICL' => 'Fujitsu ICL', 'IFS' => 'InFocus', 'INO' => 'Innolab Pte', 'IQT' => 'Hyundai',
+'IVM' => 'Idek Iiyama', 'IVO' => 'InfoVision Optronics/Kunshan',
+'KDS' => 'Korea Data Systems (KDS)', 'KFC' => 'KFC Computek', 'KOE' => 'Kaohsiung OptoElectronics',
+'KTC' => 'Kingston', 'KYY' => 'KYY',
+'LCD' => 'Toshiba Matsushita', 'LEN' => 'Lenovo', 'LGD' => 'LG Display', 'LKM' => 'Adlas/Azalea',
+'LNK' => 'LINK', 'LPL' => 'LG Philips', 'LTN' => 'Lite-On',
+'MAG' => 'MAG InnoVision', 'MAX' => 'Belinea/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',
+'NAN' => 'NANAO/EIZO', 'NEX' => 'Nexgen Mediatech', 'NCP' => 'Najing CEC Panda', 'NEC' => 'NEC',
+'NOK' => 'Nokia', 'NVD' => 'Nvidia',
+'ONK' => 'Onkyo', 'OPT' => 'Optoma','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',
+'QDI' => 'Quantum Data', 'QDS' => 'Quanta Display', 'REL' => 'Relisys', 'REN' => 'Renesas',
+'SAM' => 'Samsung', 'SAN' => 'Sanyo', 'SBI' => 'Smarttech', 'SDC' => 'Samsung', 'SEC' => 'Seiko Epson',
+'SEN' => 'Sensics', 'SHP' => 'Sharp', 'SGD' => 'Sigma Designs', 'SGI' => 'SGI', 'SHI' => 'Jiangsu Shinco',
+'SII' => 'Silicon Image', 'SIS' => 'SIS', 'SKM' => 'Guangzhou Teclast', 'SMC' => 'Samtron',
+'SMI' => 'Smile', 'SNI' => 'Siemens Nixdorf', 'SNY' => 'Sony', 'SPT' => 'Sceptre',
+'SRC' => 'Shamrock', 'STN' => 'Samsung', 'STP' => 'Sceptre', 'SUN' => 'Sun Microsystems', 'SYN' => 'Synaptics',
'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',
+'VIT' => 'Visitech', 'VLV' => 'Valve', 'VSC' => 'ViewSonic', 'VTK' => 'Viewteck', 'VTS' => 'VTech',
+'WTC' => 'Wen Technology', 'XLX' => 'Xilinx', 'YMH' => 'Yamaha', '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));
@@ -28032,24 +28284,16 @@ sub _get_many_bits {
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 !~ /^_/;
+ if ($field && $field !~ /^_/){
+ $h{$field} = unpack("C", pack('B*', join('', @l)));
+ # spec: chromacity: 0.xyz: white_point see color_characteristics
+ if ($h{$field} && $field_name eq 'color_characteristics'){
+ $h{$field} = ($field =~ /_[xy]$/) ? sprintf('%0.3f',$h{$field}/255) : [@l[1..8]];
+ }
+ }
}
\%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');
@@ -28083,11 +28327,12 @@ sub _add_standard_timing_modes {
$v;
}
sub parse_edid {
+ eval $start if $b_log;
my ($raw_edid, $verbose) = @_;
- my %edid;
+ my (%edid, @warnings);
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;
+ my $i = 0;
foreach (@edid_info) {
my ($field, $v) = ($_->[1], $vals[$i++]);
if ($field eq 'year') {
@@ -28101,6 +28346,8 @@ sub parse_edid {
$v = _get_many_bits($v, 'video_input_definition');
} elsif ($field eq 'feature_support') {
$v = _get_many_bits($v, 'feature_support');
+ } elsif ($field eq 'color_characteristics') {
+ $v = _get_many_bits($v, 'color_characteristics');
} elsif ($field eq 'established_timings') {
my $h = _get_many_bits($v, 'established_timings');
$v = [
@@ -28164,9 +28411,9 @@ sub parse_edid {
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";
+ } elsif ($vv ne "\0" x 13 && $vv ne " " x 13) {
+ push(@warnings, "parse_edid: unknown flag $flag");
+ warn "$warnings[-1]\n" if $verbose;
}
}
}
@@ -28182,7 +28429,8 @@ sub parse_edid {
$dtd_offset -= 4;
while ($dtd_offset > 0) {
if (!$v) {
- warn "parse_edid: DTD offset outside of available data\n" if $verbose;
+ push(@warnings, "parse_edid: DTD offset outside of available data");
+ warn "$warnings[-1]\n" if $verbose;
last;
}
my $h = _get_many_bits($v, 'cea_data_block_collection');
@@ -28195,7 +28443,8 @@ sub parse_edid {
$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;
+ push(@warnings, "parse_edid: unhandled CEA mode $h->{mode}");
+ warn "$warnings[-1]\n" if $verbose;
next;
}
my %det_mode = (source => 'cea_vdb');
@@ -28212,11 +28461,18 @@ sub parse_edid {
if $h->{horizontal_active} > 1 && $h->{vertical_active} > 1;
}
} else {
- $verbose && warn "parse_edid: unknown tag $tag\n";
+ push(@warnings, "parse_edid: unknown tag $tag");
+ warn "$warnings[-1]\n" if $verbose;
}
}
$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{product_code}){
+ $edid{product_code_h} = sprintf('%04x', $edid{product_code});
+ if ($edid{manufacturer_name}){
+ $edid{EISA_ID} = $edid{manufacturer_name} . $edid{product_code_h};
+ }
+ $edid{product_code_h} = '0x'. $edid{product_code_h};
+ }
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};
@@ -28260,16 +28516,27 @@ sub parse_edid {
$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{ratio_precision} &&
+ abs($edid{ratio} - $h->{horizontal_active} / $h->{vertical_active}) > ($edid{ratio_precision} eq 'mm' ? 0.02 : 0.2)) {
+ $h->{bad_ratio} = 1;
+ }
+ if ($edid{ratio_name}) {
+ $edid{ratios} = $edid{ratio_name};
+ $edid{ratios} =~ s|/|:|g;
+ $edid{ratios} = [split(/ or /, $edid{ratios})]; # "3/2 or 16/10"
+ }
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;
}
+ if ($h->{horizontal_image_size}) {
+ $h->{horizontal_image_size_i} = sprintf('%.2f',($h->{horizontal_image_size}/25.4)) + 0;
+ }
+ if ($h->{vertical_image_size}) {
+ $h->{vertical_image_size_i} = sprintf('%.2f',($h->{vertical_image_size}/25.4)) + 0;
+ }
my $dpi_string = '';
if ($h->{vertical_dpi} && $h->{horizontal_dpi}) {
$dpi_string =
@@ -28280,36 +28547,78 @@ sub parse_edid {
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' : '';
+ $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;
-
+ # we want to use null data found tests so only return errors/warnings if
+ # %edid or if verbose, since then we want to know no matter what.
+ if (%edid || $verbose){
+ _edid_errors(\%edid);
+ $edid{edid_warnings} = \@warnings if @warnings;
+ }
+ eval $end if $b_log;
\%edid;
}
+sub _edid_errors {
+ my $edid = shift @_;
+ if (!defined $edid->{edid_version}){
+ _edid_error('edid-version','undefined');
+ }
+ elsif ($edid->{edid_version} < 1 || $edid->{edid_version} > 2){
+ _edid_error('edid-version',$edid->{edid_version});
+ }
+ if (!defined $edid->{edid_revision}){
+ _edid_error('edid-revision','undefined');
+ }
+ elsif ($edid->{edid_revision} == 0xff){
+ _edid_error('edid-revision',$edid->{edid_revision});
+ }
+ if ($edid->{monitor_range}){
+ if (!$edid->{monitor_range}{horizontal_min}){
+ _edid_error('edid-sync','no horizontal');
+ }
+ elsif ($edid->{monitor_range}{horizontal_min} > $edid->{monitor_range}{horizontal_max}){
+ _edid_error('edid-sync',
+ "bad horizontal values: min: $edid->{monitor_range}{horizontal_min} max: $edid->{monitor_range}{horizontal_max}");
+ }
+ if (!$edid->{monitor_range}{vertical_min}){
+ _edid_error('edid-sync','no vertical');
+ }
+ elsif ($edid->{monitor_range}{vertical_min} > $edid->{monitor_range}{vertical_max}){
+ _edid_error('edid-sync',
+ "bad vertical values: min: $edid->{monitor_range}{vertical_min} max: $edid->{monitor_range}{vertical_max}");
+ }
+ }
+}
+sub _edid_error {
+ my ($edid,$error,$data) = @_;
+ $edid->{edid_errors} = [] if !$edid->{edid_error};
+ push(@{$edid->{edid_errors}},main::message($error,$data));
+}
sub _nearest_ratio {
my ($ratio, $max_error) = @_;
my @sorted =
@@ -28392,23 +28701,24 @@ sub get_pci_vendor {
eval $start if $b_log;
my ($device, $subsystem) = @_;
return if !$subsystem;
- my ($vendor,$sep,$temp) = ('','','');
+ my ($vendor,$sep) = ('','');
# get rid of any [({ type characters that will make regex fail
# and similar matches show as non-match
- $subsystem = clean_regex($subsystem);
- my @data = split(/\s+/, $subsystem);
- # when using strings in patterns for regex have to escape them
- foreach (@data){
- $temp = $_;
- $temp =~ s/(\+|\$|\?|\^|\*)/\\$1/g;
- if ($device !~ m|\b$temp\b|){
- $vendor .= $sep . $_;
+ my @data = split(/\s+/, clean_regex($subsystem));
+ foreach my $word (@data){
+ # AMD Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
+ # PC Partner Limited / Sapphire Technology Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
+ # $word =~ s/(\+|\$|\?|\^|\*)/\\$1/g;
+ if (length($word) == 1 || $device !~ m|\b\Q$word\E\b|i){
+ $vendor .= $sep . $word;
$sep = ' ';
}
else {
last;
}
}
+ # just in case we had a standalone last character after done
+ $vendor =~ s| [/\(\[\{a\.,-]$|| if $vendor;
eval $end if $b_log;
return $vendor;
}
@@ -28462,7 +28772,7 @@ sub get_pcie_data {
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'}))){
+ $data{'max_link_width'} ne $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'}){
@@ -28470,7 +28780,7 @@ sub get_pcie_data {
$$rows[$j]->{key($$num++,0,4,'speed')} = $data{'max_link_speed'};
}
if ($data{'max_link_width'} &&
- $data{'max_link_width'} > $data{'current_link_width'}){
+ $data{'max_link_width'} ne $data{'current_link_width'}){
$$rows[$j]->{key($$num++,0,4,'lanes')} = $data{'max_link_width'};
}
}
@@ -28751,12 +29061,14 @@ sub process_status {
my @working = split(/\s*:\s*/,$row);
($value) = ('');
# print "$working[0]::$working[1]\n";
+ # Loaded: masked (Reason: Unit sddm.service is masked.)
if ($working[0] eq 'Loaded'){
# note: sshd shows ssh for ssh.service
$working[1] =~ /^(.+?)\s*\(.*?\.service;\s+(\S+?);.*/;
$result = lc($1) if $1;
$result = lc($2) if $2; # this will be enabled/disabled
}
+ # Active: inactive (dead)
elsif ($working[0] eq 'Active'){
$working[1] =~ /^(.+?)\s*\((\S+?)\).*/;
$value = lc($1) if $1 && (!$result || $result ne 'disabled');
@@ -30413,7 +30725,7 @@ sub short_output {
my @data = ({
main::key($num++,0,0,'CPU') => $cpu_string,
main::key($num++,0,0,$speed_key) => $speed,
- main::key($num++,0,0,$kernel_os) => main::get_kernel_data(),
+ main::key($num++,0,0,$kernel_os) => join(' ', @{main::get_kernel_data()}),
main::key($num++,0,0,'Up') => main::get_uptime(),
main::key($num++,0,0,'Mem') => $memory,
main::key($num++,0,0,'Storage') => $disk_string,
@@ -30584,7 +30896,7 @@ sub system_item {
my ($index);
my $data_name = main::key($prefix++,1,0,'System');
my ($desktop,$desktop_info,$desktop_key,$dm_key,$toolkit,$wm) = ('','','Desktop','dm','','');
- my (@desktop_data,$desktop_version);
+ my (@desktop_data,$desktop_version,$tk_version,$wm_version);
my %data = (
$data_name => [{}],
);
@@ -30592,7 +30904,9 @@ sub system_item {
if ($show{'host'}){
$data{$data_name}->[$index]{main::key($num++,0,1,'Host')} = main::get_hostname();
}
- $data{$data_name}->[$index]{main::key($num++,1,1,'Kernel')} = main::get_kernel_data();
+ my $kernel_data = main::get_kernel_data();
+ $data{$data_name}->[$index]{main::key($num++,1,1,'Kernel')} = $kernel_data->[0];
+ $data{$data_name}->[$index]{main::key($num++,0,2,'arch')} = $kernel_data->[1];
$data{$data_name}->[$index]{main::key($num++,0,2,'bits')} = main::get_kernel_bits();
if ($extra > 0){
my @compiler = CompilerVersion::get(); # get compiler data
@@ -30624,11 +30938,9 @@ sub system_item {
my @desktop_data = DesktopEnvironment::get();
$desktop = $desktop_data[0] if $desktop_data[0];
$desktop_version = $desktop_data[1] if $desktop_data[1];
- $desktop .= ' ' . $desktop_version if $desktop_version;
if ($extra > 0 && $desktop_data[3]){
- # $desktop .= ' (' . $desktop_data[2];
- # $desktop .= ($desktop_data[3]) ? ' ' . $desktop_data[3] . ')' : ')';
- $toolkit = "$desktop_data[2] $desktop_data[3]";
+ $toolkit = $desktop_data[2];
+ $tk_version = $desktop_data[3];
}
if ($extra > 2 && $desktop_data[4]){
$desktop_info = $desktop_data[4];
@@ -30638,7 +30950,7 @@ sub system_item {
(!$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];
+ $wm_version = $desktop_data[6] if $extra > 2 && $desktop_data[6];
}
}
if (!$b_display || (!$desktop && $b_root)){
@@ -30669,8 +30981,14 @@ sub system_item {
}
$desktop ||= 'N/A';
$data{$data_name}->[$index]{main::key($num++,$cont_desk,1,$desktop_key)} = $desktop;
+ if ($desktop_version){
+ $data{$data_name}->[$index]{main::key($num++,0,2,'v')} = $desktop_version;
+ }
if ($toolkit){
- $data{$data_name}->[$index]{main::key($num++,0,2,'tk')} = $toolkit;
+ $data{$data_name}->[$index]{main::key($num++,1,2,'tk')} = $toolkit;
+ }
+ if ($tk_version){
+ $data{$data_name}->[$index]{main::key($num++,0,3,'v')} = $tk_version;
}
if ($extra > 2){
if ($desktop_info){
@@ -30678,14 +30996,40 @@ sub system_item {
}
}
if ($extra > 1){
- $data{$data_name}->[$index]{main::key($num++,0,2,'wm')} = $wm if $wm;
+ if ($wm){
+ $data{$data_name}->[$index]{main::key($num++,1,2,'wm')} = $wm;
+ if ($wm_version){
+ $data{$data_name}->[$index]{main::key($num++,0,3,'v')} = $wm_version;
+ }
+ }
if ($extra > 2 && $b_display && defined $ENV{'XDG_VTNR'}){
$data{$data_name}->[$index]{main::key($num++,0,2,'vt')} = $ENV{'XDG_VTNR'};
}
my $dms = main::get_display_manager();
+ # note: version only present if proper extra level so no need to test again
if ($dms || $desktop_key ne 'Console'){
- $dms ||= 'N/A';
- $data{$data_name}->[$index]{main::key($num++,0,$ind_dm,$dm_key)} = $dms;
+ if ($dms && scalar @{$dms} > 1){
+ my $i = 0;
+ $data{$data_name}->[$index]{main::key($num++,1,$ind_dm,$dm_key)} = '';
+ foreach my $dm_data (@{$dms}){
+ $i++;
+ $data{$data_name}->[$index]{main::key($num++,1,($ind_dm + 1),$i)} = $dm_data->[0];
+ if ($dm_data->[1]){
+ $data{$data_name}->[$index]{main::key($num++,0,($ind_dm + 2),'v')} = $dm_data->[1];
+ }
+ if ($dm_data->[2]){
+ $data{$data_name}->[$index]{main::key($num++,0,($ind_dm + 2),'note')} = $dm_data->[2];
+ }
+ }
+ }
+ else {
+ my $dm = ($dms && $dms->[0][0]) ? $dms->[0][0] : 'N/A';
+ $data{$data_name}->[$index]{main::key($num++,1,$ind_dm,$dm_key)} = $dm;
+ if ($dms->[0][1]){
+ $data{$data_name}->[$index]{main::key($num++,0,($ind_dm + 1),'v')} = $dms->[0][1];
+ }
+ }
+
}
}
# if ($extra > 2 && $desktop_key ne 'Console'){
diff --git a/inxi.1 b/inxi.1
index 356b2d3..7e37418 100644
--- a/inxi.1
+++ b/inxi.1
@@ -15,7 +15,7 @@
.\" with this program; if not, write to the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
-.TH INXI 1 "2022\-02\-22" "inxi" "inxi manual"
+.TH INXI 1 "2022\-03\-24" "inxi" "inxi manual"
.SH NAME
inxi \- Command line system information script for console and IRC
@@ -31,8 +31,9 @@ inxi \- Command line system information script for console and IRC
[\fB\-v NUMBER\fR] [\fB\-W LOCATION\fR]
[\fB\-\-weather\-unit\fR {\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR}] [\fB\-y WIDTH\fR]
-\fBinxi\fR [\fB\-\-memory\-modules\fR] [\fB\-\-memory\-short\fR]
-[\fB\-\-recommends\fR] [\fB\-\-sensors\-default\fR] [\fB\-\-slots\fR]
+\fBinxi\fR [\fB\-\-edid\fR] [\fB\-\-memory\-modules\fR]
+[\fB\-\-memory\-short\fR] [\fB\-\-recommends\fR] [\fB\-\-sensors\-default\fR]
+[\fB\-\-slots\fR]
\fBinxi\fB [\fB\-x\fR|\fB\-xx\fR|\fB\-xxx\fR|\fB\-a\fR] \fB\-OPTION(s)\fR
@@ -254,6 +255,17 @@ or
\fBrfkill unblock bluetooth\fR
.TP
+.B \-\-edid\fR
+.br
+Triggers full \fBEDID\fR data in Graphics, activates \fB\-G\fR and \fB\-a\fR.
+
+\- Adds monitor chromacity (\fBchroma: red:..green:...blue:...white:\fR).
+
+\- Shows all available monitor modes if > 2 present, in comma separated list.
+
+\- Shows \fBEDID\fR errors and warnings if any present.
+
+.TP
.B \-\-filter\fR, \fB\-z\fR
.br
See \fBFILTER OPTIONS\fR.
@@ -295,7 +307,8 @@ Xvesa); for Wayland: GBM/EGL data (not implemented).
Compositor information will show if detected using \fB\-xx\fR option or always
if detected and Wayland since the compositor is the server with Wayland.
-\fB\-Gxx\fR shows monitor data as well, if detected.
+\fB\-Gxx\fR shows monitor data as well, if detected. \fB\-\-edid\fR shows
+advanced monitor data (full modes, chroma, etc.).
.TP
.B \-h \fR, \fB\-\-help\fR
@@ -770,9 +783,10 @@ of optical drives.
.TP
.B \-v 8
-\- All system data available. Adds Repos (\fB\-r\fR), PCI slots
-(\fB\-\-slots\fR), processes (\fB\-tcm\fR), admin (\fB\-\-admin\fR). Useful for
-testing output and to see what data you can get from your system.
+\- All system data available. Adds advanced EDID data (\fB\-\-edid\fR), Repos
+(\fB\-r\fR), PCI slots (\fB\-\-slots\fR), processes (\fB\-tcm\fR), admin
+(\fB\-\-admin\fR). Useful for testing output and to see what data you can get
+from your system.
.TP
.B \-w \fR, \fB\-\-weather\fR
@@ -1318,6 +1332,11 @@ identification, these will only be added as relatively solid methods are
found for each distribution system base detection.
.TP
+.B \-x \-\-slots\fR
+\- Adds \fBbus\-ID:\fR. Note that this bus ID does not unfortunately appear to
+be readily detected as the source bus ID for any particular device bus ID.
+
+.TP
.B \-x \-t\fR (\fB\-\-processes\fR)
\- Adds memory use output to CPU (\fB\-xt c\fR), and CPU use to memory
(\fB\-xt m\fR).
diff --git a/inxi.changelog b/inxi.changelog
index 57e3763..0dace8a 100644
--- a/inxi.changelog
+++ b/inxi.changelog
@@ -1,4 +1,194 @@
================================================================================
+Version: 3.3.14
+Patch: 00
+Date: 2022-03-24
+--------------------------------------------------------------------------------
+RELEASE NOTES:
+--------------------------------------------------------------------------------
+
+New version, man. Continuing development of EDID and monitor features, bug
+fixes, normal fixes.
+
+--------------------------------------------------------------------------------
+KNOWN ISSUES:
+
+1. Failed to handle case for monitor positions of array type: 2-2, 3-1, 1-3,
+4-4. I'm not sure what structure those are really arranged in, but might be
+worth adding in the x+y pos values along with the row-col values.
+
+2. For Monitors and graphics Device ports, if using non free nvidia driver and:
+nvidia-drm.modeset=1 not set in grub kernel boot parameters, there will be no
+/sys/class/drm data for the nvidia device, and thus no ports data, and no
+monitor data.
+
+3. A class of high count DP or DVI port IDs are changed by Xorg drivers to for
+example: DP-6 > DP-2-3. This is very difficult to handle and will in general
+probably fail unfortunately because that level of port ID abstraction is just
+reazlly hard to deal with dynamically.
+
+4. A to-do item: add bus ID children on --slots. This will probablby be in next
+inxi.
+
+--------------------------------------------------------------------------------
+BUGS:
+
+1. None outside of the various fixes.
+
+--------------------------------------------------------------------------------
+FIXES:
+
+1. In sensors, failed to pull out BAT sensor data. In most cases, this would not
+lead to any issues, but it could have.
+
+2. This one just slipped my mind, I'd meant to do it, but in Montitor-x:, the
+primary ID should have been the 'real' kernel ID, not the mapped: ID, which is
+the X.org ID when different from the kernel ID. So mapped should be the Xorg
+version when they are different from the kernel version.
+
+3. In Graphics, monitors can show > 1 ratio, failed to set all to :, resulting
+in: ratio: 3:2 or 16/10 modes:. Also fixed ParseEDID to output an array of
+ratios, which can then be processed as wanted.
+
+4. Monitor map fixes:
+* Handle case in monitors where display ID: eDP and sys ID: eDP-1, this only
+works if 1 monitor in array. There's a variety of this type of failure, when
+X.org or its drivers decide to call the port ID XYZ with no number at all. All
+those possible cases are now handled, like eDP > eDP-1, VGA > VGA-1, and so on.
+
+* Added fallback, if no match, and if only 1 monitor, just map them to eachother
+if other mappings failed. Prompted by things like: s: DP-6 > d: DP-2-3;
+s: eDP-1 > d: DP-4, which are just impossible to create logic to map.
+
+5. Removed 'ati' driver from xorg drivers list, it's simply a wrapper for r128,
+mach64, or radeon (and maybe amdgpu), and shows as failed, unloaded, or loaded,
+because of this. ati basically assigns the correct driver, that is, but is not
+itself a driver. Thanks mrmazda for spotting this issue.
+
+6. Typo on QDI => Quantum Data.
+
+7. Added fallback for monitor model, now using vendor code plus product code
+if nothing found for vendor nice name or model. This will show as 'model-id:'
+instead of model: to help differentiate the two.
+
+8. Added Monitor product_code to manufacturer if no model name is found.
+
+9. get_pci_vendor was trimming at ' / ' if the product string also contained
+' / '. Fix is to ignore 1 character 'words' in the logic.
+
+10. In Slots, failed to remove_duplicates in the slot info field, leading to
+redundant output strings. See Enhancement 3 and Code 4.
+
+11. See Change 3, finally made -S section use full key: value pair, which makes
+stuff more explicit, like:
+
+System:
+ Host: yawn
+ Kernel: 5.16.0-11.1-liquorix-amd64
+ arch: x86_64
+ bits: 64
+ compiler: gcc
+ v: 11.2.0
+ Desktop: Xfce
+ v: 4.16.0
+ tk: Gtk
+ v: 3.24.24
+ info: xfce4-panel
+ wm: xfwm
+ v: 4.16.1
+ vt: 7
+ dm:
+ 1: LightDM
+ v: 1.26.0
+ 2: SDDM
+ note: stopped
+ Distro: Debian GNU/Linux bookworm/sid
+
+12. Fix for mageia and lsb distro data, force use of os-release for mageia if
+detected. That overrides the forced use of lsb release for mandrake/mandriva,
+because for some reason mageia has decided to carry ALL the legacy distro files:
+'/etc/lsb-release',
+'/etc/lsb-release.d',
+'/etc/mageia-release',
+'/etc/mandrake-release',
+'/etc/mandrakelinux-release',
+'/etc/mandriva-release',
+'/etc/os-release',
+'/etc/redhat-release',
+'/etc/system-release'
+which is really not what this stuff is intended for, if it's an actual derived
+distro from a living base, then yes, include the base file, but all these have
+the same distro id data for mageia, none for the derived distros.
+
+Also, fixed an lsb release thing to avoid using codename if codename contains
+release number as well. Since lsb_release is totally legacy at this point, who
+cares if we might miss a specific codename here and there on legacy system.
+
+--------------------------------------------------------------------------------
+ENHANCEMENTS:
+
+1. Added Color Characteristics to EDID parser, for some reason that had been
+left out.
+
+2. Added advanced EDID output option --edid, that allows for showing more
+advanced EDID data than is appropriate for most users cases. Ihcludes errors,
+color characteristics chroma: (chromacity), full modes, not just min/max.
+
+3. In --slots, added bus-ID.
+
+Also extended report quality, made more granular, got rid of single blob from
+Type and Designation and now get more accurate and useful data.
+
+4. In cases with > 1 DM, check to see if one or more are stopped or disabled, =
+and add (stopped) if it was detected in running service as stopped.
+
+--------------------------------------------------------------------------------
+CHANGES:
+
+1. Reversed monitor ID and mapped: ID values, that was a mistake, the mapped:
+item was supposed to contain the X.org mapped name, and the primary ID was
+supposed to be the actual real ID the kernel uses. Not a huge deal either way,
+but there it is.
+
+2. Include disabled but connected Monitors. This works around nvidia bug showing
+monitors disabled when they are enabled, but also allows for showing connected
+monitors, though without as much data.
+
+3. Made the last holdout -S > -Sa use strict full key: value pair output, like
+Desktop: XFCE v: 4.14.12 and so on.
+
+--------------------------------------------------------------------------------
+DOCUMENTATION:
+
+1. Added help/man for --edid info.
+
+--------------------------------------------------------------------------------
+CODE:
+
+1. In ParseEDID: made new key: edid_error, which contains an array ref of 1 or
+more edid errors. The previous version did a poor job and returned only the
+first error found, so there could have been > 1 error, and you'd never know it.
+
+This changes check_parsed_edid to _check_parsed_edid(). and adds a utility tool
+_edid_error, which grabs the message from main::message, giving better output
+integration.
+
+This also allows for future error handling expansion quite easily.
+
+2. In map_monitor_ids() fixed matching pattern, made more robust and explicit,
+to catch things like s: eDP-1 d: eDP or eDP-1-1, both have been seen. Also added
+fallback for single monitor, just map them to eachother if mapping failed.
+
+3. get_pci_vendor() added test for using anything that is 1 character length,
+to not break on 1 character length string matches.
+
+4. Fully refactored --slots, that was originally written purely as a proof of
+concept in terms of adding a new feature during the original inxi 2.9 rewrite,
+and was never actually touched after that.
+
+--------------------------------------------------------------------------------
+-- Harald Hope - Thu, 24 Mar 2022 12:01:50 -0800
+
+================================================================================
Version: 3.3.13
Patch: 00
Date: 2022-02-22