blob: 9e7a6ccfff75bb683254efcc5f59e6270bf99c06 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2017 ACIN, fortiss GmbH
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Martin Melik-Merkumians, Alois Zoitl - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "cwin32sercomlayer.h"
#include "cwin32sercomhandler.h"
#include "../../../core/cominfra/commfb.h"
CWin32SerComLayer::CWin32SerComLayer(forte::com_infra::CComLayer* paUpperLayer,
forte::com_infra::CBaseCommFB* paFB) :
CSerialComLayerBase(paUpperLayer, paFB){
}
CWin32SerComLayer::~CWin32SerComLayer() {
closeConnection();
}
forte::com_infra::EComResponse CWin32SerComLayer::recvData(const void *, unsigned int ) {
mInterruptResp = forte::com_infra::e_Nothing;
DWORD dwBytesRead = 0;
if(ReadFile(static_cast<HANDLE>(mSerialHandle), mRecvBuffer, mMaxRecvBuffer - 1, &dwBytesRead, NULL)){ //TODO: Failure handling and send INITO-
if(0 < dwBytesRead){
mBufFillSize = dwBytesRead;
mInterruptResp = forte::com_infra::e_ProcessDataOk;
m_poFb->interruptCommFB(this);
}
else{
mInterruptResp = forte::com_infra::e_ProcessDataRecvFaild;
}
}
return mInterruptResp;
}
forte::com_infra::EComResponse CWin32SerComLayer::sendData(void *paData, unsigned int paSize)
{
DWORD dwBytesWritten= 0, dwWaitResult = 0;
char *pcData = static_cast<char*> (paData);
unsigned int nToBeSent = paSize;
//Send payload
if(!WriteFile(static_cast<HANDLE>(mSerialHandle), pcData, nToBeSent, &dwBytesWritten, NULL))
{
return forte::com_infra::e_ProcessDataSendFailed;
}
if(dwBytesWritten != nToBeSent)
{
return forte::com_infra::e_ProcessDataSendFailed;
}
//Send termination symbol(s)
if (!WriteFile(static_cast<HANDLE>(mSerialHandle), mTerminationSymbol, strlen(mTerminationSymbol), &dwBytesWritten, NULL))
{
return forte::com_infra::e_ProcessDataSendFailed;
}
if (strlen(mTerminationSymbol) != dwBytesWritten)
{
return forte::com_infra::e_ProcessDataSendFailed;
}
return forte::com_infra::e_ProcessDataOk;
}
forte::com_infra::EComResponse CWin32SerComLayer::openSerialConnection(const SSerialParameters& paSerialParameters, CSerialComLayerBase<HANDLE>::TSerialHandleType* paHandleResult){
HANDLE serialHandle = CreateFile(
paSerialParameters.interfaceName.getValue(),
GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == serialHandle){
if(ERROR_FILE_NOT_FOUND == GetLastError()){
return forte::com_infra::e_ProcessDataNoSocket;
}
return forte::com_infra::e_ProcessDataInvalidObject;
}
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if(!GetCommState(serialHandle, &dcbSerialParams)){
return forte::com_infra::e_ProcessDataNoSocket;
}
dcbSerialParams.BaudRate = static_cast<DWORD>(paSerialParameters.baudRate);
switch (paSerialParameters.baudRate) {
//These are ok baud rates
case e110: break;
case e300: break;
case e600: break;
case e1200: break;
case e2400: break;
case e4800: break;
case e9600: break;
case e14400: break;
case e19200: break;
case e38400: break;
case e57600: break;
case e115200: break;
case e128000: break;
case e256000: break;
//all other numbers are invalid!
default: return forte::com_infra::e_InitInvalidId; break;
}
dcbSerialParams.ByteSize = static_cast<DWORD>(paSerialParameters.byteSize);
switch (paSerialParameters.stopBits){
case EForteSerialStopBits::eOneBit:
dcbSerialParams.StopBits = ONESTOPBIT;
break;
case EForteSerialStopBits::eOne5Bits:
dcbSerialParams.StopBits = ONE5STOPBITS;
break;
case EForteSerialStopBits::eTwoBits:
dcbSerialParams.StopBits = TWOSTOPBITS;
break;
}
switch (paSerialParameters.parity){
case EForteSerialParity::eNoParity:
dcbSerialParams.Parity = NOPARITY;
break;
case EForteSerialParity::eODD:
dcbSerialParams.Parity = ODDPARITY;
break;
case EForteSerialParity::eEven:
dcbSerialParams.Parity = EVENPARITY;
break;
case EForteSerialParity::eMark:
dcbSerialParams.Parity = MARKPARITY;
break;
case EForteSerialParity::eSpace:
dcbSerialParams.Parity = SPACEPARITY;
break;
}
if(!SetCommState(serialHandle, &dcbSerialParams)){
return forte::com_infra::e_ProcessDataNoSocket;
}
//Timeouts for non-blocking behaviour
COMMTIMEOUTS timeouts = { 0 };
//Read timeouts
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
//Write timeouts
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if(!SetCommTimeouts(serialHandle, &timeouts)){
return forte::com_infra::e_ProcessDataNoSocket;
}
switch (m_poFb->getComServiceType()){
case forte::com_infra::e_Server:
case forte::com_infra::e_Client:
getExtEvHandler<CWin32SerComHandler>().registerSerComLayer(this);
m_eConnectionState = forte::com_infra::e_Connected;
break;
case forte::com_infra::e_Publisher:
break;
case forte::com_infra::e_Subscriber:
break;
}
*paHandleResult = static_cast<void*>(serialHandle);
return forte::com_infra::e_InitOk;
}
void CWin32SerComLayer::closeConnection() {
getExtEvHandler<CWin32SerComHandler>().unregisterSerComLayer(this);
CloseHandle(static_cast<HANDLE>(mSerialHandle));
}