AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 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

如何防止为 cdc_acm 打开 DTR?

  • 772

我有一个通过 USB 连接的 Arduino Uno,使用cdc_acm驱动程序。可在/dev/ttyACM0.

Arduino 串行接口的约定是DTR用于复位信号的信号——当使用集成串行到 USB 适配器时,DTR/RTS/DSR/CTS 信号;或者,当使用 RS-232 电缆时,引脚 4 或 5(可能还有 6 或 8)连接到RESET引脚。

这种重置途径具有重要的优势,即使不是真正的带外,至少非常接近故障安全(由于通过始终带外串行控制器与非正常用户一起实现- 可控看门狗电路),虽然它可以被物理禁用(通过将电容器或电阻器(取决于型号)连接到RESET引脚),这样做完全破坏了这个重要的终止开关和所有相关的实用程序。

不幸的是,目前看来,当任何程序出于任何原因连接到 ACM 设备时,Linux 绝对总是发送此信号,并且(与 Windows 不同,)没有提供甚至模糊已知的可靠方法来防止这种情况发生。

(目前-hupcl,“在最后一个进程关闭 tty 时发送挂断信号”和-clocal“禁用调制解调器控制信号”都不会阻止每次打开设备时发送此信号。)


/dev/ttyACM0tl;dr:如果不向其发送 DTR/RTS/DSR/CTS 信号(没有在硬件级别阻塞信号),我需要做什么才能访问?

serial-port ioctl
  • 2 2 个回答
  • 2863 Views

2 个回答

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

    当用户态进程打开类似/dev/ttyS0or的串行设备/dev/ttyACM0时,linuxDTR/RTS默认会提升这些行,并在关闭它时丢弃它们。

    它通过调用dtr_rts由驱动程序定义的回调来实现。

    不幸的是,还没有任何 sysctl 或类似的东西可以禁用这种烦人的行为(现在很少使用),所以唯一有效的方法是从驱动程序的tty_port_operations结构中删除该回调,并重新编译驱动程序模块。

    您可以cdc-acm通过注释掉这一行来为驱动程序执行此操作:

    --- 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,
    

    这不会阻止您DTR/RTS通过串行 ioctl 使用这些行,如TIOCMSET, TIOCMBIC, TIOCMBIS,这将像往常一样acm_tty_tiocmset()由结构中的 , 等回调处理。acm_ops

    其他驱动程序也可以使用类似的技巧;我个人已经将它与PL2303usb -> 串行驱动程序一起使用。

    [差异信息丰富;它不会直接应用,因为这个网站会破坏标签和空格]

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

    我认为有一个很好的解决方法可以解决这个问题。不是从设备 /dev/ttyUSB0 或 /dev/ttyACM0 读取数据,而是从命名管道读取数据,例如 /tmp/arduino 和简单的程序(如下)将数据从设备复制到管道并保存设备打开(从而避免设置 DTR 高)。这也避免了处理从设备读取的所有困难。使用命名管道,可以使用 cat、less -f 之类的工具,或者可以使用任何具有标准 open + read 的程序,而无需发出 ioctl 命令来控制 tty。将设备复制到管道的程序将作为新贵服务运行并将数据从设备复制到管道(并且可能会产生一些日志)。该程序必须处理 SIGPIPE 信号,以避免在关闭任何管道读取器进程时被关闭。由于有意通过 fcntl 对输入设置阻塞,服务器上的负载可以忽略不计。我已经对其进行了测试,它似乎运行良好。我正在尝试解决与 Arduino 接口相同的问题。好的副作用是可以通过在需要时重新启动 upstart 服务来重新启动 Arduino,因为它将 DTR 设置为高。

    #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;
    }
    

    启动它的 shell 脚本将是(需要重新实现为 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
    

    我认为 logrotate 文件需要使用 copytruncate,因为文件仍然是打开的(我没有机会测试这个):

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

    附加说明:同时我意识到,为了避免管道损坏,可能可以通过使用 cat 或 dd 结合带有参数 PIPE 的 trap 命令来实现,这也将过滤 SIGPIPE 信号。上面的解决方案对我有用,所以我没有尝试使用 trap 命令来获得可比较的结果。

    • 0

相关问题

  • 在没有打开会话的情况下在后台运行 picocom

  • QEMU 4个以上的串口

  • 设置似乎没有 I/O 端口的 PCIe 串行卡

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve