Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 229
Alyoshak Avatar asked Feb 04 '13 19:02

Alyoshak


2 Answers

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 
like image 57
SashaZd Avatar answered Oct 26 '22 14:10

SashaZd


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.

like image 29
Alyoshak Avatar answered Oct 26 '22 13:10

Alyoshak