写给开发者
一个 Mac 应用要跟 DDC/CI 说话,得做对什么
DDC/CI 名声不好,说它不可靠。其中一部分是硬件的问题, 另一部分是——把一根两线总线当成函数调用时发生的事。
地址,以及为什么 EDID 只能读浅层
DDC/CI 在 I2C 芯片 0x37、子地址 0x51。 EDID 在 0x50 应答。EDID 的偏移寄存器只有一个字节, 所以只有基块和第一个扩展块够得着——更深的必须拒绝,而不是猜。
显示器需要「一拍」
显示器需要一点时间才能把回复组好。发完请求立刻读回答案, 在相当多的面板上什么也拿不到。
一个请求,不是两个
写入和读取共用一个请求,这样驱动才能保持总线时序。 把它们拆成两个事务,代码看起来更整洁,真机上表现更糟。
别在一块不理你的面板上花掉十次超时
把每一个已知的 VCP 功能码都探一遍,听起来很周全。 但它也意味着:一块完全不支持 DDC/CI 的面板,要先花掉十次超时, 才能得到「读一次亮度」立刻就能告诉你的结论。用亮度做探路器。
绝不要硬链接一个你的 Mac 可能没有的符号
Intel 那条路需要一个 IOKit 伞形头文件并不导出的用户态 I2C API。 直接引用那个符号,会让 App 在 dyld 里就失败—— 在任何缺这个符号的 Mac 上,它根本起不来。 用 dlsym 解析它,就把这件事变成了优雅降级到「没有 DDC」, 而不是在第一个窗口出现之前崩溃。
两条总线,一个接口
Intel Mac 通过 IOFramebuffer 的 I2C 接口走到 DDC;Apple Silicon 走 AV service。 Intel 路径上的请求是同步的,所以不需要加锁——但上层代码不能假设这一点永远成立。
诚实的边界
- 不是每块面板都应答 DDC/CI。当它不应答时,唯一诚实的回退是软件调光, 那改的是画面不是背光。
- 以上都不是标准。它只是某一个能用实现的做法, 把理由写出来,好让别人能对着源码核对。
- VCP 功能码因面板而异。成功读到其中一个,不能说明下一个也读得到。