Qual é a maneira correta de obter uma lista de todas as portas / dispositivos seriais disponíveis em um sistema Linux?
Em outras palavras, quando faço a iteração em todos os dispositivos /dev/
, como posso saber quais são as portas seriais da maneira clássica, ou seja, aquelas que geralmente oferecem suporte a taxas de transmissão e controle de fluxo RTS / CTS ?
A solução seria codificada em C.
Eu pergunto porque estou usando uma biblioteca de terceiros que faz isso claramente errado: parece apenas repetir /dev/ttyS*
. O problema é que existem, por exemplo, portas seriais sobre USB (fornecidas por adaptadores USB-RS232), e essas estão listadas em / dev / ttyUSB *. E lendo o Serial-HOWTO em Linux.org , tenho a idéia de que haverá outros espaços de nomes também, com o tempo.
Portanto, preciso encontrar a maneira oficial de detectar dispositivos seriais. O problema é que nada parece estar documentado ou não consigo encontrar.
Imagino que uma maneira seria abrir todos os arquivos do /dev/tty*
e chamar um específico ioctl()
sobre eles que está disponível apenas em dispositivos seriais. Isso seria uma boa solução, entretanto?
Atualizar
hrickards sugeriu olhar a fonte para "setserial". Seu código faz exatamente o que eu tinha em mente:
Primeiro, ele abre um dispositivo com:
fd = open (path, O_RDWR | O_NONBLOCK)
Em seguida, ele invoca:
ioctl (fd, TIOCGSERIAL, &serinfo)
Se essa chamada não retornar nenhum erro, então é um dispositivo serial, aparentemente.
Encontrei um código semelhante em Serial Programming / termios , o que sugeriu também adicionar a O_NOCTTY
opção.
Porém, há um problema com essa abordagem:
Quando testei esse código no BSD Unix (ou seja, Mac OS X), ele também funcionou. No entanto , os dispositivos seriais fornecidos por meio do Bluetooth fazem com que o sistema (driver) tente se conectar ao dispositivo Bluetooth, o que leva um tempo antes de retornar com um erro de tempo limite. Isso é causado apenas pela abertura do dispositivo. E posso imaginar que coisas semelhantes também possam acontecer no Linux - de preferência, não preciso abrir o dispositivo para descobrir seu tipo. Gostaria de saber se também existe uma maneira de invocar ioctl
funções sem um aberto, ou abrir um dispositivo de uma forma que não faça com que as conexões sejam feitas?
O que devo fazer?
fonte
Respostas:
O
/sys
sistema de arquivos deve conter muitas informações para sua missão. Meu sistema (2.6.32-40-generic # 87-Ubuntu) sugere:Que fornece descrições de todos os dispositivos TTY conhecidos pelo sistema. Um exemplo reduzido:
Seguindo um destes links:
Aqui, o
dev
arquivo contém esta informação:Este é o nó principal / secundário. Eles podem ser pesquisados no
/dev
diretório para obter nomes fáceis de usar:O
/sys/class/tty
dir contém todos os dispositivos TTY, mas você pode querer excluir aqueles terminais virtuais e pseudo terminais irritantes. Eu sugiro que você examine apenas aqueles que têm umadevice/driver
entrada:fonte
/dev/zero
. Você realmente acha que este é um dispositivo serial?Em kernels recentes (não tenho certeza desde quando) você pode listar o conteúdo de / dev / serial para obter uma lista das portas seriais em seu sistema. Na verdade, eles são links simbólicos que apontam para o / dev / node correto:
Este é um adaptador USB-Serial, como você pode ver. Observe que quando não há portas seriais no sistema, o diretório / dev / serial / não existe. Espero que isto ajude :).
fonte
Estou fazendo algo como o código a seguir. Ele funciona para dispositivos USB e também para os estúpidos dispositivos serial8250 que todos nós temos 30 - mas apenas alguns deles realmente funcionam.
Basicamente, uso o conceito de respostas anteriores. Primeiro enumere todos os dispositivos tty em / sys / class / tty /. Dispositivos que não contêm um subdiretório / device são filtrados. / sys / class / tty / console é um desses dispositivos. Em seguida, os dispositivos que realmente contêm dispositivos são aceitos como porta serial válida, dependendo do destino do driver de link simbólico.
e para ttyS0
Todos os drivers acionados pelo serial8250 devem ser probes usando o ioctl mencionado anteriormente.
Apenas a porta que relata um tipo de dispositivo válido é válido.
A fonte completa para enumerar as portas seriais se parece com isto. Adições são bem-vindas.
fonte
Acho que encontrei a resposta na documentação do meu kernel: /usr/src/linux-2.6.37-rc3/Documentation/filesystems/proc.txt
Aqui está um link para este arquivo: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob_plain;f=Documentation/filesystems/proc.txt;hb = e8883f8057c0f7c9950fa9f20568f37bfa62f34a
fonte
eu encontrei
fazendo o trabalho.
fonte
setserial com a opção -g parece fazer o que você quer e a fonte C está disponível em http://www.koders.com/c/fid39344DABD14604E70DF1B8FEA7D920A94AF78BF8.aspx .
fonte
Não tenho nenhum dispositivo serial aqui para testá-lo, mas se você tiver python e dbus, pode tentar sozinho.
Se falhar, você pode pesquisar dentro
hwmanager_i.GetAllDevicesWithProperties()
para ver se o nome do recurso "serial" que acabei de adivinhar tem um nome diferente.HTH
fonte
Não tenho um dispositivo serial USB, mas deve haver uma maneira de encontrar as portas reais usando as bibliotecas HAL diretamente:
O código python-dbus postado nem este script sh lista os dispositivos bluetooth / dev / rfcomm *, portanto, não é a melhor solução.
Observe que em outras plataformas Unix, as portas seriais não são nomeadas ttyS? e mesmo no Linux, algumas placas seriais permitem nomear os dispositivos. Presumindo que um padrão nos nomes dos dispositivos seriais esteja errado.
fonte
Usar / proc / tty / drivers indica apenas quais drivers tty estão carregados. Se você estiver procurando por uma lista de portas seriais, verifique / dev / serial, ela terá dois subdiretórios: by-id e by-path.
EX:
Graças a esta postagem: /superuser/131044/how-do-i-know-which-dev-ttys-is-my-serial-port
fonte
Minha abordagem via dialout de grupo para obter cada tty com o usuário 'dialout'
ls -l /dev/tty* | grep 'dialout'
para obter apenas sua pastals -l /dev/tty* | grep 'dialout' | rev | cut -d " " -f1 | rev
ouvir facilmente a saída tty, por exemplo, quando o arduino for serial out:
head --lines 1 < /dev/ttyUSB0
ouça cada tty em apenas uma linha:
for i in $(ls -l /dev/tty* | grep 'dialout' | rev | cut -d " " -f1 | rev); do head --lines 1 < $i; done
Eu realmente gosto da abordagem por meio da procura de drivers:
ll /sys/class/tty/*/device/driver
Você pode escolher o nome tty agora:
ls /sys/class/tty/*/device/driver | grep 'driver' | cut -d "/" -f 5
fonte
A biblioteca do gerenciador de comunicação serial possui muitos APIs e recursos direcionados para a tarefa que você deseja. Se o dispositivo for um USB-UART, seu VID / PID pode ser usado. Se o dispositivo for BT-SPP, APIs específicas da plataforma podem ser usadas. Dê uma olhada neste projeto para programação de porta serial: https://github.com/RishiGupta12/serial-communication-manager
fonte
sim, eu sei, estou muito atrasado (como sempre). Aqui está meu código (baseado na resposta de mk2). Talvez isso ajude alguém:
fonte