winpr-comm: got IOCTL_SERIAL_GET_BAUD_RATE and IOCTL_SERIAL_GET_PROPERTIES (partial)
winpr-comm: cleant up unit tests
This commit is contained in:
parent
e7f0185e69
commit
69eeeebe67
@ -33,9 +33,9 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-comm)
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-comm)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* 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.
|
||||
|
@ -41,6 +41,9 @@
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/tchar.h>
|
||||
|
||||
#include "comm_ioctl.h"
|
||||
|
||||
|
||||
/**
|
||||
* Communication Resources:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363196/
|
||||
@ -139,159 +142,6 @@ BOOL GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Linux, Windows speeds
|
||||
*
|
||||
*/
|
||||
static const speed_t _SPEED_TABLE[][2] = {
|
||||
#ifdef B0
|
||||
{B0, 0}, /* hang up */
|
||||
#endif
|
||||
#ifdef B50
|
||||
{B50, 50},
|
||||
#endif
|
||||
#ifdef B75
|
||||
{B75, 75},
|
||||
#endif
|
||||
#ifdef B110
|
||||
{B110, CBR_110},
|
||||
#endif
|
||||
#ifdef B134
|
||||
{B134, 134},
|
||||
#endif
|
||||
#ifdef B150
|
||||
{B150, 150},
|
||||
#endif
|
||||
#ifdef B200
|
||||
{B200, 200},
|
||||
#endif
|
||||
#ifdef B300
|
||||
{B300, CBR_300},
|
||||
#endif
|
||||
#ifdef B600
|
||||
{B600, CBR_600},
|
||||
#endif
|
||||
#ifdef B1200
|
||||
{B1200, CBR_1200},
|
||||
#endif
|
||||
#ifdef B1800
|
||||
{B1800, 1800},
|
||||
#endif
|
||||
#ifdef B2400
|
||||
{B2400, CBR_2400},
|
||||
#endif
|
||||
#ifdef B4800
|
||||
{B4800, CBR_4800},
|
||||
#endif
|
||||
#ifdef B9600
|
||||
{B9600, CBR_9600},
|
||||
#endif
|
||||
/* {, CBR_14400}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B19200
|
||||
{B19200, CBR_19200},
|
||||
#endif
|
||||
#ifdef B38400
|
||||
{B38400, CBR_38400},
|
||||
#endif
|
||||
/* {, CBR_56000}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B57600
|
||||
{B57600, CBR_57600},
|
||||
#endif
|
||||
#ifdef B115200
|
||||
{B115200, CBR_115200},
|
||||
#endif
|
||||
/* {, CBR_128000}, /\* unsupported on Linux *\/ */
|
||||
/* {, CBR_256000}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B230400
|
||||
{B230400, 230400},
|
||||
#endif
|
||||
#ifdef B460800
|
||||
{B460800, 460800},
|
||||
#endif
|
||||
#ifdef B500000
|
||||
{B500000, 500000},
|
||||
#endif
|
||||
#ifdef B576000
|
||||
{B576000, 576000},
|
||||
#endif
|
||||
#ifdef B921600
|
||||
{B921600, 921600},
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
{B1000000, 1000000},
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
{B1152000, 1152000},
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
{B1500000, 1500000},
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
{B2000000, 2000000},
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
{B2500000, 2500000},
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
{B3000000, 3000000},
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
{B3500000, 3500000},
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
{B4000000, 4000000}, /* __MAX_BAUD */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* Set lpDcb->BaudRate with the current baud rate.
|
||||
*/
|
||||
static BOOL _GetBaudRate(LPDCB lpDcb, struct termios *lpCurrentState)
|
||||
{
|
||||
int i;
|
||||
speed_t currentSpeed;
|
||||
|
||||
currentSpeed = cfgetispeed(lpCurrentState);
|
||||
|
||||
for (i=0; _SPEED_TABLE[i][0]<=__MAX_BAUD; i++)
|
||||
{
|
||||
if (_SPEED_TABLE[i][0] == currentSpeed)
|
||||
{
|
||||
lpDcb->BaudRate = _SPEED_TABLE[i][1];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching baud rate for the speed 0x%x", currentSpeed);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Set lpFutureState's speed to lpDcb->BaudRate.
|
||||
*/
|
||||
static BOOL _SetBaudRate(struct termios *lpFutureState, LPDCB lpDcb)
|
||||
{
|
||||
int i;
|
||||
speed_t newSpeed;
|
||||
|
||||
for (i=0; _SPEED_TABLE[i][0]<=__MAX_BAUD; i++)
|
||||
{
|
||||
if (_SPEED_TABLE[i][1] == lpDcb->BaudRate)
|
||||
{
|
||||
newSpeed = _SPEED_TABLE[i][0];
|
||||
if (cfsetspeed(lpFutureState, newSpeed) < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to set speed 0x%x (%d)", newSpeed, lpDcb->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %d", lpDcb->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -307,6 +157,7 @@ BOOL GetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
DCB *lpLocalDcb;
|
||||
struct termios currentState;
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hFile;
|
||||
DWORD bytesReturned;
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
{
|
||||
@ -343,12 +194,14 @@ BOOL GetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
|
||||
lpLocalDcb->DCBlength = lpDCB->DCBlength;
|
||||
|
||||
if (!_GetBaudRate(lpLocalDcb, ¤tState))
|
||||
SERIAL_BAUD_RATE baudRate;
|
||||
if (!CommDeviceIoControl(pComm, IOCTL_SERIAL_GET_BAUD_RATE, NULL, 0, &baudRate, sizeof(SERIAL_BAUD_RATE), &bytesReturned, NULL))
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
DEBUG_WARN("GetCommState failure: could not get the baud rate.");
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
lpLocalDcb->BaudRate = baudRate.BaudRate;
|
||||
|
||||
lpLocalDcb->fBinary = TRUE; /* TMP: TODO: seems equivalent to the raw mode */
|
||||
|
||||
lpLocalDcb->fParity = (currentState.c_iflag & INPCK) != 0;
|
||||
@ -368,15 +221,23 @@ BOOL GetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
|
||||
|
||||
/**
|
||||
* @return TRUE on success, FALSE otherwise.
|
||||
*
|
||||
* As of today, SetCommState() can fail half-way with some settings
|
||||
* applied and some others not. SetCommState() returns on the first
|
||||
* failure met. FIXME: or is it correct?
|
||||
*
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_IO_DEVICE
|
||||
*/
|
||||
BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
{
|
||||
struct termios futureState;
|
||||
struct termios currentState;
|
||||
struct termios upcomingTermios;
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hFile;
|
||||
DWORD bytesReturned;
|
||||
|
||||
// TMP: FIXME: validate changes according GetCommProperties
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
{
|
||||
@ -390,16 +251,28 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&futureState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &futureState) < 0) /* NB: preserves current settings not directly handled by the Communication Functions */
|
||||
/* NB: did the choice to call ioctls first when available and
|
||||
then to setup upcomingTermios. Don't mix both stages. */
|
||||
|
||||
/** ioctl calls stage **/
|
||||
|
||||
SERIAL_BAUD_RATE baudRate;
|
||||
baudRate.BaudRate = lpDCB->BaudRate;
|
||||
if (!CommDeviceIoControl(pComm, IOCTL_SERIAL_SET_BAUD_RATE, &baudRate, sizeof(SERIAL_BAUD_RATE), NULL, 0, &bytesReturned, NULL))
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
DEBUG_WARN("SetCommState failure: could not set the baud rate.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_SetBaudRate(&futureState, lpDCB))
|
||||
|
||||
|
||||
/** upcomingTermios stage **/
|
||||
|
||||
|
||||
ZeroMemory(&upcomingTermios, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &upcomingTermios) < 0) /* NB: preserves current settings not directly handled by the Communication Functions */
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -413,16 +286,13 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
|
||||
if (lpDCB->fParity)
|
||||
{
|
||||
futureState.c_iflag |= INPCK;
|
||||
upcomingTermios.c_iflag |= INPCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
futureState.c_iflag &= ~INPCK;
|
||||
upcomingTermios.c_iflag &= ~INPCK;
|
||||
}
|
||||
|
||||
// TMP: FIXME: validate changes according GetCommProperties
|
||||
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363423%28v=vs.85%29.aspx
|
||||
*
|
||||
* The SetCommState function reconfigures the communications
|
||||
@ -434,43 +304,12 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
* TCSANOW matches the best this definition
|
||||
*/
|
||||
|
||||
if (tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
{
|
||||
DEBUG_WARN("could not apply parameters, errno: %d", errno);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NB: tcsetattr() can succeed even if not all changes have been applied. */
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, ¤tState) < 0)
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(¤tState, &futureState, sizeof(struct termios)) != 0)
|
||||
{
|
||||
DEBUG_WARN("all parameters were not set, doing a second attempt...");
|
||||
if (tcsetattr(pComm->fd, TCSAFLUSH, &futureState) < 0)
|
||||
{
|
||||
DEBUG_WARN("could not apply parameters, errno: %d", errno);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, ¤tState) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(¤tState, &futureState, sizeof(struct termios)) != 0)
|
||||
{
|
||||
DEBUG_WARN("Failure: all parameters were not set on a second attempt.");
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE; /* TMP: double-check whether some parameters can differ anyway */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -26,7 +26,9 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
@ -67,7 +69,7 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
{
|
||||
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
|
||||
PREMOTE_SERIAL_DRIVER pRemoteSerialDriver = NULL;
|
||||
REMOTE_SERIAL_DRIVER* pRemoteSerialDriver = NULL;
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
{
|
||||
@ -87,27 +89,30 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpBytesReturned = 0; /* will be ajusted otherwise */
|
||||
*lpBytesReturned = 0; /* will be ajusted if required ... */
|
||||
|
||||
/* remoteSerialDriver to be use ... */
|
||||
/* remoteSerialDriver to be use ...
|
||||
*
|
||||
* FIXME: might prefer to use an automatic rather than static structure
|
||||
*/
|
||||
switch (pComm->remoteSerialDriverId)
|
||||
{
|
||||
case RemoteSerialDriverSerialSys:
|
||||
pRemoteSerialDriver = SerialSys();
|
||||
pRemoteSerialDriver = SerialSys_s();
|
||||
break;
|
||||
|
||||
case RemoteSerialDriverSerCxSys:
|
||||
pRemoteSerialDriver = SerCxSys();
|
||||
pRemoteSerialDriver = SerCxSys_s();
|
||||
break;
|
||||
|
||||
case RemoteSerialDriverSerCx2Sys:
|
||||
pRemoteSerialDriver = SerCx2Sys();
|
||||
pRemoteSerialDriver = SerCx2Sys_s();
|
||||
break;
|
||||
|
||||
case RemoteSerialDriverUnknown:
|
||||
default:
|
||||
DEBUG_WARN("Unknown remote serial driver (%d), using SerCx2.sys", pComm->remoteSerialDriverId);
|
||||
pRemoteSerialDriver = SerCx2Sys();
|
||||
pRemoteSerialDriver = SerCx2Sys_s();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -117,84 +122,112 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
{
|
||||
case IOCTL_SERIAL_SET_BAUD_RATE:
|
||||
{
|
||||
PSERIAL_BAUD_RATE pBaudRate = (PSERIAL_BAUD_RATE)lpInBuffer;
|
||||
|
||||
assert(nInBufferSize == sizeof(SERIAL_BAUD_RATE));
|
||||
if (nInBufferSize < sizeof(SERIAL_BAUD_RATE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pRemoteSerialDriver->set_baud_rate)
|
||||
{
|
||||
return pRemoteSerialDriver->set_baud_rate(pBaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN(_T("unsupported IoControlCode: Ox%x (remote serial driver: %s)"), dwIoControlCode, pRemoteSerialDriver->name);
|
||||
return FALSE;
|
||||
SERIAL_BAUD_RATE *pBaudRate = (SERIAL_BAUD_RATE*)lpInBuffer;
|
||||
|
||||
assert(nInBufferSize >= sizeof(SERIAL_BAUD_RATE));
|
||||
if (nInBufferSize < sizeof(SERIAL_BAUD_RATE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pRemoteSerialDriver->set_baud_rate(pComm, pBaudRate);
|
||||
}
|
||||
}
|
||||
case IOCTL_SERIAL_GET_BAUD_RATE:
|
||||
{
|
||||
if (pRemoteSerialDriver->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 (!pRemoteSerialDriver->get_baud_rate(pComm, pBaudRate))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_BAUD_RATE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
case IOCTL_SERIAL_GET_PROPERTIES:
|
||||
{
|
||||
if (pRemoteSerialDriver->get_properties)
|
||||
{
|
||||
COMMPROP *pProperties = (COMMPROP*)lpOutBuffer;
|
||||
|
||||
assert(nOutBufferSize >= sizeof(COMMPROP));
|
||||
if (nOutBufferSize < sizeof(COMMPROP))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pRemoteSerialDriver->get_properties(pComm, pProperties))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(COMMPROP);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
default:
|
||||
DEBUG_WARN("unsupported IoControlCode: Ox%x", dwIoControlCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DEBUG_WARN(_T("unsupported IoControlCode: Ox%x (remote serial driver: %s)"), dwIoControlCode, pRemoteSerialDriver->name);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* IOCTL_SERIAL_GET_BAUD_RATE 0x001B0050 */
|
||||
/* IOCTL_SERIAL_SET_LINE_CONTROL 0x001B000C */
|
||||
/* IOCTL_SERIAL_GET_LINE_CONTROL 0x001B0054 */
|
||||
/* IOCTL_SERIAL_SET_TIMEOUTS 0x001B001C */
|
||||
/* IOCTL_SERIAL_GET_TIMEOUTS 0x001B0020 */
|
||||
/* IOCTL_SERIAL_SET_CHARS 0x001B0058 */
|
||||
/* IOCTL_SERIAL_GET_CHARS 0x001B005C */
|
||||
/* IOCTL_SERIAL_SET_DTR 0x001B0024 */
|
||||
/* IOCTL_SERIAL_CLR_DTR 0x001B0028 */
|
||||
/* IOCTL_SERIAL_RESET_DEVICE 0x001B002C */
|
||||
/* IOCTL_SERIAL_SET_RTS 0x001B0030 */
|
||||
/* IOCTL_SERIAL_CLR_RTS 0x001B0034 */
|
||||
/* IOCTL_SERIAL_SET_XOFF 0x001B0038 */
|
||||
/* IOCTL_SERIAL_SET_XON 0x001B003C */
|
||||
/* IOCTL_SERIAL_SET_BREAK_ON 0x001B0010 */
|
||||
/* IOCTL_SERIAL_SET_BREAK_OFF 0x001B0014 */
|
||||
/* IOCTL_SERIAL_SET_QUEUE_SIZE 0x001B0008 */
|
||||
/* IOCTL_SERIAL_GET_WAIT_MASK 0x001B0040 */
|
||||
/* IOCTL_SERIAL_SET_WAIT_MASK 0x001B0044 */
|
||||
/* IOCTL_SERIAL_WAIT_ON_MASK 0x001B0048 */
|
||||
/* IOCTL_SERIAL_IMMEDIATE_CHAR 0x001B0018 */
|
||||
/* IOCTL_SERIAL_PURGE 0x001B004C */
|
||||
/* IOCTL_SERIAL_GET_HANDFLOW 0x001B0060 */
|
||||
/* IOCTL_SERIAL_SET_HANDFLOW 0x001B0064 */
|
||||
/* IOCTL_SERIAL_GET_MODEMSTATUS 0x001B0068 */
|
||||
/* IOCTL_SERIAL_GET_DTRRTS 0x001B0078 */
|
||||
/* IOCTL_SERIAL_GET_COMMSTATUS 0x001B0084 */
|
||||
/* IOCTL_SERIAL_GET_PROPERTIES 0x001B0074 */
|
||||
/* IOCTL_SERIAL_XOFF_COUNTER 0x001B0070 */
|
||||
/* IOCTL_SERIAL_LSRMST_INSERT 0x001B007C */
|
||||
/* IOCTL_SERIAL_CONFIG_SIZE 0x001B0080 */
|
||||
/* IOCTL_SERIAL_GET_STATS 0x001B008C */
|
||||
/* IOCTL_SERIAL_CLEAR_STATS 0x001B0090 */
|
||||
/* IOCTL_SERIAL_GET_MODEM_CONTROL 0x001B0094 */
|
||||
/* IOCTL_SERIAL_SET_MODEM_CONTROL 0x001B0098 */
|
||||
/* IOCTL_SERIAL_SET_FIFO_CONTROL 0x001B009C */
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
|
||||
{
|
||||
int result;
|
||||
struct termios currentState;
|
||||
|
||||
/* IOCTL_PAR_QUERY_INFORMATION 0x00160004 */
|
||||
/* IOCTL_PAR_SET_INFORMATION 0x00160008 */
|
||||
/* IOCTL_PAR_QUERY_DEVICE_ID 0x0016000C */
|
||||
/* IOCTL_PAR_QUERY_DEVICE_ID_SIZE 0x00160010 */
|
||||
/* IOCTL_IEEE1284_GET_MODE 0x00160014 */
|
||||
/* IOCTL_IEEE1284_NEGOTIATE 0x00160018 */
|
||||
/* IOCTL_PAR_SET_WRITE_ADDRESS 0x0016001C */
|
||||
/* IOCTL_PAR_SET_READ_ADDRESS 0x00160020 */
|
||||
/* IOCTL_PAR_GET_DEVICE_CAPS 0x00160024 */
|
||||
/* IOCTL_PAR_GET_DEFAULT_MODES 0x00160028 */
|
||||
/* IOCTL_PAR_QUERY_RAW_DEVICE_ID 0x00160030 */
|
||||
/* IOCTL_PAR_IS_PORT_FREE 0x00160054 */
|
||||
|
||||
|
||||
return TRUE;
|
||||
if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
|
||||
{
|
||||
DEBUG_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)
|
||||
{
|
||||
DEBUG_WARN("tcgetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (memcmp(¤tState, &termios_p, sizeof(struct termios)) != 0)
|
||||
{
|
||||
DEBUG_WARN("all termios parameters were not set, doing a second attempt...");
|
||||
if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
|
||||
{
|
||||
DEBUG_WARN("2nd tcsetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
}
|
||||
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if ((result = tcgetattr(fd, ¤tState)) < 0)
|
||||
{
|
||||
DEBUG_WARN("tcgetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
|
||||
{
|
||||
DEBUG_WARN("Failure: all parameters were not set on a second attempt.");
|
||||
return -1; /* TMP: double-check whether some parameters can differ anyway */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <winpr/io.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/wtypes.h>
|
||||
@ -39,7 +41,57 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define IOCTL_SERIAL_SET_BAUD_RATE 0x001B0004
|
||||
#define IOCTL_SERIAL_SET_BAUD_RATE 0x001B0004
|
||||
#define IOCTL_SERIAL_GET_BAUD_RATE 0x001B0050
|
||||
|
||||
/* #define IOCTL_SERIAL_SET_LINE_CONTROL 0x001B000C */
|
||||
/* IOCTL_SERIAL_GET_LINE_CONTROL 0x001B0054 */
|
||||
/* IOCTL_SERIAL_SET_TIMEOUTS 0x001B001C */
|
||||
/* IOCTL_SERIAL_GET_TIMEOUTS 0x001B0020 */
|
||||
/* IOCTL_SERIAL_SET_CHARS 0x001B0058 */
|
||||
/* IOCTL_SERIAL_GET_CHARS 0x001B005C */
|
||||
/* IOCTL_SERIAL_SET_DTR 0x001B0024 */
|
||||
/* IOCTL_SERIAL_CLR_DTR 0x001B0028 */
|
||||
/* IOCTL_SERIAL_RESET_DEVICE 0x001B002C */
|
||||
/* IOCTL_SERIAL_SET_RTS 0x001B0030 */
|
||||
/* IOCTL_SERIAL_CLR_RTS 0x001B0034 */
|
||||
/* IOCTL_SERIAL_SET_XOFF 0x001B0038 */
|
||||
/* IOCTL_SERIAL_SET_XON 0x001B003C */
|
||||
/* IOCTL_SERIAL_SET_BREAK_ON 0x001B0010 */
|
||||
/* IOCTL_SERIAL_SET_BREAK_OFF 0x001B0014 */
|
||||
/* IOCTL_SERIAL_SET_QUEUE_SIZE 0x001B0008 */
|
||||
/* IOCTL_SERIAL_GET_WAIT_MASK 0x001B0040 */
|
||||
/* IOCTL_SERIAL_SET_WAIT_MASK 0x001B0044 */
|
||||
/* IOCTL_SERIAL_WAIT_ON_MASK 0x001B0048 */
|
||||
/* IOCTL_SERIAL_IMMEDIATE_CHAR 0x001B0018 */
|
||||
/* IOCTL_SERIAL_PURGE 0x001B004C */
|
||||
/* IOCTL_SERIAL_GET_HANDFLOW 0x001B0060 */
|
||||
/* IOCTL_SERIAL_SET_HANDFLOW 0x001B0064 */
|
||||
/* IOCTL_SERIAL_GET_MODEMSTATUS 0x001B0068 */
|
||||
/* IOCTL_SERIAL_GET_DTRRTS 0x001B0078 */
|
||||
/* IOCTL_SERIAL_GET_COMMSTATUS 0x001B0084 */
|
||||
#define IOCTL_SERIAL_GET_PROPERTIES 0x001B0074
|
||||
/* IOCTL_SERIAL_XOFF_COUNTER 0x001B0070 */
|
||||
/* IOCTL_SERIAL_LSRMST_INSERT 0x001B007C */
|
||||
/* IOCTL_SERIAL_CONFIG_SIZE 0x001B0080 */
|
||||
/* IOCTL_SERIAL_GET_STATS 0x001B008C */
|
||||
/* IOCTL_SERIAL_CLEAR_STATS 0x001B0090 */
|
||||
/* IOCTL_SERIAL_GET_MODEM_CONTROL 0x001B0094 */
|
||||
/* IOCTL_SERIAL_SET_MODEM_CONTROL 0x001B0098 */
|
||||
/* IOCTL_SERIAL_SET_FIFO_CONTROL 0x001B009C */
|
||||
|
||||
/* IOCTL_PAR_QUERY_INFORMATION 0x00160004 */
|
||||
/* IOCTL_PAR_SET_INFORMATION 0x00160008 */
|
||||
/* IOCTL_PAR_QUERY_DEVICE_ID 0x0016000C */
|
||||
/* IOCTL_PAR_QUERY_DEVICE_ID_SIZE 0x00160010 */
|
||||
/* IOCTL_IEEE1284_GET_MODE 0x00160014 */
|
||||
/* IOCTL_IEEE1284_NEGOTIATE 0x00160018 */
|
||||
/* IOCTL_PAR_SET_WRITE_ADDRESS 0x0016001C */
|
||||
/* IOCTL_PAR_SET_READ_ADDRESS 0x00160020 */
|
||||
/* IOCTL_PAR_GET_DEVICE_CAPS 0x00160024 */
|
||||
/* IOCTL_PAR_GET_DEFAULT_MODES 0x00160028 */
|
||||
/* IOCTL_PAR_QUERY_RAW_DEVICE_ID 0x00160030 */
|
||||
/* IOCTL_PAR_IS_PORT_FREE 0x00160054 */
|
||||
|
||||
|
||||
|
||||
@ -58,11 +110,14 @@ typedef struct _REMOTE_SERIAL_DRIVER
|
||||
{
|
||||
REMOTE_SERIAL_DRIVER_ID id;
|
||||
TCHAR *name;
|
||||
BOOL (*set_baud_rate)(PSERIAL_BAUD_RATE pBaudRate);
|
||||
BOOL (*set_baud_rate)(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate /* in */);
|
||||
BOOL (*get_baud_rate)(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate /* out */);
|
||||
BOOL (*get_properties)(WINPR_COMM *pComm, COMMPROP *pProperties /* out */);
|
||||
|
||||
} REMOTE_SERIAL_DRIVER, *PREMOTE_SERIAL_DRIVER;
|
||||
} REMOTE_SERIAL_DRIVER;
|
||||
|
||||
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,26 +20,35 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "comm_sercx_sys.h"
|
||||
|
||||
#include "comm_sercx2_sys.h"
|
||||
#include "comm_serial_sys.h"
|
||||
|
||||
|
||||
/* specific functions only */
|
||||
static REMOTE_SERIAL_DRIVER _SerCx2Sys =
|
||||
{
|
||||
{
|
||||
.id = RemoteSerialDriverSerCx2Sys,
|
||||
.name = _T("SerCx2.sys"),
|
||||
.set_baud_rate = NULL,
|
||||
.get_baud_rate = NULL,
|
||||
.get_properties = NULL,
|
||||
};
|
||||
|
||||
|
||||
PREMOTE_SERIAL_DRIVER SerCx2Sys()
|
||||
REMOTE_SERIAL_DRIVER* SerCx2Sys_s()
|
||||
{
|
||||
/* _SerCxSys completed with default SerialSys functions */
|
||||
PREMOTE_SERIAL_DRIVER serialSys = SerialSys();
|
||||
/* _SerCx2Sys completed with SerialSys or SerCxSys default functions */
|
||||
//REMOTE_SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
REMOTE_SERIAL_DRIVER* pSerCxSys = SerCxSys_s();
|
||||
|
||||
_SerCx2Sys.set_baud_rate = serialSys->set_baud_rate;
|
||||
_SerCx2Sys.set_baud_rate = pSerCxSys->set_baud_rate;
|
||||
_SerCx2Sys.get_baud_rate = pSerCxSys->get_baud_rate;
|
||||
_SerCx2Sys.get_properties = pSerCxSys->get_properties;
|
||||
|
||||
return &_SerCx2Sys;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
@ -28,7 +28,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINPR_API PREMOTE_SERIAL_DRIVER SerCx2Sys();
|
||||
REMOTE_SERIAL_DRIVER* SerCx2Sys_s();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,25 +20,250 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <assert.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#include "comm_serial_sys.h"
|
||||
|
||||
|
||||
/* 0: B* (Linux termios)
|
||||
* 1: CBR_* or actual baud rate
|
||||
* 2: BAUD_* (similar to SERIAL_BAUD_*)
|
||||
*/
|
||||
static const speed_t _SERCX_SYS_BAUD_TABLE[][3] = {
|
||||
#ifdef B0
|
||||
{B0, 0, 0}, /* hang up */
|
||||
#endif
|
||||
#ifdef B50
|
||||
{B50, 50, 0},
|
||||
#endif
|
||||
#ifdef B75
|
||||
{B75, 75, BAUD_075},
|
||||
#endif
|
||||
#ifdef B110
|
||||
{B110, CBR_110, BAUD_110},
|
||||
#endif
|
||||
#ifdef B134
|
||||
{B134, 134, 0 /*BAUD_134_5*/},
|
||||
#endif
|
||||
#ifdef B150
|
||||
{B150, 150, BAUD_150},
|
||||
#endif
|
||||
#ifdef B200
|
||||
{B200, 200, 0},
|
||||
#endif
|
||||
#ifdef B300
|
||||
{B300, CBR_300, BAUD_300},
|
||||
#endif
|
||||
#ifdef B600
|
||||
{B600, CBR_600, BAUD_600},
|
||||
#endif
|
||||
#ifdef B1200
|
||||
{B1200, CBR_1200, BAUD_1200},
|
||||
#endif
|
||||
#ifdef B1800
|
||||
{B1800, 1800, BAUD_1800},
|
||||
#endif
|
||||
#ifdef B2400
|
||||
{B2400, CBR_2400, BAUD_2400},
|
||||
#endif
|
||||
#ifdef B4800
|
||||
{B4800, CBR_4800, BAUD_4800},
|
||||
#endif
|
||||
/* {, ,BAUD_7200} */
|
||||
#ifdef B9600
|
||||
{B9600, CBR_9600, BAUD_9600},
|
||||
#endif
|
||||
/* {, CBR_14400, BAUD_14400}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B19200
|
||||
{B19200, CBR_19200, BAUD_19200},
|
||||
#endif
|
||||
#ifdef B38400
|
||||
{B38400, CBR_38400, BAUD_38400},
|
||||
#endif
|
||||
/* {, CBR_56000, BAUD_56K}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B57600
|
||||
{B57600, CBR_57600, BAUD_57600},
|
||||
#endif
|
||||
#ifdef B115200
|
||||
{B115200, CBR_115200, BAUD_115200},
|
||||
#endif
|
||||
/* {, CBR_128000, BAUD_128K}, /\* unsupported on Linux *\/ */
|
||||
/* {, CBR_256000, BAUD_USER}, /\* unsupported on Linux *\/ */
|
||||
#ifdef B230400
|
||||
{B230400, 230400, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B460800
|
||||
{B460800, 460800, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B500000
|
||||
{B500000, 500000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B576000
|
||||
{B576000, 576000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B921600
|
||||
{B921600, 921600, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
{B1000000, 1000000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
{B1152000, 1152000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
{B1500000, 1500000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
{B2000000, 2000000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
{B2500000, 2500000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
{B3000000, 3000000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
{B3500000, 3500000, BAUD_USER},
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
{B4000000, 4000000, BAUD_USER}, /* __MAX_BAUD */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
|
||||
{
|
||||
int i;
|
||||
|
||||
// TMP: TODO:
|
||||
|
||||
// TMP: required?
|
||||
// ZeroMemory(pProperties, sizeof(COMMPROP);
|
||||
|
||||
/* pProperties->PacketLength; */
|
||||
/* pProperties->PacketVersion; */
|
||||
/* pProperties->ServiceMask; */
|
||||
/* pProperties->Reserved1; */
|
||||
/* pProperties->MaxTxQueue; */
|
||||
/* pProperties->MaxRxQueue; */
|
||||
pProperties->dwMaxBaud = BAUD_USER;
|
||||
/* pProperties->ProvSubType; */
|
||||
/* pProperties->ProvCapabilities; */
|
||||
/* pProperties->SettableParams; */
|
||||
|
||||
pProperties->dwSettableBaud = 0;
|
||||
for (i=0; _SERCX_SYS_BAUD_TABLE[i][1]<=__MAX_BAUD; i++)
|
||||
{
|
||||
pProperties->dwSettableBaud |= _SERCX_SYS_BAUD_TABLE[i][2];
|
||||
}
|
||||
|
||||
/* pProperties->SettableData; */
|
||||
/* pProperties->SettableStopParity; */
|
||||
/* pProperties->CurrentTxQueue; */
|
||||
/* pProperties->CurrentRxQueue; */
|
||||
/* pProperties->ProvSpec1; */
|
||||
/* pProperties->ProvSpec2; */
|
||||
/* pProperties->ProvChar[1]; */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL _set_baud_rate(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate)
|
||||
{
|
||||
int i;
|
||||
speed_t newSpeed;
|
||||
struct termios futureState;
|
||||
|
||||
ZeroMemory(&futureState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &futureState) < 0) /* NB: preserves current settings not directly handled by the Communication Functions */
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i=0; _SERCX_SYS_BAUD_TABLE[i][0]<=__MAX_BAUD; i++)
|
||||
{
|
||||
if (_SERCX_SYS_BAUD_TABLE[i][1] == pBaudRate->BaudRate)
|
||||
{
|
||||
newSpeed = _SERCX_SYS_BAUD_TABLE[i][0];
|
||||
if (cfsetspeed(&futureState, newSpeed) < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to set speed 0x%x (%d)", newSpeed, pBaudRate->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
assert(cfgetispeed(&futureState) == newSpeed);
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %d", pBaudRate->BaudRate);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL _get_baud_rate(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate)
|
||||
{
|
||||
int i;
|
||||
speed_t currentSpeed;
|
||||
struct termios currentState;
|
||||
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, ¤tState) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
currentSpeed = cfgetispeed(¤tState);
|
||||
|
||||
for (i=0; _SERCX_SYS_BAUD_TABLE[i][0]<=__MAX_BAUD; i++)
|
||||
{
|
||||
if (_SERCX_SYS_BAUD_TABLE[i][0] == currentSpeed)
|
||||
{
|
||||
pBaudRate->BaudRate = _SERCX_SYS_BAUD_TABLE[i][1];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching baud rate for the speed 0x%x", currentSpeed);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* specific functions only */
|
||||
static REMOTE_SERIAL_DRIVER _SerCxSys =
|
||||
{
|
||||
.id = RemoteSerialDriverSerCxSys,
|
||||
.name = _T("SerCx.sys"),
|
||||
.set_baud_rate = NULL,
|
||||
.set_baud_rate = _set_baud_rate,
|
||||
.get_baud_rate = _get_baud_rate,
|
||||
.get_properties = _get_properties,
|
||||
};
|
||||
|
||||
|
||||
|
||||
PREMOTE_SERIAL_DRIVER SerCxSys()
|
||||
REMOTE_SERIAL_DRIVER* SerCxSys_s()
|
||||
{
|
||||
/* _SerCxSys completed with default SerialSys functions */
|
||||
PREMOTE_SERIAL_DRIVER serialSys = SerialSys();
|
||||
|
||||
_SerCxSys.set_baud_rate = serialSys->set_baud_rate;
|
||||
//REMOTE_SERIAL_DRIVER* pSerialSys = SerialSys();
|
||||
|
||||
return &_SerCxSys;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
@ -28,7 +28,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINPR_API PREMOTE_SERIAL_DRIVER SerCxSys();
|
||||
REMOTE_SERIAL_DRIVER* SerCxSys_s();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,11 +20,227 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#include "comm_serial_sys.h"
|
||||
|
||||
static BOOL _set_baud_rate(PSERIAL_BAUD_RATE pBaudRate)
|
||||
{
|
||||
#include <winpr/crt.h>
|
||||
|
||||
/*
|
||||
* Linux, Windows speeds
|
||||
*
|
||||
*/
|
||||
static const speed_t _SERIAL_SYS_BAUD_TABLE[][2] = {
|
||||
#ifdef B0
|
||||
{B0, 0}, /* hang up */
|
||||
#endif
|
||||
/* #ifdef B50 */
|
||||
/* {B50, }, /\* undefined by serial.sys *\/ */
|
||||
/* #endif */
|
||||
#ifdef B75
|
||||
{B75, SERIAL_BAUD_075},
|
||||
#endif
|
||||
#ifdef B110
|
||||
{B110, SERIAL_BAUD_110},
|
||||
#endif
|
||||
/* #ifdef B134 */
|
||||
/* {B134, SERIAL_BAUD_134_5}, /\* TODO: might be the same? *\/ */
|
||||
/* #endif */
|
||||
#ifdef B150
|
||||
{B150, SERIAL_BAUD_150},
|
||||
#endif
|
||||
/* #ifdef B200 */
|
||||
/* {B200, }, /\* undefined by serial.sys *\/ */
|
||||
/* #endif */
|
||||
#ifdef B300
|
||||
{B300, SERIAL_BAUD_300},
|
||||
#endif
|
||||
#ifdef B600
|
||||
{B600, SERIAL_BAUD_600},
|
||||
#endif
|
||||
#ifdef B1200
|
||||
{B1200, SERIAL_BAUD_1200},
|
||||
#endif
|
||||
#ifdef B1800
|
||||
{B1800, SERIAL_BAUD_1800},
|
||||
#endif
|
||||
#ifdef B2400
|
||||
{B2400, SERIAL_BAUD_2400},
|
||||
#endif
|
||||
#ifdef B4800
|
||||
{B4800, SERIAL_BAUD_4800},
|
||||
#endif
|
||||
/* {, SERIAL_BAUD_7200} /\* undefined on Linux *\/ */
|
||||
#ifdef B9600
|
||||
{B9600, SERIAL_BAUD_9600},
|
||||
#endif
|
||||
/* {, SERIAL_BAUD_14400} /\* undefined on Linux *\/ */
|
||||
#ifdef B19200
|
||||
{B19200, SERIAL_BAUD_19200},
|
||||
#endif
|
||||
#ifdef B38400
|
||||
{B38400, SERIAL_BAUD_38400},
|
||||
#endif
|
||||
/* {, SERIAL_BAUD_56K}, /\* undefined on Linux *\/ */
|
||||
#ifdef B57600
|
||||
{B57600, SERIAL_BAUD_57600},
|
||||
#endif
|
||||
/* {, SERIAL_BAUD_128K} /\* undefined on Linux *\/ */
|
||||
#ifdef B115200
|
||||
{B115200, SERIAL_BAUD_115200}, /* _SERIAL_MAX_BAUD */
|
||||
#endif
|
||||
/* undefined by serial.sys:
|
||||
#ifdef B230400
|
||||
{B230400, },
|
||||
#endif
|
||||
#ifdef B460800
|
||||
{B460800, },
|
||||
#endif
|
||||
#ifdef B500000
|
||||
{B500000, },
|
||||
#endif
|
||||
#ifdef B576000
|
||||
{B576000, },
|
||||
#endif
|
||||
#ifdef B921600
|
||||
{B921600, },
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
{B1000000, },
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
{B1152000, },
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
{B1500000, },
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
{B2000000, },
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
{B2500000, },
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
{B3000000, },
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
{B3500000, },
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
{B4000000, }, __MAX_BAUD
|
||||
#endif
|
||||
*/
|
||||
};
|
||||
|
||||
#define _SERIAL_MAX_BAUD B115200
|
||||
|
||||
static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
|
||||
{
|
||||
int i;
|
||||
|
||||
// TMP: TODO:
|
||||
|
||||
// TMP: required?
|
||||
// ZeroMemory(pProperties, sizeof(COMMPROP);
|
||||
|
||||
/* pProperties->PacketLength; */
|
||||
/* pProperties->PacketVersion; */
|
||||
/* pProperties->ServiceMask; */
|
||||
/* pProperties->Reserved1; */
|
||||
/* pProperties->MaxTxQueue; */
|
||||
/* pProperties->MaxRxQueue; */
|
||||
pProperties->dwMaxBaud = SERIAL_BAUD_115200; /* _SERIAL_MAX_BAUD */
|
||||
/* pProperties->ProvSubType; */
|
||||
/* pProperties->ProvCapabilities; */
|
||||
/* pProperties->SettableParams; */
|
||||
|
||||
pProperties->dwSettableBaud = 0;
|
||||
for (i=0; _SERIAL_SYS_BAUD_TABLE[i][0]<=_SERIAL_MAX_BAUD; i++)
|
||||
{
|
||||
pProperties->dwSettableBaud |= _SERIAL_SYS_BAUD_TABLE[i][1];
|
||||
}
|
||||
|
||||
/* pProperties->SettableData; */
|
||||
/* pProperties->SettableStopParity; */
|
||||
/* pProperties->CurrentTxQueue; */
|
||||
/* pProperties->CurrentRxQueue; */
|
||||
/* pProperties->ProvSpec1; */
|
||||
/* pProperties->ProvSpec2; */
|
||||
/* pProperties->ProvChar[1]; */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL _set_baud_rate(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate)
|
||||
{
|
||||
int i;
|
||||
speed_t newSpeed;
|
||||
struct termios futureState;
|
||||
|
||||
ZeroMemory(&futureState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &futureState) < 0) /* NB: preserves current settings not directly handled by the Communication Functions */
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i=0; _SERIAL_SYS_BAUD_TABLE[i][0]<=_SERIAL_MAX_BAUD; i++)
|
||||
{
|
||||
if (_SERIAL_SYS_BAUD_TABLE[i][1] == pBaudRate->BaudRate)
|
||||
{
|
||||
newSpeed = _SERIAL_SYS_BAUD_TABLE[i][0];
|
||||
if (cfsetspeed(&futureState, newSpeed) < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to set speed %d (%d)", newSpeed, pBaudRate->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %d", pBaudRate->BaudRate);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL _get_baud_rate(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate)
|
||||
{
|
||||
int i;
|
||||
speed_t currentSpeed;
|
||||
struct termios currentState;
|
||||
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, ¤tState) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
currentSpeed = cfgetispeed(¤tState);
|
||||
|
||||
for (i=0; _SERIAL_SYS_BAUD_TABLE[i][0]<=_SERIAL_MAX_BAUD; i++)
|
||||
{
|
||||
if (_SERIAL_SYS_BAUD_TABLE[i][0] == currentSpeed)
|
||||
{
|
||||
pBaudRate->BaudRate = _SERIAL_SYS_BAUD_TABLE[i][1];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching baud rate for the speed 0x%x", currentSpeed);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -34,10 +250,14 @@ static REMOTE_SERIAL_DRIVER _SerialSys =
|
||||
.id = RemoteSerialDriverSerialSys,
|
||||
.name = _T("Serial.sys"),
|
||||
.set_baud_rate = _set_baud_rate,
|
||||
.get_baud_rate = _get_baud_rate,
|
||||
.get_properties = _get_properties,
|
||||
};
|
||||
|
||||
|
||||
PREMOTE_SERIAL_DRIVER SerialSys()
|
||||
REMOTE_SERIAL_DRIVER* SerialSys_s()
|
||||
{
|
||||
return &_SerialSys;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
@ -28,7 +28,30 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINPR_API PREMOTE_SERIAL_DRIVER SerialSys();
|
||||
/* Ntddser.h: http://msdn.microsoft.com/en-us/cc308432.aspx */
|
||||
#define SERIAL_BAUD_075 ((ULONG)0x00000001)
|
||||
#define SERIAL_BAUD_110 ((ULONG)0x00000002)
|
||||
#define SERIAL_BAUD_134_5 ((ULONG)0x00000004)
|
||||
#define SERIAL_BAUD_150 ((ULONG)0x00000008)
|
||||
#define SERIAL_BAUD_300 ((ULONG)0x00000010)
|
||||
#define SERIAL_BAUD_600 ((ULONG)0x00000020)
|
||||
#define SERIAL_BAUD_1200 ((ULONG)0x00000040)
|
||||
#define SERIAL_BAUD_1800 ((ULONG)0x00000080)
|
||||
#define SERIAL_BAUD_2400 ((ULONG)0x00000100)
|
||||
#define SERIAL_BAUD_4800 ((ULONG)0x00000200)
|
||||
#define SERIAL_BAUD_7200 ((ULONG)0x00000400)
|
||||
#define SERIAL_BAUD_9600 ((ULONG)0x00000800)
|
||||
#define SERIAL_BAUD_14400 ((ULONG)0x00001000)
|
||||
#define SERIAL_BAUD_19200 ((ULONG)0x00002000)
|
||||
#define SERIAL_BAUD_38400 ((ULONG)0x00004000)
|
||||
#define SERIAL_BAUD_56K ((ULONG)0x00008000)
|
||||
#define SERIAL_BAUD_128K ((ULONG)0x00010000)
|
||||
#define SERIAL_BAUD_115200 ((ULONG)0x00020000)
|
||||
#define SERIAL_BAUD_57600 ((ULONG)0x00040000)
|
||||
#define SERIAL_BAUD_USER ((ULONG)0x10000000)
|
||||
|
||||
|
||||
REMOTE_SERIAL_DRIVER* SerialSys_s();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ int TestCommConfig(int argc, char* argv[])
|
||||
{
|
||||
DCB dcb;
|
||||
HANDLE hComm;
|
||||
BOOL fSuccess;
|
||||
BOOL success;
|
||||
LPCSTR lpFileName = "\\\\.\\COM1";
|
||||
|
||||
hComm = CreateFileA(lpFileName,
|
||||
@ -41,8 +41,9 @@ int TestCommConfig(int argc, char* argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fSuccess = DefineCommDevice(lpFileName, "/dev/null");
|
||||
if(!fSuccess)
|
||||
// TMP: FIXME: check if we can proceed with tests on the actual device, skip and warn otherwise but don't fail
|
||||
success = DefineCommDevice(lpFileName, "/dev/ttyS0");
|
||||
if(!success)
|
||||
{
|
||||
printf("DefineCommDevice failure: %s\n", lpFileName);
|
||||
return EXIT_FAILURE;
|
||||
@ -68,7 +69,7 @@ int TestCommConfig(int argc, char* argv[])
|
||||
|
||||
if (!hComm || (hComm == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
printf("CreateFileA failure: %s\n", lpFileName);
|
||||
printf("CreateFileA failure: %s GetLastError() = 0x%0.8x\n", lpFileName, GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@ -76,11 +77,11 @@ int TestCommConfig(int argc, char* argv[])
|
||||
* GetLastError should return ERROR_SHARING_VIOLATION */
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
|
||||
fSuccess = GetCommState(hComm, &dcb);
|
||||
if (!fSuccess)
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
success = GetCommState(hComm, &dcb);
|
||||
if (!success)
|
||||
{
|
||||
printf("GetCommState failure: GetLastError() = %d\n", (int) GetLastError());
|
||||
printf("GetCommState failure: GetLastError() = Ox%x\n", (int) GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@ -92,19 +93,19 @@ int TestCommConfig(int argc, char* argv[])
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
|
||||
fSuccess = SetCommState(hComm, &dcb);
|
||||
success = SetCommState(hComm, &dcb);
|
||||
|
||||
if (!fSuccess)
|
||||
if (!success)
|
||||
{
|
||||
printf("SetCommState failure: GetLastError() = %d\n", (int) GetLastError());
|
||||
printf("SetCommState failure: GetLastError() = 0x%x\n", (int) GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
fSuccess = GetCommState(hComm, &dcb);
|
||||
success = GetCommState(hComm, &dcb);
|
||||
|
||||
if (!fSuccess)
|
||||
if (!success)
|
||||
{
|
||||
printf("GetCommState failure: GetLastError() = %d\n", (int) GetLastError());
|
||||
printf("GetCommState failure: GetLastError() = 0x%x\n", (int) GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,6 @@ int TestSetCommState(int argc, char* argv[])
|
||||
HANDLE hComm;
|
||||
|
||||
// TMP: FIXME: check if we can proceed with tests on the actual device, skip and warn otherwise but don't fail
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
@ -149,7 +148,7 @@ int TestSetCommState(int argc, char* argv[])
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
printf("SetCommState failure: 0x%x\n", GetLastError());
|
||||
printf("SetCommState failure: 0x%0.8x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user