Como vincular um dispositivo USB a um nome estático?

43

Eu tenho um Arduino que às vezes fica vinculado /dev/ttyUSB0e outras vezes /dev/ttyUSB1, fazendo com que meu script falhe.

Eu não quero enumerar todas as possibilidades de onde meu dispositivo pode estar, mas prefiro que ele esteja vinculado a algum lugar estático, por exemplo /dev/arduino.

Como faço para conseguir isso?

k0pernikus
fonte
4
Basta escrever uma regra simples do udev que atribuirá o symlink / dev / arduino ao dispositivo correto pelo seu VID e PID.
Eddy_Em
1
Depois de alterar as regras, consulte Como recarregar as regras do udev sem reiniciar?
Gilles 'SO- stop be evil'

Respostas:

41

Como sugerido, você pode adicionar algumas regras do udev. Eu editei o /etc/udev/rules.d/10-local.rulespara conter:

ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="my_uart"

Você pode verificar as variáveis ​​do seu dispositivo executando

udevadm info -a -p  $(udevadm info -q path -n /dev/ttyUSB0)

Há um guia mais detalhado que você pode ler em http://www.reactivated.net/writing_udev_rules.html

Kotte
fonte
Funcionou como um encanto. Uma pergunta: como sair udevam? E é importante observar que my_uartcria o link simbólico abaixo /dev/my_uart. Eu escrevi /dev/arduinopela primeira vez e falhou enquanto arduinoé suficiente.
precisa saber é o seguinte
udevadmdeve sair por si só quando terminar.
Kotte
Por algum motivo desconhecido, congelou a sessão do terminal no meu Raspberry Pi enquanto gerava o relatório.
K0pernikus 08/03
35

A sintaxe da regra acima pode funcionar em algumas distribuições, mas não na minha (Raspbian). Como nunca encontrei um único documento que explique todos os detalhes, escrevi o meu, para ser encontrado aqui . É para isso que tudo se resume.
1. descubra o que está no ttyUSB:

dmesg | grep ttyUSB  

2. liste todos os atributos do dispositivo:

udevadm info --name=/dev/ttyUSBx --attribute-walk

(com o (s) número (s) do seu dispositivo em vez de x, é claro). Escolha um conjunto de identificadores exclusivo, por exemplo, idVendor + idProduct. Você também pode precisar de SerialNumber se tiver mais de um dispositivo com o mesmo idVendor e idProduct. Os números de série devem ser exclusivos para cada dispositivo.
3. Crie um arquivo /etc/udev/rules.d/99-usb-serial.rulescom algo como esta linha:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", SYMLINK+="your_device_name" 

