16

我可以在一个小型终端应用程序中使用 ioctl 设置 RTS,但不能在我的 Mac 插件代码中设置,尽管两者都运行相同的代码。在插件中,我只能“获取”串行端口标志/引脚,但不能“设置”它们。在终端应用程序中,我既可以“获取”也可以“设置”它们。我得到了 ENODEV 的 errno。错误号是 19,消息是“设备不支持操作”。

如果这是一个安全问题(在浏览器的上下文中),是否有办法获得使用 ioctl 修改标志的权限?我有一个连接到 USB 端口的串行设备。我正在使用 FTDI vcp(虚拟 com 端口)驱动程序。Windows 端的一切都很顺利。顺便说一句,我使用 Safari 和 Firefox 得到了相同的结果。下面是我的代码:

int disableRTS ()
{
    char fd, ret, flags;

    // open device
    if ((fd = open("/dev/cu.mydevice", O_RDWR | O_NDELAY)) < 0)
    {
        fprintf(stderr, "failed to open device");
        return -1;
    }

    // Get the current state of the bits
    ioctl(fd, TIOCMGET, &flags);
    fprintf(stderr, "Flags are %x.\n", flags);    

    flags &= ~TIOCM_RTS;  // Disable the RTS bit
    ret = ioctl(fd, TIOCMSET, &flags);

    if (ret == -1)
        fprintf(stderr, "TIOCMSET failed\n");
    else
        fprintf(stderr, "TIOCMSET succeeded. flags: %x.\n", flags);

    return 0;
}

=========

更新

如果我刷新浏览器页面,强制再次执行代码,ioctl()返回0,表示成功。不幸的是,我需要它第一次工作。即使我使用 usleep() 方法编写一个循环并暂时暂停,并进行后续尝试,它也会失败。但是,当我刷新它成功时。我还在 Mozilla 提供的第二个专门的 NPAPI 项目“BasicPlugin.xcodeproj”中复制了这个问题。我的第一个插件项目是 Firebreath 项目。他们都首先失败,然后在页面重新加载时成功。我还有 2 个独立的 Mac 应用程序可以正常工作。一个是 SerialTools,它使用与我的终端应用程序和插件完全相同的方法来设置 RTS 开启(和 DTR 关闭)。

========

更新 2

我已经能够在这方面获得代码级别的 Apple 支持,因此可能会出现解决方案。这位工程师表示,代码在插件中的运行方式与在插件之外的运行方式不同是“奇怪的”,并且正在与 Safari 插件工程师交谈。

4

2 回答 2

1

您可以制作一个 AppleScript 插件,该插件将在特定时间或登录期间自动运行,或在后台连续运行。

AppleScript 可以运行终端代码。因此,您可以轻松地让它自动运行您当前在终端中运行的获取/设置代码。

AppleScript 插件的代码将是这样的::

tell application "Finder"
    display dialog explanation buttons {"GET", "SET"} default button "GET"
    if result = {button returned:"GET"} then
        tell application "Terminal"
                 set status to (do shell script "terminal code for getting the RTS here")
            end tell
    else if result = {button returned:"SET"} then
            tell application "Terminal"
                 set status to (do shell script "terminal code for setting the RTS here")
            end tell
    end if
end tell 
于 2013-04-04T13:44:25.903 回答
1

答案是,每当在调用 ioctl() 时使用 TIOCMSET 或 TIOCMGET 时,第三个参数必须是 int。我正在使用一个字符。呃。不敢相信我错过了这个。TIOCMSET 和 TIOCMGET 定义如下:

  #define   TIOCMSET    _IOW('t', 109, int) /* set all modem bits */
  …
  #define   TIOCMGET    _IOR('t', 106, int) /* get all modem bits */

因此不难想象,使用 char 作为我的“标志”变量的类型可能会导致不可预知的行为。

于 2013-07-29T20:30:31.070 回答