📄 get-edid.c
字号:
/* (c) 2000 John Fremlin */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <string.h>typedef unsigned char byte;#if defined linux#include "lrmi/lrmi.h"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)#else#if defined __DJGPP__#include <dos.h>#include <dpmi.h>#include <sys/movedata.h>typedef __dpmi_regs reg_frame;typedef int real_ptr;#define access_register(reg_frame,reg) (reg_frame .d. reg)#define access_ptr_register(reg_frame,reg) (reg_frame ->d. reg)#define access_seg_register(reg_frame,es) reg_frame .x. es#define real_mode_int(interrupt,reg_frame_ptr) __dpmi_int(interrupt,reg_frame_ptr)#define alloc_real(size) \ (__dpmi_allocate_dos_memory( (size+15)/16,&dummy )*16)int dummy;#define memcpy_from_real(buffer,block,length) \ dosmemget( block, length, buffer )#define free_real(block) /* too much hassle */#else#error No support for your compiler environment!#endif // __DJGPP__#endif // linux#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"};voidcontact_author(){ fprintf( stderr,"\n\n*********** Something special has happened!\n" ); fprintf( stderr,"Please contact the author, John Fremlin\n" ); fprintf( stderr,"E-mail: one of vii@altern.org,vii@mailcc.com,vii@mailandnews.com\n" ); fprintf( stderr, "Please include full output from this program (especially that to stderr)\n\n\n\n" );}intread_edid( unsigned controller, FILE* output ) ; int do_vbe_ddc_service(unsigned BX,reg_frame* regs) ; int report_ddc_capabilities( unsigned controller ) ; int main( int argc, char** argv ){ unsigned controller = 0; int error; FILE* output; #if defined linux if( !LRMI_init() ) { fprintf( stderr, "%s: error initialising realmode interface\n", argv[0] ); fprintf( stderr, "%s: do you have full superuser (root) permissions?\n", argv[0] ); return 10; } ioperm(0, 0x400 , 1); iopl(3);#endif error = report_ddc_capabilities(controller); if ( argc == 1 ) output = stdout; else { if ( argc != 2 ) { fprintf( stderr, "%s: syntax %s [output-filename]\n",argv[0],argv[0] ); return 3; } output = fopen( argv[1], "wb" ); if ( !output ) { fprintf( stderr, "%s: error opening file \"%s\" for binary output\n", argv[0],argv[1] ); return 4; } } if (read_edid(controller,output)) error = 1; fclose(output); return error;}int do_vbe_ddc_service(unsigned BX,reg_frame* regs){ const unsigned interrupt = 0x10; unsigned AX = 0x4f15; unsigned service = BX&0xff; unsigned function_sup; unsigned success; int error = 0; fprintf( stderr, "\nPerforming real mode VBE DDC call\n" ); fprintf( stderr, "\tInterrupt 0x%x ax=0x%x bx=0x%x cx=0x%x\n", interrupt, AX, BX, (unsigned)access_ptr_register(regs,ecx) ); if ( service > SERVICE_LAST ) { fprintf( stderr, "\tUnknown VBE service\n" ); } else { fprintf( stderr, "\t%s\n", vbe_service_message[ service ] ); } access_ptr_register(regs,eax) = AX; access_ptr_register(regs,ebx) = BX; if( real_mode_int(interrupt, regs) ) { fprintf( stderr, "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); fprintf( stderr, "%s\n", supported_message[ function_sup ] ); fprintf( stderr, "%s\n\n", call_successful_message[ success ] ); if (!success) error=1; if (!function_sup) error=2; return error;}intreport_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; fprintf( stderr, "\t%s\n", ddc1_support_message[ddc1_support] ); fprintf( stderr, "\t%s\n", ddc2_support_message[ddc2_support] ); fprintf( stderr, "\t%s\n\n", screen_blanked_message[screen_blanked_during_transfer] ); } return error;}intread_edid( unsigned controller, FILE* output ){ reg_frame regs; real_ptr block; byte* buffer; byte* pointer; unsigned blocks_left = 1; unsigned last_reported = 0; block = alloc_real( EDID_BLOCK_SIZE ); if ( !block ) { fprintf( stderr, "Error: can't allocate %x bytes of DOS memory for output block\n", EDID_BLOCK_SIZE ); return 2; }#if defined __DJGPP__ buffer = (byte*)malloc( EDID_BLOCK_SIZE ); if ( !buffer ) { fprintf( stderr, "Error: can't allocate %x bytes of memory for output block\n", EDID_BLOCK_SIZE ); return 2; }#else buffer = block;#endif memset(®s, 0, sizeof(regs)); access_seg_register(regs,es) = ((unsigned)block)/16; access_register(regs,edi) = 0; access_register(regs,ecx) = controller; do { unsigned counter; fprintf( stderr, "Reading next EDID block\n" );#if defined linux memset( block, MAGIC, EDID_BLOCK_SIZE );#endif access_register(regs,edx)=blocks_left; if ( do_vbe_ddc_service( SERVICE_READ_EDID, ®s ) ) { fprintf( stderr, "The EDID data should not be trusted as the VBE call failed\n" ); } #if defined linux for( pointer=block, counter=EDID_BLOCK_SIZE; counter; counter--,pointer++ ) { if ( *pointer != MAGIC ) goto block_ok; } fprintf( stderr, "Error: output block unchanged\n" ); break; block_ok:#else memcpy_from_real( buffer,block,EDID_BLOCK_SIZE );#endif blocks_left--; if ( buffer[ EDID_V1_BLOCKS_TO_GO_OFFSET ] > blocks_left ) { blocks_left = buffer[ EDID_V1_BLOCKS_TO_GO_OFFSET ]; fprintf( stderr, "EDID claims %u more blocks left\n", blocks_left ); if ( blocks_left == MAGIC ) { fprintf( stderr, "Possibly the EDID call did not work properly?\n" ); } else if ( last_reported == blocks_left ) { fprintf( stderr, "EDID keeps on claiming same number of blocks left. Corruption?\n" ); } else contact_author(); last_reported = blocks_left; } if ( EDID_BLOCK_SIZE != fwrite( buffer, sizeof( byte ), EDID_BLOCK_SIZE, output ) ) { fprintf( stderr, "\nError: problem writing output\n" ); return 1; } } while( blocks_left ); free_real( block ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -