Blame winpr/libwinpr/comm/comm_sercx_sys.c

Packit Service fa4841
/**
Packit Service fa4841
 * WinPR: Windows Portable Runtime
Packit Service fa4841
 * Serial Communication API
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 O.S. Systems Software Ltda.
Packit Service fa4841
 * Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
Packit Service fa4841
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2014 Hewlett-Packard Development Company, L.P.
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#if defined __linux__ && !defined ANDROID
Packit Service fa4841
Packit Service fa4841
#include <assert.h>
Packit Service fa4841
#include <termios.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/wlog.h>
Packit Service fa4841
Packit Service fa4841
#include "comm_serial_sys.h"
Packit Service fa4841
Packit Service bb5c11
Packit Service bb5c11
static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
Packit Service fa4841
{
Packit Service fa4841
	SERIAL_HANDFLOW SerCxHandflow;
Packit Service fa4841
	BOOL result = TRUE;
Packit Service fa4841
	SERIAL_DRIVER* pSerialSys = SerialSys_s();
Packit Service fa4841
Packit Service fa4841
	memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW));
Packit Service fa4841
Packit Service fa4841
	/* filter out unsupported bits by SerCx.sys
Packit Service fa4841
	 *
Packit Service fa4841
	 * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
Packit Service fa4841
	 */
Packit Service fa4841
Packit Service bb5c11
	SerCxHandflow.ControlHandShake = pHandflow->ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
Packit Service bb5c11
	SerCxHandflow.FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
Packit Service fa4841
Packit Service fa4841
	if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake)
Packit Service fa4841
	{
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit Service fa4841
		result = FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace)
Packit Service fa4841
	{
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE)
Packit Service fa4841
		{
Packit Service bb5c11
			CommLog_Print(WLOG_WARN, "SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys");
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit Service fa4841
		result = FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!pSerialSys->set_handflow(pComm, &SerCxHandflow))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	return result;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
