aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rwxr-xr-xmonitor-parse-edid69
2 files changed, 61 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 193e5ab..3134111 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@
- monitor-parse-edid:
o print EDID version and the number of EDID extension blocks
o accept EDID data with multiple extension blocks
+ o add support for Detailed Timing Descriptors in CEA EDID Timing
+ Extension
Version 2.5 - 18 October 2009, by Anssi Hannula
diff --git a/monitor-parse-edid b/monitor-parse-edid
index 68fb32b..b8f3515 100755
--- a/monitor-parse-edid
+++ b/monitor-parse-edid
@@ -153,6 +153,16 @@ my %subfields = (
8 => 'vertical_blanking_max',
8 => 'module_revision',
) ],
+
+ cea_data_block_collection => [ group_by2(
+ 3 => 'type',
+ 5 => 'size',
+ ) ],
+
+ cea_video_data_block => [ group_by2(
+ 1 => 'native',
+ 7 => 'mode',
+ ) ],
);
sub within_limit {
@@ -190,11 +200,26 @@ sub check_parsed_edid {
'';
}
+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 parse_edid {
my ($raw_edid, $verbose) = @_;
my %edid;
- my @vals = unpack(join('', map { $_->[0] } @edid_info), $raw_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++]);
@@ -237,15 +262,7 @@ sub parse_edid {
if ($pixel_clock) {
# detailed timing
- 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};
- }
+ my $h = build_detailed_timing($pixel_clock, $vv);
push @{$edid{detailed_timings}}, $h
if $h->{horizontal_active} > 0 && $h->{vertical_active} > 0;
} else {
@@ -307,6 +324,38 @@ sub parse_edid {
$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) {
+ my $h = get_many_bits($v, 'cea_data_block_collection');
+ $dtd_offset -= $h->{size} + 1;
+
+ $v = unpack("x x$h->{size} a*", $v);
+ if ($h->{type} == 0x02) { # Video Data Block
+ $verbose && warn "video data block not handled\n";
+ }
+ }
+
+ 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} > 0 && $h->{vertical_active} > 0;
+ }
+ } 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};