From 6f3baa2c7faf8eb9e59c0bed71bd581616b3ed6e Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 17 May 2026 03:49:50 -0500 Subject: [PATCH] Fix AMD GPU i2c bus PCI ID detection on Linux On newer kernels with the amdgpu driver, i2c bus symlinks in /sys/bus/i2c/devices/ resolve to paths like: /sys/devices/pci.../0000:03:00.0/i2c-4 The previous code appended '/..' and relied on sysfs path traversal to reach the parent PCI device directory. This is unreliable and causes 'Failed to read i2c device PCI device ID' errors for all AMDGPU i2c buses. Fix: after resolving the symlink with realpath(), truncate at the last '/' to directly obtain the parent PCI device directory path. Also handle DT_UNKNOWN d_type which some kernels return for sysfs symlink entries instead of DT_LNK. This allows OpenRGB to correctly register AMDGPU i2c buses with their proper vendor/device/subsystem PCI IDs, which is a prerequisite for any GPU RGB controller detection on AMD hardware under Linux. Tested on Linux Mint with ASRock Radeon RX 7700 XT (1002:747E, subsystem 1849:5323) and kernel 6.x. --- i2c_smbus/Linux/i2c_smbus_linux.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/i2c_smbus/Linux/i2c_smbus_linux.cpp b/i2c_smbus/Linux/i2c_smbus_linux.cpp index c8605504d..3d4d9fee9 100644 --- a/i2c_smbus/Linux/i2c_smbus_linux.cpp +++ b/i2c_smbus/Linux/i2c_smbus_linux.cpp @@ -147,7 +147,7 @@ bool i2c_smbus_linux_detect() path[sizeof(path) - 1] = '\0'; strncat(path, ent->d_name, sizeof(path) - strlen(path) - 1); path[sizeof(path) - 1] = '\0'; - if(ent->d_type == DT_LNK) + if(ent->d_type == DT_LNK || ent->d_type == DT_UNKNOWN) { ptr = realpath(path, NULL); if(ptr == NULL) @@ -155,9 +155,20 @@ bool i2c_smbus_linux_detect() strncpy(path, ptr, sizeof(path) - 1); path[sizeof(path) - 1] = '\0'; - strncat(path, "/..", sizeof(path) - strlen(path) - 1); - path[sizeof(path) - 1] = '\0'; free(ptr); + + /*-------------------------------------------------------------*\ + | Truncate at last '/' to get the parent PCI device directory. | + | For AMDGPU i2c buses the realpath resolves to something like: | + | /sys/devices/pci.../0000:03:00.0/i2c-4 | + | The parent (0000:03:00.0) contains vendor/device/subsystem | + | files. Using /..' traversal is unreliable in sysfs; directly | + | truncating the path is correct and portable. | + \*-------------------------------------------------------------*/ + char* last_slash = strrchr(path, '/'); + if(last_slash == NULL || last_slash == path) + continue; + *last_slash = '\0'; } else {