You are not logged in.

#1 2022-08-01 18:34:10

ctpfaff
Member
Registered: 2017-08-29
Posts: 27

[solved] How to pin the name of a i2c device

I am using https://github.com/ddccontrol/ddccontrol to adjust the settings like brightness of an external monitor attached to my laptop. It accesses the monitor via an i2c device in /dev/i2c-<a number>. For a very long time my arch installation made my screen available through the same i2c device like e.g. /dev/i2c-1 even persisting reboots. Since a while however that seems to have changed. As I want to use the tool with a shortcut on my keyboard I now have the problem that I first would have to do some extra and time consuming steps in a script to figure out what devide I need to talk to. Thus I was asking myself if there is any chance that I can pin the name of such an i2c device to a fixed one? Any help with this is appreciated.

Last edited by ctpfaff (2022-08-03 07:03:26)

Offline

#2 2022-08-01 18:56:50

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,061
Website

Re: [solved] How to pin the name of a i2c device

What creates that device node?  There is likely a driver / module loaded for it, and if so you could configure this according to it's settings (perhaps a modprobe.d/*.conf entry).

Otherwise I suspect that you could rename it through a udev rule (see the 'udev' wiki article).

Last edited by Trilby (2022-08-01 18:57:03)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3 2022-08-02 06:09:19

ctpfaff
Member
Registered: 2017-08-29
Posts: 27

Re: [solved] How to pin the name of a i2c device

Yeah. Indeed it is loaded by a module called i2c-dev which is in

cat /etc/modules-load.d/ddccontrol-i2c-dev.conf
# Load i2c-dev at boot to probe DDC/CI devices (displays)
i2c-dev

And I also found some documentation abou how the kernel handles these interfaces. They are generated and numbered in ascending order.

https://www.kernel.org/doc/Documentatio … -interface

Thanks for pointing out udev as option which might work. However as I am not very familiar with udev yet I have to read the wiki first carefully in order to understand how I might derive a solution for the problem at hand.

Last edited by ctpfaff (2022-08-02 06:09:53)

Offline

#4 2022-08-02 12:39:32

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,061
Website

Re: [solved] How to pin the name of a i2c device

Na, forget udev, you'll be better off specifying the order at the module level.  What *other* device is getting enumerated as a /dev/i2c-* entry?  Is that other device controlled by this same driver / module or a different one?

EDIT as a third option you could check if there are other links to this device that may have a hardware-location based path which would remain consistent.  To do so, first check whether the currently correct /dev/i2c-* node is itself a link, if so, what is it a link to (e.g., `ls -l /dev/i2c*`).  If it's not itself a link, check for other nodes that are a link to it:

find /sys /dev -samefile /dev/i2c-N  # where N is the relevant number / remainder of the filename

So in the order that I'd prefer to "solve" the problem if I were in your shoes:

1) check for other nodes under /dev/ or /sys/ that point to the same hardware, these might have more reliably consistent paths/names, if so, use that name and you're done
2) otherwise configure module loading to get a consistent ordering (this may depend on whether the multiple i2c devices are controlled by the same module or multiple modules)
3) if all else fails, fall back to udev to try to rename and / or create additional links for these dev nodes

Last edited by Trilby (2022-08-02 12:49:59)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2022-08-02 18:10:13

ctpfaff
Member
Registered: 2017-08-29
Posts: 27

Re: [solved] How to pin the name of a i2c device

Trilby wrote:

What *other* device is getting enumerated as a /dev/i2c-* entry?
Is that other device controlled by this same driver / module or a different
one?

I just checked the dev folder. And I was surprised that there is so many of
these device entries.

ls /dev/i2c-*
/dev/i2c-0  /dev/i2c-1  /dev/i2c-10  /dev/i2c-2  /dev/i2c-3  /dev/i2c-4  /dev/i2c-5  /dev/i2c-6  /dev/i2c-7  /dev/i2c-8  /dev/i2c-9

The search for links pointing to the same device was without success.

