Read DDC/CI from the AUX bus, not the EDID bus
With I2C access granted, the helper still found nothing: every connected monitor was probed on the wrong bus. A connector has two. The `ddc` symlink points at the classic I2C line that carries EDID on HDMI and DVI. DisplayPort carries DDC/CI over the AUX channel instead, which appears as a child directory of the connector. Both exist on a DP connector and both resolve, so the wrong choice looks entirely reasonable and simply finds no monitor: this machine's DP-2 has ddc -> i2c-5, where ddcutil reports "No monitor detected", while its AUX child i2c-9 answers VCP 0x10 immediately. This is the guess the previous commit said was unverified, and it was wrong in the way that mattered. Enumerating from sysfs is still right -- it gives the connector name Hyprland uses and skips empty connectors -- but it has to prefer the AUX child and fall back to the symlink. The fixture now mirrors sysfs properly: /sys/class/drm/<connector> is a SYMLINK to the real device directory, and `find` does not follow the path it is given. A fixture built from plain directories passes whether or not the code resolves the symlink first, which is a test that agrees with itself rather than with the kernel. Verified on hardware: the Kuycon P20 reports 100%, accepts 70 and returns to 100, and the media keys move it through codex's OSD path. Both bus-selection mistakes are now caught by the contract. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
@@ -57,6 +57,39 @@ has_accessible_bus() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# The I2C bus that carries DDC/CI for one connector.
|
||||
#
|
||||
# There are two, and picking the wrong one finds no monitor at all:
|
||||
#
|
||||
# DisplayPort carries DDC/CI over the AUX channel. That adapter shows up as a
|
||||
# child directory of the connector -- /sys/class/drm/card1-DP-2/i2c-9 -- and
|
||||
# is the one ddcutil talks to.
|
||||
#
|
||||
# The connector's `ddc` symlink points at the classic I2C line used for EDID
|
||||
# on HDMI and DVI. On a DisplayPort connector it still exists and still
|
||||
# resolves, but nothing answers on it: this machine's DP-2 has ddc -> i2c-5,
|
||||
# where ddcutil reports "No monitor detected", while i2c-9 answers VCP 0x10
|
||||
# immediately.
|
||||
#
|
||||
# So prefer the AUX child and fall back to the symlink. Note the readlink: the
|
||||
# entries under /sys/class/drm are symlinks, and `find` does not follow the path
|
||||
# it is given, so searching the unresolved path silently finds nothing.
|
||||
bus_for_connector() {
|
||||
local path="$1" real aux ddc
|
||||
|
||||
real="$(readlink -f "$path")"
|
||||
aux="$(find "$real" -maxdepth 1 -name 'i2c-*' -printf '%f' -quit 2>/dev/null)"
|
||||
if [[ -n "$aux" ]]; then
|
||||
printf '%s' "${aux#i2c-}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ddc="$(readlink -f "$path/ddc" 2>/dev/null)" || return 1
|
||||
[[ -n "$ddc" ]] || return 1
|
||||
ddc="$(basename "$ddc")"
|
||||
printf '%s' "${ddc#i2c-}"
|
||||
}
|
||||
|
||||
cmd_list() {
|
||||
has_accessible_bus || emit_error 'no I2C bus is accessible. ddcutil ships a udev rule that grants this, but only to devices created after it was installed. Run: sudo udevadm control --reload-rules && sudo udevadm trigger --subsystem-match=i2c-dev --subsystem-match=drm'
|
||||
|
||||
@@ -69,8 +102,7 @@ cmd_list() {
|
||||
connector="$(basename "$path")"
|
||||
connector="${connector#card*-}"
|
||||
|
||||
bus="$(basename "$(readlink -f "$path/ddc")")"
|
||||
bus="${bus#i2c-}"
|
||||
bus="$(bus_for_connector "$path")"
|
||||
[[ "$bus" =~ ^[0-9]+$ ]] || continue
|
||||
|
||||
# A monitor that does not implement 0x10 is not an error; it simply
|
||||
|
||||
Reference in New Issue
Block a user