AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 446088
Accepted
JamesTheAwesomeDude
JamesTheAwesomeDude
Asked: 2018-05-26 17:04:17 +0800 CST2018-05-26 17:04:17 +0800 CST 2018-05-26 17:04:17 +0800 CST

Como evitar que o DTR seja aberto para cdc_acm?

  • 772

Eu tenho um Arduino Uno conectado via USB, usando o cdc_acmdriver. Está disponível em /dev/ttyACM0.

A convenção para a interface serial do Arduino é que o DTRsinal seja usado para um sinal de reinicialização - ao usar o adaptador serial para USB integrado, o sinal DTR/RTS/DSR/CTS; ou, ao usar um cabo RS-232, os pinos 4 ou 5 (e possivelmente 6 ou 8) são conectados ao RESETpino.

Este caminho de redefinição tem a importante vantagem de ser, se não verdadeiramente fora de banda, pelo menos muito próximo à segurança (devido a ser implementado por meio do controlador serial sempre fora de banda em conjunto com o usuário não normal - circuito watchdog controlável), e enquanto ele pode ser fisicamente desabilitado (através da fiação de um capacitor ou um resistor, dependendo do modelo, ao RESETpino), fazê-lo arruína completamente este importante interruptor de interrupção e todos os utilitários associados.

Infelizmente, parece que , atualmente, o Linux sempre envia esse sinal quando qualquer programa se conecta a um dispositivo ACM por qualquer motivo e ( ao contrário do Windows ) não fornece nenhuma maneira confiável, mesmo vagamente conhecida, de evitar isso.

(Atualmente -hupcl, "enviar um sinal de desligamento quando o último processo fechar o tty" e "desativar sinais -clocalde controle do modem" não impedem que esse sinal seja enviado toda vez que o dispositivo é aberto .)


tl;dr: O que preciso fazer para acessar /dev/ttyACM0sem enviar um sinal DTR/RTS/DSR/CTS (sem bloquear o sinal no nível do hardware)?

serial-port ioctl
  • 2 2 respostas
  • 2863 Views

2 respostas

  • Voted
  1. Best Answer
    mosvy
    2019-09-25T12:27:27+08:002019-09-25T12:27:27+08:00

    Quando um processo userland está abrindo um dispositivo serial como /dev/ttyS0ou /dev/ttyACM0, o linux aumentará as DTR/RTSlinhas por padrão e as descartará ao fechá-lo.

    Ele faz isso chamando um dtr_rtsretorno de chamada definido pelo driver.

    Infelizmente, ainda não existe nenhum sysctl ou similar que permita desabilitar esse comportamento irritante (pouco útil hoje em dia), então a única coisa que funciona é remover esse callback da tty_port_operationsestrutura do driver e recompilar o módulo do driver.

    Você pode fazer isso para o cdc-acmdriver comentando esta linha :

    --- drivers/usb/class/cdc-acm.c~
    +++ drivers/usb/class/cdc-acm.c
    @@ -1063,7 +1063,7 @@
     }
    
     static const struct tty_port_operations acm_port_ops = {
    -       .dtr_rts = acm_port_dtr_rts,
    +       /* .dtr_rts = acm_port_dtr_rts, */
            .shutdown = acm_port_shutdown,
            .activate = acm_port_activate,
            .destruct = acm_port_destruct,
    

    Isso não impedirá que você use as DTR/RTSlinhas por meio de ioctls seriais como TIOCMSET, TIOCMBIC, TIOCMBIS, que serão tratadas pelos acm_tty_tiocmset()callbacks , etc da acm_opsestrutura, como de costume.

    Hacks semelhantes podem ser usados ​​com outros drivers; Eu pessoalmente usei isso com o PL2303driver usb -> serial.

    [A diferença é informativa; não será aplicado diretamente porque este site altera guias e espaços em branco]

    • 5
  2. ludvik02
    2021-02-10T16:12:36+08:002021-02-10T16:12:36+08:00

    Eu acho que há uma boa solução alternativa que resolve o problema. Em vez de ler os dados do dispositivo /dev/ttyUSB0 ou /dev/ttyACM0, eles podem ser lidos do pipe nomeado, por exemplo, /tmp/arduino e o programa simples (abaixo) copiaria os dados do dispositivo para o pipe e manteria o dispositivo aberto (evitando assim configurar DTR alto). Isso também evita lidar com todas as dificuldades de leitura do dispositivo. Com o pipe nomeado, ferramentas como cat, less -f podem ser usadas ou apenas qualquer programa com padrão open + read sem a necessidade de emitir comandos ioctl para controlar tty. O programa para copiar o dispositivo para o pipe seria executado, por exemplo, como um serviço inicial e copiar dados do dispositivo para o pipe (e talvez produzir alguns logs). O programa tem que cuidar do sinal SIGPIPE, para evitar que seja fechado ao fechar qualquer processo de leitura de pipe. A carga no servidor seria insignificante devido ao bloqueio intencional da entrada via fcntl. Eu testei e parece estar funcionando bem. Estou realmente tentando resolver o mesmo problema com a interface do Arduino. O bom efeito colateral é que a reinicialização do Arduino pode ser feita simplesmente reiniciando o serviço upstart sempre que necessário, pois define o DTR alto.

    #include <unistd.h>
    #include <string.h>
    #include <signal.h>
    #include <fcntl.h>
    
    /* for simplicity, most error handling is ommited, make sure you add it before using in production code */
    void ignore_signal(int sig)
    {
            static struct sigaction _sigact;
            memset(&_sigact, 0, sizeof(_sigact));
            _sigact.sa_handler = SIG_IGN;
            sigaction(sig, &_sigact, NULL);
    }
    
    int main()
    {
            ignore_signal(SIGPIPE);
    
            int flags;
            flags = fcntl(0, F_GETFL, 0) & ~O_NONBLOCK;
            fcntl(0, F_SETFL, flags);
    
    
            char c;
            int n;
            while(1)
            {
                    n = read(0,&c,1);
                    if(n!=1)
                    {
                            sleep(1);
                    }
                    else
                    {
                            write(1,&c,1); /* ignoring the case that return code = -1 and errno = EPIPE means that data from Arduino are lost whenever pipe is not read */
                            write(2,&c,1);
                    }
            }
            return 0;
    }
    

    O script de shell para iniciá-lo seria (precisa ser reimplementado como serviço upstart):

    #!/bin/bash
    
    DEV=/dev/ttyUSB0
    PIPE=/tmp/arduino
    LOG=/var/log/arduino.log
    
    if test ! -p $PIPE
    then
        rm -f $PIPE
        mkfifo $PIPE
    fi
    
    ./my_dd <$DEV >$PIPE 2>>$LOG &
    dd if=$PIPE of=/dev/null count=0 bs=1
    

    Acho que o arquivo logrotate precisa usar copytruncate, porque o arquivo ainda está aberto (não tive chance de testar isso):

    /var/log/arduino.log {
      rotate 5
      daily
      compress
      missingok
      notifempty
      create 640 root root
      copytruncate
    }
    

    Nota adicional: Enquanto isso, percebi que, para evitar o tubo quebrado, provavelmente poderia ser alcançado com o uso de cat ou dd em combinação com o comando trap com o parâmetro PIPE, que estaria filtrando o sinal SIGPIPE também. A solução acima funciona para mim, então não estava experimentando o comando trap para obter resultados comparáveis.

    • 0

relate perguntas

  • Executando picocom em segundo plano sem sessão aberta

  • QEMU mais de 4 portas seriais

  • Configurando uma placa serial PCIe que não parece possuir portas de E/S

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve