123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- /**
- * WinPR: Windows Portable Runtime
- * Serial Communication API
- *
- * Copyright 2011 O.S. Systems Software Ltda.
- * Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
- * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- * Copyright 2014 Hewlett-Packard Development Company, L.P.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #if defined __linux__ && !defined ANDROID
- #include <assert.h>
- #include <errno.h>
- #include <winpr/wlog.h>
- #include "comm.h"
- #include "comm_ioctl.h"
- #include "comm_serial_sys.h"
- #include "comm_sercx_sys.h"
- #include "comm_sercx2_sys.h"
- /* NB: MS-RDPESP's recommendation:
- *
- * <2> Section 3.2.5.1.6: Windows Implementations use IOCTL constants
- * for IoControlCode values. The content and values of the IOCTLs are
- * opaque to the protocol. On the server side, the data contained in
- * an IOCTL is simply packaged and sent to the client side. For
- * maximum compatibility between the different versions of the Windows
- * operating system, the client implementation only singles out
- * critical IOCTLs and invokes the applicable Win32 port API. The
- * other IOCTLS are passed directly to the client-side driver, and the
- * processing of this value depends on the drivers installed on the
- * client side. The values and parameters for these IOCTLS can be
- * found in [MSFT-W2KDDK] Volume 2, Part 2—Serial and Parallel
- * Drivers, and in [MSDN-PORTS].
- */
- const char* _comm_serial_ioctl_name(ULONG number)
- {
- int i;
- for (i = 0; _SERIAL_IOCTL_NAMES[i].number != 0; i++)
- {
- if (_SERIAL_IOCTL_NAMES[i].number == number)
- {
- return _SERIAL_IOCTL_NAMES[i].name;
- }
- }
- return "(unknown ioctl name)";
- }
- static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
- DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
- LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
- {
- WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
- SERIAL_DRIVER* pServerSerialDriver = NULL;
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- if (lpOverlapped)
- {
- SetLastError(ERROR_NOT_SUPPORTED);
- return FALSE;
- }
- if (lpBytesReturned == NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER); /* since we doesn't suppport lpOverlapped != NULL */
- return FALSE;
- }
- /* clear any previous last error */
- SetLastError(ERROR_SUCCESS);
- *lpBytesReturned = 0; /* will be ajusted if required ... */
- CommLog_Print(WLOG_DEBUG, "CommDeviceIoControl: IoControlCode: 0x%0.8x", dwIoControlCode);
- /* remoteSerialDriver to be use ...
- *
- * FIXME: might prefer to use an automatic rather than static structure
- */
- switch (pComm->serverSerialDriverId)
- {
- case SerialDriverSerialSys:
- pServerSerialDriver = SerialSys_s();
- break;
- case SerialDriverSerCxSys:
- pServerSerialDriver = SerCxSys_s();
- break;
- case SerialDriverSerCx2Sys:
- pServerSerialDriver = SerCx2Sys_s();
- break;
- case SerialDriverUnknown:
- default:
- CommLog_Print(WLOG_DEBUG, "Unknown remote serial driver (%d), using SerCx2.sys",
- pComm->serverSerialDriverId);
- pServerSerialDriver = SerCx2Sys_s();
- break;
- }
- assert(pServerSerialDriver != NULL);
- switch (dwIoControlCode)
- {
- case IOCTL_USBPRINT_GET_1284_ID:
- {
- /* FIXME:
- * http://msdn.microsoft.com/en-us/library/windows/hardware/ff551803(v=vs.85).aspx */
- *lpBytesReturned = nOutBufferSize; /* an empty OutputBuffer will be returned */
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
- }
- case IOCTL_SERIAL_SET_BAUD_RATE:
- {
- if (pServerSerialDriver->set_baud_rate)
- {
- SERIAL_BAUD_RATE* pBaudRate = (SERIAL_BAUD_RATE*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_BAUD_RATE));
- if (nInBufferSize < sizeof(SERIAL_BAUD_RATE))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_baud_rate(pComm, pBaudRate);
- }
- break;
- }
- case IOCTL_SERIAL_GET_BAUD_RATE:
- {
- if (pServerSerialDriver->get_baud_rate)
- {
- SERIAL_BAUD_RATE* pBaudRate = (SERIAL_BAUD_RATE*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_BAUD_RATE));
- if (nOutBufferSize < sizeof(SERIAL_BAUD_RATE))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_baud_rate(pComm, pBaudRate))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_BAUD_RATE);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_GET_PROPERTIES:
- {
- if (pServerSerialDriver->get_properties)
- {
- COMMPROP* pProperties = (COMMPROP*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(COMMPROP));
- if (nOutBufferSize < sizeof(COMMPROP))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_properties(pComm, pProperties))
- return FALSE;
- *lpBytesReturned = sizeof(COMMPROP);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_CHARS:
- {
- if (pServerSerialDriver->set_serial_chars)
- {
- SERIAL_CHARS* pSerialChars = (SERIAL_CHARS*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_CHARS));
- if (nInBufferSize < sizeof(SERIAL_CHARS))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_serial_chars(pComm, pSerialChars);
- }
- break;
- }
- case IOCTL_SERIAL_GET_CHARS:
- {
- if (pServerSerialDriver->get_serial_chars)
- {
- SERIAL_CHARS* pSerialChars = (SERIAL_CHARS*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_CHARS));
- if (nOutBufferSize < sizeof(SERIAL_CHARS))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_serial_chars(pComm, pSerialChars))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_CHARS);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_LINE_CONTROL:
- {
- if (pServerSerialDriver->set_line_control)
- {
- SERIAL_LINE_CONTROL* pLineControl = (SERIAL_LINE_CONTROL*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_LINE_CONTROL));
- if (nInBufferSize < sizeof(SERIAL_LINE_CONTROL))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_line_control(pComm, pLineControl);
- }
- break;
- }
- case IOCTL_SERIAL_GET_LINE_CONTROL:
- {
- if (pServerSerialDriver->get_line_control)
- {
- SERIAL_LINE_CONTROL* pLineControl = (SERIAL_LINE_CONTROL*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_LINE_CONTROL));
- if (nOutBufferSize < sizeof(SERIAL_LINE_CONTROL))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_line_control(pComm, pLineControl))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_LINE_CONTROL);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_HANDFLOW:
- {
- if (pServerSerialDriver->set_handflow)
- {
- SERIAL_HANDFLOW* pHandflow = (SERIAL_HANDFLOW*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_HANDFLOW));
- if (nInBufferSize < sizeof(SERIAL_HANDFLOW))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_handflow(pComm, pHandflow);
- }
- break;
- }
- case IOCTL_SERIAL_GET_HANDFLOW:
- {
- if (pServerSerialDriver->get_handflow)
- {
- SERIAL_HANDFLOW* pHandflow = (SERIAL_HANDFLOW*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_HANDFLOW));
- if (nOutBufferSize < sizeof(SERIAL_HANDFLOW))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_handflow(pComm, pHandflow))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_HANDFLOW);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_TIMEOUTS:
- {
- if (pServerSerialDriver->set_timeouts)
- {
- SERIAL_TIMEOUTS* pHandflow = (SERIAL_TIMEOUTS*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_TIMEOUTS));
- if (nInBufferSize < sizeof(SERIAL_TIMEOUTS))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_timeouts(pComm, pHandflow);
- }
- break;
- }
- case IOCTL_SERIAL_GET_TIMEOUTS:
- {
- if (pServerSerialDriver->get_timeouts)
- {
- SERIAL_TIMEOUTS* pHandflow = (SERIAL_TIMEOUTS*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_TIMEOUTS));
- if (nOutBufferSize < sizeof(SERIAL_TIMEOUTS))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_timeouts(pComm, pHandflow))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_TIMEOUTS);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_DTR:
- {
- if (pServerSerialDriver->set_dtr)
- {
- return pServerSerialDriver->set_dtr(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_CLR_DTR:
- {
- if (pServerSerialDriver->clear_dtr)
- {
- return pServerSerialDriver->clear_dtr(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_SET_RTS:
- {
- if (pServerSerialDriver->set_rts)
- {
- return pServerSerialDriver->set_rts(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_CLR_RTS:
- {
- if (pServerSerialDriver->clear_rts)
- {
- return pServerSerialDriver->clear_rts(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_GET_MODEMSTATUS:
- {
- if (pServerSerialDriver->get_modemstatus)
- {
- ULONG* pRegister = (ULONG*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(ULONG));
- if (nOutBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_modemstatus(pComm, pRegister))
- return FALSE;
- *lpBytesReturned = sizeof(ULONG);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_WAIT_MASK:
- {
- if (pServerSerialDriver->set_wait_mask)
- {
- ULONG* pWaitMask = (ULONG*)lpInBuffer;
- assert(nInBufferSize >= sizeof(ULONG));
- if (nInBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_wait_mask(pComm, pWaitMask);
- }
- break;
- }
- case IOCTL_SERIAL_GET_WAIT_MASK:
- {
- if (pServerSerialDriver->get_wait_mask)
- {
- ULONG* pWaitMask = (ULONG*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(ULONG));
- if (nOutBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_wait_mask(pComm, pWaitMask))
- return FALSE;
- *lpBytesReturned = sizeof(ULONG);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_WAIT_ON_MASK:
- {
- if (pServerSerialDriver->wait_on_mask)
- {
- ULONG* pOutputMask = (ULONG*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(ULONG));
- if (nOutBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->wait_on_mask(pComm, pOutputMask))
- {
- *lpBytesReturned = sizeof(ULONG);
- return FALSE;
- }
- *lpBytesReturned = sizeof(ULONG);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_QUEUE_SIZE:
- {
- if (pServerSerialDriver->set_queue_size)
- {
- SERIAL_QUEUE_SIZE* pQueueSize = (SERIAL_QUEUE_SIZE*)lpInBuffer;
- assert(nInBufferSize >= sizeof(SERIAL_QUEUE_SIZE));
- if (nInBufferSize < sizeof(SERIAL_QUEUE_SIZE))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->set_queue_size(pComm, pQueueSize);
- }
- break;
- }
- case IOCTL_SERIAL_PURGE:
- {
- if (pServerSerialDriver->purge)
- {
- ULONG* pPurgeMask = (ULONG*)lpInBuffer;
- assert(nInBufferSize >= sizeof(ULONG));
- if (nInBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->purge(pComm, pPurgeMask);
- }
- break;
- }
- case IOCTL_SERIAL_GET_COMMSTATUS:
- {
- if (pServerSerialDriver->get_commstatus)
- {
- SERIAL_STATUS* pCommstatus = (SERIAL_STATUS*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(SERIAL_STATUS));
- if (nOutBufferSize < sizeof(SERIAL_STATUS))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_commstatus(pComm, pCommstatus))
- return FALSE;
- *lpBytesReturned = sizeof(SERIAL_STATUS);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_SET_BREAK_ON:
- {
- if (pServerSerialDriver->set_break_on)
- {
- return pServerSerialDriver->set_break_on(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_SET_BREAK_OFF:
- {
- if (pServerSerialDriver->set_break_off)
- {
- return pServerSerialDriver->set_break_off(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_SET_XOFF:
- {
- if (pServerSerialDriver->set_xoff)
- {
- return pServerSerialDriver->set_xoff(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_SET_XON:
- {
- if (pServerSerialDriver->set_xon)
- {
- return pServerSerialDriver->set_xon(pComm);
- }
- break;
- }
- case IOCTL_SERIAL_GET_DTRRTS:
- {
- if (pServerSerialDriver->get_dtrrts)
- {
- ULONG* pMask = (ULONG*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(ULONG));
- if (nOutBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->get_dtrrts(pComm, pMask))
- return FALSE;
- *lpBytesReturned = sizeof(ULONG);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_CONFIG_SIZE:
- {
- if (pServerSerialDriver->config_size)
- {
- ULONG* pSize = (ULONG*)lpOutBuffer;
- assert(nOutBufferSize >= sizeof(ULONG));
- if (nOutBufferSize < sizeof(ULONG))
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- if (!pServerSerialDriver->config_size(pComm, pSize))
- return FALSE;
- *lpBytesReturned = sizeof(ULONG);
- return TRUE;
- }
- break;
- }
- case IOCTL_SERIAL_IMMEDIATE_CHAR:
- {
- if (pServerSerialDriver->immediate_char)
- {
- UCHAR* pChar = (UCHAR*)lpInBuffer;
- assert(nInBufferSize >= sizeof(UCHAR));
- if (nInBufferSize < sizeof(UCHAR))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return pServerSerialDriver->immediate_char(pComm, pChar);
- }
- break;
- }
- case IOCTL_SERIAL_RESET_DEVICE:
- {
- if (pServerSerialDriver->reset_device)
- {
- return pServerSerialDriver->reset_device(pComm);
- }
- break;
- }
- }
- CommLog_Print(
- WLOG_WARN, _T("unsupported IoControlCode=[0x%08" PRIX32 "] %s (remote serial driver: %s)"),
- dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), pServerSerialDriver->name);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED); /* => STATUS_NOT_IMPLEMENTED */
- return FALSE;
- }
- /**
- * FIXME: to be used through winpr-io's DeviceIoControl
- *
- * Any previous error as returned by GetLastError is cleared.
- *
- * ERRORS:
- * ERROR_INVALID_HANDLE
- * ERROR_INVALID_PARAMETER
- * ERROR_NOT_SUPPORTED lpOverlapped is not supported
- * ERROR_INSUFFICIENT_BUFFER
- * ERROR_CALL_NOT_IMPLEMENTED unimplemented ioctl
- */
- BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
- DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
- LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
- {
- WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
- BOOL result;
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- result = _CommDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
- nOutBufferSize, lpBytesReturned, lpOverlapped);
- if (lpBytesReturned && *lpBytesReturned != nOutBufferSize)
- {
- /* This might be a hint for a bug, especially when result==TRUE */
- CommLog_Print(WLOG_WARN,
- "lpBytesReturned=%" PRIu32 " and nOutBufferSize=%" PRIu32 " are different!",
- *lpBytesReturned, nOutBufferSize);
- }
- if (pComm->permissive)
- {
- if (!result)
- {
- CommLog_Print(
- WLOG_WARN,
- "[permissive]: whereas it failed, made to succeed IoControlCode=[0x%08" PRIX32
- "] %s, last-error: 0x%08" PRIX32 "",
- dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), GetLastError());
- }
- return TRUE; /* always! */
- }
- return result;
- }
- int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
- {
- int result;
- struct termios currentState;
- if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
- {
- CommLog_Print(WLOG_WARN, "tcsetattr failure, errno: %d", errno);
- return result;
- }
- /* NB: tcsetattr() can succeed even if not all changes have been applied. */
- ZeroMemory(¤tState, sizeof(struct termios));
- if ((result = tcgetattr(fd, ¤tState)) < 0)
- {
- CommLog_Print(WLOG_WARN, "tcgetattr failure, errno: %d", errno);
- return result;
- }
- if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
- {
- CommLog_Print(WLOG_DEBUG,
- "all termios parameters are not set yet, doing a second attempt...");
- if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
- {
- CommLog_Print(WLOG_WARN, "2nd tcsetattr failure, errno: %d", errno);
- return result;
- }
- ZeroMemory(¤tState, sizeof(struct termios));
- if ((result = tcgetattr(fd, ¤tState)) < 0)
- {
- CommLog_Print(WLOG_WARN, "tcgetattr failure, errno: %d", errno);
- return result;
- }
- if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
- {
- CommLog_Print(WLOG_WARN,
- "Failure: all termios parameters are still not set on a second attempt");
- return -1;
- }
- }
- return 0;
- }
- #endif /* __linux__ */
|