From 24459b2fbf26840e1d1c3ab011022d6c9afac967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 10 Oct 2025 14:24:11 +0800 Subject: [PATCH] Brightness (macOS): enhance DDC/CI detection by enumerating all I2C buses --- src/detection/brightness/brightness_apple.c | 87 ++++++++++++--------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index de3750a94..5552e6141 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -55,7 +55,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa // Works for Apple Silicon and USB-C adapter connection ( but not HTMI ) static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { - if (!IOAVServiceCreate || !IOAVServiceReadI2C) + if (!IOAVServiceCreate || !IOAVServiceReadI2C || !IOAVServiceWriteI2C) return "IOAVService is not available"; FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; @@ -136,52 +136,63 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F if (framebuffer == 0) continue; IOItemCount count; - if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue; - - io_service_t interface = 0; - if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; - - uint8_t i2cOut[12] = {}; - IOI2CConnectRef connect; - if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) + if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) { - IOObjectRelease(interface); + IOObjectRelease(framebuffer); continue; } - uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; - i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; + bool found = false; + for (IOItemCount bus = 0; bus < count && !found; ++bus) + { + io_service_t interface = 0; + if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; - IOI2CRequest request = { - .commFlags = kNilOptions, - .sendAddress = 0x6e, - .sendTransactionType = kIOI2CSimpleTransactionType, - .sendBuffer = (vm_address_t) i2cIn, - .sendBytes = ARRAY_SIZE(i2cIn), - .minReplyDelay = options->ddcciSleep, - .replyAddress = 0x6F, - .replySubAddress = 0x51, - .replyTransactionType = kIOI2CDDCciReplyTransactionType, - .replyBytes = ARRAY_SIZE(i2cOut), - .replyBuffer = (vm_address_t) i2cOut, - }; - IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); - IOI2CInterfaceClose(connect, kNilOptions); - IOObjectRelease(interface); + uint8_t i2cOut[12] = {}; + IOI2CConnectRef connect; + if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) + { + IOObjectRelease(interface); + continue; + } - if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue; + uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; + i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; - if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; + IOI2CRequest request = { + .commFlags = kNilOptions, + .sendAddress = 0x6e, + .sendTransactionType = kIOI2CSimpleTransactionType, + .sendBuffer = (vm_address_t) i2cIn, + .sendBytes = ARRAY_SIZE(i2cIn), + .minReplyDelay = options->ddcciSleep * 1000ULL, + .replyAddress = 0x6F, + .replySubAddress = 0x51, + .replyTransactionType = kIOI2CDDCciReplyTransactionType, + .replyBytes = ARRAY_SIZE(i2cOut), + .replyBuffer = (vm_address_t) i2cOut, + }; + IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); + IOI2CInterfaceClose(connect, kNilOptions); + IOObjectRelease(interface); - uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; - uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; + if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue; + if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; - FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->max = max; - brightness->min = 0; - brightness->current = current; - ffStrbufInitCopy(&brightness->name, &display->name); - brightness->builtin = false; + uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; + uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitCopy(&brightness->name, &display->name); + brightness->builtin = false; + + found = true; + } + + IOObjectRelease(framebuffer); } }