diff options
Diffstat (limited to 'K2LABI/IPC')
-rw-r--r-- | K2LABI/IPC/IPCFlowDecoder.cpp | 140 | ||||
-rw-r--r-- | K2LABI/IPC/IPCFlowDecoder.h | 28 | ||||
-rw-r--r-- | K2LABI/IPC/Ipc.h | 29 | ||||
-rw-r--r-- | K2LABI/IPC/K2LIPC.cpp | 70 | ||||
-rw-r--r-- | K2LABI/IPC/K2LIPC.h | 199 |
5 files changed, 466 insertions, 0 deletions
diff --git a/K2LABI/IPC/IPCFlowDecoder.cpp b/K2LABI/IPC/IPCFlowDecoder.cpp new file mode 100644 index 0000000..6b6ec19 --- /dev/null +++ b/K2LABI/IPC/IPCFlowDecoder.cpp @@ -0,0 +1,140 @@ +#include "windows-adapter.h" +#include "IPCFlowDecoder.h" +#include "Ipc.h" +#include <assert.h> + + +#define PACKET_BUFFER_SIZE (1 << 18) +#define PACKET_TEST_DEPTH 0 + +CIPCFlowDecoder::CIPCFlowDecoder(CIpc* pIpc) : CFlowDecoder() + , m_pPacket(new BYTE[PACKET_BUFFER_SIZE]) + , m_ValidPacketCount(PACKET_TEST_DEPTH) + , m_ReceiveIndex(0) + , m_pIpc(pIpc) +{ +} + +CIPCFlowDecoder::~CIPCFlowDecoder() +{ + delete [] m_pPacket; +} + +void CIPCFlowDecoder::Reset() +{ + m_ReceiveIndex = 0; + m_ValidPacketCount = 0; + this->CFlowDecoder::Reset(); +} + +CFlowDecoder::eStateRetVal CIPCFlowDecoder::ReceiveHeader() +{ + unsigned long bytesMissingForHeader = sizeof(CIpcPacket) - m_ReceiveIndex; + unsigned long bytesToAppend = (bytesMissingForHeader <= GetNumberOfBytesInBuffer() ) ? bytesMissingForHeader : GetNumberOfBytesInBuffer(); + + if (!CopyFromBuffer(&m_pPacket[m_ReceiveIndex], bytesToAppend) ) + return E_STATE_NEEDS_MORE_DATA; + + m_ReceiveIndex += bytesToAppend; + + if (m_ReceiveIndex < sizeof(CIpcPacket) ) + { + RemoveBytesFromBuffer(bytesToAppend); + return E_STATE_NEEDS_MORE_DATA; + } + + CIpcPacket* pHeader = reinterpret_cast<CIpcPacket*>(m_pPacket); + + if (pHeader->m_head != ABI_IPC_PACKET_HEAD) + { + if(m_nSynchronized && m_pIpc) + { + //::OutputDebugString("Check: Head wrong\n"); + IIPCListener* listener = m_pIpc->GetListener(); + + if(listener) + listener->OnError(m_pIpc); + } + + // Something went wrong... + m_ReceiveIndex = 0; + m_ValidPacketCount = 0; + + // Remove 1 byte from buffer + RemoveBytesFromBuffer(1); + return E_STATE_GOT_WRONG_DATA; + } + + // We've found a header now check the checksum + unsigned char checksum = 0; + + // Omit last byte -> checksum! + for (int i = 0; i < sizeof(CIpcPacket) - 1; i++) + { + checksum += m_pPacket[i]; + } + + if (checksum != pHeader->m_hdrCrc) + { + if(m_nSynchronized && m_pIpc) + { + //::OutputDebugString("Check: Crc wrong\n"); + IIPCListener* listener = m_pIpc->GetListener(); + if(listener) + listener->OnError(m_pIpc); + } + + // Something went wrong... + m_ReceiveIndex = 0; + m_ValidPacketCount = 0; + + // Remove 1 byte from buffer + RemoveBytesFromBuffer(1); + return E_STATE_GOT_WRONG_DATA; + } + //if(!m_nSynchronized) ::OutputDebugString("Check: Header correct\n"); + m_nSynchronized = true; + + RemoveBytesFromBuffer(bytesToAppend); + + // Valid header found!!! + return E_STATE_OK; +} + +CFlowDecoder::eStateRetVal CIPCFlowDecoder::ReceivePacket() +{ + unsigned long nLengthOfPacket = reinterpret_cast<CIpcPacket*>(m_pPacket)->m_length + sizeof(CIpcPacket); + unsigned long bytesMissingForPacket = nLengthOfPacket - m_ReceiveIndex; + unsigned long bytesToAppend = (bytesMissingForPacket > GetNumberOfBytesInBuffer() ) ? GetNumberOfBytesInBuffer() : bytesMissingForPacket; + + // Copy buffer... should (must) never fail! + if (!CopyFromBuffer(&m_pPacket[m_ReceiveIndex], bytesToAppend) ) + return E_STATE_NEEDS_MORE_DATA; + + // Accept the data as valid now and go on... + m_ReceiveIndex += bytesToAppend; + + // Remove bytes from source buffer... + RemoveBytesFromBuffer(bytesToAppend); + + // Received enough data? + if (m_ReceiveIndex < nLengthOfPacket) + return E_STATE_NEEDS_MORE_DATA; + + m_ReceiveIndex = 0; + + if (m_ValidPacketCount >= PACKET_TEST_DEPTH) + { + // Dispatch Message if there's was no overflow during copy! + if (m_pIpc) + { + m_pIpc->OnPacket(reinterpret_cast<CIpcPacket*>(m_pPacket) ); + } + } + else + { + m_ValidPacketCount++; + } + + return E_STATE_OK; +} diff --git a/K2LABI/IPC/IPCFlowDecoder.h b/K2LABI/IPC/IPCFlowDecoder.h new file mode 100644 index 0000000..d099275 --- /dev/null +++ b/K2LABI/IPC/IPCFlowDecoder.h @@ -0,0 +1,28 @@ +#ifndef __IPC_FLOW_DECODER_H__ +#define __IPC_FLOW_DECODER_H__ + +#include "FlowDecoder.h" +#include "K2LIPC.h" + +using namespace K2L::Automotive::IPC; +class CIpc; + +class CIPCFlowDecoder : public CFlowDecoder +{ +public: + CIPCFlowDecoder(CIpc* pIpc); + ~CIPCFlowDecoder(); + virtual void Reset(); + +protected: + eStateRetVal ReceiveHeader(); + eStateRetVal ReceivePacket(); + +private: + BYTE* m_pPacket; + unsigned long m_ReceiveIndex; + int m_ValidPacketCount; + CIpc* m_pIpc; +}; + +#endif // __IPC_FLOW_DECODER_H__ diff --git a/K2LABI/IPC/Ipc.h b/K2LABI/IPC/Ipc.h new file mode 100644 index 0000000..1775ebf --- /dev/null +++ b/K2LABI/IPC/Ipc.h @@ -0,0 +1,29 @@ +#pragma once +#include "K2LIPC.h" +#include "SLock.h" + +using namespace K2L::Automotive::IPC; + +class CIpc : public IIpc +{ +public: + CIpc(); + virtual ~CIpc(); + + int Init(IIPCListener* pListener); + int Deinit(); + int FormatRequest(BYTE channel, BYTE ifaceId, BYTE funId, DWORD dwSenderID, const BYTE *pData, DWORD dataLen, BYTE* pResult, int nResultLen, int* nResultLenNeeded); + IIPCListener* GetListener(); + void OnPacket(CIpcPacket* pPacket); + void Decode(BYTE* pBuffer, DWORD nLen); + IIPCListener* CreateListener(FCT_OnMessageEvent callback, FCT_OnEvent error, FCT_OnEvent overflow); + void DestroyListener(); + +private: + CIPCFlowDecoder* m_pFlowDecoder; + BYTE* m_pResultBuffer; + int m_nResultLen; + int m_errorCode; + IIPCListener* m_pIpcListener; + CLock m_lock; +};
\ No newline at end of file diff --git a/K2LABI/IPC/K2LIPC.cpp b/K2LABI/IPC/K2LIPC.cpp new file mode 100644 index 0000000..5d17359 --- /dev/null +++ b/K2LABI/IPC/K2LIPC.cpp @@ -0,0 +1,70 @@ +#include "windows-adapter.h" +#include "K2LIPC.h" +#include "IPCFlowDecoder.h" +#include "Ipc.h" + +IIpc* CIpcFactory::CreateIpc() +{ + return new CIpc(); +} + +//----------------------------------------------------------------------------- +void CIpcFactory::DestroyIpc(IIpc* pIpc) +{ + delete pIpc; +} + +//----------------------------------------------------------------------------- +K2LABI_API IPC_HANDLE CreateIPC() +{ + CIpc* pIpc = new CIpc; + return reinterpret_cast<IPC_HANDLE>(pIpc); +} + +//----------------------------------------------------------------------------- +K2LABI_API void DestroyIPC(IPC_HANDLE hIpc) +{ + CIpc* pIpc = reinterpret_cast<CIpc*>(hIpc); + delete pIpc; +} + +//----------------------------------------------------------------------------- +K2LABI_API int IPCInit(IPC_HANDLE hIpc, FCT_OnMessageEvent callback, FCT_OnEvent error, FCT_OnEvent overflow) +{ + CIpc* pIpc = reinterpret_cast<CIpc*>(hIpc); + if (!pIpc) + return -1; + + IIPCListener* pListener = pIpc->CreateListener(callback, error, overflow); + return pIpc->Init(pListener); +} + +//----------------------------------------------------------------------------- +K2LABI_API int IPCDeinit(IPC_HANDLE hIpc) +{ + CIpc* pIpc = reinterpret_cast<CIpc*>(hIpc); + if (!pIpc) + return -1; + + pIpc->DestroyListener(); + return pIpc->Deinit(); +} + +//----------------------------------------------------------------------------- +K2LABI_API int IPCFormatRequest(IPC_HANDLE hIpc, BYTE channel, BYTE ifaceId, BYTE funId, DWORD dwSenderID, const BYTE *pReqData, DWORD dataLen, BYTE* pResult, int nResultLen, int* nNeededResultLen) +{ + CIpc* pIpc = reinterpret_cast<CIpc*>(hIpc); + if (!pIpc) + return -1; + + return pIpc->FormatRequest(channel, ifaceId, funId, dwSenderID, pReqData, dataLen, pResult, nResultLen, nNeededResultLen); +} + +//----------------------------------------------------------------------------- +K2LABI_API void IPCDecode(IPC_HANDLE hIpc, BYTE* pData, int nDataLen) +{ + CIpc* pIpc = reinterpret_cast<CIpc*>(hIpc); + + if (pIpc) + pIpc->Decode(pData, nDataLen); +} diff --git a/K2LABI/IPC/K2LIPC.h b/K2LABI/IPC/K2LIPC.h new file mode 100644 index 0000000..e959dbf --- /dev/null +++ b/K2LABI/IPC/K2LIPC.h @@ -0,0 +1,199 @@ +/*=== K2L GmbH ===============================================================*/ +/** +\file + This file contains the API of the \ref IPC interface. + +\ingroup IPC + +\par COPYRIGHT (c) 2000-2011 by K2L GmbH + All rights reserved. +*/ +/*============================================================================== + Alle Rechte an der Software verbleiben bei der K2L GmbH. + + Die K2L GmbH raeumt dem Lizenznehmer nach vollstaendiger + Bezahlung der Lizenzgebuehr ein nicht ausschliessliches, + unwiderrufliches, nicht uebertragbares, zeitlich und geografisch + nicht beschraenktes Recht zur Nutzung der jeweils + auftragsgegenstaendlichen Software innerhalb des Lizenznehmers ein. + + Die Weitergabe des Nutzungsrechts durch den Lizenznehmer ist auf + dessen Zulieferer beschraenkt. Die Zulieferer sind zu verpflichten, + die Software nur im Rahmen von Projekten fuer den Lizenznehmer + zu verwenden; weitere Rechte der Zulieferer sind auszuschliessen. +===HEADER END=================================================================*/ +//@{ + +#pragma once + +/// \defgroup IPC Interprocess communication +/// The IPC group ... +namespace K2L +{ + namespace Automotive + { + namespace IPC + { + +class IIpc; + +/// Identifies the head of the packet. +#define ABI_IPC_PACKET_HEAD 0x04 + +/// Identifies the IPC channel 7. +#define ABI_IPC_CHANNEL7 0x07 + +/// Identifies the IPC channel 8. +#define ABI_IPC_CHANNEL8 0x08 + +#pragma pack(push, 1) +/// \brief Class holding all informations to create a IPC message. +/// \ingroup IPC +class CIpcPacket +{ +public: + /// The header of the IPC packet. + BYTE m_head; + + /// The channel of the IPC packet. + BYTE m_channel; + + /// The length of the IPC packet. + DWORD m_length; + + /// The error code of the IPC packet. + BYTE m_errorCode; + + /// Checksum of the IPC header. + BYTE m_hdrCrc; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +/// \brief Class holding all informations to create a IPC request. +/// \ingroup IPC +class CRequest +{ +public: + /// Message processing group in the ABI device. + BYTE m_interface; + + /// Function id of the request. + BYTE m_function; + + /// Request Id. + DWORD m_requestId; +}; +#pragma pack(pop) + +/*============================================================================*/ +/// \brief Interface of IPC event listener. +/// \note Abstract base class. So it has to be implemented. +/// \ingroup IPC +/*============================================================================*/ +class K2LABI_API IIPCListener +{ +public: + virtual ~IIPCListener() {} + + /// Called if packet arrived. + /// \param[in] pIpc Pointer to IPC that has occured event. + /// \param[in] pPacket Pointer to data package. + /// \param[in] nLen Length of package. + virtual void OnMessage(IIpc* pIpc, BYTE channel, BYTE errorCode, BYTE* pPacket, int nLen) = 0; + + /// Called if error occured. + /// \param[in] pIpc Pointer to IPC that has occured event. + virtual void OnError(IIpc* pIpc) = 0; + + /// Called if message lost caused by an overflow. + /// \param[in] pIpc Pointer to IPC that has occured event. + virtual void OnMessageLost(IIpc* pIpc) = 0; +}; + +/*============================================================================*/ +/// \brief Interface of interprocess connection. +/// \ingroup IPC +/*============================================================================*/ +class K2LABI_API IIpc +{ +public: + virtual ~IIpc() {} + + /// Initializes IPC connection. + /// \param[in] Device to connect. + /// \param[in] Event listener. + /// \return 0 if operation successful. + /// \return !0 if operation failed. + virtual int Init(IIPCListener* pListener) = 0; + + /// Deinitializes IPC connection. + /// \return 0 if operation successful. + /// \return !0 if operation failed. + virtual int Deinit() = 0; + + /// Sends a request to the device. + /// \param[in] Namespace ID of command. + /// \param[in] Function ID of command. + /// \param[in] Pointer to data that should be send. + /// \param[in] Length of data. + /// \param[out] Length of result. + /// \param[out] Error code of operation. + /// \return Response of request. NULL if no response returned. + virtual int FormatRequest(BYTE channel, BYTE ifaceId, BYTE funId, DWORD dwSenderID, const BYTE *pData, DWORD dataLen, BYTE* pResult, int nResultLen, int* nResultLenNeeded) = 0; + + /// Decodes a IPC message from the buffer. + /// \param[in] pPipe Pipe to check if an overflow occurr. + /// \param[in] pBuffer Pointer to the first byte of message that should be decoded. + /// \param[in] nLen Length of message. + virtual void Decode(BYTE* pBuffer, DWORD nLen) = 0; + + /// Gets a pointer to the registered event listener. + /// \return Pointer to event listener. + virtual IIPCListener* GetListener() = 0; +}; + +/*============================================================================*/ +/// \brief Factory to create IPC connections. +/// \ingroup IPC +/*============================================================================*/ +class K2LABI_API CIpcFactory +{ +public: + /// Create new IPC connection. + /// \return Pointer to new IPC connection. + static IIpc* CreateIpc(); + + /// Destroy IPC connection. + /// \param[in] Pointer to IPC connection that should be destroied. + static void DestroyIpc(IIpc* pIpc); +}; + } + } +} + +/*============================================================================*/ +/* C interface */ +/*============================================================================*/ + +extern "C" +{ +#define IPC_HANDLE HANDLE + +typedef void (*FCT_OnMessageEvent) (IPC_HANDLE, BYTE, BYTE, BYTE*, int); +typedef void (*FCT_OnEvent) (IPC_HANDLE); + +K2LABI_API IPC_HANDLE CreateIPC (); +K2LABI_API void DestroyIPC (IPC_HANDLE hIpc); + +K2LABI_API int IPCInit (IPC_HANDLE hIpc, FCT_OnMessageEvent callback, FCT_OnEvent error, FCT_OnEvent overflow); +K2LABI_API int IPCDeinit (IPC_HANDLE hIpc); +K2LABI_API int IPCFormatRequest (IPC_HANDLE hIpc, BYTE channel, BYTE ifaceId, BYTE funId, DWORD dwSenderID, const BYTE *pReqData, DWORD dataLen, BYTE* pResult, int nResultLen, int* nNeededResultLen); +K2LABI_API void IPCDecode (IPC_HANDLE hIpc, BYTE* pData, int nDataLen); +K2LABI_API void IPCDecodeFlow (IPC_HANDLE hIpc, HANDLE hReaderPipe, BYTE* pData, int nDataLen); +} + +//@} +/*============================================================================*/ +/* END OF FILE */ +/*============================================================================*/ |