Портирование последовательного порта Win32 (RS232) на POSIX - PullRequest
0 голосов
/ 20 декабря 2018

В настоящее время я портирую приложение Win32 на POSIX.Самому программному обеспечению уже несколько десятков лет, и оно используется для обновления проприетарных машин.

Хотя большинство функций было относительно легко заменить простыми макросами и некоторыми небольшими функциями, вызывающими функции POSIX, функции, связанные с связью RS232, оказываются трудными.

Приложение использует эти функции для связичерез RS232:

BOOL GetCommState(HANDLE comPort, DCB* dataControlBlock);

BOOL SetCommState(HANDLE comPort, DCB* dataControlBlock);

BOOL GetCommTimeouts(HANDLE comPort, LPCOMMTIMEOUTS comTimeouts);

BOOL SetCommTimeouts(HANDLE comPort, LPCOMMTIMEOUTS comTimeouts);

BOOL SetCommMask(HANDLE comPort, DWORD eventMask);

BOOL GetCommMask(HANDLE comPort, LPDWORD eventMask);

BOOL WaitCommEvent(HANDLE comPort, LPDWORD eventMask, LPOVERLAPPED overlapped);

Наряду со следующими структурами:

typedef struct _DCB { /*...*/ } DCB, *LPDCB;

typedef struct _COMMTIMEOUTS { /*...*/ } COMMTIMEOUTS, *LPCOMMTIMEOUTS;

Во время поиска я наткнулся на эту ссылку, в которой упоминается termios.hи sys / select.h, но структура этих заголовков слишком разная на мой взгляд.Другие ответы упоминались с использованием Wine, который просто не подходит из-за аппаратного обеспечения, на которое переносится приложение.

Если возможно, я бы хотел реализовать более простое решение и сохранить структуры, используемые в настоящее время приложением, - чтобы попытаться сохранить все кросс-совместимым.

Есть ли способ достичь этого?Или я застрял с переписыванием валовых частей приложения?

1 Ответ

0 голосов
/ 20 декабря 2018

В зависимости от сложности вашего приложения я вижу два возможных решения:

  1. Замените вызовы Win32 эквивалентными вызовами POSIX, как указано в комментариях P__J__.Если вы сделаете это, эквивалентные вызовы, вероятно, будут выглядеть следующим образом:

GetCommState: tcgetattr

SetCommState: tcsetattr

Get/SetCommTimeouts: Вы по-прежнему устанавливаете это с помощью tcsetattr, измените запись c_cc[VTIME] в struct termios

Set/GetCommMask: К сожалению, API POSIX не имеет эквивалентаэта функция.Если вам нужно заботиться о сигналах управления (CTS, DSR, RING), вам необходимо прочитать состояние линии в цикле.Если вам нужно только чтение байтов, которые возвращаются, вам не нужно беспокоиться об этом.

WaitCommEvent: эквивалент для POSIX будет либо select (старый стиль), либо poll (более современный).Как и в случае с CommMask, как указано выше, select/poll будет возвращаться, когда есть данные для чтения, а не при изменении линий управления.

Если вы не хотите самостоятельно пытаться выяснить кросс-платформенные проблемы, есть несколько библиотек (в C), которые поддерживают кроссплатформенность.Вот краткий список:

  • CSerial (примечание: это моя библиотека, поэтому я склонен к ней)
  • libserialport

.. и это все, что я знаю.Все остальные библиотеки, которые мне известны, предназначены для C ++.

...