aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/epl/SharedBuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/epl/SharedBuff.c')
-rw-r--r--drivers/staging/epl/SharedBuff.c2041
1 files changed, 2041 insertions, 0 deletions
diff --git a/drivers/staging/epl/SharedBuff.c b/drivers/staging/epl/SharedBuff.c
new file mode 100644
index 00000000000..1833d718246
--- /dev/null
+++ b/drivers/staging/epl/SharedBuff.c
@@ -0,0 +1,2041 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Implementation of platform independend part for the
+ shared buffer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/27 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#if defined(WIN32) || defined(_WIN32)
+
+ #ifdef UNDER_RTSS
+ // RTX header
+ #include <windows.h>
+ #include <process.h>
+ #include <rtapi.h>
+
+ #elif __BORLANDC__
+ // borland C header
+ #include <windows.h>
+ #include <process.h>
+
+ #elif WINCE
+ #include <windows.h>
+
+ #else
+ // MSVC needs to include windows.h at first
+ // the following defines ar necessary for function prototypes for waitable timers
+ #define _WIN32_WINDOWS 0x0401
+ #define _WIN32_WINNT 0x0400
+ #include <windows.h>
+ #include <process.h>
+ #endif
+
+#endif
+
+#include "global.h"
+#include "SharedBuff.h"
+#include "ShbIpc.h"
+
+// d.k. Linux kernel modules needs other header files for memcpy()
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ #include <linux/string.h>
+#else
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+#endif
+
+
+
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------
+// Constant definitions
+//---------------------------------------------------------------------------
+
+#define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
+#define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
+
+
+
+//---------------------------------------------------------------------------
+// Local types
+//---------------------------------------------------------------------------
+
+// structure to administrate circular shared buffer head
+typedef struct
+{
+ unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
+ unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
+ unsigned long m_ulBufferDataSize; // size of complete data area
+ unsigned long m_ulWrIndex; // current write index (set bevore write)
+ unsigned long m_ulRdIndex; // current read index (set after read)
+ unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
+ unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
+ unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
+ unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
+ unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
+ unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
+ tShbCirSigHndlrNewData m_pfnSigHndlrNewData;// application handler to signal new data
+ unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
+ tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
+ unsigned char m_Data; // start of data area (the real data size is unknown at this time)
+
+} tShbCirBuff;
+
+
+// structure to administrate linear shared buffer head
+typedef struct
+{
+ unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
+ unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
+ unsigned long m_ulBufferDataSize; // size of complete data area
+ unsigned char m_Data; // start of data area (the real data size is unknown at this time)
+
+} tShbLinBuff;
+
+
+// type to save size of a single data block inside the circular shared buffer
+typedef struct
+{
+ unsigned int m_uiFullBlockSize : 28; // a single block must not exceed a length of 256MByte :-)
+ unsigned int m_uiAlignFillBytes : 4;
+
+} tShbCirBlockSize;
+
+#define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
+#define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
+
+#define SBL_BLOCK_ALIGNMENT 4
+#define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
+
+
+
+//---------------------------------------------------------------------------
+// Global variables
+//---------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------
+// Local variables
+//---------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------
+// Prototypes of internal functions
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Get pointer to Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbCirBuff* ShbCirGetBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+
+
+ pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance_p);
+ ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
+
+ return (pShbCirBuff);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Get pointer to Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbLinBuff* ShbLinGetBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbLinBuff* pShbLinBuff;
+
+
+ pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance_p);
+ ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
+
+ return (pShbLinBuff);
+
+}
+
+
+
+// not inlined internal functions
+int ShbCirSignalHandlerNewData (tShbInstance pShbInstance_p);
+void ShbCirSignalHandlerReset (tShbInstance pShbInstance_p, unsigned int fTimeOut_p);
+
+#endif
+
+
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(INLINE_ENABLED)
+// not inlined external functions
+
+//---------------------------------------------------------------------------
+// Initialize Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbInit (void)
+{
+
+tShbError ShbError;
+
+
+ ShbError = ShbIpcInit();
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Deinitialize Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbExit (void)
+{
+
+tShbError ShbError;
+
+
+ ShbError = ShbIpcExit();
+
+ return (ShbError);
+
+}
+
+
+
+
+
+//-------------------------------------------------------------------------//
+// //
+// C i r c u l a r S h a r e d B u f f e r //
+// //
+//-------------------------------------------------------------------------//
+
+//---------------------------------------------------------------------------
+// Allocate Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbCirAllocBuffer (
+ unsigned long ulBufferSize_p,
+ const char* pszBufferID_p,
+ tShbInstance* ppShbInstance_p,
+ unsigned int* pfShbNewCreated_p)
+{
+
+tShbInstance pShbInstance;
+tShbCirBuff* pShbCirBuff;
+unsigned int fShbNewCreated;
+unsigned long ulBufferDataSize;
+unsigned long ulBufferTotalSize;
+tShbError ShbError;
+
+
+ // check arguments
+ if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL))
+ {
+ return (kShbInvalidArg);
+ }
+
+
+ // calculate length of memory to allocate
+ ulBufferDataSize = (ulBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
+ ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
+
+ // allocate a new or open an existing shared buffer
+ ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p,
+ &pShbInstance, &fShbNewCreated);
+ if (ShbError != kShbOk)
+ {
+ goto Exit;
+ }
+
+ if (pShbInstance == NULL)
+ {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+
+ // get pointer to shared buffer
+ pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance);
+
+ // if the shared buffer was new created, than this process has
+ // to initialize it, otherwise the buffer is already in use
+ // and *must not* be reseted
+ if ( fShbNewCreated )
+ {
+ #ifndef NDEBUG
+ {
+ memset (pShbCirBuff, 0xCC, ulBufferTotalSize);
+ }
+ #endif
+
+
+ pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
+ pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
+ pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ pShbCirBuff->m_ulNumOfWriteJobs = 0;
+ pShbCirBuff->m_ulDataInUse = 0;
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+ pShbCirBuff->m_ulDataReadable = 0;
+ pShbCirBuff->m_ulBlocksReadable = 0;
+ pShbCirBuff->m_pfnSigHndlrNewData = NULL;
+ pShbCirBuff->m_fBufferLocked = FALSE;
+ pShbCirBuff->m_pfnSigHndlrReset = NULL;
+ }
+ else
+ {
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+ }
+
+
+Exit:
+
+ *ppShbInstance_p = pShbInstance;
+ *pfShbNewCreated_p = fShbNewCreated;
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Release Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbCirReleaseBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+
+ ShbError = ShbIpcReleaseBuffer (pShbInstance_p);
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+#endif // !defined(INLINE_ENABLED)
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Reset Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirResetBuffer (
+ tShbInstance pShbInstance_p,
+ unsigned long ulTimeOut_p,
+ tShbCirSigHndlrReset pfnSignalHandlerReset_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // start reset job by setting request request in buffer header
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ if ( !pShbCirBuff->m_fBufferLocked )
+ {
+ ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
+
+ pShbCirBuff->m_fBufferLocked = TRUE;
+ pShbCirBuff->m_pfnSigHndlrReset = pfnSignalHandlerReset_p;
+ }
+ else
+ {
+ ShbError = kShbAlreadyReseting;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+ if (ShbError != kShbOk)
+ {
+ goto Exit;
+ }
+
+
+ // if there is currently no running write operation then reset buffer
+ // immediately, otherwise wait until the last write job is ready by
+ // starting a signal process
+ if (ulNumOfWriteJobs == 0)
+ {
+ // there is currently no running write operation
+ // -> reset buffer immediately
+ ShbCirSignalHandlerReset (pShbInstance_p, FALSE);
+ ShbError = kShbOk;
+ }
+ else
+ {
+ // there is currently at least one running write operation
+ // -> starting signal process to wait until the last write job is ready
+ ShbError = ShbIpcStartSignalingJobReady (pShbInstance_p, ulTimeOut_p, ShbCirSignalHandlerReset);
+ }
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Write data block to Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirWriteDataBlock (
+ tShbInstance pShbInstance_p,
+ const void* pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+tShbCirBlockSize ShbCirBlockSize;
+unsigned int uiFullBlockSize;
+unsigned int uiAlignFillBytes;
+unsigned char* pShbCirDataPtr;
+unsigned char* pScrDataPtr;
+unsigned long ulDataSize;
+unsigned long ulChunkSize;
+unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
+unsigned int fSignalNewData;
+unsigned int fSignalReset;
+tShbError ShbError;
+tShbError ShbError2;
+int fRes;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
+ {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE)
+ {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ pScrDataPtr = (unsigned char*)pSrcDataBlock_p;
+ fSignalNewData = FALSE;
+ fSignalReset = FALSE;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // calculate data block size in circular buffer
+ ulDataSize = (ulDataBlockSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
+ uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
+ uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
+
+ ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
+ ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
+
+
+ // reserve the needed memory for the write operation to do now
+ // and make necessary adjustments in the circular buffer header
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ // check if there is sufficient memory available to store
+ // the new data
+ fRes = uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse);
+ if ( fRes )
+ {
+ // set write pointer for the write operation to do now
+ // to the current write pointer of the circular buffer
+ ulWrIndex = pShbCirBuff->m_ulWrIndex;
+
+ // reserve the needed memory for the write operation to do now
+ pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
+
+ // set new write pointer behind the reserved memory
+ // for the write operation to do now
+ pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
+ pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // increment number of currently (parallel running)
+ // write operations
+ pShbCirBuff->m_ulNumOfWriteJobs++;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ if ( !fRes )
+ {
+ ShbError = kShbBufferFull;
+ goto Exit;
+ }
+
+
+ // copy the data to the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+ // write real size of current block (incl. alignment fill bytes)
+ *(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
+ ulWrIndex += sizeof(tShbCirBlockSize);
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize)
+ {
+ // linear write operation
+ memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataBlockSize_p);
+ }
+ else
+ {
+ // wrap-around write operation
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
+ memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
+ memcpy (pShbCirDataPtr, pScrDataPtr + ulChunkSize, ulDataBlockSize_p - ulChunkSize);
+ }
+
+
+ // adjust header information for circular buffer with properties
+ // of the wiritten data block
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataApended += uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksApended ++;
+
+ // decrement number of currently (parallel running) write operations
+ if ( !--pShbCirBuff->m_ulNumOfWriteJobs )
+ {
+ // if there is no other write process running then
+ // set new size of readable (complete written) data and
+ // adjust number of readable blocks
+ pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended;
+ pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended;
+
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+
+ fSignalNewData = TRUE;
+ fSignalReset = pShbCirBuff->m_fBufferLocked;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ // signal new data event to a potentially reading application
+ if ( fSignalNewData )
+ {
+ ShbError2 = ShbIpcSignalNewData (pShbInstance_p);
+ if (ShbError == kShbOk)
+ {
+ ShbError = ShbError2;
+ }
+ }
+
+ // signal that the last write job has been finished to allow
+ // a waiting application to reset the buffer now
+ if ( fSignalReset )
+ {
+ ShbError2 = ShbIpcSignalJobReady (pShbInstance_p);
+ if (ShbError == kShbOk)
+ {
+ ShbError = ShbError2;
+ }
+ }
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Allocate block within the Circular Shared Buffer for chunk writing
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirAllocDataBlock (
+ tShbInstance pShbInstance_p,
+ tShbCirChunk* pShbCirChunk_p,
+ unsigned long ulDataBufferSize_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+tShbCirBlockSize ShbCirBlockSize;
+unsigned int uiFullBlockSize;
+unsigned int uiAlignFillBytes;
+unsigned char* pShbCirDataPtr;
+unsigned long ulDataSize;
+unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
+tShbError ShbError;
+int fRes;
+
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL))
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if (ulDataBufferSize_p == 0)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE)
+ {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // calculate data block size in circular buffer
+ ulDataSize = (ulDataBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
+ uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
+ uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
+
+ ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
+ ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
+
+
+ // reserve the needed memory for the write operation to do now
+ // and make necessary adjustments in the circular buffer header
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ // check if there is sufficient memory available to store
+ // the new data
+ fRes = (uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse));
+ if ( fRes )
+ {
+ // set write pointer for the write operation to do now
+ // to the current write pointer of the circular buffer
+ ulWrIndex = pShbCirBuff->m_ulWrIndex;
+
+ // reserve the needed memory for the write operation to do now
+ pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
+
+ // set new write pointer behind the reserved memory
+ // for the write operation to do now
+ pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
+ pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // increment number of currently (parallel running)
+ // write operations
+ pShbCirBuff->m_ulNumOfWriteJobs++;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ if ( !fRes )
+ {
+ ShbError = kShbBufferFull;
+ goto Exit;
+ }
+
+
+ // setup header information for allocated buffer
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+ // write real size of current block (incl. alignment fill bytes)
+ *(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
+ ulWrIndex += sizeof(tShbCirBlockSize);
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // setup chunk descriptor
+ pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
+ pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
+ pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
+ pShbCirChunk_p->m_fBufferCompleted = FALSE;
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Write data chunk into an allocated buffer of the Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirWriteDataChunk (
+ tShbInstance pShbInstance_p,
+ tShbCirChunk* pShbCirChunk_p,
+ const void* pSrcDataChunk_p,
+ unsigned long ulDataChunkSize_p,
+ unsigned int* pfBufferCompleted_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+unsigned char* pShbCirDataPtr;
+unsigned char* pScrDataPtr;
+unsigned long ulSubChunkSize;
+unsigned long ulWrIndex;
+unsigned int fBufferCompleted;
+unsigned int fSignalNewData;
+unsigned int fSignalReset;
+tShbError ShbError;
+tShbError ShbError2;
+
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL) || (pfBufferCompleted_p == NULL))
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0))
+ {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if ( pShbCirChunk_p->m_fBufferCompleted )
+ {
+ ShbError = kShbBufferAlreadyCompleted;
+ goto Exit;
+ }
+
+ if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize)
+ {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ pScrDataPtr = (unsigned char*)pSrcDataChunk_p;
+ fSignalNewData = FALSE;
+ fSignalReset = FALSE;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
+
+
+ // copy the data to the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+
+ if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize)
+ {
+ // linear write operation
+ memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataChunkSize_p);
+ }
+ else
+ {
+ // wrap-around write operation
+ ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
+ memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
+ memcpy (pShbCirDataPtr, pScrDataPtr + ulSubChunkSize, ulDataChunkSize_p - ulSubChunkSize);
+ }
+
+
+ // adjust chunk descriptor
+ ulWrIndex += ulDataChunkSize_p;
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
+ pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
+
+ fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
+ pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
+
+
+ // if the complete allocated buffer is filled with data then
+ // adjust header information for circular buffer with properties
+ // of the wiritten data block
+ if ( fBufferCompleted )
+ {
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataApended += pShbCirChunk_p->m_uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksApended ++;
+
+ // decrement number of currently (parallel running) write operations
+ if ( !--pShbCirBuff->m_ulNumOfWriteJobs )
+ {
+ // if there is no other write process running then
+ // set new size of readable (complete written) data and
+ // adjust number of readable blocks
+ pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended;
+ pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended;
+
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+
+ fSignalNewData = TRUE;
+ fSignalReset = pShbCirBuff->m_fBufferLocked;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+ }
+
+
+ // signal new data event to a potentially reading application
+ if ( fSignalNewData )
+ {
+ ShbError2 = ShbIpcSignalNewData (pShbInstance_p);
+ if (ShbError == kShbOk)
+ {
+ ShbError = ShbError2;
+ }
+ }
+
+ // signal that the last write job has been finished to allow
+ // a waiting application to reset the buffer now
+ if ( fSignalReset )
+ {
+ ShbError2 = ShbIpcSignalJobReady (pShbInstance_p);
+ if (ShbError == kShbOk)
+ {
+ ShbError = ShbError2;
+ }
+ }
+
+
+ *pfBufferCompleted_p = fBufferCompleted;
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Read data block from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirReadDataBlock (
+ tShbInstance pShbInstance_p,
+ void* pDstDataBlock_p,
+ unsigned long ulRdBuffSize_p,
+ unsigned long* pulDataBlockSize_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+tShbCirBlockSize ShbCirBlockSize;
+unsigned long ulDataReadable;
+unsigned char* pShbCirDataPtr;
+unsigned char* pDstDataPtr;
+unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
+unsigned long ulChunkSize;
+unsigned long ulRdIndex;
+tShbError ShbError;
+
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL))
+ {
+ return (kShbInvalidArg);
+ }
+
+ if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0))
+ {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+
+ ShbError = kShbOk;
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ pDstDataPtr = (unsigned char*)pDstDataBlock_p;
+ ulDataSize = 0;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // get total number of readable bytes for the whole circular buffer
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ // if there are readable data available, then there must be at least
+ // one complete readable data block
+ if (ulDataReadable > 0)
+ {
+ // get pointer to start of data area and current read index
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+ ulRdIndex = pShbCirBuff->m_ulRdIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex);
+ ulRdIndex += sizeof(tShbCirBlockSize);
+ ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // get size of user data inside the current block
+ ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+ }
+
+
+ // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
+ if (ulDataSize > ulRdBuffSize_p)
+ {
+ ulDataSize = ulRdBuffSize_p;
+ ShbError = kShbDataTruncated;
+ }
+
+ if (ulDataSize == 0)
+ {
+ // nothing to do here
+ ShbError = kShbNoReadableData;
+ goto Exit;
+ }
+
+
+ // copy the data from the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
+ {
+ // linear read operation
+ memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
+ }
+ else
+ {
+ // wrap-around read operation
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
+ memcpy (pDstDataPtr + ulChunkSize, pShbCirDataPtr, ulDataSize - ulChunkSize);
+ }
+
+
+ #ifndef NDEBUG
+ {
+ tShbCirBlockSize ClrShbCirBlockSize;
+
+ if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
+ {
+ // linear buffer
+ memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
+ }
+ else
+ {
+ // wrap-around read operation
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
+ memset (pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
+ }
+
+ ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int)*/ -1; // -1 = xFFFFFFF
+ ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int)*/ -1; // -1 = Fxxxxxxx
+ *(tShbCirBlockSize*)(pShbCirDataPtr + pShbCirBuff->m_ulRdIndex) = ClrShbCirBlockSize;
+ }
+ #endif // #ifndef NDEBUG
+
+
+ // set new size of readable data, data in use, new read index
+ // and adjust number of readable blocks
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksReadable --;
+
+ //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ if ((pShbCirBuff->m_ulDataInUse == 0) && (pShbCirBuff->m_ulDataReadable == 0))
+ {
+ ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
+
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ }
+ else
+ //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ {
+ pShbCirBuff->m_ulRdIndex += ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
+ }
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+Exit:
+
+ *pulDataBlockSize_p = ulDataSize;
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Get data size of next readable block from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirGetReadDataSize (
+ tShbInstance pShbInstance_p,
+ unsigned long* pulDataBlockSize_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+unsigned long ulDataReadable;
+unsigned char* pShbCirDataPtr;
+tShbCirBlockSize ShbCirBlockSize;
+unsigned long ulDataSize;
+tShbError ShbError;
+
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL))
+ {
+ return (kShbInvalidArg);
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ulDataSize = 0;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // get total number of readable bytes for the whole circular buffer
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ // if there are readable data available, then there must be at least
+ // one complete readable data block
+ if (ulDataReadable > 0)
+ {
+ pShbCirDataPtr = &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize = *(tShbCirBlockSize*)pShbCirDataPtr;
+
+ // get size of user data inside the current block
+ ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+ }
+
+
+Exit:
+
+ *pulDataBlockSize_p = ulDataSize;
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Get number of readable blocks from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirGetReadBlockCount (
+ tShbInstance pShbInstance_p,
+ unsigned long* pulDataBlockCount_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+unsigned long ulBlockCount;
+tShbError ShbError;
+
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL))
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ulBlockCount = 0;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ *pulDataBlockCount_p = ulBlockCount;
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Set application handler to signal new data for Circular Shared Buffer
+// d.k.: new parameter priority as enum
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData (
+ tShbInstance pShbInstance_p,
+ tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,
+ tShbPriority ShbPriority_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ if (pfnSignalHandlerNewData_p != NULL)
+ {
+ // set a new signal handler
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
+ {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+
+ pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
+ ShbError = ShbIpcStartSignalingNewData (pShbInstance_p, ShbCirSignalHandlerNewData, ShbPriority_p);
+ }
+ else
+ {
+ // remove existing signal handler
+ ShbError = ShbIpcStopSignalingNewData (pShbInstance_p);
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
+ {
+ pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, 0);
+ }
+ pShbCirBuff->m_pfnSigHndlrNewData = NULL;
+ }
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+#endif
+
+#if !defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// DEBUG: Trace Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbCirTraceBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+char szMagigID[sizeof(SBC_MAGIC_ID)+1];
+tShbCirBlockSize ShbCirBlockSize;
+unsigned long ulDataReadable;
+unsigned char* pShbCirDataPtr;
+unsigned long ulBlockIndex;
+unsigned int nBlockCount;
+unsigned long ulDataSize;
+unsigned long ulChunkSize;
+unsigned long ulRdIndex;
+tShbError ShbError;
+
+
+ TRACE0("\n\n##### Circular Shared Buffer #####\n");
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p);
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ *(unsigned long*) &szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
+ szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
+
+
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbCirBuff);
+
+ TRACE0("\nHeader Info:");
+ TRACE2("\nMagigID: '%s' (%08lX)", szMagigID, pShbCirBuff->m_ShbCirMagicID);
+ TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferTotalSize);
+ TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferDataSize);
+ TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
+ TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
+ TRACE1("\nNumOfWriteJobs: %4lu", pShbCirBuff->m_ulNumOfWriteJobs);
+ TRACE1("\nDataInUse: %4lu [Bytes]", pShbCirBuff->m_ulDataInUse);
+ TRACE1("\nDataApended: %4lu [Bytes]", pShbCirBuff->m_ulDataApended);
+ TRACE1("\nBlocksApended: %4lu", pShbCirBuff->m_ulBlocksApended);
+ TRACE1("\nDataReadable: %4lu [Bytes]", pShbCirBuff->m_ulDataReadable);
+ TRACE1("\nBlocksReadable: %4lu", pShbCirBuff->m_ulBlocksReadable);
+ TRACE1("\nSigHndlrNewData: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
+ TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
+ TRACE1("\nSigHndlrReset: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
+
+ ShbTraceDump (&pShbCirBuff->m_Data, pShbCirBuff->m_ulBufferDataSize,
+ 0x00000000L, "\nData Area:");
+
+
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ nBlockCount = 1;
+ ulBlockIndex = pShbCirBuff->m_ulRdIndex;
+
+ while (ulDataReadable > 0)
+ {
+ TRACE1("\n\n--- Block #%u ---", nBlockCount);
+
+ // get pointer to start of data area and current read index
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+ ulRdIndex = ulBlockIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex);
+ ulRdIndex += sizeof(tShbCirBlockSize);
+ ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // get size of user data inside the current block
+ ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+
+ TRACE1("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)", ShbCirBlockSize.m_uiFullBlockSize);
+ TRACE1("\nUser Data Size: %4lu [Bytes]", ulDataSize);
+ TRACE1("\nAlignment Fill Bytes: %4u [Bytes]", ShbCirBlockSize.m_uiAlignFillBytes);
+
+
+ if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
+ {
+ // linear data buffer
+ ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulDataSize, 0x00000000L, NULL);
+ }
+ else
+ {
+ // wrap-around data buffer
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulChunkSize, 0x00000000L, NULL);
+ ShbTraceDump (pShbCirDataPtr, ulDataSize - ulChunkSize, ulChunkSize, NULL);
+ }
+
+ nBlockCount++;
+
+ ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
+ ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
+ }
+
+ ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount-1);
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+
+Exit:
+
+ return (ShbError);
+
+}
+#endif
+
+
+
+
+
+//-------------------------------------------------------------------------//
+// //
+// L i n e a r S h a r e d B u f f e r //
+// //
+//-------------------------------------------------------------------------//
+
+//---------------------------------------------------------------------------
+// Allocate Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbLinAllocBuffer (
+ unsigned long ulBufferSize_p,
+ const char* pszBufferID_p,
+ tShbInstance* ppShbInstance_p,
+ unsigned int* pfShbNewCreated_p)
+{
+
+tShbInstance pShbInstance;
+tShbLinBuff* pShbLinBuff;
+unsigned int fShbNewCreated;
+unsigned long ulBufferDataSize;
+unsigned long ulBufferTotalSize;
+tShbError ShbError;
+
+
+ // check arguments
+ if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL))
+ {
+ return (kShbInvalidArg);
+ }
+
+
+ // calculate length of memory to allocate
+ ulBufferDataSize = (ulBufferSize_p + (SBL_BLOCK_ALIGNMENT-1)) & ~(SBL_BLOCK_ALIGNMENT-1);
+ ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
+
+ // allocate a new or open an existing shared buffer
+ ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p,
+ &pShbInstance, &fShbNewCreated);
+ if (ShbError != kShbOk)
+ {
+ goto Exit;
+ }
+
+ if (pShbInstance == NULL)
+ {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+
+ // get pointer to shared buffer
+ pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance);
+
+ // if the shared buffer was new created, than this process has
+ // to initialize it, otherwise the buffer is already in use
+ // and *must not* be reseted
+ if ( fShbNewCreated )
+ {
+ #ifndef NDEBUG
+ {
+ memset (pShbLinBuff, 0xCC, ulBufferTotalSize);
+ }
+ #endif
+
+
+ pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
+ pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
+ pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
+ }
+ else
+ {
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+ }
+
+
+Exit:
+
+ *ppShbInstance_p = pShbInstance;
+ *pfShbNewCreated_p = fShbNewCreated;
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Release Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbLinReleaseBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+
+ ShbError = ShbIpcReleaseBuffer (pShbInstance_p);
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+#endif // !defined(INLINE_ENABLED)
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Write data block to Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbLinWriteDataBlock (
+ tShbInstance pShbInstance_p,
+ unsigned long ulDstBufferOffs_p,
+ const void* pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+tShbLinBuff* pShbLinBuff;
+unsigned char* pShbLinDataPtr;
+unsigned char* pScrDataPtr;
+unsigned long ulBufferDataSize;
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
+ {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE)
+ {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+
+ pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
+ pScrDataPtr = (unsigned char*)pSrcDataBlock_p;
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // check if offeset and size for the write operation matches with
+ // the size of the shared buffer
+ ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
+ if ( (ulDstBufferOffs_p > ulBufferDataSize) ||
+ (ulDataBlockSize_p > ulBufferDataSize) ||
+ ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) )
+ {
+ ShbError = kShbDataOutsideBufferArea;
+ goto Exit;
+ }
+
+
+ // copy the data to the linear buffer
+ // (the copy process will be done inside of any critical/locked section)
+ pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
+ pShbLinDataPtr += ulDstBufferOffs_p;
+
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ memcpy (pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Read data block from Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbLinReadDataBlock (
+ tShbInstance pShbInstance_p,
+ void* pDstDataBlock_p,
+ unsigned long ulSrcBufferOffs_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+tShbLinBuff* pShbLinBuff;
+unsigned char* pShbLinDataPtr;
+unsigned char* pDstDataPtr;
+unsigned long ulBufferDataSize;
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
+ {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE)
+ {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+
+ pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
+ pDstDataPtr = (unsigned char*)pDstDataBlock_p;
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ // check if offeset and size for the read operation matches with
+ // the size of the shared buffer
+ ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
+ if ( (ulSrcBufferOffs_p > ulBufferDataSize) ||
+ (ulDataBlockSize_p > ulBufferDataSize) ||
+ ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) )
+ {
+ ShbError = kShbDataOutsideBufferArea;
+ goto Exit;
+ }
+
+
+ // copy the data to the linear buffer
+ // (the copy process will be done inside of any critical/locked section)
+ pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
+ pShbLinDataPtr += ulSrcBufferOffs_p;
+
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ memcpy (pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+Exit:
+
+ return (ShbError);
+
+}
+
+#endif
+
+
+#if !defined(INLINE_ENABLED)
+
+
+//---------------------------------------------------------------------------
+// DEBUG: Trace Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbLinTraceBuffer (
+ tShbInstance pShbInstance_p)
+{
+
+tShbLinBuff* pShbLinBuff;
+char szMagigID[sizeof(SBL_MAGIC_ID)+1];
+tShbError ShbError;
+
+
+ TRACE0("\n\n##### Linear Shared Buffer #####\n");
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p);
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+
+ pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
+ {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+
+ *(unsigned int*) &szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
+ szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
+
+
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbLinBuff);
+
+ TRACE0("\nHeader Info:");
+ TRACE2("\nMagigID: '%s' (%08X)", szMagigID, pShbLinBuff->m_ShbLinMagicID);
+ TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferTotalSize);
+ TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferDataSize);
+
+ ShbTraceDump (&pShbLinBuff->m_Data, pShbLinBuff->m_ulBufferDataSize,
+ 0x00000000L, "\nData Area:");
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+
+Exit:
+
+ return (ShbError);
+
+}
+#endif
+
+
+
+
+
+//---------------------------------------------------------------------------
+// Dump buffer contents
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbTraceDump (
+ const unsigned char* pabStartAddr_p,
+ unsigned long ulDataSize_p,
+ unsigned long ulAddrOffset_p,
+ const char* pszInfoText_p)
+{
+
+const unsigned char* pabBuffData;
+unsigned long ulBuffSize;
+unsigned char bData;
+int nRow;
+int nCol;
+
+
+ // get pointer to buffer and length of buffer
+ pabBuffData = pabStartAddr_p;
+ ulBuffSize = ulDataSize_p;
+
+
+ if (pszInfoText_p != NULL)
+ {
+ TRACE0(pszInfoText_p);
+ }
+
+ // dump buffer contents
+ for (nRow=0; ; nRow++)
+ {
+ TRACE1("\n%08lX: ", (unsigned long)(nRow*0x10) + ulAddrOffset_p);
+
+ for (nCol=0; nCol<16; nCol++)
+ {
+ if ((unsigned long)nCol < ulBuffSize)
+ {
+ TRACE1("%02X ", (unsigned int)*(pabBuffData+nCol));
+ }
+ else
+ {
+ TRACE0(" ");
+ }
+ }
+
+ TRACE0(" ");
+
+ for (nCol=0; nCol<16; nCol++)
+ {
+ bData = *pabBuffData++;
+ if ((unsigned long)nCol < ulBuffSize)
+ {
+ if ((bData >= 0x20) && (bData < 0x7F))
+ {
+ TRACE1("%c", bData);
+ }
+ else
+ {
+ TRACE0(".");
+ }
+ }
+ else
+ {
+ TRACE0(" ");
+ }
+ }
+
+ if (ulBuffSize > 16)
+ {
+ ulBuffSize -= 16;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+
+ return (kShbOk);
+
+}
+#endif // #ifndef NDEBUG
+
+
+
+
+
+
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// Handler to signal new data event for Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+int ShbCirSignalHandlerNewData (
+ tShbInstance pShbInstance_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+unsigned long ulDataSize;
+unsigned long ulBlockCount;
+tShbError ShbError;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ return FALSE;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ return FALSE;
+ }
+
+
+ // call application handler
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
+ {
+/* do
+ {*/
+ ShbError = ShbCirGetReadDataSize (pShbInstance_p, &ulDataSize);
+ if ((ulDataSize > 0) && (ShbError == kShbOk))
+ {
+ pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, ulDataSize);
+ }
+
+ ShbError = ShbCirGetReadBlockCount (pShbInstance_p, &ulBlockCount);
+/* }
+ while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
+ }
+
+ // Return TRUE if there are pending blocks.
+ // In that case ShbIpc tries to call this function again immediately if there
+ // is no other filled shared buffer with higher priority.
+ return ((ulBlockCount > 0) && (ShbError == kShbOk));
+
+}
+
+
+
+//---------------------------------------------------------------------------
+// Handler to reset Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+void ShbCirSignalHandlerReset (
+ tShbInstance pShbInstance_p,
+ unsigned int fTimeOut_p)
+{
+
+tShbCirBuff* pShbCirBuff;
+
+
+ // check arguments
+ if (pShbInstance_p == NULL)
+ {
+ return;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
+ {
+ return;
+ }
+
+
+ // reset buffer header
+ if ( !fTimeOut_p )
+ {
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ pShbCirBuff->m_ulNumOfWriteJobs = 0;
+ pShbCirBuff->m_ulDataInUse = 0;
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+ pShbCirBuff->m_ulDataReadable = 0;
+ pShbCirBuff->m_ulBlocksReadable = 0;
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ #ifndef NDEBUG
+ {
+ memset (&pShbCirBuff->m_Data, 0xCC, pShbCirBuff->m_ulBufferDataSize);
+ }
+ #endif
+ }
+
+
+ // call application handler
+ if (pShbCirBuff->m_pfnSigHndlrReset != NULL)
+ {
+ pShbCirBuff->m_pfnSigHndlrReset (pShbInstance_p, fTimeOut_p);
+ }
+
+
+ // unlock buffer
+ ShbIpcEnterAtomicSection (pShbInstance_p);
+ {
+ pShbCirBuff->m_fBufferLocked = FALSE;
+ pShbCirBuff->m_pfnSigHndlrReset = NULL;
+ }
+ ShbIpcLeaveAtomicSection (pShbInstance_p);
+
+
+ return;
+
+}
+
+#endif
+
+
+// EOF
+