1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform independend part for the
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
51 -------------------------------------------------------------------------
53 2006/06/27 -rs: V 1.00 (initial version)
55 ****************************************************************************/
57 #if defined(WIN32) || defined(_WIN32)
74 // MSVC needs to include windows.h at first
75 // the following defines ar necessary for function prototypes for waitable timers
76 #define _WIN32_WINDOWS 0x0401
77 #define _WIN32_WINNT 0x0400
85 #include "SharedBuff.h"
88 #include <linux/string.h>
89 #include <linux/kernel.h>
91 /***************************************************************************/
94 /* G L O B A L D E F I N I T I O N S */
97 /***************************************************************************/
99 //---------------------------------------------------------------------------
101 //---------------------------------------------------------------------------
103 //---------------------------------------------------------------------------
104 // Constant definitions
105 //---------------------------------------------------------------------------
107 #define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
108 #define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
110 //---------------------------------------------------------------------------
112 //---------------------------------------------------------------------------
114 // structure to administrate circular shared buffer head
116 unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
117 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
118 unsigned long m_ulBufferDataSize; // size of complete data area
119 unsigned long m_ulWrIndex; // current write index (set bevore write)
120 unsigned long m_ulRdIndex; // current read index (set after read)
121 unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
122 unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
123 unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
124 unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
125 unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
126 unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
127 tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
128 unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
129 tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
130 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
134 // structure to administrate linear shared buffer head
136 unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
137 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
138 unsigned long m_ulBufferDataSize; // size of complete data area
139 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
143 // type to save size of a single data block inside the circular shared buffer
145 unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
146 unsigned int m_uiAlignFillBytes:4;
150 #define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
151 #define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
153 #define SBL_BLOCK_ALIGNMENT 4
154 #define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
156 //---------------------------------------------------------------------------
158 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
162 //---------------------------------------------------------------------------
164 //---------------------------------------------------------------------------
165 // Prototypes of internal functions
166 //---------------------------------------------------------------------------
168 //---------------------------------------------------------------------------
169 // Get pointer to Circular Shared Buffer
170 //---------------------------------------------------------------------------
172 tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
175 tShbCirBuff *pShbCirBuff;
177 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
178 ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
180 return (pShbCirBuff);
184 //---------------------------------------------------------------------------
185 // Get pointer to Linear Shared Buffer
186 //---------------------------------------------------------------------------
188 tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
191 tShbLinBuff *pShbLinBuff;
193 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
194 ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
196 return (pShbLinBuff);
200 // not inlined internal functions
201 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
202 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
203 unsigned int fTimeOut_p);
206 //=========================================================================//
208 // P U B L I C F U N C T I O N S //
210 //=========================================================================//
212 // not inlined external functions
214 //---------------------------------------------------------------------------
215 // Initialize Shared Buffer Module
216 //---------------------------------------------------------------------------
218 tShbError ShbInit(void)
223 ShbError = ShbIpcInit();
229 //---------------------------------------------------------------------------
230 // Deinitialize Shared Buffer Module
231 //---------------------------------------------------------------------------
233 tShbError ShbExit(void)
238 ShbError = ShbIpcExit();
244 //-------------------------------------------------------------------------//
246 // C i r c u l a r S h a r e d B u f f e r //
248 //-------------------------------------------------------------------------//
250 //---------------------------------------------------------------------------
251 // Allocate Circular Shared Buffer
252 //---------------------------------------------------------------------------
254 tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
255 const char *pszBufferID_p,
256 tShbInstance * ppShbInstance_p,
257 unsigned int *pfShbNewCreated_p)
260 tShbInstance pShbInstance;
261 tShbCirBuff *pShbCirBuff;
262 unsigned int fShbNewCreated;
263 unsigned long ulBufferDataSize;
264 unsigned long ulBufferTotalSize;
268 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
269 return (kShbInvalidArg);
272 // calculate length of memory to allocate
275 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
276 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
278 // allocate a new or open an existing shared buffer
279 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
280 &pShbInstance, &fShbNewCreated);
281 if (ShbError != kShbOk) {
285 if (pShbInstance == NULL) {
286 ShbError = kShbOutOfMem;
290 // get pointer to shared buffer
291 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
293 // if the shared buffer was new created, than this process has
294 // to initialize it, otherwise the buffer is already in use
295 // and *must not* be reseted
296 if (fShbNewCreated) {
299 memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
303 pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
304 pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
305 pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
306 pShbCirBuff->m_ulWrIndex = 0;
307 pShbCirBuff->m_ulRdIndex = 0;
308 pShbCirBuff->m_ulNumOfWriteJobs = 0;
309 pShbCirBuff->m_ulDataInUse = 0;
310 pShbCirBuff->m_ulDataApended = 0;
311 pShbCirBuff->m_ulBlocksApended = 0;
312 pShbCirBuff->m_ulDataReadable = 0;
313 pShbCirBuff->m_ulBlocksReadable = 0;
314 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
315 pShbCirBuff->m_fBufferLocked = FALSE;
316 pShbCirBuff->m_pfnSigHndlrReset = NULL;
318 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
319 ShbError = kShbInvalidBufferType;
326 *ppShbInstance_p = pShbInstance;
327 *pfShbNewCreated_p = fShbNewCreated;
333 //---------------------------------------------------------------------------
334 // Release Circular Shared Buffer
335 //---------------------------------------------------------------------------
337 tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
343 if (pShbInstance_p == NULL) {
348 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
356 //---------------------------------------------------------------------------
357 // Reset Circular Shared Buffer
358 //---------------------------------------------------------------------------
360 tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
361 unsigned long ulTimeOut_p,
362 tShbCirSigHndlrReset pfnSignalHandlerReset_p)
365 tShbCirBuff *pShbCirBuff;
366 unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
370 if (pShbInstance_p == NULL) {
371 ShbError = kShbInvalidArg;
375 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
378 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
379 ShbError = kShbInvalidBufferType;
383 // start reset job by setting request request in buffer header
384 ShbIpcEnterAtomicSection(pShbInstance_p);
386 if (!pShbCirBuff->m_fBufferLocked) {
387 ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
389 pShbCirBuff->m_fBufferLocked = TRUE;
390 pShbCirBuff->m_pfnSigHndlrReset =
391 pfnSignalHandlerReset_p;
393 ShbError = kShbAlreadyReseting;
396 ShbIpcLeaveAtomicSection(pShbInstance_p);
398 if (ShbError != kShbOk) {
402 // if there is currently no running write operation then reset buffer
403 // immediately, otherwise wait until the last write job is ready by
404 // starting a signal process
405 if (ulNumOfWriteJobs == 0) {
406 // there is currently no running write operation
407 // -> reset buffer immediately
408 ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
411 // there is currently at least one running write operation
412 // -> starting signal process to wait until the last write job is ready
414 ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
415 ShbCirSignalHandlerReset);
424 //---------------------------------------------------------------------------
425 // Write data block to Circular Shared Buffer
426 //---------------------------------------------------------------------------
428 tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
429 const void *pSrcDataBlock_p,
430 unsigned long ulDataBlockSize_p)
433 tShbCirBuff *pShbCirBuff;
434 tShbCirBlockSize ShbCirBlockSize;
435 unsigned int uiFullBlockSize;
436 unsigned int uiAlignFillBytes;
437 unsigned char *pShbCirDataPtr;
438 unsigned char *pScrDataPtr;
439 unsigned long ulDataSize;
440 unsigned long ulChunkSize;
441 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
442 unsigned int fSignalNewData;
443 unsigned int fSignalReset;
449 if (pShbInstance_p == NULL) {
450 ShbError = kShbInvalidArg;
454 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
455 // nothing to do here
460 if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
461 ShbError = kShbExceedDataSizeLimit;
465 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
466 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
467 fSignalNewData = FALSE;
468 fSignalReset = FALSE;
471 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
472 ShbError = kShbInvalidBufferType;
476 // calculate data block size in circular buffer
479 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
480 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
481 uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
483 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
484 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
486 // reserve the needed memory for the write operation to do now
487 // and make necessary adjustments in the circular buffer header
488 ShbIpcEnterAtomicSection(pShbInstance_p);
490 // check if there is sufficient memory available to store
494 (pShbCirBuff->m_ulBufferDataSize -
495 pShbCirBuff->m_ulDataInUse);
497 // set write pointer for the write operation to do now
498 // to the current write pointer of the circular buffer
499 ulWrIndex = pShbCirBuff->m_ulWrIndex;
501 // reserve the needed memory for the write operation to do now
502 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
504 // set new write pointer behind the reserved memory
505 // for the write operation to do now
506 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
507 pShbCirBuff->m_ulWrIndex %=
508 pShbCirBuff->m_ulBufferDataSize;
510 // increment number of currently (parallel running)
512 pShbCirBuff->m_ulNumOfWriteJobs++;
515 ShbIpcLeaveAtomicSection(pShbInstance_p);
518 ShbError = kShbBufferFull;
522 // copy the data to the circular buffer
523 // (the copy process itself will be done outside of any
524 // critical/locked section)
525 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
527 // write real size of current block (incl. alignment fill bytes)
528 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
529 ulWrIndex += sizeof(tShbCirBlockSize);
530 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
532 if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
533 // linear write operation
534 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
537 // wrap-around write operation
538 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
539 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
540 memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
541 ulDataBlockSize_p - ulChunkSize);
544 // adjust header information for circular buffer with properties
545 // of the wiritten data block
546 ShbIpcEnterAtomicSection(pShbInstance_p);
548 pShbCirBuff->m_ulDataApended += uiFullBlockSize;
549 pShbCirBuff->m_ulBlocksApended++;
551 // decrement number of currently (parallel running) write operations
552 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
553 // if there is no other write process running then
554 // set new size of readable (complete written) data and
555 // adjust number of readable blocks
556 pShbCirBuff->m_ulDataReadable +=
557 pShbCirBuff->m_ulDataApended;
558 pShbCirBuff->m_ulBlocksReadable +=
559 pShbCirBuff->m_ulBlocksApended;
561 pShbCirBuff->m_ulDataApended = 0;
562 pShbCirBuff->m_ulBlocksApended = 0;
564 fSignalNewData = TRUE;
565 fSignalReset = pShbCirBuff->m_fBufferLocked;
568 ShbIpcLeaveAtomicSection(pShbInstance_p);
570 // signal new data event to a potentially reading application
571 if (fSignalNewData) {
572 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
573 if (ShbError == kShbOk) {
574 ShbError = ShbError2;
577 // signal that the last write job has been finished to allow
578 // a waiting application to reset the buffer now
580 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
581 if (ShbError == kShbOk) {
582 ShbError = ShbError2;
592 //---------------------------------------------------------------------------
593 // Allocate block within the Circular Shared Buffer for chunk writing
594 //---------------------------------------------------------------------------
596 tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
597 tShbCirChunk * pShbCirChunk_p,
598 unsigned long ulDataBufferSize_p)
601 tShbCirBuff *pShbCirBuff;
602 tShbCirBlockSize ShbCirBlockSize;
603 unsigned int uiFullBlockSize;
604 unsigned int uiAlignFillBytes;
605 unsigned char *pShbCirDataPtr;
606 unsigned long ulDataSize;
607 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
612 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
613 ShbError = kShbInvalidArg;
617 if (ulDataBufferSize_p == 0) {
618 ShbError = kShbInvalidArg;
622 if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
623 ShbError = kShbExceedDataSizeLimit;
627 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
630 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
631 ShbError = kShbInvalidBufferType;
635 // calculate data block size in circular buffer
637 (ulDataBufferSize_p +
638 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
639 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
640 uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
642 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
643 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
645 // reserve the needed memory for the write operation to do now
646 // and make necessary adjustments in the circular buffer header
647 ShbIpcEnterAtomicSection(pShbInstance_p);
649 // check if there is sufficient memory available to store
653 (pShbCirBuff->m_ulBufferDataSize -
654 pShbCirBuff->m_ulDataInUse));
656 // set write pointer for the write operation to do now
657 // to the current write pointer of the circular buffer
658 ulWrIndex = pShbCirBuff->m_ulWrIndex;
660 // reserve the needed memory for the write operation to do now
661 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
663 // set new write pointer behind the reserved memory
664 // for the write operation to do now
665 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
666 pShbCirBuff->m_ulWrIndex %=
667 pShbCirBuff->m_ulBufferDataSize;
669 // increment number of currently (parallel running)
671 pShbCirBuff->m_ulNumOfWriteJobs++;
674 ShbIpcLeaveAtomicSection(pShbInstance_p);
677 ShbError = kShbBufferFull;
681 // setup header information for allocated buffer
682 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
684 // write real size of current block (incl. alignment fill bytes)
685 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
686 ulWrIndex += sizeof(tShbCirBlockSize);
687 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
689 // setup chunk descriptor
690 pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
691 pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
692 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
693 pShbCirChunk_p->m_fBufferCompleted = FALSE;
701 //---------------------------------------------------------------------------
702 // Write data chunk into an allocated buffer of the Circular Shared Buffer
703 //---------------------------------------------------------------------------
705 tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
706 tShbCirChunk *pShbCirChunk_p,
707 const void *pSrcDataChunk_p,
708 unsigned long ulDataChunkSize_p,
709 unsigned int *pfBufferCompleted_p)
712 tShbCirBuff *pShbCirBuff;
713 unsigned char *pShbCirDataPtr;
714 unsigned char *pScrDataPtr;
715 unsigned long ulSubChunkSize;
716 unsigned long ulWrIndex;
717 unsigned int fBufferCompleted;
718 unsigned int fSignalNewData;
719 unsigned int fSignalReset;
724 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
725 || (pfBufferCompleted_p == NULL)) {
726 ShbError = kShbInvalidArg;
730 if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
731 // nothing to do here
736 if (pShbCirChunk_p->m_fBufferCompleted) {
737 ShbError = kShbBufferAlreadyCompleted;
741 if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
742 ShbError = kShbExceedDataSizeLimit;
746 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
747 pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
748 fSignalNewData = FALSE;
749 fSignalReset = FALSE;
752 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
753 ShbError = kShbInvalidBufferType;
757 ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
759 // copy the data to the circular buffer
760 // (the copy process itself will be done outside of any
761 // critical/locked section)
762 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
764 if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
765 // linear write operation
766 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
769 // wrap-around write operation
770 ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
771 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
772 memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
773 ulDataChunkSize_p - ulSubChunkSize);
776 // adjust chunk descriptor
777 ulWrIndex += ulDataChunkSize_p;
778 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
780 pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
781 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
783 fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
784 pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
786 // if the complete allocated buffer is filled with data then
787 // adjust header information for circular buffer with properties
788 // of the wiritten data block
789 if (fBufferCompleted) {
790 ShbIpcEnterAtomicSection(pShbInstance_p);
792 pShbCirBuff->m_ulDataApended +=
793 pShbCirChunk_p->m_uiFullBlockSize;
794 pShbCirBuff->m_ulBlocksApended++;
796 // decrement number of currently (parallel running) write operations
797 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
798 // if there is no other write process running then
799 // set new size of readable (complete written) data and
800 // adjust number of readable blocks
801 pShbCirBuff->m_ulDataReadable +=
802 pShbCirBuff->m_ulDataApended;
803 pShbCirBuff->m_ulBlocksReadable +=
804 pShbCirBuff->m_ulBlocksApended;
806 pShbCirBuff->m_ulDataApended = 0;
807 pShbCirBuff->m_ulBlocksApended = 0;
809 fSignalNewData = TRUE;
810 fSignalReset = pShbCirBuff->m_fBufferLocked;
813 ShbIpcLeaveAtomicSection(pShbInstance_p);
816 // signal new data event to a potentially reading application
817 if (fSignalNewData) {
818 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
819 if (ShbError == kShbOk) {
820 ShbError = ShbError2;
823 // signal that the last write job has been finished to allow
824 // a waiting application to reset the buffer now
826 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
827 if (ShbError == kShbOk) {
828 ShbError = ShbError2;
832 *pfBufferCompleted_p = fBufferCompleted;
840 //---------------------------------------------------------------------------
841 // Read data block from Circular Shared Buffer
842 //---------------------------------------------------------------------------
844 tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
845 void *pDstDataBlock_p,
846 unsigned long ulRdBuffSize_p,
847 unsigned long *pulDataBlockSize_p)
850 tShbCirBuff *pShbCirBuff;
851 tShbCirBlockSize ShbCirBlockSize;
852 unsigned long ulDataReadable;
853 unsigned char *pShbCirDataPtr;
854 unsigned char *pDstDataPtr;
855 unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
856 unsigned long ulChunkSize;
857 unsigned long ulRdIndex;
861 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
862 return (kShbInvalidArg);
865 if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
866 // nothing to do here
872 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
873 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
876 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
877 ShbError = kShbInvalidBufferType;
881 // get total number of readable bytes for the whole circular buffer
882 ShbIpcEnterAtomicSection(pShbInstance_p);
884 ulDataReadable = pShbCirBuff->m_ulDataReadable;
886 ShbIpcLeaveAtomicSection(pShbInstance_p);
888 // if there are readable data available, then there must be at least
889 // one complete readable data block
890 if (ulDataReadable > 0) {
891 // get pointer to start of data area and current read index
892 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
893 ulRdIndex = pShbCirBuff->m_ulRdIndex;
895 // get real size of current block (incl. alignment fill bytes)
897 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
898 ulRdIndex += sizeof(tShbCirBlockSize);
899 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
901 // get size of user data inside the current block
903 ShbCirBlockSize.m_uiFullBlockSize -
904 ShbCirBlockSize.m_uiAlignFillBytes;
905 ulDataSize -= sizeof(tShbCirBlockSize);
908 // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
909 if (ulDataSize > ulRdBuffSize_p) {
910 ulDataSize = ulRdBuffSize_p;
911 ShbError = kShbDataTruncated;
914 if (ulDataSize == 0) {
915 // nothing to do here
916 ShbError = kShbNoReadableData;
920 // copy the data from the circular buffer
921 // (the copy process itself will be done outside of any
922 // critical/locked section)
923 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
924 // linear read operation
925 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
927 // wrap-around read operation
928 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
929 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
930 memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
931 ulDataSize - ulChunkSize);
936 tShbCirBlockSize ClrShbCirBlockSize;
938 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
940 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
942 // wrap-around read operation
944 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
945 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
946 memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
949 ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
950 ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
951 *(tShbCirBlockSize *) (pShbCirDataPtr +
952 pShbCirBuff->m_ulRdIndex) =
955 #endif // #ifndef NDEBUG
957 // set new size of readable data, data in use, new read index
958 // and adjust number of readable blocks
959 ShbIpcEnterAtomicSection(pShbInstance_p);
961 pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
962 pShbCirBuff->m_ulDataReadable -=
963 ShbCirBlockSize.m_uiFullBlockSize;
964 pShbCirBuff->m_ulBlocksReadable--;
966 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
967 if ((pShbCirBuff->m_ulDataInUse == 0)
968 && (pShbCirBuff->m_ulDataReadable == 0)) {
969 ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
971 pShbCirBuff->m_ulWrIndex = 0;
972 pShbCirBuff->m_ulRdIndex = 0;
974 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
976 pShbCirBuff->m_ulRdIndex +=
977 ShbCirBlockSize.m_uiFullBlockSize;
978 pShbCirBuff->m_ulRdIndex %=
979 pShbCirBuff->m_ulBufferDataSize;
982 ShbIpcLeaveAtomicSection(pShbInstance_p);
986 *pulDataBlockSize_p = ulDataSize;
992 //---------------------------------------------------------------------------
993 // Get data size of next readable block from Circular Shared Buffer
994 //---------------------------------------------------------------------------
996 tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
997 unsigned long *pulDataBlockSize_p)
1000 tShbCirBuff *pShbCirBuff;
1001 unsigned long ulDataReadable;
1002 unsigned char *pShbCirDataPtr;
1003 tShbCirBlockSize ShbCirBlockSize;
1004 unsigned long ulDataSize;
1008 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1009 return (kShbInvalidArg);
1012 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1016 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1017 ShbError = kShbInvalidBufferType;
1021 // get total number of readable bytes for the whole circular buffer
1022 ShbIpcEnterAtomicSection(pShbInstance_p);
1024 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1026 ShbIpcLeaveAtomicSection(pShbInstance_p);
1028 // if there are readable data available, then there must be at least
1029 // one complete readable data block
1030 if (ulDataReadable > 0) {
1032 &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1034 // get real size of current block (incl. alignment fill bytes)
1035 ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1037 // get size of user data inside the current block
1039 ShbCirBlockSize.m_uiFullBlockSize -
1040 ShbCirBlockSize.m_uiAlignFillBytes;
1041 ulDataSize -= sizeof(tShbCirBlockSize);
1046 *pulDataBlockSize_p = ulDataSize;
1052 //---------------------------------------------------------------------------
1053 // Get number of readable blocks from Circular Shared Buffer
1054 //---------------------------------------------------------------------------
1056 tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1057 unsigned long *pulDataBlockCount_p)
1060 tShbCirBuff *pShbCirBuff;
1061 unsigned long ulBlockCount;
1065 if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1066 ShbError = kShbInvalidArg;
1070 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1074 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1075 ShbError = kShbInvalidBufferType;
1079 ShbIpcEnterAtomicSection(pShbInstance_p);
1081 ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1083 ShbIpcLeaveAtomicSection(pShbInstance_p);
1085 *pulDataBlockCount_p = ulBlockCount;
1093 //---------------------------------------------------------------------------
1094 // Set application handler to signal new data for Circular Shared Buffer
1095 // d.k.: new parameter priority as enum
1096 //---------------------------------------------------------------------------
1098 tShbError ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p,
1099 tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,
1100 tShbPriority ShbPriority_p)
1103 tShbCirBuff *pShbCirBuff;
1107 if (pShbInstance_p == NULL) {
1108 ShbError = kShbInvalidArg;
1112 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1115 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1116 ShbError = kShbInvalidBufferType;
1120 if (pfnSignalHandlerNewData_p != NULL) {
1121 // set a new signal handler
1122 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1123 ShbError = kShbAlreadySignaling;
1127 pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1129 ShbIpcStartSignalingNewData(pShbInstance_p,
1130 ShbCirSignalHandlerNewData,
1133 // remove existing signal handler
1134 ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1135 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1136 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1138 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1147 //---------------------------------------------------------------------------
1148 // DEBUG: Trace Circular Shared Buffer
1149 //---------------------------------------------------------------------------
1152 tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1155 tShbCirBuff *pShbCirBuff;
1156 char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
1157 tShbCirBlockSize ShbCirBlockSize;
1158 unsigned long ulDataReadable;
1159 unsigned char *pShbCirDataPtr;
1160 unsigned long ulBlockIndex;
1161 unsigned int nBlockCount;
1162 unsigned long ulDataSize;
1163 unsigned long ulChunkSize;
1164 unsigned long ulRdIndex;
1167 TRACE0("\n\n##### Circular Shared Buffer #####\n");
1170 if (pShbInstance_p == NULL) {
1171 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1172 (unsigned long)pShbInstance_p);
1173 ShbError = kShbInvalidArg;
1177 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1180 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1181 ShbError = kShbInvalidBufferType;
1185 *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1186 szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1188 ShbIpcEnterAtomicSection(pShbInstance_p);
1190 TRACE1("\nBuffer Address: 0x%08lX\n",
1191 (unsigned long)pShbCirBuff);
1193 TRACE0("\nHeader Info:");
1194 TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
1195 pShbCirBuff->m_ShbCirMagicID);
1196 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1197 pShbCirBuff->m_ulBufferTotalSize);
1198 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1199 pShbCirBuff->m_ulBufferDataSize);
1200 TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
1201 TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
1202 TRACE1("\nNumOfWriteJobs: %4lu",
1203 pShbCirBuff->m_ulNumOfWriteJobs);
1204 TRACE1("\nDataInUse: %4lu [Bytes]",
1205 pShbCirBuff->m_ulDataInUse);
1206 TRACE1("\nDataApended: %4lu [Bytes]",
1207 pShbCirBuff->m_ulDataApended);
1208 TRACE1("\nBlocksApended: %4lu",
1209 pShbCirBuff->m_ulBlocksApended);
1210 TRACE1("\nDataReadable: %4lu [Bytes]",
1211 pShbCirBuff->m_ulDataReadable);
1212 TRACE1("\nBlocksReadable: %4lu",
1213 pShbCirBuff->m_ulBlocksReadable);
1214 TRACE1("\nSigHndlrNewData: %08lX",
1215 (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
1216 TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
1217 TRACE1("\nSigHndlrReset: %08lX",
1218 (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
1220 ShbTraceDump(&pShbCirBuff->m_Data,
1221 pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1224 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1226 ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1228 while (ulDataReadable > 0) {
1229 TRACE1("\n\n--- Block #%u ---", nBlockCount);
1231 // get pointer to start of data area and current read index
1232 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
1233 ulRdIndex = ulBlockIndex;
1235 // get real size of current block (incl. alignment fill bytes)
1237 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1238 ulRdIndex += sizeof(tShbCirBlockSize);
1239 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1241 // get size of user data inside the current block
1243 ShbCirBlockSize.m_uiFullBlockSize -
1244 ShbCirBlockSize.m_uiAlignFillBytes;
1245 ulDataSize -= sizeof(tShbCirBlockSize);
1248 ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
1249 ShbCirBlockSize.m_uiFullBlockSize);
1250 TRACE1("\nUser Data Size: %4lu [Bytes]",
1252 TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1253 ShbCirBlockSize.m_uiAlignFillBytes);
1255 if (ulRdIndex + ulDataSize <=
1256 pShbCirBuff->m_ulBufferDataSize) {
1257 // linear data buffer
1258 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1259 ulDataSize, 0x00000000L, NULL);
1261 // wrap-around data buffer
1263 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1264 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1265 ulChunkSize, 0x00000000L, NULL);
1266 ShbTraceDump(pShbCirDataPtr,
1267 ulDataSize - ulChunkSize,
1273 ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1274 ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1276 ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1279 ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1281 ShbIpcLeaveAtomicSection(pShbInstance_p);
1290 //-------------------------------------------------------------------------//
1292 // L i n e a r S h a r e d B u f f e r //
1294 //-------------------------------------------------------------------------//
1296 //---------------------------------------------------------------------------
1297 // Allocate Linear Shared Buffer
1298 //---------------------------------------------------------------------------
1300 tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1301 const char *pszBufferID_p,
1302 tShbInstance * ppShbInstance_p,
1303 unsigned int *pfShbNewCreated_p)
1306 tShbInstance pShbInstance;
1307 tShbLinBuff *pShbLinBuff;
1308 unsigned int fShbNewCreated;
1309 unsigned long ulBufferDataSize;
1310 unsigned long ulBufferTotalSize;
1314 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1315 return (kShbInvalidArg);
1318 // calculate length of memory to allocate
1321 (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1322 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1324 // allocate a new or open an existing shared buffer
1325 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1326 &pShbInstance, &fShbNewCreated);
1327 if (ShbError != kShbOk) {
1331 if (pShbInstance == NULL) {
1332 ShbError = kShbOutOfMem;
1336 // get pointer to shared buffer
1337 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1339 // if the shared buffer was new created, than this process has
1340 // to initialize it, otherwise the buffer is already in use
1341 // and *must not* be reseted
1342 if (fShbNewCreated) {
1345 memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1349 pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1350 pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1351 pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1353 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1354 ShbError = kShbInvalidBufferType;
1361 *ppShbInstance_p = pShbInstance;
1362 *pfShbNewCreated_p = fShbNewCreated;
1368 //---------------------------------------------------------------------------
1369 // Release Linear Shared Buffer
1370 //---------------------------------------------------------------------------
1372 tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1378 if (pShbInstance_p == NULL) {
1383 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1391 //---------------------------------------------------------------------------
1392 // Write data block to Linear Shared Buffer
1393 //---------------------------------------------------------------------------
1394 tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1395 unsigned long ulDstBufferOffs_p,
1396 const void *pSrcDataBlock_p,
1397 unsigned long ulDataBlockSize_p)
1400 tShbLinBuff *pShbLinBuff;
1401 unsigned char *pShbLinDataPtr;
1402 unsigned char *pScrDataPtr;
1403 unsigned long ulBufferDataSize;
1407 if (pShbInstance_p == NULL) {
1408 ShbError = kShbInvalidArg;
1412 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1413 // nothing to do here
1418 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1419 ShbError = kShbExceedDataSizeLimit;
1423 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1424 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1427 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1428 ShbError = kShbInvalidBufferType;
1432 // check if offeset and size for the write operation matches with
1433 // the size of the shared buffer
1434 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1435 if ((ulDstBufferOffs_p > ulBufferDataSize) ||
1436 (ulDataBlockSize_p > ulBufferDataSize) ||
1437 ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1438 ShbError = kShbDataOutsideBufferArea;
1442 // copy the data to the linear buffer
1443 // (the copy process will be done inside of any critical/locked section)
1444 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1445 pShbLinDataPtr += ulDstBufferOffs_p;
1447 ShbIpcEnterAtomicSection(pShbInstance_p);
1449 memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1451 ShbIpcLeaveAtomicSection(pShbInstance_p);
1459 //---------------------------------------------------------------------------
1460 // Read data block from Linear Shared Buffer
1461 //---------------------------------------------------------------------------
1462 tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1463 void *pDstDataBlock_p,
1464 unsigned long ulSrcBufferOffs_p,
1465 unsigned long ulDataBlockSize_p)
1468 tShbLinBuff *pShbLinBuff;
1469 unsigned char *pShbLinDataPtr;
1470 unsigned char *pDstDataPtr;
1471 unsigned long ulBufferDataSize;
1475 if (pShbInstance_p == NULL) {
1476 ShbError = kShbInvalidArg;
1480 if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1481 // nothing to do here
1486 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1487 ShbError = kShbExceedDataSizeLimit;
1491 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1492 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1495 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1496 ShbError = kShbInvalidBufferType;
1500 // check if offeset and size for the read operation matches with
1501 // the size of the shared buffer
1502 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1503 if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
1504 (ulDataBlockSize_p > ulBufferDataSize) ||
1505 ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1506 ShbError = kShbDataOutsideBufferArea;
1510 // copy the data to the linear buffer
1511 // (the copy process will be done inside of any critical/locked section)
1512 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1513 pShbLinDataPtr += ulSrcBufferOffs_p;
1515 ShbIpcEnterAtomicSection(pShbInstance_p);
1517 memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1519 ShbIpcLeaveAtomicSection(pShbInstance_p);
1527 //---------------------------------------------------------------------------
1528 // DEBUG: Trace Linear Shared Buffer
1529 //---------------------------------------------------------------------------
1532 tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1535 tShbLinBuff *pShbLinBuff;
1536 char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1539 TRACE0("\n\n##### Linear Shared Buffer #####\n");
1542 if (pShbInstance_p == NULL) {
1543 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1544 (unsigned long)pShbInstance_p);
1545 ShbError = kShbInvalidArg;
1549 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1552 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1553 ShbError = kShbInvalidBufferType;
1557 *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1558 szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1560 ShbIpcEnterAtomicSection(pShbInstance_p);
1562 TRACE1("\nBuffer Address: 0x%08lX\n",
1563 (unsigned long)pShbLinBuff);
1565 TRACE0("\nHeader Info:");
1566 TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
1567 pShbLinBuff->m_ShbLinMagicID);
1568 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1569 pShbLinBuff->m_ulBufferTotalSize);
1570 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1571 pShbLinBuff->m_ulBufferDataSize);
1573 ShbTraceDump(&pShbLinBuff->m_Data,
1574 pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1577 ShbIpcLeaveAtomicSection(pShbInstance_p);
1586 //---------------------------------------------------------------------------
1587 // Dump buffer contents
1588 //---------------------------------------------------------------------------
1591 tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1592 unsigned long ulDataSize_p,
1593 unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1596 const unsigned char *pabBuffData;
1597 unsigned long ulBuffSize;
1598 unsigned char bData;
1602 // get pointer to buffer and length of buffer
1603 pabBuffData = pabStartAddr_p;
1604 ulBuffSize = ulDataSize_p;
1606 if (pszInfoText_p != NULL) {
1607 TRACE1("%s", pszInfoText_p);
1609 // dump buffer contents
1610 for (nRow = 0;; nRow++) {
1612 (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1614 for (nCol = 0; nCol < 16; nCol++) {
1615 if ((unsigned long)nCol < ulBuffSize) {
1617 (unsigned int)*(pabBuffData + nCol));
1625 for (nCol = 0; nCol < 16; nCol++) {
1626 bData = *pabBuffData++;
1627 if ((unsigned long)nCol < ulBuffSize) {
1628 if ((bData >= 0x20) && (bData < 0x7F)) {
1629 TRACE1("%c", bData);
1638 if (ulBuffSize > 16) {
1648 #endif // #ifndef NDEBUG
1650 //=========================================================================//
1652 // P R I V A T E F U N C T I O N S //
1654 //=========================================================================//
1656 //---------------------------------------------------------------------------
1657 // Handler to signal new data event for Circular Shared Buffer
1658 //---------------------------------------------------------------------------
1660 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1663 tShbCirBuff *pShbCirBuff;
1664 unsigned long ulDataSize;
1665 unsigned long ulBlockCount;
1669 if (pShbInstance_p == NULL) {
1673 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1676 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1680 // call application handler
1681 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1684 ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1685 if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1686 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1691 ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1693 while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1695 // Return TRUE if there are pending blocks.
1696 // In that case ShbIpc tries to call this function again immediately if there
1697 // is no other filled shared buffer with higher priority.
1698 return ((ulBlockCount > 0) && (ShbError == kShbOk));
1702 //---------------------------------------------------------------------------
1703 // Handler to reset Circular Shared Buffer
1704 //---------------------------------------------------------------------------
1706 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1707 unsigned int fTimeOut_p)
1710 tShbCirBuff *pShbCirBuff;
1713 if (pShbInstance_p == NULL) {
1717 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1718 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1722 // reset buffer header
1724 ShbIpcEnterAtomicSection(pShbInstance_p);
1726 pShbCirBuff->m_ulWrIndex = 0;
1727 pShbCirBuff->m_ulRdIndex = 0;
1728 pShbCirBuff->m_ulNumOfWriteJobs = 0;
1729 pShbCirBuff->m_ulDataInUse = 0;
1730 pShbCirBuff->m_ulDataApended = 0;
1731 pShbCirBuff->m_ulBlocksApended = 0;
1732 pShbCirBuff->m_ulDataReadable = 0;
1733 pShbCirBuff->m_ulBlocksReadable = 0;
1735 ShbIpcLeaveAtomicSection(pShbInstance_p);
1739 memset(&pShbCirBuff->m_Data, 0xCC,
1740 pShbCirBuff->m_ulBufferDataSize);
1745 // call application handler
1746 if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1747 pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1751 ShbIpcEnterAtomicSection(pShbInstance_p);
1753 pShbCirBuff->m_fBufferLocked = FALSE;
1754 pShbCirBuff->m_pfnSigHndlrReset = NULL;
1756 ShbIpcLeaveAtomicSection(pShbInstance_p);