aboutsummaryrefslogtreecommitdiffstats
path: root/monitor-parse-edid
blob: c2c9d7a99817c0246f315c8ccb9539e18537d290 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/perl
# Copyright (C) 2005-2010 by Mandriva SA
#                            Pascal Rigaux
#                            Anssi Hannula
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

use Getopt::Long;
use Parse::EDID;

GetOptions(
    'v' => \ (my $verbose),
    'perl' => \ (my $raw_perl),
    'MonitorsDB' => \ (my $MonitorsDB),
) or usage();

my ($file, $F);
if (@ARGV == 0) {
    $F = *STDIN;
} elsif (@ARGV == 1) {
    open($F, $file = $ARGV[0]) or usage();
} else {
    usage();
}

my $input = join('', <$F>);

my @raw_edids;
my $length = length($input);
if ($length % 128 == 0 && $length >= 128 && $length <= 128 * 254) {
    @raw_edids = $input;
} else {
    @raw_edids = find_edid_in_string($input) or error("bad edid");
}

foreach my $raw_edid (@raw_edids) {
    my $edid = parse_edid($raw_edid, $verbose);
    if (my $err = check_parsed_edid($edid)) {
	die "$err\n";
    }
    $edid->{file} = $file if $file;

    if ($raw_perl) {
	use Data::Dumper;
	$Data::Dumper::Sortkeys = 1;
	my $s = Dumper($edid);
	$s =~ s/.*? = {/+{/;	# remove variable name we don't want
	$s =~ s/};$/}/m;
	print $s;
    } elsif ($MonitorsDB) {
	my $s = to_MonitorsDB($edid);
	print "$s\n" if $s;
    } else {
	print_edid($edid, $verbose);
    }
}

sub usage() {
    die <<'EOF';
usage: monitor-parse-edid [-v] [--perl] [<edid file>]
You can also do "xrandr --prop | monitor-parse-edid"
EOF
}

sub error {
    my ($msg) = @_;
    print STDERR ($file ? "$file: " : ''), $msg, "\n";
    exit 1;
}

sub print_edid {
    my ($edid, $verbose) = @_;

    print "Name: $edid->{monitor_name}\n" if $edid->{monitor_name};
    print "EISA ID: $edid->{EISA_ID}\n" if $edid->{EISA_ID};
    print "EDID version: $edid->{edid_version}.$edid->{edid_revision}\n";
    # this is a number, despite the official name containing "flag":
    print "EDID extension blocks: $edid->{extension_flag}\n";
    printf "Screen size: %.1f cm x %.1f cm (%3.2f inches%s)\n",
      $edid->{max_size_horizontal},
      $edid->{max_size_vertical},
      $edid->{diagonal_size},
      $edid->{ratio_name} ? sprintf(", aspect ratio %s = %.2f", $edid->{ratio_name}, $edid->{ratio}) :
	$edid->{ratio} ? sprintf(", aspect ratio %.2f", $edid->{ratio}) : '';
    
    print "Gamma: ", $edid->{gamma} / 100 + 1, "\n";
    printf "%s signal\n", $edid->{video_input_definition}{digital} ? 'Digital' : 'Analog';

    if ($verbose) {
	foreach (@{$edid->{established_timings} || []}) {
	    print "Standard resolution: $_->{X}x$_->{Y} @ $_->{vfreq} Hz (established timing)\n" if !$_->{interlace};
	}
	foreach (@{$edid->{standard_timings} || []}) {
	    print "Standard resolution: $_->{X}x$_->{Y} @ $_->{vfreq} Hz, ratio $_->{ratio}",
	      $edid->{ratio_name} && index($edid->{ratio_name}, $_->{ratio}) == -1 ? ' (!)' : '',
	      "\n";
	}
    }

    if ($edid->{monitor_range}) {
	printf "Max video bandwidth: %u MHz\n", $edid->{monitor_range}{pixel_clock_max} if $edid->{monitor_range}{pixel_clock_max};
	print "\n";
	printf "\tHorizSync %u-%u\n", $edid->{monitor_range}{horizontal_min}, $edid->{monitor_range}{horizontal_max};
	printf "\tVertRefresh %u-%u\n", $edid->{monitor_range}{vertical_min}, $edid->{monitor_range}{vertical_max};
    }

    foreach my $h (@{$edid->{detailed_timings}}) {
	print "\n";
	print "\t", $h->{ModeLine_comment}, $h->{bad_ratio} ? ' (bad ratio)' : '', "\n";
	print "\tModeLine ", $h->{ModeLine}, "\n";	
    }
}