Skip to content

Instantly share code, notes, and snippets.

@tao-j
Last active September 2, 2023 02:17
Show Gist options
  • Save tao-j/c7a3c1ec7c2f59ebe45d161d620d9169 to your computer and use it in GitHub Desktop.
Save tao-j/c7a3c1ec7c2f59ebe45d161d620d9169 to your computer and use it in GitHub Desktop.

Revisions

  1. tao-j revised this gist Jul 3, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions brt.m
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,7 @@

    // clang -fmodules -o brt brt.m && ./brt

    // credit to @zhuowei for discovering the following APIs
    typedef CFTypeRef IOAVServiceRef;
    extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator);
    extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2);
  2. tao-j revised this gist Jul 2, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion brt.m
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,7 @@ 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?");
    NSLog(@"Can't open IOAVService: do you have an external monitor? Are you on M1?");
    return 1;
    }

  3. tao-j revised this gist Jul 1, 2021. No changes.
  4. tao-j created this gist Jul 1, 2021.
    56 changes: 56 additions & 0 deletions brt.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    @import Darwin;
    @import Foundation;
    @import IOKit;

    // clang -fmodules -o brt brt.m && ./brt

    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);

    #define BRIGHTNESS 0x10
    #define CONTRAST 0x12
    #define AUDIO_SPEAKER_VOLUME 0x62
    #define AUDIO_MUTE 0x8D

    struct DDCWriteCommand
    {
    UInt8 control_id;
    UInt8 new_value;
    };


    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;
    }

    char data[16];
    struct DDCWriteCommand command;
    command.control_id = BRIGHTNESS;
    if (argc == 2) {
    command.new_value = atoi(argv[1]);
    }
    else {
    command.new_value = 1;
    }


    data[0] = 0x84;
    data[1] = 0x03;
    data[2] = command.control_id;
    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];
    IOReturn err = IOAVServiceWriteI2C(avService, 0x37, 0x51, data, 6);
    return err;
    }