#include <IOKit/IOKitLib.h>
#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/i2c/IOI2CInterface.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
SInt32 EDIDSum( const UInt8 * bytes, IOByteCount len )
{
int i,j;
UInt8 sum;
for (j=0; j < len; j += 128)
{
sum = 0;
for (i=0; i < 128; i++)
sum += bytes[j+i];
if(sum)
return (j/128);
}
return (-1);
}
void EDIDDump( const UInt8 * bytes, IOByteCount len )
{
int i;
fprintf(stderr, "/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */");
for (i = 0; i < len; i++)
{
if( 0 == (i & 15))
fprintf(stderr, "\n ");
fprintf(stderr, "0x%02x,", bytes[i]);
}
fprintf(stderr, "\n");
}
void EDIDRead( IOI2CConnectRef connect, Boolean save )
{
kern_return_t kr;
IOI2CRequest request;
UInt8 data[128];
int i;
bzero( &request, sizeof(request) );
request.commFlags = 0;
request.sendAddress = 0xA0;
request.sendTransactionType = kIOI2CSimpleTransactionType;
request.sendBuffer = (vm_address_t) &data[0];
request.sendBytes = 0x01;
data[0] = 0x00;
request.replyAddress = 0xA1;
request.replyTransactionType = kIOI2CSimpleTransactionType;
request.replyBuffer = (vm_address_t) &data[0];
request.replyBytes = sizeof(data);
bzero( &data[0], request.replyBytes );
kr = IOI2CSendRequest( connect, kNilOptions, &request );
assert( kIOReturnSuccess == kr );
fprintf(stderr, "/* Read result 0x%x, 0x%lx bytes */\n", request.result, request.replyBytes);
if( kIOReturnSuccess != request.result)
return;
EDIDDump( data, request.replyBytes );
i = EDIDSum( &data[0], request.replyBytes );
if( i >= 0)
fprintf(stderr, "/* Block %d checksum bad */\n", i);
else
fprintf(stderr, "/* Checksums ok */\n");
if( save)
write( STDOUT_FILENO, data, request.replyBytes );
}
int main( int argc, char * argv[] )
{
kern_return_t kr;
io_service_t framebuffer, interface;
io_string_t path;
IOOptionBits bus;
IOItemCount busCount;
Boolean save;
framebuffer = CGDisplayIOServicePort(CGMainDisplayID());
{
kr = IORegistryEntryGetPath(framebuffer, kIOServicePlane, path);
assert( KERN_SUCCESS == kr );
fprintf(stderr, "\n/* Using device: %s */\n", path);
kr = IOFBGetI2CInterfaceCount( framebuffer, &busCount );
assert( kIOReturnSuccess == kr );
for( bus = 0; bus < busCount; bus++ )
{
IOI2CConnectRef connect;
fprintf(stderr, "/* Bus %ld: */\n", bus);
kr = IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface);
if( kIOReturnSuccess != kr)
continue;
kr = IOI2CInterfaceOpen( interface, kNilOptions, &connect );
IOObjectRelease(interface);
assert( kIOReturnSuccess == kr );
if( kIOReturnSuccess != kr)
continue;
save = (argc > 1) && (argv[1][0] == 's');
EDIDRead( connect, save );
IOI2CInterfaceClose( connect, kNilOptions );
}
}
exit(0);
return(0);
}