Énumération cohérente des périphériques Linux

13

Dans notre boîte Linux, nous avons un périphérique série USB -> qui a toujours été identifié comme /dev/ttyACM0. J'ai donc écrit une candidature et jusqu'à hier, tout s'est bien passé. Mais soudain (ouais, lors de la présentation à distance ...) l'appareil a cessé de fonctionner. Après une recherche rapide, j'ai constaté que la connexion a changé pour /dev/ttyACM1. C'était un peu inopportun, mais maintenant j'ai un problème - comment identifier sans ambiguïté mon appareil? Comme, par exemple, le lecteur de stockage peut être initialisé à l'aide de l'UUID bien que le /dev/sd**ait changé. Existe-t-il un moyen de le faire pour les périphériques série?

Maintenant, j'utilise une solution stupide:

for(int i = 0; i < 10; i ++)
{
    m_port = std::string("/dev/ttyACM") + (char)('0' + i);
    m_fd = open(m_port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
}

Le lien vers l'appareil que nous utilisons.

folibis
la source

Réponses:

19

Puisque nous parlons de périphériques USB et en supposant que vous avez udev, vous pouvez configurer certaines règles udev.

Je suppose, et c'est juste une supposition sauvage, quelqu'un ou quelque chose a débranché / retiré l'appareil et l'a rebranché / ajouté à nouveau l'appareil, ce qui augmente le nombre.

Maintenant, vous devez d'abord avoir les identifiants du fournisseur et du produit:

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 011: ID 0403:6001 FTDI FT232 USB-Serial (UART) IC

Ensuite, vous avez besoin du numéro de série (au cas où vous en auriez plusieurs):

# udevadm info -a -n /dev/ttyUSB1 | grep '{serial}' | head -n1
    ATTRS{serial}=="A6008isP"

Maintenant, créons une règle udev:

Les règles UDEV sont généralement dispersées dans de nombreux fichiers dans /etc/udev/rules.d. Créez un nouveau fichier appelé 99-usb-serial.ruleset mettez la ligne suivante là-dedans, j'ai trois appareils, chacun avec un numéro de série différent:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A6008isP", SYMLINK+="MySerialDevice"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A7004IXj", SYMLINK+="MyOtherSerialDevice"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTDIF46B", SYMLINK+="YetAnotherSerialDevice"

ls -l /dev/MySerialDevice
lrwxrwxrwx 1 root root 7 Nov 25 22:12 /dev/MySerialDevice -> ttyUSB1

Si vous ne voulez pas le numéro de série, tout appareil du fournisseur avec la même puce recevra alors le même lien symbolique, un seul peut être branché à un moment donné.

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="MySerialDevice"

Pris d'ici

la carpe
la source
3
Si vous avez une distribution Linux récente, il est très probable qu'elle crée déjà automatiquement le périphérique en tant que /dev/serial/by-id/usb-XXXX_USB2.0-Serial-if00-port0. Cela pourrait vous suffire sans règles udev personnalisées.
Josef dit Réintégrer Monica
1
Malheureusement, de nombreux appareils sans nom portent tous le numéro de série "0123456789abcdef". C'est là que ça devient intéressant.
Mosvy
@mosvy les numéros de série sont-ils immuables?
OganM
@OganM, ils peuvent être modifiés ... si vous êtes capable de rooter les appareils.
mosvy