Skip to content

Instantly share code, notes, and snippets.

@alin23
Created July 5, 2021 06:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alin23/b476a02a8cd298436848e28476aed07b to your computer and use it in GitHub Desktop.
Save alin23/b476a02a8cd298436848e28476aed07b to your computer and use it in GitHub Desktop.
@import Darwin;
@import Foundation;
@import IOKit;
// clang -fmodules -o i2cwrite i2cwrite.m && ./i2cwrite
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator);
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service);
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2);
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize);
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize);
#define BRIGHTNESS 0x10
#define CONTRAST 0x12
#define AUDIO_SPEAKER_VOLUME 0x62
#define AUDIO_MUTE 0x8D
#define INPUT_SOURCE 0x60
#define DPMS 0xD6
struct DDCWriteCommand {
UInt8 control_id;
UInt8 new_value;
};
int main(int argc, char** argv)
{
io_iterator_t iter;
io_service_t service = 0;
io_registry_entry_t root = IORegistryGetRootEntry(kIOMasterPortDefault);
kern_return_t kerr = IORegistryEntryCreateIterator(root, "IOService", kIORegistryIterateRecursively, &iter);
if (kerr != KERN_SUCCESS) {
IOObjectRelease(iter);
NSLog(@"Error on IORegistryEntryCreateIterator: %d", kerr);
return 1;
}
CFStringRef edidUUIDKey = CFStringCreateWithCString(kCFAllocatorDefault, "EDID UUID", kCFStringEncodingASCII);
CFStringRef locationKey = CFStringCreateWithCString(kCFAllocatorDefault, "Location", kCFStringEncodingASCII);
CFStringRef displayAttributesKey = CFStringCreateWithCString(kCFAllocatorDefault, "DisplayAttributes", kCFStringEncodingASCII);
CFStringRef externalAVServiceLocation = CFStringCreateWithCString(kCFAllocatorDefault, "External", kCFStringEncodingASCII);
while ((service = IOIteratorNext(iter)) != MACH_PORT_NULL) {
io_name_t name;
IORegistryEntryGetName(service, name);
if (strcmp(name, "AppleCLCD2") == 0) {
CFStringRef edidUUID = IORegistryEntrySearchCFProperty(service, kIOServicePlane, edidUUIDKey, kCFAllocatorDefault, kIORegistryIterateRecursively);
CFDictionaryRef displayAttrs = IORegistryEntrySearchCFProperty(service, kIOServicePlane, displayAttributesKey, kCFAllocatorDefault, kIORegistryIterateRecursively);
if (displayAttrs) {
NSDictionary* displayAttrsNS = (NSDictionary*)displayAttrs;
NSDictionary* productAttrs = [displayAttrsNS objectForKey:@"ProductAttributes"];
if (productAttrs) {
NSString* monitorName = [productAttrs objectForKey:@"ProductName"];
NSLog(@"Testing monitor %@ [UUID: %@]", monitorName, edidUUID);
NSLog(@"Attributes: %@", productAttrs);
}
}
}
if (strcmp(name, "DCPAVServiceProxy") == 0) {
IOAVServiceRef avService = IOAVServiceCreateWithService(kCFAllocatorDefault, service);
CFStringRef location = IORegistryEntrySearchCFProperty(service, kIOServicePlane, locationKey, kCFAllocatorDefault, kIORegistryIterateRecursively);
if (location == NULL) {
NSLog(@"No location for service %d: %s\n\n\n", service, name);
continue;
}
if (!avService) {
NSLog(@"No AVService for service %d: %s\n\n\n", service, name);
continue;
}
if (CFStringCompare(externalAVServiceLocation, location, 0) == 0) {
NSLog(@"Found External AVService for %d: %d", service, avService);
} else {
NSLog(@"Found Embedded AVService for %d: %d\n\n\n", service, avService);
continue;
}
struct DDCWriteCommand command;
command.control_id = BRIGHTNESS;
UInt8 data[256];
memset(data, 0, sizeof(data));
data[0] = 0x84;
data[1] = 0x03;
data[2] = command.control_id;
for (int br = 10; br <= 90; br += 10) {
command.new_value = br;
NSLog(@"Setting BRIGHTNESS to %d", command.new_value);
data[3] = (command.new_value) >> 8;
data[4] = command.new_value & 255;
data[5] = 0x6E ^ 0x51 ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4];
for (int i = 0; i < 3; ++i) {
IOReturn err = IOAVServiceWriteI2C(avService, 0x37, 0x51, data, 6);
if (err) {
NSLog(@"i2c error: %s", mach_error_string(err));
}
usleep(32000);
}
usleep(100000);
}
for (int br = 90; br >= 50; br -= 10) {
command.new_value = br;
NSLog(@"Setting BRIGHTNESS to %d", command.new_value);
data[3] = (command.new_value) >> 8;
data[4] = command.new_value & 255;
data[5] = 0x6E ^ 0x51 ^ data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4];
for (int i = 0; i < 3; ++i) {
IOReturn err = IOAVServiceWriteI2C(avService, 0x37, 0x51, data, 6);
if (err) {
NSLog(@"i2c error: %s", mach_error_string(err));
}
usleep(32000);
}
usleep(100000);
}
}
}
CFRelease(locationKey);
CFRelease(edidUUIDKey);
CFRelease(displayAttributesKey);
CFRelease(externalAVServiceLocation);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment