Un ‘notificateur’ en USB
Alors qu’il fouillait « L’Armoire à Goodies » à la recherche de cadeaux pour les Auditeurs, Yann de Futuradios a exhumé une espèce de boite en forme d’enveloppe connectable en USB qui s’allume pour notifier de la présence de messages (mail, réseaux réseaux sociaux)…
Yann a donné le gadget en question à mon fils Yvan pour voir s’il y a moyen de l’utiliser à la radio, par exemple pour afficher en studio l’arrivée d’une dédicace.
Bien que le gadget ci-dessous soit à la base de cet article les concepts sont utilisables avec la LED située sur la carte du Raspberry ou avec un autre gadget.
La « chose » est fournie avec un mini cdrom contenant un logiciel dédié fonctionnant sous Windows, je ne l’ai pas installé puisqu’il s’agit de l’utiliser sur un des Raspberry Pi installés dans le studio…
Je m’attendais à ce que la « chose » soit reconnue comme un HID (Human Interface Device) et j’avais commencé à me documenter sur le sujet… C’est donc en m’attendant au pire que j’ai branché le connecteur USB. La commande ‘dmesg’ renvoie ceci:
[ 218.872752] usb 1-1.4: new low-speed USB device number 5 using dwc_otg [ 219.014859] usb 1-1.4: New USB device found, idVendor=1294, idProduct=1320 [ 219.014877] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 219.014888] usb 1-1.4: Product: MAIL [ 219.014901] usb 1-1.4: Manufacturer: MAIL [ 219.026698] hid-led 0003:1294:1320.0002: hidraw0: USB HID v1.10 Device [MAIL MAIL ] on usb-3f980000.usb-1.4/input0 [ 219.027199] hid-led 0003:1294:1320.0002: Riso Kagaku Webmail Notifier initialized
On voit la séquence classique de connexion d’un équipement USB et « Ô Surprise » on voit également que le driver ‘hid-led’ a reconnu notre appareil… Le code du driver est disponible sur github hid-led.c
Dans /sys/class/leds on retrouve les 2 LED présentes sur le Raspberry et 3 LED ‘riso_kagaku0’, une pour chaque couleur RGB, chacun de ces liens pointant vers un répertoire. Notez au passage la numérotation des LED.
pi@raspberrypi:~ $ cd /sys/class/leds/ pi@raspberrypi:~ $ ls -l /sys/class/leds total 0 lrwxrwxrwx 1 root root 0 May 6 20:55 led0 -> ../../devices/platform/leds/leds/led0 lrwxrwxrwx 1 root root 0 May 6 20:55 led1 -> ../../devices/platform/leds/leds/led1 lrwxrwxrwx 1 root root 0 May 6 20:55 riso_kagaku0:blue -> ../../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:1294:1320.0003/leds/riso_kagaku0:blue lrwxrwxrwx 1 root root 0 May 6 20:55 riso_kagaku0:green -> ../../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:1294:1320.0003/leds/riso_kagaku0:green lrwxrwxrwx 1 root root 0 May 6 20:55 riso_kagaku0:red -> ../../devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:1294:1320.0003/leds/riso_kagaku0:red
Dans le répertoire correspondants aux LED deux fichiers sont intéressants, il s’agit de ‘brightness’ et ‘max_brightness’, qui vont permettre de positionner la luminosité et de connaître la valeur maximale de la luminosité.
pi@raspberrypi:~ $ ls -l /sys/class/leds/riso_kagaku0\:green/ total 0 -rw-r--r-- 1 root root 4096 May 7 19:26 brightness lrwxrwxrwx 1 root root 0 May 7 19:26 device -> ../../../0003:1294:1320.0003 -r--r--r-- 1 root root 4096 May 7 19:26 max_brightness drwxr-xr-x 2 root root 0 May 7 19:26 power lrwxrwxrwx 1 root root 0 May 7 19:26 subsystem -> ../../../../../../../../../../../class/leds -rw-r--r-- 1 root root 4096 May 7 19:26 trigger -rw-r--r-- 1 root root 4096 May 6 19:39 uevent
Dans le cas de notre gadget la luminosité maximale est de 1, il est possible de positionner et de relire la luminosité. Les LED sur la carte du Raspberry ont un max_brightness à 255.
pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:green/max_brightness 1 pi@raspberrypi:~ $ cat /sys/class/leds/led0/max_brightness 255 pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:green/brightness 0 pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:green/brightness 1 pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:green/brightness 1
Nous avons allumé la LED verte (‘green’), visiblement il y a un petit soucis (et pas uniquement lié à mon daltonisme)… Le bleu et le vert sont inversés:
En fait le problème de ces gadgets est qu’il existe de nombreuses contrefaçons, pardon, de nombreux modèles ressemblants. D’ailleurs dans le code du driver, on trouve les lignes suivantes qui sont intéressantes:
static bool riso_kagaku_switch_green_blue; module_param(riso_kagaku_switch_green_blue, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(riso_kagaku_switch_green_blue, "switch green and blue RGB component for Riso Kagaku devices"); [.../...] if (riso_kagaku_switch_green_blue) return RISO_KAGAKU_IX(r, b, g); else return RISO_KAGAKU_IX(r, g, b);
Ce paramètre est visible par la commande ‘modinfo’:
pi@raspberrypi:~ $ modinfo hid-led filename: /lib/modules/4.14.79-v7+/kernel/drivers/hid/hid-led.ko description: Simple USB RGB LED driver author: Heiner Kallweitlicense: GPL srcversion: BB1E27E615F4DDF35EBB58E alias: hid:b0003g*v000004D8p0000F372 alias: hid:b0003g*v00000FC5p0000B080 alias: hid:b0003g*v000027B8p000001ED alias: hid:b0003g*v00001D34p0000000A alias: hid:b0003g*v00001D34p00000004 alias: hid:b0003g*v00001294p00001320 depends: intree: Y name: hid_led vermagic: 4.14.79-v7+ SMP mod_unload modversions ARMv7 p2v8 parm: riso_kagaku_switch_green_blue:switch green and blue RGB component for Riso Kagaku devices (bool)
Nous pouvons consulter et modifier la valeur de ce paramètre pour vérifier que notre gadget affiche la bonne couleur.
pi@raspberrypi:~ $ cat /sys/module/hid_led/parameters/riso_kagaku_switch_green_blue N pi@raspberrypi:~ $ echo Y | sudo tee /sys/module/hid_led/parameters/riso_kagaku_switch_green_blue Y pi@raspberrypi:~ $ cat /sys/module/hid_led/parameters/riso_kagaku_switch_green_blue Y pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:green/brightness 1 pi@raspberrypi:~ $ echo 0 | sudo tee /sys/class/leds/riso_kagaku0\:green/brightness 0 pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:blue/brightness 1
Le problème c’est qu’à chaque redémarrage du Rasperry les couleurs vont être inversées, ‘hid_led’ étant un module kernel comme un autre il est possible de fixer ses paramètres de la même manière:
pi@raspberrypi:~ $ cat << EOF | sudo tee /etc/modprobe.d/hid_led.conf options hid_led riso_kagaku_switch_green_blue=Y EOF pi@raspberrypi:~ $ sudo rmmod hid_led pi@raspberrypi:~ $ sudo modprobe hid_led pi@raspberrypi:~ $ cat /sys/module/hid_led/parameters/riso_kagaku_switch_green_blue Y pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:green/brightness
Un petit 'goodie' au passage, une commande pour afficher la valeur courante des 3 couleurs:
pi@raspberrypi:~ $ for c in red green blue ; do echo -n "$c: " ; cat /sys/class/leds/riso_kagaku0\:$c/brightness; done red: 0 green: 0 blue: 1
Vous avez certainement remarqué un fichier appelé 'trigger' dans le répertoire de chacune des LED, il permet de faire gérer la LED automatiquement par le système en fonction d'un déclencheur. Les divers déclencheurs sont listés ci-dessous. Celui entre crochets est le déclencheur actif (ici 'none' c'est à dire aucun):
pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/trigger [none] rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot heartbeat backlight gpio cpu cpu0 cpu1 cpu2 cpu3 default-on input panic mmc0 rfkill-any
Les déclencheurs sont les suivants
- rc-feedback: l'état du récepteur de télécommande infrarouge si le Raspberry en est équipé (cas des media-centers par exemple)
- kbd: l'état du clavier
- timer: faire clignoter la LED
- oneshot: allumer la LED un temps donné
- heartbeat: faire clignoter la LED comme un battement de coeurs
- cpu: activité des CPU
- panic: en cas de kernel panic
- mmc0: activité de la carte mémoire du Raspberry Pi
- rfkill-any: mode avion
La sélection d'un déclencheur peut faire apparaître de nouveaux fichiers dans le répertoire de la LED concernée, c'est le cas du déclencheur 'timer' par exemple, deux nouveaux fichiers 'delay_off' et 'delay_on' permettent de spécifier les temps d'allumage et d'extinction en millisecondes:
pi@raspberrypi:~ $ echo none | sudo tee /sys/class/leds/riso_kagaku0\:red/trigger none pi@raspberrypi:~ $ ls -l /sys/class/leds/riso_kagaku0\:red/ total 0 -rw-r--r-- 1 root root 4096 May 8 14:09 brightness lrwxrwxrwx 1 root root 0 May 8 14:09 device -> ../../../0003:1294:1320.0005 -r--r--r-- 1 root root 4096 May 8 14:09 max_brightness drwxr-xr-x 2 root root 0 May 8 14:09 power lrwxrwxrwx 1 root root 0 May 8 14:09 subsystem -> ../../../../../../../../../../../class/leds -rw-r--r-- 1 root root 4096 May 8 14:11 trigger -rw-r--r-- 1 root root 4096 May 8 14:09 uevent pi@raspberrypi:~ $ echo timer | sudo tee /sys/class/leds/riso_kagaku0\:red/trigger timer pi@raspberrypi:~ $ ls -l /sys/class/leds/riso_kagaku0\:red/ total 0 -rw-r--r-- 1 root root 4096 May 8 14:09 brightness -rw-r--r-- 1 root root 4096 May 8 14:11 delay_off -rw-r--r-- 1 root root 4096 May 8 14:11 delay_on lrwxrwxrwx 1 root root 0 May 8 14:09 device -> ../../../0003:1294:1320.0005 -r--r--r-- 1 root root 4096 May 8 14:09 max_brightness drwxr-xr-x 2 root root 0 May 8 14:09 power lrwxrwxrwx 1 root root 0 May 8 14:09 subsystem -> ../../../../../../../../../../../class/leds -rw-r--r-- 1 root root 4096 May 8 14:11 trigger -rw-r--r-- 1 root root 4096 May 8 14:09 uevent pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/delay_on 500 pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/delay_off 500 pi@raspberrypi:~ $ echo 100 | sudo tee /sys/class/leds/riso_kagaku0\:red/delay_on 100
Dans le cas du déclencheur 'heartbeat' il est possible d'inverser le battement de coeur (deux extinctions rapides au lieu de deux allumages rapides):
pi@raspberrypi:~ $ echo heartbeat | sudo tee /sys/class/leds/riso_kagaku0\:red/trigger heartbeat pi@raspberrypi:~ $ ls -l /sys/class/leds/riso_kagaku0\:red/ total 0 -rw-r--r-- 1 root root 4096 May 8 14:09 brightness lrwxrwxrwx 1 root root 0 May 8 14:09 device -> ../../../0003:1294:1320.0005 -rw-r--r-- 1 root root 4096 May 8 14:22 invert -r--r--r-- 1 root root 4096 May 8 14:09 max_brightness drwxr-xr-x 2 root root 0 May 8 14:09 power lrwxrwxrwx 1 root root 0 May 8 14:09 subsystem -> ../../../../../../../../../../../class/leds -rw-r--r-- 1 root root 4096 May 8 14:22 trigger -rw-r--r-- 1 root root 4096 May 8 14:09 uevent pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/invert 0 pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:red/invert 1
Vous pouvez expérimenter le déclencheur 'oneshot':
pi@raspberrypi:~ $ ls -l /sys/class/leds/riso_kagaku0\:red/ total 0 -rw-r--r-- 1 root root 4096 May 8 14:09 brightness -rw-r--r-- 1 root root 4096 May 8 14:25 delay_off -rw-r--r-- 1 root root 4096 May 8 14:25 delay_on lrwxrwxrwx 1 root root 0 May 8 14:09 device -> ../../../0003:1294:1320.0005 -rw-r--r-- 1 root root 4096 May 8 14:25 invert -r--r--r-- 1 root root 4096 May 8 14:09 max_brightness drwxr-xr-x 2 root root 0 May 8 14:09 power --w------- 1 root root 4096 May 8 14:25 shot lrwxrwxrwx 1 root root 0 May 8 14:09 subsystem -> ../../../../../../../../../../../class/leds -rw-r--r-- 1 root root 4096 May 8 14:25 trigger -rw-r--r-- 1 root root 4096 May 8 14:09 uevent pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/delay_off 100 pi@raspberrypi:~ $ cat /sys/class/leds/riso_kagaku0\:red/delay_on 100 pi@raspberrypi:~ $ echo 1 | sudo tee /sys/class/leds/riso_kagaku0\:red/shot 1
Il existe de nombreux autres gadgets similaires... A vous de vous amuser avec.