/*****************************************************************************
 * Copyright (C) Cinterion Wireless Modules GmbH
 *****************************************************************************
 * Project: CE-MUX-Driver
 *****************************************************************************
 * Author : Siemens AG Berlin COM WM RD SW
 *****************************************************************************
 * $Workfile: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/MuxDrv/MuxProt/mux_msgqueue.c $
 * $Revision: /main/ms-d/9 $
 * $Date: 2014-03-14 11:54:21 $
 * $Author: mwohler $
 *****************************************************************************
 * Target:
 *  Microsoft Windows CE 4.2 or 5.0
 *****************************************************************************
 *
 * $Log: O:/mwohler_z_ms-d/z_ms-d/src/working/Classic/MuxDrv/MuxProt/mux_msgqueue.c$ 
 * 
 * /main/ms-d/9   2014-03-14 11:54:21   mwohler 
 * Use latest version of mux protocol implementation based on development for Miami client driver 
 * 
 * /main/ms-d/8   2009-02-18 11:59:08   ctna0256 
 * Set copyright text 
 * 
 * /main/ms-d/7   2008-11-21 10:44:18   ctna0450 
 * Switch to 32 bit buffer handling to allow any mux frame size.
 * Increase max. mux frame size from 244 bytes to 16 kilo bytes.
 *
 * /main/ms-d/6   2008-08-20 11:37:54   ctna0450
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/5   2005-11-08 17:13:04   kr36712
 * the protocol is suitable for several instances
 *
 * /main/ms-d/4   2005-10-21 13:08:39   WM36264
 * Removed usage of C++ in mux protocol implementation
 *
 * /main/ms-d/3   2005-10-20 13:47:42   WM36264
 * Added proper copyright header
 *
 * /main/ms-d/1   2005-10-07 16:29:12   wm36264
 * First version of Windows CE Muxer
 *
*/

//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Cinterion Wireless Modules GmbH
// Copyright (C) 2005-2008 Siemens AG
//
// Version: 1.0
// Date:    dummy
//
//////////////////////////////////////////////////////////////////////////////

#include "mux_msgqueue.h"


/*****                           Macros                                  *****/

/*****                          Typedefs                                 *****/

/*****       (enums, structs and unions shall always be typedef'd)       *****/


/*****                      Public Variables                             *****/


//============================================================================
// private functions of mux_msgqueue
//============================================================================
static void CallMsgAvailable(
    MUX_INSTANCE_t  *pMux
)
{
    if (NULL != pMux->MuxInterface.pMuxMsgAvailable)
    {
        pMux->MuxInterface.pMuxMsgAvailable ((DWORD)pMux, pMux->dwMuxUserData);
    }
}


//============================================================================
// public interface of mux_msgqueue
//============================================================================
void MuxMsg_Init (
    MUX_INSTANCE_t      *pMux
)
{
    UINT32  i;

    // init MuxMsgQueue (ring buffer)
    pMux->MuxMsgQueue.pMuxMsgRead     = NULL;
    pMux->MuxMsgQueue.pMuxMsgWrite    = &pMux->MuxMsgMem[0];

    for (i = 0; i < MAX_MUX_MSG_MEMEORY - 1; i++)
    {
        (&pMux->MuxMsgMem[i])->pNext = &pMux->MuxMsgMem[i + 1];
        MEMCLR(&(&pMux->MuxMsgMem[i])->MuxMsg, sizeof(MP_PRIMITIVE));
    }
    (&pMux->MuxMsgMem[i])->pNext = &pMux->MuxMsgMem[0];
}


DWORD MuxMsg_Get (
    MUX_INSTANCE_t      *pMux,
    MP_PRIMITIVE        *pMuxMsg
)
{
    MSG_QUEUE_t     *MuxMsgQueue = &pMux->MuxMsgQueue;

    if (NULL == MuxMsgQueue->pMuxMsgRead)
    {
        return MUXMSG_QUEUE_EMPTY;
    }

    // copy message
    MEMCPY(pMuxMsg, &MuxMsgQueue->pMuxMsgRead->MuxMsg, sizeof(MP_PRIMITIVE));

    // move MuxMsgQueue.pMuxMsgRead to the next message
    MuxMsgQueue->pMuxMsgRead = MuxMsgQueue->pMuxMsgRead->pNext;

    if (MuxMsgQueue->pMuxMsgRead == MuxMsgQueue->pMuxMsgWrite)
    {
        MuxMsgQueue->pMuxMsgRead = NULL;
    }

    return MUXMSG_OK;
}


DWORD MuxMsg_Put (
    MUX_INSTANCE_t      *pMux,
    MP_PRIMITIVE        *pMuxMsg
)
{
    MSG_QUEUE_t     *MuxMsgQueue = &pMux->MuxMsgQueue;

    if (MuxMsgQueue->pMuxMsgWrite == MuxMsgQueue->pMuxMsgRead)
    {
        MUXDBG(ZONE_MUX_FRAME_ERROR, (TEXT("MuxDrv: Mux message queue full, message lost!")));
        return MUXMSG_QUEUE_FULL;
    }

    // copy message
    MEMCPY(&MuxMsgQueue->pMuxMsgWrite->MuxMsg, pMuxMsg, sizeof(MP_PRIMITIVE));

    // move MuxMsgQueue.pMuxMsgWrite to the next buffer
    if (MuxMsgQueue->pMuxMsgRead == NULL)
    {
        MuxMsgQueue->pMuxMsgRead = MuxMsgQueue->pMuxMsgWrite;
    }

    MuxMsgQueue->pMuxMsgWrite = MuxMsgQueue->pMuxMsgWrite->pNext;

    // send signal
    CallMsgAvailable(pMux);

    return MUXMSG_OK;
}


BOOL MuxMsg_Exist(
    MUX_INSTANCE_t      *pMux
)
{
    return (pMux->MuxMsgQueue.pMuxMsgRead == NULL) ? FALSE : TRUE;
}

