No Linux, qual é a melhor maneira para um programa detectar quando "um evento" acontece que altera as atribuições de ttys para dispositivos USB?
Especificamente, tenho uma caixa Linux com alguns dispositivos conectados (nesse caso, um dongle USB Zigbee 3.0 e um adaptador serial RS232). Por um motivo desconhecido ( dmesg
saída incluída abaixo), o dispositivo USB para o adaptador serial simplesmente mudou de /dev/ttyUSB1 para /dev/ttyUSB2.
Meu aplicativo precisa fechar o primeiro dispositivo e reabrir o novo dispositivo, mas não tenho uma boa maneira de detectar que isso ocorreu. Eu executo meu aplicativo como um usuário regular (não root), embora o usuário seja group dialout
, portanto, por padrão, ele tem permissões para abrir/escrever em dispositivos /dev/tty...
Existe uma maneira padrão para um usuário não root ser notificado quando ocorrerem alterações no USB?
Caso contrário, a mesma pergunta vale para o root? - neste caso, criarei um processo daemon apenas para encaminhar a notificação.
saída dmesg:
[379860.188382] usb usb1-port1: disabled by hub (EMI?), re-enabling...
[379860.188447] usb 1-1: USB disconnect, device number 4
[379860.190728] usb 1-1: failed to send control message: -19
[379860.191332] ch341-uart ttyUSB1: ch341-uart converter now disconnected from ttyUSB1
[379860.191370] ch341 1-1:1.0: device disconnected
[379860.471428] usb 1-1: new full-speed USB device number 5 using ohci-pci
[379860.672320] usb 1-1: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.54
[379860.672334] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[379860.672338] usb 1-1: Product: USB2.0-Ser!
[379860.675389] ch341 1-1:1.0: ch341-uart converter detected
[379860.693520] usb 1-1: ch341-uart converter now attached to ttyUSB1
[568726.990913] usb usb1-port1: disabled by hub (EMI?), re-enabling...
[568726.990978] usb 1-1: USB disconnect, device number 5
[568726.992847] usb 1-1: failed to send control message: -19
[568726.993907] ch341-uart ttyUSB1: ch341-uart converter now disconnected from ttyUSB1
[568726.993938] ch341 1-1:1.0: device disconnected
[568727.270327] usb 1-1: new full-speed USB device number 6 using ohci-pci
[568727.467843] usb 1-1: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.54
[568727.467856] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[568727.467860] usb 1-1: Product: USB2.0-Ser!
[568727.470926] ch341 1-1:1.0: ch341-uart converter detected
[568727.489050] usb 1-1: ch341-uart converter now attached to ttyUSB2
Observação: até onde sei, nada aconteceu com esta caixa, ela estava parada (sem supervisão) na mesa e funcionando bem por pelo menos 24 horas, então esse "evento" ocorreu.
Não há um hub externo, ambos os cabos USB são conectados na parte traseira da caixa. Sei que há um chip "hub USB" dentro da maioria dos PCs, então é provável que seja a isso que o dmesg
esteja se referindo.
Na pior das hipóteses, provavelmente posso:
- Identifique a falha de gravação dentro do meu aplicativo.
- Listar todos os dispositivos /dev/tty...
- Use
udevadm
para identificar cada tty. - Reconecte-se ao correto.
Estou apenas perguntando para ver se há algo melhor (ou seja, ser notificado imediatamente em vez de esperar a próxima gravação para detectar a falha).
Talvez seja melhor não usar os
/dev/ttyUSB
nomes, mas sim usar o ID do dispositivo.Por exemplo, se eu olhar na minha máquina:
Podemos ver que tenho duas portas seriais USB visíveis; atualmente elas são mostradas como
ttyUSB0
ettyUSB3
. Mas não me importo com essesttyUSB
nomes.Esses dois dispositivos sempre estarão
/dev/serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if00-port0
e/dev/serial/by-id/usb-utek_USB__-__Serial_Cable_FTVW64JR-if01-port0
Então esses nomes são consistentes.
Outra solução alternativa seria usar
udev
para criar nomes consistentes.Por exemplo, em outra máquina tenho estas regras:
Agora, o que isso faz é que quando eu conecto meu stick Zigbee/Zwave, ele cria novos links simbólicos para o nome real:
Com ambas as opções, não preciso me importar com o
ttyUSB
número; tenho um nome consistente que sempre aponta para o dispositivo certo.Seu dispositivo serial sendo desconectado geralmente é um sinal de um problema de hardware, por exemplo, devido à necessidade de muita energia dos soquetes USB quando um novo dispositivo é conectado, ou interferência elétrica transitória. Como isso não deveria acontecer, você deve tentar consertar a causa, em vez de contorná-la em seu programa.
Dispositivos Zigbee podem causar interferência de radiofrequência e também estar sujeitos a ela. Soquetes USB3 podem interferir na zona de 2,4 GHz. Geralmente, é recomendado não conectar dispositivos Zigbee diretamente em um soquete USB do computador, mas usar um cabo de extensão USB adequadamente blindado.
Por exemplo, veja este conselho para assistentes domésticos .
O subsistema udev tem um retorno de chamada que normalmente é projetado para iniciar um serviço quando um dispositivo é conectado - já que é isso que está ocorrendo (com base no log do dmesg), uma regra semelhante pode ser usada neste caso.
Isto pode ser conseguido adicionando um arquivo:
Contendo:
Onde
abcd
estão1234
os IDs do fornecedor e do produto do dispositivo a ser detectado e o binário de retorno de chamada é apenas um executável que sinaliza ao serviço principal para escanear novamente seus dispositivos.Também é possível adicionar uma
remove
regra para que seja possível usá-la para indicar que ocorreu um problema (por exemplo, se o dispositivo não foi detectado novamente).