I guess the i2c-dev module is the only source responsible to create these
particular entries but when I understand the documentation correctly then this
is just for convenient access. The registration of these devices can happen
somewhere else.

Interestingly I found this in the documentation

You can examine /sys/class/i2c-dev/ to see what number corresponds to which
adapter...

/sys/class/i2c-dev
* ls -l
insgesamt 0
drwxr-xr-x  2 root root 0  2. Aug 19:10 .
drwxr-xr-x 77 root root 0  2. Aug 19:10 ..
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-0 -> ../../devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-0/i2c-dev/i2c-0
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-1 -> ../../devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1/i2c-dev/i2c-1
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-10 -> ../../devices/pci0000:00/0000:00:1f.4/i2c-10/i2c-dev/i2c-10
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-2 -> ../../devices/pci0000:00/0000:00:19.0/i2c_designware.2/i2c-2/i2c-dev/i2c-2
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-3 -> ../../devices/pci0000:00/0000:00:02.0/i2c-3/i2c-dev/i2c-3
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-4 -> ../../devices/pci0000:00/0000:00:02.0/i2c-4/i2c-dev/i2c-4
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-5 -> ../../devices/pci0000:00/0000:00:02.0/i2c-5/i2c-dev/i2c-5
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-6 -> ../../devices/pci0000:00/0000:00:02.0/i2c-6/i2c-dev/i2c-6
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-7 -> ../../devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/i2c-7/i2c-dev/i2c-7
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-8 -> ../../devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/i2c-8/i2c-dev/i2c-8
lrwxrwxrwx  1 root root 0  2. Aug 19:11 i2c-9 -> ../../devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-9/i2c-dev/i2c-9

... where the last one is the one I am interested in (DP-2). I hope that this
label in the path will stay more consistent. So with just two lines of bash I
can point ddccontrol right away to the correct location. Just tried. Works
perfectly.

#!/usr/bin/env bash

device=`ls -l /sys/class/i2c-dev | grep DP-2 | rev | cut -d/ -f 1 | rev`
ddccontrol -r 0x10 -w ${1} dev:/dev/${device}

Last edited by ctpfaff (2022-08-02 18:21:28)

Offline

#6 2022-08-02 18:10:42

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 132

Re: [solved] How to pin the name of a i2c device

Trilby wrote:

Na, forget udev, you'll be better off specifying the order at the module level.

Imho symlink with udev is a standart solution for such kind of issue. E.g. recently i got new /dev/i2c-* device after kernel upgrade and it messed all enumeration. Of course it is possible to map /dev/ to /sys/ "manually" but udev already does it for you.

Offline

#7 2022-08-02 18:20:55

ctpfaff
Member
Registered: 2017-08-29
Posts: 27

Re: [solved] How to pin the name of a i2c device

dimich wrote:
Trilby wrote:

Na, forget udev, you'll be better off specifying the order at the module level.

Imho symlink with udev is a standart solution for such kind of issue. E.g. recently i got new /dev/i2c-* device after kernel upgrade and it messed all enumeration. Of course it is possible to map /dev/ to /sys/ "manually" but udev already does it for you.

So did you manage to fix the order to your liking with udev? And if so could you please exemplify to an extend that I might be able to adapt this to my situation?

Offline

#8 2022-08-02 19:11:13

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,061
Website

Re: [solved] How to pin the name of a i2c device

Why all the gymastics parsing ls to set device??  Just use the correct one from the start

device=/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-9/i2c-dev/i2c-9
ddcontrol # ...

