Changer la source de l'écran programmatiquement sur Linux

mardi 20 février 2024 · 4 minutes · 752 mots

J’ai un switch clavier/souris/écran pour connecter 2 PC : un sous Linux et un sous Windows.

Quand je connecte tous les ports, cela fonctionne, mais à chaque bascule vers le laptop Windows, j’ai une reconfiguration de l’écran, mes fenêtres sont déplacées et cela m’énerve. Le switch fait comme si j’avais débranché/rebranché l’écran physiquement et Windows se sent obligé d’adapter toute la disposition !

Pour régler ce problème, j’ai enlevé la connexion de l’écran du switch et branché les 2 ordinateurs sur les 2 sources de l’écran (HDMI 1 et 2) : ok, Windows ne me rechange pas toutes mes fenêtres quand je bascule dessus, mais maintenant, je dois basculer à la fois sur le switch pour avoir mon clavier et ma souris, et je dois aussi changer manuellement la source de l’écran pour passer du HDMI 1 vers le 2. Et vice-et-versa quand je retourne sur mon Linux !

Il me fallait un moyen de basculer la source de l’écran en même temps que je basculais le switch. Genre, un truc qui détecte que je switch et hop, change la source de l’écran pour moi.

Ça doit être possible sur Linux ?

Et bien oui, c’est possible.

Sous Linux, on a un utilitaire ddcutil qui permet de “dialoguer” avec l’écran et de lui envoyer des ordres (comme changer la source).

Voici la commande pour changer la source :

sudo ddcutil setvcp 60 x

où x correspond à la valeur hexadécimale de la source et le 60 correspond à la fonctionnalité de changement de source.

D’après les résultats de ddcutil capabilities, j’étais censé utiliser les valeurs 11 pour HDMI 1, 12 pour HDMI 2 et 0F pour le display port.

sudo ddcutil capabilities
...
   Feature: 60 (Input Source)
      Values:
         11: HDMI-1
         12: HDMI-2
         0f: DisplayPort-1
...

(J’ai omis les autres informations fournies par la commande pour ne focaliser que sur la source de l’écran)

En réalité, les valeurs 11 et 12 ne donnaient rien. J’ai testé toutes les valeurs de x0f et en descendant, jusqu’à obtenir une réaction de l’écran.

Et pour moi, c’était respectivement 5 et 6 pour HDMI 1 et HDMI 2.

Donc, pour passer sur le HDMI 1, je devais faire

sudo ddcutil setvcp 60 x5

et pour le HDMI 2 :

sudo ddcutil setvcp 60 x6

Pour préparer la suite, je crée 2 fichiers scripts avec ces commandes.

Le premier, que je nomme set-hdmi1.sh est le script qui change la source de l’écran vers HDMI 1 :

#!/bin/sh
# set input source to HDMI 1
sudo ddcutil setvcp 60 x5 --display 2

Je n’oublie pas de rendre exécutable ce script :

chmod a+x /usr/local/bin/set-hdmi1.sh

Le deuxième, set-hdmi2.sh est le script qui change la source de l’écran vers HDMI 2 :

#!/bin/sh
# set input source to HDMI 2
sudo ddcutil setvcp 60 x6 --display 2

Et je le rend exécutable :

chmod a+x /usr/local/bin/set-hdmi2.sh

Ok, maintenant que ça fonctionne, je dois détecter le switch clavier.

Linux permet de réagir à des modifications matérielles et de lancer ses propres actions, grâce à udev. On peut par exemple faire une action si on branche ou on débranche un clavier.

Pour cela, on doit cibler le bon matériel, et cela passe par trouver les ses identifiants. La commande lsusb me liste tous les appareils connectés en USB sur mon Linux, mais je ne m’intéresse qu’aux claviers, d’où le filtre par la commande grep.

lsusb | grep -i key
Bus 001 Device 039: ID 04d9:0295 Holtek Semiconductor, Inc. USB-HID Keyboard

Les valeurs importantes sont juste après le ID :

  • 04d9 identifie le vendeur
  • 0295 le produit

Ensuite, je crée un nouveau fichier de règles udev, par exemple 99-kvm.rules dans le dossier /etc/udev/rules.d avec le contenu suivant :

ACTION=="remove", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="0295", RUN+="/usr/local/bin/set-hdmi2.sh"
ACTION=="add", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="0295", RUN+="/usr/local/bin/set-hdmi1.sh"
  • ACTION me permet de réagir, soit au retrait du clavier (action ‘remove’, je bascule vers HDMI 2), soit à son insertion (action ‘add’, je bascule vers HDMI 1).

  • Ensuite, j’identifie mon matériel grâce aux valeurs notées plus haut, pour les attributs idVendor et idProduct.

  • Enfin, j’exécute le bon script.

C’est presque terminé : si on veut que ces règles soient prises en compte immédiatement (plutôt qu’au prochain reboot), on peut lancer les commandes suivantes :

sudo udevadm control --reload-rules && sudo udevadm trigger

Et voilà ! Maintenant, j’appuie sur le switch clavier pour changer la source de l’écran et Windows reste tranquille ! Merci Linux !

Remarque : la prochaine fois que je change le KVM, j’en prends un basic qui ne fait que clavier et souris :-)

kvm linux howto