read-edid-3.0.2/0000755000175000017550000000000012520031445012345 5ustar mkernmkernread-edid-3.0.2/get-edid/0000755000175000017550000000000012520030613014023 5ustar mkernmkernread-edid-3.0.2/get-edid/get-edid.c0000644000175000017550000000722212433623437015673 0ustar mkernmkern/* This file mostly just does some ui and calls the two main functions (in other files) * * * (C)opyright 2008-2014 Matthew Kern * Full license terms in file LICENSE */ #include #include #include int quiet=0; int i2conly=0; //0=both, 1=i2conly, 2=classiconly int i2cbus=-1; int classmon=0; #define display(...) if (quiet == 0) { fprintf(stderr, __VA_ARGS__); } #define version "3.0.2" int stuped(char *str) { int i; char temp[128]; for (i=0;i= '0' && str[i] <= '9') { temp[i] = str[i]; display("%c\n", temp[i]); } else { if (i==0) { display("-b and -m require numerical arguments.\n"); exit(3); } temp[i] = '\0'; break; } } return atoi(temp); } #if defined I2CBUILD && defined CLASSICBUILD #define BOTHBUILD #endif #ifdef CLASSICBUILD int classicmain( unsigned contr, int qit ); #endif #ifdef I2CBUILD int i2cmain( int bus, int qit ); #endif void help() { display("get-edid, from read-edid %s. Licensed under the GPL.\n", version); display("Current version by Matthew Kern \n"); display("Previous work by John Fremlin \n"); display("and others (See AUTHORS).\n\n"); display("Usage:\n"); #ifdef I2CBUILD display(" -b BUS, --bus BUS Only scan the i2c bus BUS.\n"); #endif #ifdef BOTHBUILD display(" -c, --classiconly Do not check the i2c bus for an EDID\n"); #endif display(" -h, --help Display this help\n"); #ifdef BOTHBUILD display(" -i, --i2conly Do not check for an EDID over VBE\n"); #endif #ifdef CLASSICBUILD display(" -m NUM, --monitor NUM For VBE only - some lame attempt at selecting monitors.\n"); #endif display(" -q, --quiet Do not output anything over stderr (messages, essentially)\n\n"); display("For help, go to or\n"); display("email .\n"); exit(0); } int main(int argc, char *argv[]) { int i; // display("%s\n", argv[2]); for (i=1;i.\n"); return 1; } read-edid-3.0.2/get-edid/i2c.c0000644000175000017550000000666712433623555014703 0ustar mkernmkern/* The Great I2C Getter. * * (C)opyright 2008-2014 Matthew Kern * Full license terms in file LICENSE */ #ifdef I2CBUILD #include #include "i2c-dev.h"//use ours 'cuz it's betterer. #include #include #include #include #include #include //Ideas (but not too much actual code) taken from i2c-tools. Thanks guys. int quiet; #define display(...) if (quiet == 0) { fprintf(stderr, __VA_ARGS__); } int open_i2c_dev(int i2cbus) { int i2cfile; char filename[16]; unsigned long funcs; sprintf(filename, "/dev/i2c-%d", i2cbus); i2cfile = open(filename, O_RDWR); if (i2cfile < 0 && errno == ENOENT) { filename[8] = '/'; i2cfile = open(filename, O_RDWR); } if (errno == EACCES) { display("Permission denied opening i2c. Run as root!\n"); i2cfile = -2; } if (i2cfile >=0) { if (ioctl(i2cfile, I2C_FUNCS, &funcs) < 0) { if (quiet==0) { perror("ioctl I2C_FUNCS"); } i2cfile=-3; } if (!(funcs & (I2C_FUNC_SMBUS_READ_BYTE_DATA))) { display("No byte reading on this bus...\n"); i2cfile=-4; } if (ioctl(i2cfile, I2C_SLAVE, 0x50) < 0) { if (quiet==0) {perror("Problem requesting slave address");} i2cfile=-5; } } return i2cfile; } int i2cmain( int bus, int qit ) { int i, j, ret, len, numbusses=0, tryonly=-1, i2cfile, i2cbus=0; int goodbus[128]; unsigned char block[256]; quiet = qit; if (bus==-1) { for (i2cfile = open_i2c_dev(i2cbus);i2cfile >= 0 || i2cfile < -3;) { //read a byte. This is the official way to scan if (i2cfile < -3) //problem with a bus, not general enough. Skip and close. goto endloop; ret = i2c_smbus_read_byte_data(i2cfile, 0); if (ret < 0) { display("No EDID on bus %i\n", i2cbus); } else { goodbus[numbusses] = i2cbus; numbusses++; } endloop: close(i2cfile); i2cbus++; i2cfile = open_i2c_dev(i2cbus); } if (i2cfile == -2) { return 1; } if (numbusses == 0) { display("Looks like no busses have an EDID. Sorry!\n"); return 2; } display("%i potential busses found:", numbusses); for (i=0;i 1) { if (bus == -1) display("Will scan through until the first EDID is found.\nPass a bus number as an option to this program to go only for that one.\n"); } } else { tryonly = bus; numbusses=1; display("Only trying %i as per your request.\n", tryonly); } ret=1; for (i=0;i= 0) { i2cbus = tryonly; } i2cfile = open_i2c_dev(i2cbus); if (i2cfile >=0) {//no matter how many times, >=0 still looks really angry. for (j=0;j<256;j++) block[j] = i2c_smbus_read_byte_data(i2cfile, j); } close(i2cfile); if (block[0]==0x00&&block[7]==0x00&&block[1]==0xff&&block[2]==0xff&&block[3]==0xff&&block[4]==0xff&&block[5]==0xff&&block[6]==0xff) { ret = 0; break; } else display("Bus %i doesn't really have an EDID...\n", i2cbus); } if (ret==0) { if (block[128] == 0xff) len = 128; else len = 256; display("%i-byte EDID successfully retrieved from i2c bus %i\n", len, i2cbus); if (i2cbus < (numbusses-1)) display("If this isn't the EDID you were looking for, consider the other potential busses.\n"); for (i=0;i 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 2 of the License, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* $Id: i2c-dev.h 5361 2008-10-19 09:47:02Z khali $ */ #ifndef LIB_I2CDEV_H #define LIB_I2CDEV_H #include #include /* -- i2c.h -- */ /* * I2C Message - used for pure i2c transaction, also from /dev interface */ struct i2c_msg { __u16 addr; /* slave address */ unsigned short flags; #define I2C_M_TEN 0x10 /* we have a ten bit chip address */ #define I2C_M_RD 0x01 #define I2C_M_NOSTART 0x4000 #define I2C_M_REV_DIR_ADDR 0x2000 #define I2C_M_IGNORE_NAK 0x1000 #define I2C_M_NO_RD_ACK 0x0800 short len; /* msg length */ char *buf; /* pointer to msg data */ }; /* To determine what functionality is present */ #define I2C_FUNC_I2C 0x00000001 #define I2C_FUNC_10BIT_ADDR 0x00000002 #define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ #define I2C_FUNC_SMBUS_PEC 0x00000008 #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_QUICK 0x00010000 #define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 #define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 #define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 #define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 #define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 #define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 #define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 #define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ #define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ I2C_FUNC_SMBUS_WRITE_BYTE) #define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \ I2C_FUNC_SMBUS_WRITE_BYTE_DATA) #define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \ I2C_FUNC_SMBUS_WRITE_WORD_DATA) #define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) #define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) /* Old name, for compatibility */ #define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC /* * Data for SMBus Messages */ #define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ #define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ union i2c_smbus_data { __u8 byte; __u16 word; __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ /* and one more for PEC */ }; /* smbus_access read or write markers */ #define I2C_SMBUS_READ 1 #define I2C_SMBUS_WRITE 0 /* SMBus transaction types (size parameter in the above functions) Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ #define I2C_SMBUS_QUICK 0 #define I2C_SMBUS_BYTE 1 #define I2C_SMBUS_BYTE_DATA 2 #define I2C_SMBUS_WORD_DATA 3 #define I2C_SMBUS_PROC_CALL 4 #define I2C_SMBUS_BLOCK_DATA 5 #define I2C_SMBUS_I2C_BLOCK_BROKEN 6 #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ #define I2C_SMBUS_I2C_BLOCK_DATA 8 /* ----- commands for the ioctl like i2c_command call: * note that additional calls are defined in the algorithm and hw * dependent layers - these can be listed here, or see the * corresponding header files. */ /* -> bit-adapter specific ioctls */ #define I2C_RETRIES 0x0701 /* number of times a device address */ /* should be polled when not */ /* acknowledging */ #define I2C_TIMEOUT 0x0702 /* set timeout - call with int */ /* this is for i2c-dev.c */ #define I2C_SLAVE 0x0703 /* Change slave address */ /* Attn.: Slave address is 7 or 10 bits */ #define I2C_SLAVE_FORCE 0x0706 /* Change slave address */ /* Attn.: Slave address is 7 or 10 bits */ /* This changes the address, even if it */ /* is already taken! */ #define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ #define I2C_FUNCS 0x0705 /* Get the adapter functionality */ #define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ #define I2C_PEC 0x0708 /* != 0 for SMBus PEC */ #define I2C_SMBUS 0x0720 /* SMBus-level access */ /* -- i2c.h -- */ /* Note: 10-bit addresses are NOT supported! */ /* This is the structure as used in the I2C_SMBUS ioctl call */ struct i2c_smbus_ioctl_data { char read_write; __u8 command; int size; union i2c_smbus_data *data; }; /* This is the structure as used in the I2C_RDWR ioctl call */ struct i2c_rdwr_ioctl_data { struct i2c_msg *msgs; /* pointers to i2c_msgs */ int nmsgs; /* number of i2c_msgs */ }; static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, int size, union i2c_smbus_data *data) { struct i2c_smbus_ioctl_data args; args.read_write = read_write; args.command = command; args.size = size; args.data = data; return ioctl(file,I2C_SMBUS,&args); } static inline __s32 i2c_smbus_write_quick(int file, __u8 value) { return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); } static inline __s32 i2c_smbus_read_byte(int file) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) return -1; else return 0x0FF & data.byte; } static inline __s32 i2c_smbus_write_byte(int file, __u8 value) { return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL); } static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) return -1; else return 0x0FF & data.byte; } static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) { union i2c_smbus_data data; data.byte = value; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BYTE_DATA, &data); } static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA,&data)) return -1; else return 0x0FFFF & data.word; } static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value) { union i2c_smbus_data data; data.word = value; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_WORD_DATA, &data); } static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) { union i2c_smbus_data data; data.word = value; if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_PROC_CALL,&data)) return -1; else return 0x0FFFF & data.word; } /* Returns the number of read bytes */ static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values) { union i2c_smbus_data data; int i; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_BLOCK_DATA,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_DATA, &data); } /* Returns the number of read bytes */ /* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you ask for less than 32 bytes, your code will only work with kernels 2.6.23 and later. */ static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; data.block[0] = length; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN : I2C_SMBUS_I2C_BLOCK_DATA,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_I2C_BLOCK_BROKEN, &data); } /* Returns the number of read bytes */ static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_PROC_CALL,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } #endif /* LIB_I2CDEV_H */ read-edid-3.0.2/get-edid/classic.c0000644000175000017550000002227712520027422015626 0ustar mkernmkern/* (c) 2000,2001,2002 John Fremlin */ /* (c) 2010,2011 Matthew Kern */ #ifdef CLASSICBUILD #include #include #include #include #include #include #include #include typedef u_int8_t byte; typedef u_int32_t uint32; typedef struct LRMI_regs reg_frame; typedef byte* real_ptr; #define access_register(reg_frame,reg) (reg_frame . reg) #define access_ptr_register(reg_frame,reg) (reg_frame -> reg) #define access_seg_register(reg_frame,es) reg_frame.es #define real_mode_int(interrupt,reg_frame_ptr) !LRMI_int(interrupt,reg_frame_ptr) #define alloc_real(size) LRMI_alloc_real(size) #define free_real(block) LRMI_free_real(block) #define dosmemput(buffer,length,offset) memcpy(offset,buffer,length) #define display(...) if (quiet == 0) { fprintf(stderr, __VA_ARGS__); } int quiet; real_ptr far_ptr_to_real_ptr( uint32 farptr ) { unsigned segment = (farptr & 0xffff0000)>>16; unsigned offset = (farptr & 0xffff); return (real_ptr)((size_t)(segment*16+offset)); } #define MAGIC 0x13 #define EDID_BLOCK_SIZE 128 #define EDID_V1_BLOCKS_TO_GO_OFFSET 126 #define SERVICE_REPORT_DDC 0 #define SERVICE_READ_EDID 1 #define SERVICE_LAST 1 // Read VDIF has been removed from the spec. const char* ddc1_support_message[] = { "Monitor and video card combination does not support DDC1 transfers", "Monitor and video card combination supports DDC1 transfers" } ; const char* ddc2_support_message[] = { "Monitor and video card combination does not support DDC2 transfers", "Monitor and video card combination supports DDC2 transfers" } ; const char* screen_blanked_message[] = { "Screen is not blanked during DDC transfer", "Screen is blanked during DDC transfer" } ; const char* supported_message[] = { "Function unsupported", "Function supported" } ; const char* call_successful_message[] = { "Call failed", "Call successful" } ; const char* vbe_service_message[] = { "Report DDC capabilities", "Read EDID" } ; void contact_author() { display("\n\n*********** Something special has happened!\n" ); display("This happens a lot with TV's, and other devices\n"); display("with extension blocks. If you have a TV, don't bother.\n"); #ifdef I2CBUILD display("Odds are good that I2C will work for you. Try 'modprobe i2c-dev'.\n"); #else display("I'd suggest building the I2C version and trying that if you can.\n"); #endif display("Otherwise, please contact the author, Matthew Kern\n" ); display("E-mail: pyrophobicman@gmail.com\n" ); display("Please include full output from this program (especially that to stderr)\n\n\n\n" ); } int read_edid( unsigned controller, FILE* output ); int do_vbe_ddc_service(unsigned BX,reg_frame* regs); int report_ddc_capabilities( unsigned controller ); int report_vcontroller(); int classicmain( unsigned contr, int qit ) { unsigned controller = 0; int error; FILE* output; //fprintf(stderr, "%s: get-edid version %s\n", argv[0], VERSION); quiet=qit; if( !LRMI_init() ) { display( "error initialising realmode interface\n"); display( "do you have full superuser (root) permissions?\n"); return 10; } ioperm(0, 0x400 , 1); iopl(3); /*if ( argc == 1 ) output = stdout; else { if ( argc > 3 ) { display( "%s: syntax %s [output-filename] [controller]\n", argv[0],argv[0] ); return 3; } output = fopen( argv[1], "wb" ); if ( !output ) { display( "%s: error opening file \"%s\" for binary output\n", argv[0],argv[1] ); return 4; } if ( argc == 3 ) controller = strtol( argv[2],0,0 ); } */ output = stdout; controller = contr; report_vcontroller(); error = report_ddc_capabilities(controller); if (read_edid(controller,output)) error = 1; fclose(output); return error; } int do_vbe_service(unsigned AX,unsigned BX,reg_frame* regs) { const unsigned interrupt = 0x10; unsigned function_sup; unsigned success; int error = 0; access_ptr_register(regs,eax) = AX; access_ptr_register(regs,ebx) = BX; display( "\n\tPerforming real mode VBE call\n" ); display( "\tInterrupt 0x%x ax=0x%x bx=0x%x cx=0x%x\n", interrupt, AX, BX, (unsigned)access_ptr_register(regs,ecx) ); if( real_mode_int(interrupt, regs) ) { display( "Error: something went wrong performing real mode interrupt\n" ); error = 1; } AX = access_ptr_register(regs,eax); function_sup = ((AX & 0xff) == 0x4f); success = ((AX & 0xff00) == 0); display( "\t%s\n", supported_message[ function_sup ] ); display( "\t%s\n\n", call_successful_message[ success ] ); if (!success) error=1; if (!function_sup) error=2; return error; } int do_vbe_ddc_service(unsigned BX,reg_frame* regs) { unsigned service = BX&0xff; unsigned AX = 0x4f15; display( "\nVBE/DDC service about to be called\n" ); if ( service > SERVICE_LAST ) { display( "\tUnknown VBE/DDC service\n" ); } else { display( "\t%s\n", vbe_service_message[ service ] ); } return do_vbe_service(AX,BX,regs); } int report_ddc_capabilities( unsigned controller ) { reg_frame regs; int error; unsigned seconds_per_edid_block; unsigned ddc1_support; unsigned ddc2_support; unsigned screen_blanked_during_transfer; memset(®s, 0, sizeof(regs)); access_register(regs,ecx) = controller; error = do_vbe_ddc_service( SERVICE_REPORT_DDC,®s ); if ( !error ) { seconds_per_edid_block = (access_register(regs,ebx) & 0xff00)>>16; ddc1_support = (access_register(regs,ebx) & 0x1)?1:0; ddc2_support = (access_register(regs,ebx) & 0x2)?1:0; screen_blanked_during_transfer = (access_register(regs,ebx) & 0x4)?1:0; display( "\t%s\n", ddc1_support_message[ddc1_support] ); display( "\t%s\n", ddc2_support_message[ddc2_support] ); display( "\t%u seconds per 128 byte EDID block transfer\n", seconds_per_edid_block ); display( "\t%s\n\n", screen_blanked_message[screen_blanked_during_transfer] ); } return error; } int read_edid( unsigned controller, FILE* output ) { reg_frame regs; real_ptr block; byte* buffer; byte* pointer; unsigned blocks_left = 1; unsigned last_reported = 0x1000; /* just a large number */ unsigned author_msg_shown = 0; int err = 0; block = alloc_real( EDID_BLOCK_SIZE ); if ( !block ) { display( "Error: can't allocate 0x%x bytes of DOS memory for output block\n", EDID_BLOCK_SIZE ); return 2; } buffer = block; do { unsigned counter; display( "Reading next EDID block\n" ); memset( block, MAGIC, EDID_BLOCK_SIZE ); memset(®s, 0, sizeof(regs)); access_seg_register(regs,es) = (unsigned)((size_t)block)/16; access_register(regs,edi) = 0; access_register(regs,ecx) = controller; access_register(regs,edx)= blocks_left; if ( do_vbe_ddc_service( SERVICE_READ_EDID, ®s ) ) { display( "The EDID data should not be trusted as the VBE call failed\n" ); } for( pointer=block, counter=EDID_BLOCK_SIZE; counter; counter--,pointer++ ) { if ( *pointer != MAGIC ) goto block_ok; } display( "Error: output block unchanged\n" ); err = 1; break; block_ok: if ( EDID_BLOCK_SIZE != fwrite( buffer, sizeof( byte ), EDID_BLOCK_SIZE, output ) ) { display( "\nError: problem writing output\n" ); err = 1; break; } blocks_left--; if ( buffer[ EDID_V1_BLOCKS_TO_GO_OFFSET ] > blocks_left ) { int reported = buffer[ EDID_V1_BLOCKS_TO_GO_OFFSET ]; display( "EDID claims %u more blocks left\n", reported); if ( last_reported <= reported || reported == 0xff /* 0xff frequently comes up in corrupt edids */ || reported == MAGIC ) { display( "EDID blocks left is wrong.\n" "Your EDID is probably invalid.\n"); } else { if(!author_msg_shown) { contact_author(); author_msg_shown = 1; } last_reported = reported; blocks_left = reported; } } } while( blocks_left ); free_real( block ); return err; } int report_vcontroller() { const unsigned info_block_length = 0x200; real_ptr block; real_ptr oem_string; reg_frame regs; byte* buffer; uint32 oem_string_ptr; byte next; unsigned vbe_version=0; memset(®s, 0, sizeof(regs)); block = alloc_real( info_block_length ); if ( !block ) { display( "Error: can't allocate %x bytes of DOS memory for videocard info block\n", info_block_length ); return 2; } buffer = block; dosmemput("VBE2",4,block); access_seg_register(regs,es) = (unsigned)((size_t)block)/16; access_register(regs,edi) = 0; do_vbe_service(0x4f00,0,®s); memcpy( &vbe_version, buffer+4, 2 ); memcpy( &oem_string_ptr, buffer+6, 4 ); oem_string = far_ptr_to_real_ptr( oem_string_ptr ); display( "\tVBE version %x\n", vbe_version ); display( "\tVBE string at 0x%x \"", (unsigned)((size_t)oem_string) ); for(;;) { next = *oem_string; if ( !next ) break; fputc( next,stderr ); oem_string++; } display("\"\n" ); return 1; } #endif read-edid-3.0.2/ChangeLog0000644000175000017550000000255612520031141014120 0ustar mkernmkern2015-04-28 Matthew Kern * parse-edid.c:: Fix for certain "you have data blocks, but not video ones..." errors. * classic.c: Add language suggesting use of I2C method. 2014-02-04 Matthew Kern * INSTALL: Rewrite for CMake instructions 2011-10-10 Matthew Kern * get-edid.c: new modular design, added i2c support * parse-edid.c: complete rewrite with e-edid support * CMakeLists.txt: Move from autotools to CMake 2008-09-21 Matthew Kern * get-edid.c: moved from lrmi to libx86 - same functions, more portable. 2008-08-25 Matthew Kern * lrmi.c: fixed for linux-2.6.26 and up. * makefile.am, configure.in: Made get-edid not build on !x86. 2001-06-10 John Fremlin * get-edid.c (read_edid): Fooled around with multiple block handling error logic some more. 2001-06-03 John Fremlin * get-edid.c (read_edid): Change action for EDIDs that keep claiming more blocks to return error. 2001-03-11 John Fremlin * parse-edid.c (parse_edid): Workaround lack of snprintf on djgpp 2001-03-04 John Fremlin * parse-edid.c (parse_timing_description): Fix commented out hfreq value - problem spotted by "GEORGE KUKA" read-edid-3.0.2/README0000644000175000017550000000045312274334506013241 0ustar mkernmkernThis package will try to read the monitor details directly from the monitor. The program get-edid asks a VBE BIOS for the EDID data. The program parse-edid parses the data and prints out a human readable summary. Please see http://www.polypux.org/projects/read-edid/ for more detailed information read-edid-3.0.2/.LICENSE.swp0000644000175000017550000003000012433626131014236 0ustar mkernmkernb0VIM 7.4’&oTÍH(r}mkernpenguin~mkern/devel/read-edid/devel/read-edid-3.0.1/LICENSEutf-8 U3210#"! Utp adŠ Ö  ÝÈÇxCò¤ ŸYÖ \  È © ] K * I am still indebted to those guys for a ton of the ideas. * possible * * * * * * * I am still indebted to those guys for a ton of the I am still indebte I am still indebted to thos I am still indebted to those guys for a ton of the ideas. possible. I am still indebted to those guys for a ton of the ideas. possible. A I am still indebted to those guys for a ton of the ideas. possible. I am still indebted to those g I am sti I I am still indebted to those guys for a ton of the ideas. possible. All of the current code is a rewrite of my own work, but Please see AUTHORS for a list of the people who made this software express or implied. The copyright holders shall not be held liable for any * This software is presented "as-is", and as such there is no sort of warranty, * Use of this software is permitted for any reason.This is free software. It is being made available under the following license:All Rights Reserved.(C)opyright 2008-2014 Matthew Kernread-edid-3.0.2/cmake/0000755000175000017550000000000012207732225013433 5ustar mkernmkernread-edid-3.0.2/cmake/Modules/0000755000175000017550000000000012207733745015053 5ustar mkernmkernread-edid-3.0.2/cmake/Modules/Findx86.cmake0000644000175000017550000000032212207733060017266 0ustar mkernmkerninclude(LibFindMacros) find_path(x86_INCLUDE_DIR NAMES libx86.h PATHS) find_library(x86_LIBRARY NAMES libx86) set(x86_PROCESS_INCLUDES x86_INCLUDE_DIR) set(x86_PROCESS_LIBS x86_LIBRARY) libfind_process(x86) read-edid-3.0.2/parse-edid/0000755000175000017550000000000012520031465014364 5ustar mkernmkernread-edid-3.0.2/parse-edid/parse-edid.c0000644000175000017550000003062512520030412016542 0ustar mkernmkern/* Complete parse-edid rewrite. Using some unix-specific stuff - I don't care about dos * * Hope it works :P * * * (C)opyright 2008-2014 Matthew Kern * Full license terms in file LICENSE * */ #include //for the *printf's et al. #include //read, and because it's nice to have #include //exit, and because it's nice to have #include "modes.h" typedef unsigned char byte; byte edid[128]; //edid itself byte extb[128]; //extension block. Hope there's only 1, for now. char modearray[128][128]; int native; int currentmode; static void die(char *msg) { fprintf(stderr, "%s", msg); exit(1); } static void warn(char *msg) { fprintf(stderr, "WARNING: "); fprintf(stderr, "%s", msg); fprintf(stderr, "Trying to continue...\n"); } static void diewemail(char *msg) { fprintf(stderr, "%s", msg); fprintf(stderr, "Something strange happened. Please contact the author,\nMatthew Kern at \n"); exit(1); } int parseedid() { int i; int j; byte sum = 0; char modelname[13]; //int ptm; int compsync = 0; int hres; int vres; //check the checksum for (i = 0; i<128; i++) { sum += edid[i]; } if (sum) warn("Checksum failed\n"); else fprintf(stderr, "Checksum Correct\n\n"); //check header for (i = 0; i < 8; i++) { if (!(((i == 0 || i == 7) && edid[i] == 0x00) || (edid[i] == 0xff))) //0x00 0xff 0xff 0xff 0xff 0xff 0x00 diewemail("Header incorrect. Probably not an edid\n"); } //Make a monitor section... printf("Section \"Monitor\"\n"); //Product Identification /* Model Name: Only thing I do out of order of edid, to comply with X standards... */ for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks... if (edid[i] == 0x00) { //not a timing descriptor if (edid[i+3] == 0xfc) { //Model Name tag for (j = 0; j < 13; j++) { if (edid[i+5+j] == 0x0a) modelname[j] = 0x00; else modelname[j] = edid[i+5+j]; } } } } printf("\tIdentifier \"%s\"\n\tModelName \"%s\"\n", modelname, modelname); /* Vendor Name: 3 characters, standardized by microsoft, somewhere. * bytes 8 and 9: f e d c b a 9 8 7 6 5 4 3 2 1 0 * Character 1 is e d c b a * Character 2 is 9 8 7 6 5 * Character 3 is 4 3 2 1 0 * Those values start at 0 (0x00 is 'A', 0x01 is 'B', 0x19 is 'Z', etc.) */ printf("\tVendorName \"%c%c%c\"\n", (edid[8] >> 2 & 0x1f) + 'A' - 1, (((edid[8] & 0x3) << 3) | ((edid[9] & 0xe0) >> 5)) + 'A' - 1, (edid[9] & 0x1f) + 'A' - 1 ); /* Skip Product ID and Serial Number. */ /* Week and Year: not required, but do it for fun. */ if (edid[0x10] <= 54) printf("\t# Monitor Manufactured week %i of %i\n", (int)(edid[0x10]), ((int)(edid[0x11])) + 1990); else if (edid[0x10] != 0xff) printf("\t# Monitor Manufactured in %i\n", ((int)(edid[0x11])) + 1990); else if (edid[0x10] == 0xff) printf("\t# Monitor Model Year: %i\n", ((int)(edid[0x11])) + 1990); //Edid Version printf("\t# EDID version %i.%i\n", (int)(edid[0x12]), (int)(edid[0x13])); //Basic Display Parameter /* Digital or not? */ if (edid[0x14] & 0x80) printf("\t# Digital Display\n"); else { printf("\t# Analog Display\n"); if (edid[0x14] & 0x02) //sync on green. printf("\tOption \"SyncOnGreen\" \"true\"\n"); if (edid[0x14] & 0x04) compsync = 1; //Composite sync. Save for modelines. } /* Ignore video input definitions, because X doesn't care. */ /* Size parameters: H and V, in centimeters. Projectors put 0 here. * DiplaySize is in millimeters, so multiply by 10 * If 0x16 is 0, but not 0x15, you really should do aspect ratio... */ if (edid[0x15] && edid[0x16]) printf("\tDisplaySize %i %i\n", ((int)(edid[0x15])) * 10, ((int)(edid[0x16])) * 10); else printf("\t# Display Physical Size not given. Normal for projectors.\n"); /* Gamma. Divide by 100, add 1. Defaults to 1, so if 0, it'll be 1 anyway. */ if (edid[0x17] != 0xff) printf("\tGamma %.2f\n", (float)((((float)edid[0x17]) / 100) + 1)); /* DPMS. Simple yes or no. */ printf("\tOption \"DPMS\" \"%s\"\n", (edid[0x18] & 0xE0) ? "true" : "false"); /* Preferred timing mode. This has no meaning, really. The first mode given is preferred. */ //ptm = ((edid[0x18] & 0x02) ? 1 : 0); //printf("\t# preferred timing mode %sfound\n", ptm ? "" : "not "); /* GTF. Not sure what it means to X, so ignore it (for now) */ /* ignore chroma stuff as well. */ //Monitor Limits... okay, another one out of order with the EDID... for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks... if (edid[i] == 0x00) { //not a timing descriptor if (edid[i+3] == 0xfd) { //monitor limits tag printf("\tHorizsync %i-%i\n", (int)edid[i+7] + (((edid[i+4] & 0x0c) & 0x04) ? 255 : 0), (int)edid[i+8] + ((edid[i+4] & 0x08) ? 255 : 0)); printf("\tVertRefresh %i-%i\n", (int)edid[i+5] + (((edid[i+4] & 0x03) & 0x01) ? 255 : 0), (int)edid[i+6] + ((edid[i+4] & 0x02) ? 255 : 0)); printf("\t# Maximum pixel clock is %iMHz\n", (int)edid[i+9] * 10); } } } //I can ignore predefined modes - X knows these already. int hactive, vactive, pixclk, hsyncoff, hsyncwidth, hblank, vsyncoff, vsyncwidth, vblank; //Parse for Detailed Timing Descriptors... for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks... if ((edid[i] != 0x00) && (edid[i+1] != 0x00)) { //a dtd hactive = edid[i+2] + ((edid[i+4] & 0xf0) << 4); hblank = edid[i+3] + ((edid[i+4] & 0x0f) << 8); vactive = edid[i+5] + ((edid[i+7] & 0xf0) << 4); vblank = edid[i+6] + ((edid[i+7] & 0x0f) << 8); //printf("\tModeline \t\"%dx%d\" ", hactive, vactive); pixclk = (edid[i+1] << 8) | (edid[i]); sprintf(modearray[currentmode], "%.2f ", (double)pixclk / 100.0); //I'm using Fremlin's nomenclature... //sync offset = front porch //sync width = sync pulse width hsyncoff = edid[i+8] | ((edid[i+11] & 0xC0) << 2); hsyncwidth = edid[i+9] | ((edid[i+11] & 0x30) << 4); vsyncoff = ((edid[i+10] & 0xf0) >> 4) | ((edid[i+11] & 0x0C) << 2); vsyncwidth = (edid[i+10] & 0x0f) | ((edid[i+11] & 0x03) << 4); sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], hactive, hactive+hsyncoff, hactive+hsyncoff+hsyncwidth, hactive+hblank); sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], vactive, vactive+vsyncoff, vactive+vsyncoff+vsyncwidth, vactive+vblank); if ( (edid[i+17]&0x80) || ((edid[i+17]&0x18) == 0x18) ) { sprintf(modearray[currentmode], "%s%shsync %svsync %s", modearray[currentmode], ((edid[i+17]&0x10) && edid[i+17]&0x02) ? "+": "-", ((edid[i+17]&0x10) && edid[i+17]&0x04) ? "+": "-", (edid[i+17]&0x80) ? "interlace": ""); //hehe... there's been at least 2 bugs in the old parse-edid the whole time - somebody caught the htimings one, and I just caught two problems right here - lack of checking for analog sync and getting hsync and vsync backwards... yes, vsync and hsync have been flipped this whole time. Glad I'm rewriting //printf("%s\n", modearray[currentmode]); currentmode++; } //printf("\tEndmode\n"); } } //Standard Timings - put these after dtd's, because this way preferred is up top. /* I started doing this, but I think it's unnecessary. Think not? you do it. I'll comment what you're missing.*/ int refresh; for (i = 0x26; i < 0x36; i += 0x2) { //read through list of resolutions... if (!(edid[i] == 1 && edid[i+1] == 1)) { //skip if it's "blank" hres = (((int)edid[i]) + 31) * 8; switch ((edid[i+1] & 0xC0) >> 6) { case 0: vres = (hres * 10) / 16; //16:10 aspect ratio break; case 1: vres = (hres * 3) / 4; //4:3 break; case 2: vres = (hres * 4) / 5; //5:4 break; case 3: vres = (hres * 9) / 16; //16:9 break; default: diewemail("The impossible has happened.\n"); } refresh = (edid[i+1] & 0x3F) + 60; printf("\t#Not giving standard mode: "); printf("%ix%i, %iHz\n", hres, vres, refresh); /* printf("\tMode\t\"%ix%i\"\n", hres, vres); printf("\t\tDotClock\t%.6f\n", (float)((hres * vres) * (((edid[i+1] & 0x3f) + 60)) / 1000000)); //(pixels/screen) * (screen/sec) / a million = megapixels/sec, aka dot clock in mHz printf("\t\tHTimings\t\n");*/ } } } int parseextb() { int i, curloc, j; //char nativename[64]; byte sum =0; printf("\n\t#Extension block found. Parsing...\n"); /* for (i = 0; i < 128; i++) printf("byte %xh is 0x%x\n", i, extb[i]); */ //printf("Tag: %x\n", extb[0]); for (i=0;i<128;i++) { sum +=extb[i]; } if (sum != 0x00) { die("Extension block checksum failed\n"); } if (extb[0] != 0x02) diewemail("I only know about extension blocks of type 02h. PLEASE email me!\n"); curloc = extb[2]; if (curloc == 0) { printf("#No data in the extension block\n"); return 0; } //printf("There are %i bytes of data block\n", curloc - 4); //see CEA tables 28-30 if (curloc > 4) { if ((extb[4] & 0xE0) != 0x40) { //if the first one is not a video one printf("extb[4]: 0x%x (0x%x)\n", extb[4], extb[4]&0xE0); diewemail("Hmm, you have data blocks, but not video ones... weird\n"); } for (i=0;i<(extb[4]&0x1F);i++) { if ((extb[5+i]&0x7f) > 59) { printf("#WARNING: I may have missed a mode (CEA mode %i)\n", extb[5+i]&0x7f); if (native==-1) printf("#DOUBLE WARNING: It's your first mode, too, so this may actually be important.\n"); } else { if (native==-1) native = currentmode; sprintf(modearray[currentmode], "%s", ceamodes[extb[5+i]&0x7F]); currentmode++; } } } //starting 18-byte DTD's. //Copypaste the DTD stuff from above. int hactive, vactive, pixclk, hsyncoff, hsyncwidth, hblank, vsyncoff, vsyncwidth, vblank; //Parse for Detailed Timing Descriptors... for (i = curloc; i < curloc+(18*4); i += 0x12) { //read through descriptor blocks... if ((extb[i] != 0x00) && (extb[i+1] != 0x00)) { //a dtd hactive = extb[i+2] + ((extb[i+4] & 0xf0) << 4); hblank = extb[i+3] + ((extb[i+4] & 0x0f) << 8); vactive = extb[i+5] + ((extb[i+7] & 0xf0) << 4); vblank = extb[i+6] + ((extb[i+7] & 0x0f) << 8); //printf("\tModeline \t\"%dx%d\" ", hactive, vactive); if (i == curloc && (extb[3]&0x0F) > 0) { native = currentmode; //sprintf(nativename, "%dx%d", hactive, vactive); } pixclk = (extb[i+1] << 8) | (extb[i]); sprintf(modearray[currentmode], "%.2f ", (double)pixclk / 100.0); //I'm using Fremlin's nomenclature... //sync offset = front porch //sync width = sync pulse width hsyncoff = extb[i+8] | ((extb[i+11] & 0xC0) << 2); hsyncwidth = extb[i+9] | ((extb[i+11] & 0x30) << 4); vsyncoff = ((extb[i+10] & 0xf0) >> 4) | ((extb[i+11] & 0x0C) << 2); vsyncwidth = (extb[i+10] & 0x0f) | ((extb[i+11] & 0x03) << 4); sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], hactive, hactive+hsyncoff, hactive+hsyncoff+hsyncwidth, hactive+hblank); sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], vactive, vactive+vsyncoff, vactive+vsyncoff+vsyncwidth, vactive+vblank); if ( (extb[i+17]&0x80) || ((extb[i+17]&0x18) == 0x18) ) { sprintf(modearray[currentmode], "%s%shsync %svsync %s", modearray[currentmode], ((extb[i+17]&0x10) && extb[i+17]&0x02) ? "+": "-", ((extb[i+17]&0x10) && extb[i+17]&0x04) ? "+": "-", (extb[i+17]&0x80) ? "interlace": ""); //hehe... there's been at least 2 bugs in the old parse-edid the whole time - somebody caught the htimings one, and I just caught two problems right here - lack of checking for analog sync and getting hsync and vsync backwards... yes, vsync and hsync have been flipped this whole time. Glad I'm rewriting } //printf("\n"); currentmode++; } } } int dofooter() { int i; if (native != -1) printf("\tModeline \t\"Mode %i\" %s\n", native, modearray[native]); for (i=0;i 0x01) diewemail("You seem to have too many extension blocks. Will not continue to parse\n"); parseedid(); if (extblock) parseextb(); dofooter(); return 0; } read-edid-3.0.2/parse-edid/CMakeLists.txt0000644000175000017550000000012612207730127017126 0ustar mkernmkernadd_executable (parse-edid parse-edid.c) install (TARGETS parse-edid DESTINATION bin) read-edid-3.0.2/parse-edid/modes.h0000644000175000017550000000741611644153225015661 0ustar mkernmkernchar ceamodes[61][128] = { //Guess who had to do these by hand... you're welcome. "", "25.200 640 656 752 800 480 490 492 525 -hsync -vsync", "27.027 720 736 798 858 480 489 495 525 -hsync -vsync", "27.027 720 736 798 858 480 489 495 525 -hsync -vsync", "74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync", "74.250 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace", "27.027 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace", "27.027 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace", "27.027 1440 1478 1602 1716 240 244 247 262 -hsync -vsync", "27.027 1440 1478 1602 1716 240 244 247 262 -hsync -vsync", "54.054 2880 2956 3204 3432 480 484 487 525 -hsync -vsync interlace", "54.054 2880 2956 3204 3432 480 484 487 525 -hsync -vsync interlace", "54.054 2880 2956 3204 3432 240 244 247 262 -hsync -vsync", "54.054 2880 2956 3204 3432 240 244 247 262 -hsync -vsync", "54.054 1440 1472 1596 1716 480 489 495 525 -hsync -vsync", "54.054 1440 1472 1596 1716 480 489 495 525 -hsync -vsync", "148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync",//16 "27.000 720 732 796 864 576 581 586 625 -hsync -vsync", "27.000 720 732 796 864 576 581 586 625 -hsync -vsync", "74.250 1280 1720 1760 1980 720 725 730 750 +hsync +vsync", "74.250 1920 2448 2492 2640 1080 1082 1089 1125 +hsync +vsync interlace", "27.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "27.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "27.000 1440 1464 1590 1728 288 290 293 312 -hsync -vsync", "27.000 1440 1464 1590 1728 288 290 293 312 -hsync -vsync", "54.000 2880 2928 3180 3456 576 578 581 625 -hsync -vsync interlace", "54.000 2880 2928 3180 3456 576 578 581 625 -hsync -vsync interlace", "54.000 2880 2928 3180 3456 288 290 393 312 -hsync -vsync", "54.000 2880 2928 3180 3456 288 290 393 312 -hsync -vsync", "54.000 1440 1464 1592 1728 576 581 586 625 -hsync -vsync", "54.000 1440 1464 1592 1728 576 581 586 625 -hsync -vsync", "148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync", "74.250 1920 2558 2602 2750 1080 1084 1089 1125 +hsync +vsync",//32 "74.250 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync", "74.250 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync", "108.000 2880 2944 3192 3432 480 489 495 525 -hsync -vsync", "108.000 2880 2944 3192 3432 480 489 495 525 -hsync -vsync", "108.000 2880 2928 3184 3456 576 581 586 625 -hsync -vsync", "108.000 2880 2928 3184 3456 576 581 586 625 -hsync -vsync", "72.000 1920 1952 2120 2304 1080 1103 1108 1250 +hsync +vsync interlace", "148.500 1920 2448 2492 2640 1080 1082 1087 1125 +hsync +vsync interlace", "148.500 1280 1720 1760 1980 720 725 730 750 +hsync +vsync", "54.000 720 732 796 864 576 581 586 625 -hsync -vsync", "54.000 720 732 796 864 576 581 586 625 -hsync -vsync", "54.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "54.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "148.500 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace", "148.500 1280 1390 1430 1650 720 725 730 750 +hsync +vsync", "54.000 720 736 798 858 480 489 495 525 -hsync -vsync", //48 "54.000 720 736 798 858 480 489 495 525 -hsync -vsync", "54.000 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace", "54.000 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace", "108.00 720 732 796 864 576 581 586 625 -hsync -vsync", "108.00 720 732 796 864 576 581 586 625 -hsync -vsync", "108.00 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "108.00 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace", "108.108 720 736 798 858 480 489 495 525 -hsync -vsync", "108.108 720 736 798 858 480 489 495 525 -hsync -vsync", "108.108 1440 1478 1602 1716 480 484 587 525 -hsync -vsync interlace", "108.108 1440 1478 1602 1716 480 484 587 525 -hsync -vsync interlace", }; read-edid-3.0.2/AUTHORS0000644000175000017550000000135311644417255013434 0ustar mkernmkernThe lrmi files were written by Josh Vanderhoof. Matthew Kern (poly-p man) is the current maintainer, fixed some minor bugs, and rewrote a significant chunk of code for 3.0.0. John Fremlin wrote get-edid and the original parse-edid. He was the maintainer until 1.4.1. Dan Hugo afforded immoral support, resulting in the 1.3 series. Martin Kavalec enhanced parse-edid to display frequencies and DPMS features. He also added better monitor name detection and h/vsync type printing. Branden Robinson wrote the manpage. If you want to distribute or modify read-edid, please e-mail the maintainer, Matthew Kern, a courtesy message. read-edid-3.0.2/get-edid.10000644000175000017550000000431112274334534014123 0ustar mkernmkern.TH get\-edid 1 "2013-08-29" .SH NAME get\-edid, parse\-edid \- read\-edid tools to retrieve and interpret monitor specifications using the VESA VBE DDC protocol .SH SYNOPSIS .B get\-edid [\fIOPTIONS\fR] | .B parse\-edid .br .B get\-edid [\fIOPTIONS\fR] > .I filename .br .B parse\-edid < .I filename .SH DESCRIPTION The .I read\-edid utility comprises two tools: .B get\-edid and .BR parse\-edid . .PP .B get\-edid uses real mode calls to perform Data Display Channel (DDC) transfers, or Linux i2c calls to perform Enhanced DDC transfers to retrieve information from monitors, including identification strings, supported sync ranges, available video modes, and video mode parameters. Such information can be useful for configuring X Window System servers in certain cases. .PP .B get\-edid returns the raw Extended Display Identification Data (EDID) block directly from the monitor, so the .B parse\-edid command is available to interpret it and generate a human-readable block of text information that can also be included in a X11 xorg.conf file. .PP Generally the output of .B get\-edid is piped directly to .BR parse\-edid . .PP New in version 3.0.0, .B get\-edid takes a few options. .TP \fB\-b \fIBUS\fR, \fB\-\-bus \fIBUS only scan the i2c bus \fIBUS\fR (if built with i2c support) .TP \fB\-c\fR, \fB\-\-classiconly only use the older VBE interface (if built with i2c and VBE support) .TP \fB\-h\fR, \fB\-\-help display a basic help message .TP \fB\-i\fR, \fB\-\-i2conly only use the newer i2c interface (if built with i2c and VBE support) .TP \fB\-m \fINUM\fR, \fB\-\-monitor \fINUM try to return information about monitor number \fINUM\fR (VBE only) .TP \fB\-q\fR, \fB\-\-quiet do not output messages over stderr .PP .B parse\-edid still does not take any options. \fB\-\-help\fR will show you which options your build of \fIread\-edid\fR supports. .SH AUTHOR .I read\-edid is originally the work of John Fremlin and others. Since 1.4.2, the new maintainer and programmer has been Matthew Kern. Nearly all of the code for this project, as well as this manual page, has been rewritten for 3.0.0 by Matthew Kern. See AUTHORS for more details. .SH "SEE ALSO" Matthew Kern's \fIread\-edid\fR website at read-edid-3.0.2/CMakeLists.txt0000644000175000017550000000075212274463156015127 0ustar mkernmkerncmake_minimum_required (VERSION 2.6) project (read-edid) option(I2CBUILD "Build I2C get-edid implementation" ON) option(CLASSICBUILD "Build VBE get-edid implementation" ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules") if (I2CBUILD OR CLASSICBUILD) add_subdirectory (get-edid) endif () add_subdirectory (parse-edid) INSTALL(FILES get-edid.1 DESTINATION share/man/man1) INSTALL(FILES AUTHORS ChangeLog COPYING README DESTINATION share/doc/read-edid) read-edid-3.0.2/INSTALL0000644000175000017550000000115612274334164013413 0ustar mkernmkernread-edid is packaged using CMake. To install, simply run: cmake . from the current directory. Use the options '-DCLASSICBUILD=OFF' or '-DI2CBUILD=OFF' to disable building of either the VBE interface or the I2C interface to get-edid, respectively. Use both to disable building get-edid entirely. After CMake has completed, use 'make' and 'make install' to build and install the package. The latter command will most likely require root access to run. A note: read-edid requires CMake 2.6 or greater, as well as the libx86 library (and related development packages on binary ditributions) if VBE usage is to be built. read-edid-3.0.2/LICENSE0000644000175000017550000000166412433623222013364 0ustar mkernmkern * This is an unofficial license. Let's call it BSD-like, with these terms: * * You are free to use this software for any purpose. I cannot guarantee * anything about this software or its fitness for any purpose. I will * offer support for this software as long as I am capable of doing so, * but this should not be interpreted as a support contract of any kind. * * * You are free to modify, distribute, etc. this code under the strict * condition that you email me, Matthew Kern , a * brief message on what you're doing. Nothing will be rejected, this is * simply to keep tabs on my work, and maybe we can share ideas on EDIDs. * * * (C)opyright 2008-2014 Matthew Kern * * Please see AUTHORS for a list of the people who made this software * possible. All of the current code is a rewrite of my own work, but * I am still indebted to those guys for a ton of the ideas.