Parsing ls could be as error prone as just assuming it would always be a specific /dev/i2c- number, but the pci address will not change (at least as long as you don't rearrange the hardware wiring).

EDIT: oh, because the tail of the path will change - still

device=/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-*/i2c-dev/i2c-*

udev can be useful for renaming, but then you'll have to rename it ... why bother, it has a consistent path already.  And with udev renaming you can potentially end up running into race conditions depending how / when the old / new device names are used.  This parallels the logic of using UUIDs for disks and partitions rather than trying to force the kernel to (re)enumerate devices the same way every boot up: don't try to force a given device to always be sda (rather than sdb, etc), just use the UUID instead as that will already be consistent across boots.

Last edited by Trilby (2022-08-02 19:19:29)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#9 2022-08-02 20:02:27

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 132

Re: [solved] How to pin the name of a i2c device

ctpfaff wrote:

So did you manage to fix the order to your liking with udev? And if so could you please exemplify to an extend that I might be able to adapt this to my situation?

In my case the device is USB-to-I2C adapter so i can identify it simply by vendor/product id:

ACTION=="add|change", SUBSYSTEM=="i2c-dev", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", SYMLINK+="i2c-adapter"

In your case, as i understand, it is I2C controller on video card. So we should figure out how to distinguish between them. E.g. my video card has four I2C adapters, currently from i2c-2 to i2c-5:

$ i2cdetect -l
i2c-0	smbus     	SMBus I801 adapter at efa0      	SMBus adapter
i2c-1	i2c       	i2c-ch341-u2c at bus 005 device 003	I2C adapter
i2c-2	i2c       	NVIDIA i2c adapter 1 at 1:00.0  	I2C adapter
i2c-3	i2c       	NVIDIA i2c adapter 3 at 1:00.0  	I2C adapter
i2c-4	i2c       	NVIDIA i2c adapter 5 at 1:00.0  	I2C adapter
i2c-5	i2c       	NVIDIA i2c adapter 6 at 1:00.0  	I2C adapter

Let's see what attributes they have and how we can idenify them:

$ udevadm info -a /dev/i2c-2 > adapter1.txt
$ udevadm info -a /dev/i2c-5 > adapter6.txt
$ diff -y --suppress-common-lines adapter1.txt adapter6.txt 
  looking at device '/devices/pci0000:00/0000:00:01.0/0000:01 |	  looking at device '/devices/pci0000:00/0000:00:01.0/0000:01
    KERNEL=="i2c-2"					      |	    KERNEL=="i2c-5"
    ATTR{name}=="NVIDIA i2c adapter 1 at 1:00.0"	      |	    ATTR{name}=="NVIDIA i2c adapter 6 at 1:00.0"
  looking at parent device '/devices/pci0000:00/0000:00:01.0/ |	  looking at parent device '/devices/pci0000:00/0000:00:01.0/
    KERNELS=="i2c-2"					      |	    KERNELS=="i2c-5"
    ATTRS{name}=="NVIDIA i2c adapter 1 at 1:00.0"	      |	    ATTRS{name}=="NVIDIA i2c adapter 6 at 1:00.0"
    ATTRS{power/runtime_active_time}=="1423246"		      |	    ATTRS{power/runtime_active_time}=="1438529"
    ATTRS{power/runtime_active_time}=="1423260"		      |	    ATTRS{power/runtime_active_time}=="1438542"

ATTR{name} differs, so we can try to use it. E.g. we want to pin "adapter 6" which is currently on /dev/i2c-5. Create /etc/udev/rules/99-backlight.rules:

ACTION=="add|change", SUBSYSTEM=="i2c-dev", ATTRS{name}=="NVIDIA i2c adapter 6 *", SYMLINK+="i2c-backlight"

Then

$ sudo udevadm control -R
$ sudo udevadm trigger
$ readlink /dev/i2c-backlight 
i2c-5

Offline

#10 2022-08-02 21:38:15

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 132

Re: [solved] How to pin the name of a i2c device

Trilby wrote:
device=/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/i2c-9/i2c-dev/i2c-9
ddcontrol # ...

This path is special sysfs file or directory. ddccontrol expect spidev's character device. It will fail on calling spidev-specific ioctls.

Last edited by dimich (2022-08-02 21:54:14)

Offline

#11 2022-08-02 22:07:30

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 132

Re: [solved] How to pin the name of a i2c device

ctpfaff wrote:

You can examine /sys/class/i2c-dev/ to see what number corresponds to which adapter...

Ah, then it might be simpler without udev. If there is only one i2c-* entry in /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/

ddccontrol dev:/dev/$(basename /sys/devices/pci*/*/drm/card0/card0-DP-2/i2c-*) ...

This should work unless you install one more video card.

Offline

#12 2022-08-02 22:12:10

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,061
Website

Re: [solved] How to pin the name of a i2c device

dimich wrote:

This path is special sysfs file or directory. ddccontrol expect spidev's character device. It will fail on calling spidev-specific ioctls.

Have you tried?  That doesn't make much sense as the /dev/i2c-* nodes are just links to the sysfs entries ... they're literally the same target destination.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#13 2022-08-02 23:08:00

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 132

Re: [solved] How to pin the name of a i2c device

Trilby wrote:

Have you tried?

I have different /sys/class/drm/ tree structure, there are no i2c-* entries provided by driver in drm subsystem. I can try with another path:

$ ddccontrol -d dev:/dev/i2c-4
ddccontrol version 0.5.2
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.

Reading EDID and initializing DDC/CI at bus dev:/dev/i2c-4...
I/O warning : failed to load external entity "/usr/share/ddccontrol-db/monitor/PHLC211.xml"
Document not parsed successfully.

EDID readings:
	Plug and Play ID: PHLC211 [VESA standard monitor]
	Input type: Analog
=============================== WARNING ===============================
There is no support for your monitor in the database, but ddccontrol is
using a basic generic profile. Many controls will not be supported, and
some controls may not work as expected.
Please update ddccontrol-db, or, if you are already using the latest
version, please send the output of the following command to
ddccontrol-users@lists.sourceforge.net:

LANG= LC_ALL= ddccontrol -p -c -d

Thank you.
=============================== WARNING ===============================

Controls (valid/current/max) [Description - Value name]:
Control 0x02: +/2/2 C [New Control Value - Some values changed]
Control 0x04: +/0/1 C [Restore Factory Defaults]
Control 0x05: +/0/1 C [Restore Brightness and Contrast]
Control 0x06: +/0/1   [???]
Control 0x08: +/0/1 C [Restore Factory Default Color]
Control 0x0b: +/100/0 C [???]
Control 0x0c: +/70/255 C [???]
Control 0x0e: +/0/100   [???]
Control 0x10: +/90/100 C [Brightness]
Control 0x12: +/50/100 C [Contrast]
Control 0x14: +/5/11 C [???]
Control 0x16: +/100/100 C [Red maximum level]
Control 0x18: +/100/100 C [Green maximum level]
Control 0x1a: +/100/100 C [Blue maximum level]
Control 0x1e: +/0/1   [???]
Control 0x1f: +/1/1   [???]
Control 0x20: +/50/100   [???]
Control 0x30: +/50/100   [???]
Control 0x3e: +/0/100   [???]
Control 0x52: +/0/100 C [???]
Control 0x54: +/0/1 C [Color Temperature Request]
Control 0x60: +/17/17 C [Input Source Select (Main)]
Control 0x62: +/80/100 C [Audio Speaker Volume Adjust]
Control 0x6c: +/128/100 C [Red minimum level]
Control 0x6e: +/128/100 C [Green minimum level]
Control 0x70: +/128/100 C [Blue minimum level]
Control 0x72: +/120/160 C [???]
Control 0x86: +/8/8 C [???]
Control 0x87: +/5/10 C [???]
Control 0x8d: +/2/2 C [???]
Control 0xac: +/1/2064 C [???]
Control 0xae: +/6010/65535 C [???]
Control 0xb2: +/1/1 C [???]
Control 0xb6: +/3/5 C [???]
Control 0xc6: +/90/255 C [???]
Control 0xc8: +/9/0 C [???]
Control 0xc9: +/1/65535   [???]
Control 0xca: +/1/2 C [???]
Control 0xcc: +/2/36 C [???]
Control 0xd6: +/1/5 C [DPMS Control - On]
Control 0xdc: +/0/31 C [???]
Control 0xdf: +/514/65535 C [???]
Control 0xe9: +/0/2 C [???]
$ ddccontrol -d dev:/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/i2c-4/i2c-dev/i2c-4
ddccontrol version 0.5.2
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.

Reading EDID and initializing DDC/CI at bus dev:/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/i2c-4/i2c-dev/i2c-4...
Open monitor failed: GDBus.Error:ddccontrol.DDCControl.Error.InvalidDevice: only detected devices are allowed
.
DDC/CI at dev:/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/i2c-4/i2c-dev/i2c-4 is unusable (-1).
If your graphics card need it, please check all the required kernel modules are loaded (i2c-dev, and your framebuffer driver).

But i know what /dev/i2c-* are.

Trilby wrote:

That doesn't make much sense as the /dev/i2c-* nodes are just links to the sysfs entries

Are you sure?

$ stat -c "%A %n %N" /dev/i2c-* /dev/i2c/*
crw-rw---- /dev/i2c-0 '/dev/i2c-0'
crw-rw---- /dev/i2c-1 '/dev/i2c-1'
crw-rw---- /dev/i2c-2 '/dev/i2c-2'
crw-rw---- /dev/i2c-3 '/dev/i2c-3'
crw-rw---- /dev/i2c-4 '/dev/i2c-4'
crw-rw---- /dev/i2c-5 '/dev/i2c-5'
lrwxrwxrwx /dev/i2c-adapter '/dev/i2c-adapter' -> 'i2c-1'
lrwxrwxrwx /dev/i2c-backlight '/dev/i2c-backlight' -> 'i2c-5'
lrwxrwxrwx /dev/i2c/0 '/dev/i2c/0' -> '../i2c-0'
lrwxrwxrwx /dev/i2c/1 '/dev/i2c/1' -> '../i2c-1'
lrwxrwxrwx /dev/i2c/2 '/dev/i2c/2' -> '../i2c-2'
lrwxrwxrwx /dev/i2c/3 '/dev/i2c/3' -> '../i2c-3'
lrwxrwxrwx /dev/i2c/4 '/dev/i2c/4' -> '../i2c-4'
lrwxrwxrwx /dev/i2c/5 '/dev/i2c/5' -> '../i2c-5'

I just messed 'spidev' and 'i2c-dev' in previous post, but it doesn't matter. Character device is not sysfs entry.

UPD: I forgot to add /sys/ for path in second code block for ddccontrol, edited. But the result obviously is the same, target is a directory.

Last edited by dimich (2022-08-02 23:58:40)

Offline

#14 2022-08-03 00:05:06

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,061
Website

Re: [solved] How to pin the name of a i2c device

dimich wrote:
Trilby wrote:

That doesn't make much sense as the /dev/i2c-* nodes are just links to the sysfs entries

Are you sure?

No.  Apparently I misread a post by the OP thinking he was responding to my request for information but it may have been a reply to you ... I thought the `ls -l` output in post #5 was for the /dev/i2c-* nodes as this is what I had been asking about, but it seems it was for something else.  Sorry for the noise.

Last edited by Trilby (2022-08-03 00:05:25)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#15 2022-08-03 06:50:24

ctpfaff
Member
Registered: 2017-08-29
Posts: 27

Re: [solved] How to pin the name of a i2c device

Thanks to you both for that elaborate discussion and the examples. There is definitely more to take away from that than just the solution. That is nice.

dimich wrote:

Ah, then it might be simpler without udev. If there is only one i2c-* entry in /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-2/

ddccontrol dev:/dev/$(basename /sys/devices/pci*/*/drm/card0/card0-DP-2/i2c-*) ...

This should work unless you install one more video card.

Very elegant, that works perfectly for now. I will go with that oneliner. Thanks.

Last edited by ctpfaff (2022-08-03 06:51:01)

Offline

Board footer

Powered by FluxBB