|
1 | 1 | #include "brightness.h" |
2 | 2 | #include "detection/displayserver/displayserver.h" |
3 | 3 | #include "util/apple/cf_helpers.h" |
4 | | -#include "util/apple/ddcci.h" |
5 | 4 | #include "util/edidHelper.h" |
6 | 5 |
|
| 6 | +#include <CoreGraphics/CoreGraphics.h> |
| 7 | + |
| 8 | +// DDC/CI |
| 9 | +#ifdef __aarch64__ |
| 10 | +typedef CFTypeRef IOAVServiceRef; |
| 11 | +extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import)); |
| 12 | +extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import)); |
| 13 | +extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import)); |
| 14 | +extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import)); |
| 15 | +extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import)); |
| 16 | +#else |
| 17 | +// DDC/CI (Intel) |
| 18 | +#include <IOKit/IOKitLib.h> |
| 19 | +#include <IOKit/graphics/IOGraphicsLib.h> |
| 20 | +#include <IOKit/i2c/IOI2CInterface.h> |
| 21 | +extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import)); |
| 22 | +#endif |
| 23 | + |
| 24 | +// ACPI |
7 | 25 | extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import)); |
8 | 26 |
|
9 | 27 | // Works for internal display |
@@ -31,9 +49,10 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa |
31 | 49 | return NULL; |
32 | 50 | } |
33 | 51 |
|
| 52 | +#ifdef __aarch64__ |
34 | 53 | // https://github.com/waydabber/m1ddc |
35 | 54 | // Works for Apple Silicon and USB-C adapter connection ( but not HTMI ) |
36 | | -FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result) |
| 55 | +static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFlist* result) |
37 | 56 | { |
38 | 57 | if (!IOAVServiceCreate || !IOAVServiceReadI2C) |
39 | 58 | return "IOAVService is not available"; |
@@ -105,17 +124,80 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result) |
105 | 124 |
|
106 | 125 | return NULL; |
107 | 126 | } |
| 127 | +#else |
| 128 | +static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) |
| 129 | +{ |
| 130 | + if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available"; |
| 131 | + |
| 132 | + FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) |
| 133 | + { |
| 134 | + if (display->type == FF_DISPLAY_TYPE_EXTERNAL) |
| 135 | + { |
| 136 | + io_service_t framebuffer = 0; |
| 137 | + CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer); |
| 138 | + if (framebuffer == 0) continue; |
| 139 | + |
| 140 | + IOItemCount count; |
| 141 | + if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue; |
| 142 | + |
| 143 | + io_service_t interface = 0; |
| 144 | + if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; |
| 145 | + |
| 146 | + uint8_t i2cOut[12] = {}; |
| 147 | + IOI2CConnectRef connect; |
| 148 | + if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) |
| 149 | + { |
| 150 | + IOObjectRelease(interface); |
| 151 | + continue; |
| 152 | + } |
| 153 | + |
| 154 | + uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; |
| 155 | + i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; |
| 156 | + |
| 157 | + IOI2CRequest request = { |
| 158 | + .commFlags = kNilOptions, |
| 159 | + .sendAddress = 0x6e, |
| 160 | + .sendTransactionType = kIOI2CSimpleTransactionType, |
| 161 | + .sendBuffer = (vm_address_t) i2cIn, |
| 162 | + .sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]), |
| 163 | + .minReplyDelay = 10, |
| 164 | + .replyAddress = 0x6F, |
| 165 | + .replySubAddress = 0x51, |
| 166 | + .replyTransactionType = kIOI2CDDCciReplyTransactionType, |
| 167 | + .replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]), |
| 168 | + .replyBuffer = (vm_address_t) i2cOut, |
| 169 | + }; |
| 170 | + IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); |
| 171 | + IOI2CInterfaceClose(connect, kNilOptions); |
| 172 | + IOObjectRelease(interface); |
| 173 | + |
| 174 | + if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue; |
| 175 | + |
| 176 | + if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; |
| 177 | + |
| 178 | + uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; |
| 179 | + uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; |
| 180 | + |
| 181 | + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); |
| 182 | + brightness->max = max; |
| 183 | + brightness->min = 0; |
| 184 | + brightness->current = current; |
| 185 | + ffStrbufInitCopy(&brightness->name, &display->name); |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | + return NULL; |
| 190 | +} |
| 191 | +#endif |
108 | 192 |
|
109 | 193 | const char* ffDetectBrightness(FFlist* result) |
110 | 194 | { |
111 | 195 | const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); |
112 | 196 |
|
113 | 197 | detectWithDisplayServices(displayServer, result); |
114 | 198 |
|
115 | | - #ifdef __aarch64__ |
116 | 199 | if (displayServer->displays.length > result->length) |
117 | | - detectWithDdcci(result); |
118 | | - #endif |
| 200 | + detectWithDdcci(displayServer, result); |
119 | 201 |
|
120 | 202 | return NULL; |
121 | 203 | } |
0 commit comments