Skip to content

Instantly share code, notes, and snippets.

@zhuowei
Last active August 12, 2023 02:41
Show Gist options
  • Save zhuowei/bf37b110152aeb61383a3885cb465cc5 to your computer and use it in GitHub Desktop.
Save zhuowei/bf37b110152aeb61383a3885cb465cc5 to your computer and use it in GitHub Desktop.
@import Darwin;
@import Foundation;
@import IOKit;
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator);
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2);
// outputBufferSize must be less than (1 << 12) (4096 bytes)
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer,
uint32_t outputBufferSize);
// This didn't work for me (returned no error, but EDID not written)
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer,
uint32_t inputBufferSize);
// Hopefully prints EDID of the external monitor on an Apple Silicon device??????
// clang -fmodules -o printedid printedid.m
int main(int argc, char** argv) {
IOAVServiceRef avService = IOAVServiceCreate(kCFAllocatorDefault);
if (!avService) {
NSLog(@"Can't open IOAVService: do you have an external monitor? Are you root?");
return 1;
}
CFDataRef edid;
// Read EDID from the external monitor.
// Tested on Mac Mini M1 attached to a TinyPilot/"HDMI TO USB" capture card on macOS 12 beta 1.
IOReturn err = IOAVServiceCopyEDID(avService, &edid);
if (err) {
NSLog(@"Can't copy EDID: %s", mach_error_string(err));
return 1;
}
if (!edid) {
NSLog(@"No edid detected");
return 1;
}
NSLog(@"EDID??? %@", edid);
NSError* error;
if (![edid writeToFile:@"edid.bin" options:0 error:&error]) {
NSLog(@"%@", error);
}
char i2cBytes[0x1000];
memset(i2cBytes, 0, sizeof(i2cBytes));
// Read the EDID by talking to I2C directly.
// Tested on Mac Mini M1 attached to a TinyPilot/"HDMI TO USB" capture card on macOS 12 beta 1.
err = IOAVServiceReadI2C(avService, 0x50, 0x0, i2cBytes, sizeof(i2cBytes));
if (err) {
NSLog(@"Nope first i2c: %s", mach_error_string(err));
} else {
FILE* f = fopen("edid_raw_i2c.bin", "wb");
fwrite(i2cBytes, 1, 0x100, f);
fclose(f);
}
#ifdef DO_WRITE
// Try writing to EDID.
// Does _not_ work on Mac Mini M1/my capture card: there's no error but the EDID is unchanged.
// Not sure why - maybe the capture card doesn't have writable EDID?
char writeBytes[] = {0x42, 0x42, 0x42, 0x42};
err = IOAVServiceWriteI2C(avService, 0x50, 0, writeBytes, sizeof(writeBytes));
if (err) {
NSLog(@"Nope i2c: %s", mach_error_string(err));
}
#endif
return 0;
}
00000000: 00ff ffff ffff ff00 2157 0100 0100 0000 ........!W......
00000010: 011d 0104 8246 2778 2ad9 b0a3 5749 9c25 .....F'x*...WI.%
00000020: 1149 4b21 0800 7140 81c0 8100 8140 8180 .IK!..q@.....@..
00000030: 9500 a9c0 b300 023a 8018 7138 2d40 582c .......:..q8-@X,
00000040: 4500 c48e 2100 001e 0000 00fd 0017 551e E...!.........U.
00000050: 641e 0410 0000 0000 0001 0000 00f7 000a d...............
00000060: 0040 c644 0000 0000 0000 0000 0000 00fc [email protected]............
00000070: 0048 444d 4920 544f 2055 5342 0a20 01d4 .HDMI TO USB. ..
00000080: 0203 2cf1 5101 0203 0411 1213 1f20 2122 ..,.Q........ !"
00000090: 3c3d 3e90 5f64 2309 0707 8301 0000 6703 <=>._d#.......g.
000000a0: 0c00 1000 b83c e50e 6160 6665 011d 0072 .....<..a`fe...r
000000b0: 51d0 1e20 6e28 5500 c48e 2100 001e 8c0a Q.. n(U...!.....
000000c0: d08a 20e0 2d10 103e 9600 c48e 2100 0018 .. .-..>....!...
000000d0: 8c0a d090 2040 3120 0c40 5500 c48e 2100 .... @1 .@U...!.
000000e0: 0018 4e1f 0080 5100 1e30 4080 3700 c48e [email protected]...
000000f0: 2100 0018 0000 0000 0000 0000 0000 0022 !.............."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment