mardi 2 juin 2015

souris qui s'endort

Quoi de plus énervant que d'avoir une souris qui s'endort tout le temps: après quelques secondes d'inactivité, il faut chaque fois la réveiller avec un clic.
Essayons de trouver la source du problème.
Utilisons tout d'abord lsusb:

[toto@rigel ~]$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 0461:4d64 Primax Electronics, Ltd 
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
[toto@rigel ~]$ 

La deuxième ligne correspond à notre souris.

Cherchons des infos sur le descripteur de périphérique /dev/bus/usb/002/002

[toto@rigel ~]$ udevadm info /dev/bus/usb/002/002 
P: /devices/pci0000:00/0000:00:02.0/usb2/2-3
N: bus/usb/002/002
E: BUSNUM=002
E: DEVNAME=/dev/bus/usb/002/002
E: DEVNUM=002
E: DEVPATH=/devices/pci0000:00/0000:00:02.0/usb2/2-3
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=USB_Optical_Mouse
E: ID_MODEL_ENC=USB\x20Optical\x20Mouse
E: ID_MODEL_ID=4d64
E: ID_REVISION=0200
E: ID_SERIAL=0461_USB_Optical_Mouse
E: ID_USB_INTERFACES=:030102:
E: ID_VENDOR=0461
E: ID_VENDOR_ENC=0461
E: ID_VENDOR_FROM_DATABASE=Primax Electronics, Ltd
E: ID_VENDOR_ID=0461
E: MAJOR=189
E: MINOR=129
E: PRODUCT=461/4d64/200
E: SUBSYSTEM=usb
E: TYPE=0/0/0
E: USEC_INITIALIZED=201152
[toto@rigel ~]$ 

(En gras ce que nous allons utiliser pour la suite)

Vérifions le contenu du fichier power/control adéquat:

[toto@rigel ~]$ cat /sys/bus/usb/devices/2-3/power/control
auto
[toto@rigel ~]$ 

Sur cette machine, plusieurs distributions sont installées. Cette fois nous sommes dans Manjaro. Pour d'autres distributions où la souris fonctionne correctement, le même fichier contient on.
De ce fait nous essayons

[root@rigel ~]# echo "on" > /sys/bus/usb/devices/2-3/power/control
[root@rigel ~]# 

qui résout instantanément le problème, mais jusqu'au prochain boot seulement

Pour une solution définitive ajoutons la règle

ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0461", ATTR{idProduct}=="4d64", TEST=="power/control", ATTR{power/control}="on"

nommée usb-power.rules dans /etc/udev/rules.d, puis nous redémarrons le système.

Caramba, ça ne fonctionne pas!

Vérifions ce qu'il en est en lançant la commande:

[root@rigel ~]# udevadm test /bus/usb/devices/2-3  2>&1 | grep writing

Nous redirigeons le canal 2 vers le canal 1 afin que tout soit filtré par grep (plus d'infos sur les redirections dans ce billet), car la plus grande partie du flux de sortie de la commande udevadm transite par le canal 2 (qui n'est pas filtré par grep).

Le résultat en image:


Donc power/control est effectivement mis sur on et la souris fonctionne aussitôt la commande exécutée (bien qu'il s'agisse d'un test).
La règle ajoutée joue bien son rôle. Le mystère reste entier.

Cependant:

[root@rigel ~]# udevadm test /bus/usb/devices/2-3  2>/dev/null | tail -1
run: 'lmt-udev force modules=runtime-pm devices=2-3'
[root@rigel ~]# 

Le responsable ne serait-il pas lmt-udev qui s'exécute en dernier, après application de toutes les règles?
Si lmt-udev est le responsable, pourquoi cette fois la souris ne s'endort elle plus?
Mais sans doute parce-qu'il s'agit d'un test et que lmt-udev n'est pas exécuté.
D'ailleurs nous sommes prévenu:

[root@rigel ~]# udevadm test /sys/bus/usb/devices/2-3 2>/dev/null | head -3
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

D'autre part:

[toto@rigel ~]$ udevadm test /sys/bus/usb/devices/2-3  2>&1 1>/dev/null | grep 'RUN'
RUN 'lmt-udev force modules=runtime-pm devices=%k' /usr/lib/udev/rules.d/99-laptop-mode.rules:3
toto@rigel ~]$ awk 'NR==3' /usr/lib/udev/rules.d/99-laptop-mode.rules
ACTION=="add|remove", SUBSYSTEM=="usb", RUN+="lmt-udev force modules=runtime-pm devices=%k"

/usr/lib/udev/lmt-udev est bien un programme spécifié par une clef RUN (règle 3 de 99-laptop-mode.rules). C'est un script qui appelle /usr/bin/laptop_mode.
Après quelques recherches nous trouvons le fichier /etc/laptop-mode/conf.d/runtime-pm.conf dans lequel nous pouvons mettre notre souris sur une blacklist:

# The list of Device IDs that should not use autosuspend. Use system commands or
# look into sysfs to find out the IDs of your devices.
# Example: AUTOSUSPEND_DEVID_BLACKLIST="046d:c025 0123:abcd"
AUTOSUSPEND_RUNTIME_DEVID_BLACKLIST="0461:4d64"

Dans le même fichier on pourrait à la place blacklister le pilote usb:

# The list of device driver types that should not use autosuspend.  The driver
# type is given by "DRIVER=..." in a device's uevent file.
# Example: AUTOSUSPEND_DEVID_BLACKLIST="usbhid usb-storage"
AUTOSUSPEND_RUNTIME_DEVTYPE_BLACKLIST="usb"


Le problème est résolu!