Forum Linux.embarqué Créer udev rule pour périphérique USB avec plusieurs ports virtuels

Posté par  . Licence CC By‑SA.
Étiquettes :
1
15
juin
2023

Hello Linux community,

Dans le cadre de mon travail sous linux avec différents device USB, je me retrouve à écrire des udev rules afin d'éviter de vérifier le port USB du device à chaque pluggin et de l'ajuster dans le code.

Dans ce processus, un certain périphérique me pose problème car il a deux ports virtuels (config et data), et lorsque je fais mes rules standard, je ne crée qu'un port équivalent au port config, donc le port data est comme ignoré.

Quelqu'un a déjà testé des trucs la dessus ? Une aide peut être ?

Merci,
Lilia

  • # C'est censé être possible

    Posté par  (Mastodon) . Évalué à 5.

    Je bosse sur des appareils qui ont 3 ports UART sur un seul connecteur, je n'ai aucune difficulté à faire des règles udev.

    Mais comme ça sans donner d'exemples ça va être compliqué de t'aider.

    • Comment se déclarent les ports point de vue du kernel ? (lsusb, dmesg…)
    • Quelles règles as-tu tenté jusqu'ici ?
    • Et je te donne mes deux commandes magiques qui me servent à écrire les règles :
      • udevadm info --query=property --name /dev/ttyUSB2
      • udevadm info --attribute-walk --name /dev/ttyUSB2

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: C'est censé être possible

      Posté par  . Évalué à 2.

      Bon conseils.

      Auxquels j'ajoute ma faible expérience perso.

      • facile avec des interfaces réseau, grâce à l'adresse MAC

      • j'ai utilisé pas mal d'adaptateurs USB/Séries-USART. Et tous ne sont pas égaux. Les meilleurs sont les FTDI, parce que chaque device a son n° de série, utilisable dans une règle udev. Les autres, Prolific, CH34x … Rien, impossible d'en distinguer deux identiques

      Je plussois donc le commentaire précédent : utiliser les lsusb et udevadm pour trouver la propriété qui permettra d'identifier le device dans une règle. Sinon, pleurer … Ou, mais ça peut être pénible ou impossible :

      1. identifier les deux ports, sans savoir au préalable lequel est config, lequel est data
      2. tenter une communication sur chacun, par une commande d'identification avec un retour particulier

      J'ai "rencontré" quelques appareils de mesure de labo qui répondaient à la commande "*IDN?" qui semble plutôt fréquente dans le domaine.

  • # C'est possible

    Posté par  (site web personnel) . Évalué à 4.

    Je ne suis pas certain de ce que tu entends par « je ne crée qu'un port équivalent au port config ». J'imagine que ça peut signifier créer un lien symbolique sous /dev pour ce port en question ?

    Quoi qu'il en soit, c'est une problématique très classique dans la gestion des modems et des équipements type liaison série. Dans le premier cas, il y a des ports de gestion/commandes AT, des ports de données, etc. La règle (udev) numéro 1, c'est de regarder ce que font les autres règles (/lib/udev/rules.d/*.rules me dépanne 75 % du temps).

    Si tu cherches principalement à peupler /dev, tu peux discriminer entre les ports via le numéro d'interface. Exemple :

    SUBSYSTEMS=="usb", ENV{.LOCAL_ifNum}="$attr{bInterfaceNumber}"
    SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ACTION=="add", \
            ATTRS{idVendor}=="<foo id>", ATTRS{idProduct}=="<bar id>", ATTRS{product}=="Foo Bar Config port", \
            ENV{.LOCAL_ifNum}=="00", SYMLINK+="foo-bar-config%s{devpath}", GROUP="if-you-need-it", MODE="0666"
    SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ACTION=="add", \
            ATTRS{idVendor}=="<foo id>", ATTRS{idProduct}=="<bar id>", ATTRS{product}=="Foo Bar Data port", \
            ENV{.LOCAL_ifNum}=="01", SYMLINK+="foo-bar-data%s{devpath}", GROUP="if-you-need-it", MODE="0666"
    

    Après bien sûr, on peut faire des choses plus avancées :

    • ajouter des métadonnées via l'environnement pour faire des recherches faciles depuis udevadm ou les API udev : ENV{VARIABLE1}="valeur1" (on peut en mettre plusieurs).
    • taguer un port (ou plusieurs) avec systemd et ajouter une référence vers une unité systemd pour qu'elle donne lieu au lancement automatique d'une unité : TAG+="systemd", ENV{SYSTEMD_WANTS}="unit-for-foo-bar@foo-bar-config-%s{devpath}.service". Une des subtilités ici est de savoir si on veut une unité par port ou une par device. Dans le second cas, une fois les liens symboliques en place, c'est plutôt facile de passer d'un port à un autre… C'est ce que j'ai privilégié sur un projet client, cela signifie une seule unité à surveiller, et pas d'interaction entre deux unités « sœurs » à gérer.

    Attention à la gestion du hotplug : en fonction du matériel, on peut avoir besoin d'accepter d'autres valeurs qu'add pour ACTION (par exemple add|change|move|bind, vu pour des modems).

    Debian Consultant @ DEBAMAX

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.