/*cc -o /tmp/i2cexample i2cexample.c -framework IOKit -framework ApplicationServices -Wall -g */ #include #include #include #include #include #include /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 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); }