(supondo que você não precise de um número de série e, é claro, com os números de idVendor e idProduct que você encontrou na etapa 2.
4. Carregue a nova regra:

sudo udevadm trigger

5. Verifique o que aconteceu:

ls -l /dev/your_device_name  

mostrará para qual número ttyUSB o link simbólico foi. Se for /dev/ttyUSB1, verifique quem é o proprietário e a qual grupo pertence:

ls -l /dev/ttyUSB1   

Então, apenas por diversão:

udevadm test -a -p  $(udevadm info -q path -n /dev/your_device_name)
RolfBly
fonte
Então, existe alguma solução se o idVendore idProductfor exatamente o mesmo? (dois sensores ligados em modelo USB idênticos aos módulos UART)
Steven Lu
@StevenLu Sim, consulte a etapa 2, faça udevadm info --name=/dev/ttyUSB1 --attribute-walkpara ambos os dispositivos e procure números de série, eles devem ser exclusivos para cada dispositivo. Se seus sensores não tiverem número de série, você pode especificar o que são?
RolfBly
isso é incrível, eu vou relatar de volta quando eu tentar fazer isso
Steven Lu
Meus dongles de USB para UART de US $ 2 têm o número de série 0001. Não posso dizer que estou surpreso. Parece que eu tenho que identificar os sensores com base em seu protocolo de saída.
Steven Lu
@StevenLu Bad luck. Os conversores USB-UART da FTDI possuem um número de série exclusivo, AFAIK. Alguns dólares extras, mas menos tempo para se desenvolver.
RolfBly
9

O problema de vários dispositivos USB idênticos

Eu tenho um Rasperry Pi com quatro câmeras. Eu tomo pix com fswebcamque identifica as câmeras como /dev/video0.. video3. Às vezes, a câmera é video0, vide02, video4e video6mas podemos esquecer que, por enquanto.

Eu preciso de um ID persistente para identificar um número de câmera, de modo que, por exemplo, video0seja sempre a mesma câmera, porque eu legendo as fotos. Infelizmente, isso não acontece de maneira confiável - na inicialização, as câmeras são enumeradas como video0... video3mas nem sempre da mesma maneira.

As câmeras têm o mesmo ID e número de série.

A solução para esse problema envolve regras do udev, mas também existem muitos anzóis.

Se você emitir o comando

udevadm info –attribute-walk –path=/dev/video0

você obtém uma mesa de saída, mas os bits salientes são

KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.

O bit KERNELS é uma porta de hub USB. Com quatro câmeras, há quatro delas - elas não mudam na reinicialização, mas a video{x}associada a uma porta pode mudar.

Portanto, precisamos de uma regra do udev para vincular um número de vídeo a uma porta de hub USB - algo como:

KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0” 

Parece simples - acesse a câmera com

fswebcam –d  $realpath /dev/camera0

Exceto que não funciona - se você colocar isso em uma regra do udev e o sistema tiver alocado video0 (na inicialização) para uma porta diferente, a regra do udev será ignorada. O link simbólico para /dev/camera0basicamente diz no such device. Quadrado um.

O que queremos é vincular um link simbólico a um endereço de hub USB, não a um video{x}número. Foi necessário um programa Python.

O primeiro passo foi correr

fswebcam –d /dev/video${x}  tst.jpg

para xentre 1 e 8. A existência de tst.jpgapós cada chamada identifica a existência de uma câmara nesta número de vídeo. A partir disso, faça uma lista dos números de vídeo ativos. Minha experiência tem sido que é tanto 0,1,2,3ou 0,2,4,6para câmeras que tenho usado.

Outros podem, é claro, criar essa lista usando um processo diferente.

Em seguida, para cada número de vídeo na lista, execute

udevadm info –attribute-walk –path=/dev/videox > dd

e extraia o KERNELS= linede dd. Nesse processo, você acaba com uma lista dos endereços de porta USB das câmeras. Classifique esta lista para que, na próxima etapa, você sempre a processe na mesma ordem. Chame isso de "lista de endereços".

Execute a udevadm … > ddcoisa novamente e faça uma lista que se parece com

KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.

Agora, percorra a lista de endereços - para cada entrada, encontre a entrada correspondente na lista de vídeos. Crie uma nova lista que se pareça com uma coleção de linhas como

KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”

O x (número do link simbólico) é substituído pelo número de sequência na lista de endereços.

Agora você tem uma regra do udev que funciona. Um link simbólico vinculado a um endereço de hub USB, independentemente do número de vídeo atribuído a essa porta na inicialização.

Escreva a lista final em um arquivo /etc/udev/rules.d/cam.rules. Execute udevadm triggerpara ativá-lo e o trabalho está concluído. /dev/camera2será a mesma câmera (porta USB), independentemente do número de vídeo.

Ian Boag
fonte
Bem-vindo ao unix stackexchange. Formate sua resposta usando remarcação. Eu apenas fiz isso por você. Lembre-se também de que queremos que as respostas sejam objetivas. Isso parece mais uma entrada de blog (que não é totalmente ruim), mas não é tão útil ler primeiro sobre abordagens que não funcionaram. Você pode descartar essa parte.
K0pernikus
Desculpe. Eu sou novo aqui. Eu pesquisei esse problema por meses. Encontrei outras pessoas com o mesmo problema e não encontrei uma resposta que funcionasse para mim. Só para eu saber, onde você recomendaria que eu publicasse algo assim? Eu me contive e não incluir a fonte Python :-)
Ian Boag
1

Eu também consegui encontrar um dispositivo exclusivo no /dev/serial/by-id. Ainda não tentei reiniciar, mas os arquivos nesse diretório eram apenas links para o arquivo de dispositivo apropriado ( ttyACM[0-9]).

Estou executando o arch linux no Raspberry Pi, mas me deparei com eles apenas fazendo um findpara nomes de arquivos que contêm "Arduino". Meus programas python funcionam bem usando esses arquivos como dispositivos para ler / gravar dados de / para meus Arduinos (até agora, dois em um único Pi).

huey_driver
fonte
0

Apenas para dizer que o acima funcionou para mim e também montou automaticamente o dispositivo para mim depois que eu coloquei uma entrada no / etc / fstab (e também chama umount após remover o stick)

ie

/ etc / fstab

# See /etc/udev/rules.d/5-usb-disk.rules
/dev/backup     /vol/backup     ext4    defaults,errors=remount-ro 0       1

cat /etc/udev/rules.d/5-usb-stick.rules

#
# the next line creates a symlink to this disk drive called /dev/backup 
# i.e.
#   root:# ls -la /dev/backup 
#   lrwxrwxrwx 1 root root 3 Jul 22 19:33 /dev/backup -> sg0

# Backup usb stick - create /dev/backup
# ATTRS{model}=="Cruzer Blade    "
ACTION=="add", ATTRS{model}=="Cruzer Blade    ", SYMLINK+="backup"

# Clean up after removal  
ACTION=="remove", ATTRS{model}=="Cruzer Blade    ", RUN+="/bin/umount /vol/backup"

Então, depois de inserir meu pendrive, recebo:

root:# mount | grep sd
/dev/sda1 on /vol/backup type ext4 (rw,relatime,errors=remount-ro,data=ordered)
Vai
fonte