How can I set the RTS with ioctl() in a Mac plugin?

你。 提交于 2021-02-07 11:20:50

问题


I am able to set the RTS with ioctl in a small Terminal app, but not in my Mac plugin code, although both run the same code. In the plugin I can only "get" the serial ports flags/pins, but not "set" them. In the Terminal app I can both "get and "set" them. I get an errno of ENODEV. The error number is 19 and the message is "Operation not supported by device."

If this is a security issue (being in the context of a browser) is there a way to get permission to modify the flag with ioctl? I have a serial device attached to a usb port. Am using the FTDI vcp (virtual com port) driver. Everything smooth on the Windows side. Btw, I get the same result using both Safari and Firefox. Below is my code:

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

=========

Update

If I refresh the browser page, forcing the code to be executed again, ioctl() returns 0, indicating success. Unfortunately, I need it to work the first time. Even if I write a loop and pause momentarily, using the usleep() method, and make subsequent tries, it fails. But then, when I refresh it succeeds. I've also duplicated the issue in a second, exclusively NPAPI project "BasicPlugin.xcodeproj", supplied by Mozilla. My first plugin project is a Firebreath project. They both fail at first, then succeed on page reload. I also have 2 separate Mac apps that work properly. One is SerialTools, and it uses the exact same method of setting the RTS on (and DTR off) as the my Terminal app and the plugins.

========

Update 2

I've been able to get code-level Apple support on this, so a solution may be coming. The engineer said it was "bizarre" that the code runs differently in a plugin than outside of one, and is speaking with Safari plugin engineers.


回答1:


You can make a AppleScript plugin, that will run automatically at particular times or during your login, or continuously in the background.

AppleScript can run terminal code. So you can easily have it automatically run the get/set code that you currently run in Terminal.

The code for the AppleScript plugin will be something like this ::

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 



回答2:


The answer is that whenever TIOCMSET or TIOCMGET are used in a call to ioctl() the 3rd parameter must be an int. I was using a char. Duh. Can't believe I missed this. TIOCMSET and TIOCMGET are defined as follows:

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

and so it is not difficult to imagine that using a char as the type for my "flags" var might cause unpredictable behavior.



来源:https://stackoverflow.com/questions/14693724/how-can-i-set-the-rts-with-ioctl-in-a-mac-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!