Как установить RTS с помощью ioctl() в плагине Mac? - программирование
Подтвердить что ты не робот

Как установить RTS с помощью ioctl() в плагине Mac?

Я могу установить RTS с ioctl в маленьком приложении Terminal, но не в моем коде плагина Mac, хотя оба запускают тот же код. В плагине я могу только "получить" флаги/контакты последовательных портов, но не "установить" их. В приложении "Терминал" я могу "получить" и "установить" их. Я получаю errno от ENODEV. Номер ошибки равен 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;
}

=========

Update

Если я обновляю страницу браузера, заставляя код запускаться снова, ioctl() возвращает 0, что указывает на успех. К сожалению, мне нужно, чтобы он работал в первый раз. Даже если я пишу цикл и пауза на мгновение, используя метод usleep() и выполняю последующие попытки, он терпит неудачу. Но тогда, когда я обновляю, это удается. Я также дублировал эту проблему во втором, исключительно NPAPI проекте "BasicPlugin.xcodeproj", поставляемом Mozilla. Мой первый проект плагина - проект Firebreath. Сначала они оба терпят неудачу, а затем выполняют перезагрузку страницы. У меня также есть 2 отдельных приложения для Mac, которые работают правильно. Один из них - SerialTools, и он использует тот же самый метод установки RTS (и DTR off) в качестве приложения терминала и плагинов.

========

Обновление 2

Я смог получить поддержку Apple на уровне кода, поэтому решение может появиться. Инженер сказал, что это "странно", что код работает по-разному в плагине, чем за пределами одного, и разговаривает с инженерами плагинов Safari.

4b9b3361

Ответ 1

Ответ заключается в том, что всякий раз, когда TIOCMSET или TIOCMGET используются при вызове ioctl(), третий параметр должен быть int. Я использовал char. Duh. Не могу поверить, что я пропустил это. TIOCMSET и TIOCMGET определяются следующим образом:

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

и поэтому нетрудно представить, что использование char в качестве типа для моих "флагов" var может привести к непредсказуемому поведению.

Ответ 2

Вы можете создать плагин AppleScript, который будет запускаться автоматически в определенное время или во время вашего входа в систему или постоянно в фоновом режиме.

AppleScript может запускать код терминала. Таким образом, вы можете легко автоматически запустить код get/set, который вы сейчас используете в терминале.

Код плагина 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