Packit Service bb5c11
static BOOL _get_handflow(WINPR_COMM *pComm, SERIAL_HANDFLOW *pHandflow)
Packit Service fa4841
{
Packit Service fa4841
	BOOL result;
Packit Service fa4841
	SERIAL_DRIVER* pSerialSys = SerialSys_s();
Packit Service fa4841
Packit Service fa4841
	result = pSerialSys->get_handflow(pComm, pHandflow);
Packit Service fa4841
Packit Service fa4841
	/* filter out unsupported bits by SerCx.sys
Packit Service fa4841
	 *
Packit Service fa4841
	 * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
Packit Service fa4841
	 */
Packit Service fa4841
Packit Service bb5c11
	pHandflow->ControlHandShake = pHandflow->ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
Packit Service fa4841
	pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
Packit Service fa4841
Packit Service fa4841
	return result;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
/* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
Packit Service bb5c11
static const ULONG _SERCX_SYS_SUPPORTED_EV_MASK =
Packit Service bb5c11
	SERIAL_EV_RXCHAR   |
Packit Service bb5c11
	/* SERIAL_EV_RXFLAG   | */
Packit Service bb5c11
	SERIAL_EV_TXEMPTY  |
Packit Service bb5c11
	SERIAL_EV_CTS      |
Packit Service bb5c11
	SERIAL_EV_DSR      |
Packit Service bb5c11
	SERIAL_EV_RLSD     |
Packit Service bb5c11
	SERIAL_EV_BREAK    |
Packit Service bb5c11
	SERIAL_EV_ERR      |
Packit Service bb5c11
	SERIAL_EV_RING    /* |
Packit Service bb5c11
	SERIAL_EV_PERR     |
Packit Service bb5c11
	SERIAL_EV_RX80FULL |
Packit Service bb5c11
	SERIAL_EV_EVENT1   |
Packit Service bb5c11
	SERIAL_EV_EVENT2*/;
Packit Service bb5c11
Packit Service bb5c11
Packit Service bb5c11
static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask)
Packit Service fa4841
{
Packit Service fa4841
	ULONG possibleMask;
Packit Service fa4841
	SERIAL_DRIVER* pSerialSys = SerialSys_s();
Packit Service fa4841
Packit Service fa4841
	possibleMask = *pWaitMask & _SERCX_SYS_SUPPORTED_EV_MASK;
Packit Service fa4841
Packit Service fa4841
	if (possibleMask != *pWaitMask)
Packit Service fa4841
	{
Packit Service bb5c11
		CommLog_Print(WLOG_WARN, "Not all wait events supported (SerCx.sys), requested events= 0x%08"PRIX32", possible events= 0x%08"PRIX32"", *pWaitMask, possibleMask);
Packit Service fa4841
Packit Service fa4841
		/* FIXME: shall we really set the possibleMask and return FALSE? */
Packit Service fa4841
		pComm->WaitEventMask = possibleMask;
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
Packit Service fa4841
	return pSerialSys->set_wait_mask(pComm, pWaitMask);
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
/* specific functions only */
Packit Service bb5c11
static SERIAL_DRIVER _SerCxSys =
Packit Service bb5c11
{
Packit Service bb5c11
	.id		  = SerialDriverSerCxSys,
Packit Service bb5c11
	.name		  = _T("SerCx.sys"),
Packit Service bb5c11
	.set_baud_rate    = NULL,
Packit Service bb5c11
	.get_baud_rate    = NULL,
Packit Service bb5c11
	.get_properties   = NULL,
Packit Service fa4841
	.set_serial_chars = NULL,
Packit Service fa4841
	.get_serial_chars = NULL,
Packit Service fa4841
	.set_line_control = NULL,
Packit Service fa4841
	.get_line_control = NULL,
Packit Service bb5c11
	.set_handflow     = _set_handflow,
Packit Service bb5c11
	.get_handflow     = _get_handflow,
Packit Service bb5c11
	.set_timeouts     = NULL,
Packit Service bb5c11
	.get_timeouts     = NULL,
Packit Service bb5c11
	.set_dtr          = NULL,
Packit Service bb5c11
	.clear_dtr        = NULL,
Packit Service bb5c11
	.set_rts          = NULL,
Packit Service bb5c11
	.clear_rts        = NULL,
Packit Service bb5c11
	.get_modemstatus  = NULL,
Packit Service bb5c11
	.set_wait_mask    = _set_wait_mask,
Packit Service bb5c11
	.get_wait_mask    = NULL,
Packit Service bb5c11
	.wait_on_mask     = NULL,
Packit Service bb5c11
	.set_queue_size   = NULL,
Packit Service bb5c11
	.purge            = NULL,
Packit Service bb5c11
	.get_commstatus   = NULL,
Packit Service bb5c11
	.set_break_on     = NULL,
Packit Service bb5c11
	.set_break_off    = NULL,
Packit Service bb5c11
	.set_xoff         = NULL,
Packit Service bb5c11
	.set_xon          = NULL,
Packit Service bb5c11
	.get_dtrrts       = NULL,
Packit Service bb5c11
	.config_size      = NULL, /* not supported by SerCx.sys */
Packit Service bb5c11
	.immediate_char   = NULL,
Packit Service bb5c11
	.reset_device     = NULL, /* not supported by SerCx.sys */
Packit Service fa4841
};
Packit Service fa4841
Packit Service bb5c11
Packit Service bb5c11
Packit Service fa4841
SERIAL_DRIVER* SerCxSys_s()
Packit Service fa4841
{
Packit Service fa4841
	/* _SerCxSys completed with inherited functions from SerialSys */
Packit Service fa4841
	SERIAL_DRIVER* pSerialSys = SerialSys_s();
Packit Service fa4841
Packit Service bb5c11
	_SerCxSys.set_baud_rate    = pSerialSys->set_baud_rate;
Packit Service bb5c11
	_SerCxSys.get_baud_rate    = pSerialSys->get_baud_rate;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.get_properties = pSerialSys->get_properties;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_serial_chars = pSerialSys->set_serial_chars;
Packit Service fa4841
	_SerCxSys.get_serial_chars = pSerialSys->get_serial_chars;
Packit Service fa4841
	_SerCxSys.set_line_control = pSerialSys->set_line_control;
Packit Service fa4841
	_SerCxSys.get_line_control = pSerialSys->get_line_control;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_timeouts = pSerialSys->set_timeouts;
Packit Service fa4841
	_SerCxSys.get_timeouts = pSerialSys->get_timeouts;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_dtr = pSerialSys->set_dtr;
Packit Service fa4841
	_SerCxSys.clear_dtr = pSerialSys->clear_dtr;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_rts = pSerialSys->set_rts;
Packit Service fa4841
	_SerCxSys.clear_rts = pSerialSys->clear_rts;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.get_modemstatus = pSerialSys->get_modemstatus;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_wait_mask = pSerialSys->set_wait_mask;
Packit Service fa4841
	_SerCxSys.get_wait_mask = pSerialSys->get_wait_mask;
Packit Service bb5c11
	_SerCxSys.wait_on_mask  = pSerialSys->wait_on_mask;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.set_queue_size = pSerialSys->set_queue_size;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.purge = pSerialSys->purge;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.get_commstatus = pSerialSys->get_commstatus;
Packit Service fa4841
Packit Service bb5c11
	_SerCxSys.set_break_on  = pSerialSys->set_break_on;
Packit Service fa4841
	_SerCxSys.set_break_off = pSerialSys->set_break_off;
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
	_SerCxSys.set_xoff = pSerialSys->set_xoff;
Packit Service bb5c11
	_SerCxSys.set_xon  = pSerialSys->set_xon;
Packit Service fa4841
Packit Service bb5c11
	_SerCxSys.get_dtrrts  = pSerialSys->get_dtrrts;
Packit Service fa4841
Packit Service fa4841
	_SerCxSys.immediate_char = pSerialSys->immediate_char;
Packit Service fa4841
Packit Service fa4841
	return &_SerCxSys;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#endif /* __linux__ */