root/i2c-tools/trunk/eeprom/decode-edid

Revision 5561, 6.0 KB (checked in by khali, 3 years ago)

Strip trailing whitespace and redundant spaces.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl -w
2#
3# Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org>
4#
5#    This program is free software; you can redistribute it and/or modify
6#    it under the terms of the GNU General Public License as published by
7#    the Free Software Foundation; either version 2 of the License, or
8#    (at your option) any later version.
9#
10#    This program is distributed in the hope that it will be useful,
11#    but WITHOUT ANY WARRANTY; without even the implied warranty of
12#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#    GNU General Public License for more details.
14#
15#    You should have received a copy of the GNU General Public License
16#    along with this program; if not, write to the Free Software
17#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18#    MA 02110-1301 USA.
19#
20# Version 0.1  2003-07-17  Jean Delvare <khali@linux-fr.org>
21# Version 0.2  2003-07-22  Jean Delvare <khali@linux-fr.org>
22#  Use print instead of syswrite.
23# Version 0.3  2003-08-24  Jean Delvare <khali@linux-fr.org>
24#  Fix data block length (128 bytes instead of 256).
25# Version 1.0  2004-02-08  Jean Delvare <khali@linux-fr.org>
26#  Added support for Linux 2.5/2.6 (i.e. sysfs).
27# Version 1.1  2006-09-01  Jean Delvare <khali@linux-fr.org>
28#  Append /usr/sbin or /usr/local/sbin to $PATH if needed.
29#
30# EEPROM data decoding for EDID. EDID (Extended Display Identification
31# Data) is a VESA standard which allows storing (on manufacturer's side)
32# and retrieving (on user's side) of configuration information about
33# displays, such as manufacturer, serial number, physical dimensions and
34# allowed horizontal and vertical refresh rates.
35#
36# Using the eeprom kernel driver, you have two possibilities to
37# make use of these data:
38#  1* The ddcmon script.
39#  2* This script.
40# Both solutions will return a different kind of information. The first
41# method will report user-interesting information, such as the model number
42# or the year of manufacturing. The second method will report video-card-
43# interesting information, such as video modes and refresh rates.
44#
45# Note that this script does almost nothing by itself. It simply converts
46# what it finds in /proc to binary data to feed the parse-edid program.
47# The parse-edid program was written by John Fremlin and is available at
48# the following address:
49#   http://john.fremlin.de/programs/linux/read-edid/
50
51use strict;
52use Fcntl qw(:DEFAULT :seek);
53use vars qw($bus $address);
54use constant PROCFS => 1;
55use constant SYSFS  => 2;
56
57# parse-edid will typically be installed in /usr/sbin or /usr/local/sbin
58# even though regular users can run it
59$ENV{PATH} .= ':/usr/local/sbin'
60        if $ENV{PATH} !~ m,(^|:)/usr/local/sbin/?(:|$),
61        && -x '/usr/local/sbin/parse-edid';
62$ENV{PATH} .= ':/usr/sbin'
63        if $ENV{PATH} !~ m,(^|:)/usr/sbin/?(:|$),
64        && -x '/usr/sbin/parse-edid';
65
66sub edid_valid_procfs
67{
68        my ($bus, $addr) = @_;
69
70        open EEDATA, "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/00";
71        my $line = <EEDATA>;
72        close EEDATA;
73        return 1
74                if $line =~ m/^0 255 255 255 255 255 255 0 /;
75        return 0;
76}
77
78# Only used for sysfs
79sub rawread
80{
81        my ($filename, $length, $offset) = @_;
82        my $bytes = '';
83
84        sysopen(FH, $filename, O_RDONLY)
85                or die "Can't open $filename";
86        if ($offset)
87        {
88                sysseek(FH, $offset, SEEK_SET)
89                        or die "Can't seek in $filename";
90        }
91
92        $offset = 0;
93        while ($length)
94        {
95                my $r = sysread(FH, $bytes, $length, $offset);
96                die "Can't read $filename"
97                        unless defined($r);
98                die "Unexpected EOF in $filename"
99                        unless $r;
100                $offset += $r;
101                $length -= $r;
102        }
103        close(FH);
104
105        return $bytes;
106}
107
108sub edid_valid_sysfs
109{
110        my ($bus, $addr) = @_;
111        my $bytes = rawread("/sys/bus/i2c/devices/$bus-00$addr/eeprom", 8, 0);
112
113        return 1
114                if $bytes eq "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00";
115        return 0;
116}
117
118sub bus_detect
119{
120        my $max = shift;
121
122        for (my $i=0; $i<$max; $i++)
123        {
124                if (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-50/00")
125                {
126                        if (edid_valid_procfs($i, '50'))
127                        {
128                                print STDERR
129                                        "decode-edid: using bus $i (autodetected)\n";
130                                return $i;
131                        }
132                }
133                elsif (-r "/sys/bus/i2c/devices/$i-0050/eeprom")
134                {
135                        if (edid_valid_sysfs($i, '50'))
136                        {
137                                print STDERR
138                                        "decode-edid: using bus $i (autodetected)\n";
139                                return $i;
140                        }
141                }
142        }
143
144        return; # default
145}
146
147sub edid_decode
148{
149        my ($bus, $addr, $mode) = @_;
150
151        # Make sure it is an EDID EEPROM.
152
153        unless (($mode == PROCFS && edid_valid_procfs ($bus, $addr))
154             || ($mode == SYSFS  && edid_valid_sysfs  ($bus, $addr)))
155        {
156                print STDERR
157                        "decode-edid: not an EDID EEPROM at $bus-$addr\n";
158                return;
159        }
160
161        $SIG{__WARN__} = sub { };
162        open PIPE, "| parse-edid"
163                or die "Can't open parse-edid. Please install read-edid.\n";
164        delete $SIG{__WARN__};
165        binmode PIPE;
166
167        if ($mode == PROCFS)
168        {
169                for (my $i=0; $i<=0x70; $i+=0x10)
170                {
171                        my $file = sprintf '%02x', $i;
172                        my $output = '';
173                        open EEDATA, "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/$file"
174                                or die "Can't read /proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/$file";
175                        while(<EEDATA>)
176                        {
177                                foreach my $item (split)
178                                {
179                                        $output .= pack "C", $item;
180                                }
181                        }
182                        close EEDATA;
183                        print PIPE $output;
184                }
185        }
186        elsif ($mode == SYSFS)
187        {
188                print PIPE rawread("/sys/bus/i2c/devices/$bus-00$address/eeprom", 128, 0);
189        }
190
191        close PIPE;
192}
193
194# Get the address. Default to 0x50 if not given.
195$address = $ARGV[1] || 0x50;
196# Convert to decimal, whatever the value.
197$address = oct $address if $address =~ m/^0/;
198# Convert to an hexadecimal string.
199$address = sprintf '%02x', $address;
200
201# Get the bus. Try to autodetect if not given.
202$bus = $ARGV[0] if defined $ARGV[0];
203$bus = bus_detect(8) unless defined $bus;
204
205if(defined $bus)
206{
207        print STDERR
208                "decode-edid: decode-edid version 1.1\n";
209        if (-r "/proc/sys/dev/sensors/eeprom-i2c-$bus-$address")
210        {
211                edid_decode ($bus, $address, PROCFS);
212                exit 0;
213        }
214        elsif (-r "/sys/bus/i2c/devices/$bus-00$address")
215        {
216                edid_decode ($bus, $address, SYSFS);
217                exit 0;
218        }
219}
220
221print STDERR
222        "EDID EEPROM not found.  Please make sure that the eeprom module is loaded.\n";
223print STDERR
224        "Maybe your EDID EEPROM is on another bus.  Try \"decode-edid ".($bus+1)."\".\n"
225        if defined $bus;
Note: See TracBrowser for help on using the browser.