É possível ter duas portas seriais (simplex) unidirecionais separadas para fazer um único dispositivo tty?

4

Eu estou construindo um dispositivo embarcado que tem comunicação IR com o PC e ele terá dois pares de LED / detector IR que são unidirecionais e são configurados assim: Comandos de entrada da fonte de infravermelho - > próximo detector localizado dispositivo embutido para receber comandos, fonte de infravermelho próximo incorporado para monitorar a saída - > detector perto de saída para dispositivo externo para obter dados de monitoramento.

Descobri que o método mais simples de implementar em hardware é ter portas de comunicação serial unidirecionais separadas para cada par IR / detector: primeiro para enviar comandos, segundo para monitorar a saída.

Na minha caixa de Linux, eu tenho essas duas portas seriais separadas listadas como, por exemplo, /dev/ttyUSB1 e /dev/ttyUSB2 . O que eu quero é ter um ttyUSB agindo como uma entrada, outro como saída, mas ser capaz de acessar ambos com terminal como porta bidirecional única.

A solução de dispositivo virtual em /dev/ deve ser suficiente, mas não é obrigatória, a possibilidade de fazer um programa como minicom (ou seu substituto) reagir em duas portas separadas sem novos dispositivos virtuais seria suficiente.

O problema é apenas no lado do PC e acho que deve ser resolvido em software: se não houver solução para este problema, provavelmente adicionarei algum buffer / multiplexação de hardware personalizado para tornar a porta de comunicação única a partir desses dois.

Edit: Eu adicionei (em vez de rascunho) imagem para melhor ilustração, onde está o meu problema:

    
por IBr 05.08.2013 / 14:18

1 resposta

1

Eu usaria LD_PRELOAD e uma biblioteca dinâmica (você precisa criá-la) para substituir as chamadas que o minicom faz, open() , read() , write() , ioctl() , close() , eu não acho que são muito mais.

google for "ld_preload override" você deve encontrar muitos exemplos sobre a técnica.

  • use o comando strace com minicom para ver as chamadas que faz
  • comece a substituir o open() na sua biblioteca
  • define um nome de dispositivo tty que não existe, por exemplo: /dev/mytty
  • execute o minicom sobre este tty
  • na sua implementação de open() corresponde a este nome de dispositivo
    • se corresponder, então você deve abrir seu par ttyUSB real
    • se não corresponder ao retorno real ao open()

a biblioteca substituirá todos os open() chamados pelo minicom, portanto, para o nome de arquivo sem correspondência, você deve retornar ao real (não apenas para open() , mas para todas as chamadas que você substituir) .

retorna um descritor de arquivo válido se você abriu seu par tty com sucesso, senão um erro.
Com este descritor de arquivo, na biblioteca, você quer associar mais informações (por exemplo: o descritor de dois arquivos do seu verdadeiro tty).

Para as outras chamadas, o que você precisa corresponder é o descritor de arquivo; se corresponder ao retornado de aberto, a chamada será para /dev/mytty , se for um write() para o qual você deseja chamar uma% realwrite() no seu ttyUSB1, se for um read() um% realread() em ttyUSB2. Se o descritor não corresponder à chamada real.

O ioctl() poderia ser o não-trivial, talvez alguns ioctl precisem ir para o seu dispositivo de leitura e alguns para o dispositivo de gravação, alguns para ambos ... dependem dos argumentos ioctl.

EDITAR

Provavelmente um terminal bem feito como o minicom usa uma abordagem sem bloqueio, então você terá que agrupar chamadas como select() ou poll() , o que certamente adiciona alguma complexidade, mas eu acho ainda mais fácil do que obter um driver de kernel ou refazer o hardware.

EDITAR

Este ttypersist resolve um problema diferente usando a mesma técnica.

    
por 11.08.2013 / 05:22