From 412da37667cc06fd16b1e28b1b5f20e9a467de8f Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sat, 2 Jan 2010 05:10:29 +0000 Subject: Add handling of EDID extension blocks. --- NEWS | 3 +++ get-edid.h | 3 +++ monitor-get-edid-using-vbe.c | 2 +- monitor-parse-edid | 4 ++-- vbe.c | 26 ++++++++++++++++++++++---- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index af96b80..193e5ab 100644 --- a/NEWS +++ b/NEWS @@ -5,8 +5,11 @@ interface on non-x86 hosts as well (fixes Mandriva bug #53866, which was caused by a bug in the removed code) o fix the retrieval of VBE vendor strings when using the LRMI interface + o retrieve up to 4 EDID extension blocks + - monitor-parse-edid: o print EDID version and the number of EDID extension blocks + o accept EDID data with multiple extension blocks Version 2.5 - 18 October 2009, by Anssi Hannula diff --git a/get-edid.h b/get-edid.h index 4b82204..b61dc98 100644 --- a/get-edid.h +++ b/get-edid.h @@ -1,3 +1,6 @@ +#define EDID_BLOCK_SIZE 128 +#define MAX_EXTENSION_COUNT 4 + int verbose; int get_edid(char *edid, int port); diff --git a/monitor-get-edid-using-vbe.c b/monitor-get-edid-using-vbe.c index ba04224..c70e663 100644 --- a/monitor-get-edid-using-vbe.c +++ b/monitor-get-edid-using-vbe.c @@ -15,7 +15,7 @@ int verbose = 0; int main(int argc, char **argv) { - char edid[256]; + char edid[(1 + MAX_EXTENSION_COUNT) * EDID_BLOCK_SIZE]; int try_in_console = 0; int port = 0; int i; diff --git a/monitor-parse-edid b/monitor-parse-edid index a033c35..68fb32b 100755 --- a/monitor-parse-edid +++ b/monitor-parse-edid @@ -487,7 +487,7 @@ sub print_edid { sub edid_from_lines { my (@l) = @_; my $edid_str = join('', map { /\s+([0-9a-f]{32})$/ && $1 } @l); - length($edid_str) == 256 or return (); + length($edid_str) % (2 * 128) == 0 or return (); pack("C*", map { hex($_) } $edid_str =~ /(..)/g); } @@ -536,7 +536,7 @@ sub error { } my @raw_edids; -if (length($input) == 128 || length($input) == 256) { +if (length($input) % 128 == 0 && length($input) <= 128 * 254) { @raw_edids = $input; } else { @raw_edids = find_edid_in_string($input) or error("bad edid"); diff --git a/vbe.c b/vbe.c index 8eb74fc..56882d3 100644 --- a/vbe.c +++ b/vbe.c @@ -209,11 +209,10 @@ static int vbe_check_ddc_capabilities(int port) return 1; } -static int vbe_get_edid_info(char *edid, int port) +static int vbe_get_edid_info(char *edid, int port, int block) { int i; unsigned char *mem; - const int EDID_BLOCK_SIZE = 128; struct LRMI_regs regs; /* initialize LRMI */ @@ -235,6 +234,7 @@ static int vbe_get_edid_info(char *edid, int port) regs.eax = 0x4f15; regs.ebx = 0x0001; regs.ecx = port; + regs.edx = block; regs.es = (uintptr_t)(mem - LRMI_base_addr()) >> 4; regs.edi = (uintptr_t)(mem - LRMI_base_addr()) & 0x0f; @@ -262,6 +262,7 @@ static int vbe_get_edid_info(char *edid, int port) int get_edid(char *edid, int port) { + int i, extensions; int ok = 0; if (getuid() != 0) { @@ -272,9 +273,26 @@ int get_edid(char *edid, int port) ok = (box_is_xbox() || (vbe_check_vbe_info() && vbe_check_ddc_capabilities(port))) && - vbe_get_edid_info(edid, port); + vbe_get_edid_info(edid, port, 0); - return ok ? 128 : 0; + if (!ok) + return 0; + + extensions = ((unsigned char*)edid)[126]; + if (extensions > MAX_EXTENSION_COUNT) { + log_err("EDID: Reported %d extensions, only reading %d\n", + extensions, MAX_EXTENSION_COUNT); + extensions = MAX_EXTENSION_COUNT; + } + + for (i = 1; i <= extensions; i++) { + if (!vbe_get_edid_info(edid + i * EDID_BLOCK_SIZE, port, i)) { + log_err("EDID: Failure reading extension block %d\n", i); + break; + } + } + + return i * EDID_BLOCK_SIZE; } int box_is_xbox() { -- cgit v1.2.1