Logo Search packages:      
Sourcecode: dahdi-linux version File versions  Download package

oct6100_conf_bridge.c

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

File: oct6100_conf_bridge.c

    Copyright (c) 2001-2007 Octasic Inc.
    
Description: 

      This file contains all functions related to a conference bridge.  Procedures
      needed to open/close a bridge, add/remove a participant to a conference 
      bridge, mute/unmute a participant, etc..  are all present in this source 
      file.

This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API  is 
free software; you can redistribute it and/or modify it under the terms of 
the GNU General Public License as published by the Free Software Foundation; 
either version 2 of the License, or (at your option) any later version.

The OCT6100 GPL API is distributed in the hope that it will be useful, but 
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
for more details. 

You should have received a copy of the GNU General Public License 
along with the OCT6100 GPL API; if not, write to the Free Software 
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.

$Octasic_Release: OCT612xAPI-01.00-PR49 $

$Octasic_Revision: 146 $

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/


/*****************************  INCLUDE FILES  *******************************/

#include "octdef.h"

#include "oct6100api/oct6100_defines.h"
#include "oct6100api/oct6100_errors.h"
#include "oct6100api/oct6100_apiud.h"

#include "apilib/octapi_llman.h"

#include "oct6100api/oct6100_tlv_inst.h"
#include "oct6100api/oct6100_chip_open_inst.h"
#include "oct6100api/oct6100_chip_stats_inst.h"
#include "oct6100api/oct6100_interrupts_inst.h"
#include "oct6100api/oct6100_remote_debug_inst.h"
#include "oct6100api/oct6100_debug_inst.h"
#include "oct6100api/oct6100_api_inst.h"
#include "oct6100api/oct6100_channel_inst.h"
#include "oct6100api/oct6100_mixer_inst.h"
#include "oct6100api/oct6100_conf_bridge_inst.h"

#include "oct6100api/oct6100_interrupts_pub.h"
#include "oct6100api/oct6100_chip_open_pub.h"
#include "oct6100api/oct6100_channel_pub.h"
#include "oct6100api/oct6100_mixer_pub.h"
#include "oct6100api/oct6100_conf_bridge_pub.h"

#include "oct6100_chip_open_priv.h"
#include "oct6100_miscellaneous_priv.h"
#include "oct6100_memory_priv.h"
#include "oct6100_tsst_priv.h"
#include "oct6100_channel_priv.h"
#include "oct6100_mixer_priv.h"
#include "oct6100_conf_bridge_priv.h"


/****************************  PUBLIC FUNCTIONS  *****************************/


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeOpen

Description:    This function opens a conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeOpen       Pointer to conference bridge open structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeOpenDef
UINT32 Oct6100ConfBridgeOpenDef(
                        tPOCT6100_CONF_BRIDGE_OPEN                f_pConfBridgeOpen )
{
      f_pConfBridgeOpen->pulConfBridgeHndl = NULL;
      f_pConfBridgeOpen->fFlexibleConferencing = FALSE;

      return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ConfBridgeOpen
UINT32 Oct6100ConfBridgeOpen(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_OPEN                f_pConfBridgeOpen )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure.*/
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeOpenSer( f_pApiInstance, f_pConfBridgeOpen );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeClose

Description:    This function closes a conference bridge.  A conference
                        bridge can only be closed if no participants are present on 
                        the bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeClose            Pointer to conference bridge close structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeCloseDef
UINT32 Oct6100ConfBridgeCloseDef(
                        tPOCT6100_CONF_BRIDGE_CLOSE               f_pConfBridgeClose )
{
      f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ConfBridgeClose
UINT32 Oct6100ConfBridgeClose(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_CLOSE               f_pConfBridgeClose )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure. */
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeCloseSer( f_pApiInstance, f_pConfBridgeClose );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanAdd

Description:    This function adds an echo channel (participant) to a 
                        conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeAdd        Pointer to conference bridge channel addition structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanAddDef
UINT32 Oct6100ConfBridgeChanAddDef(
                        tPOCT6100_CONF_BRIDGE_CHAN_ADD            f_pConfBridgeAdd )
{
      f_pConfBridgeAdd->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT;
      f_pConfBridgeAdd->ulListenerMaskIndex = cOCT6100_INVALID_VALUE;
      f_pConfBridgeAdd->ulListenerMask = 0;
      f_pConfBridgeAdd->fMute = FALSE;
      f_pConfBridgeAdd->ulTappedChannelHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ConfBridgeChanAdd
UINT32 Oct6100ConfBridgeChanAdd(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_CHAN_ADD            f_pConfBridgeAdd )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure. */
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeChanAddSer( f_pApiInstance, f_pConfBridgeAdd );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanRemove

Description:    This function removes an echo channel (participant) from a 
                        conference bridge.  All participants can be removed from
                        the bridge if a special flag (fRemoveAll) is set to TRUE.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeRemove           Pointer to conference bridge channel removal structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanRemoveDef
UINT32 Oct6100ConfBridgeChanRemoveDef(
                        tPOCT6100_CONF_BRIDGE_CHAN_REMOVE   f_pConfBridgeRemove )
{
      f_pConfBridgeRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeRemove->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeRemove->fRemoveAll = FALSE;

      return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ConfBridgeChanRemove
UINT32 Oct6100ConfBridgeChanRemove(
                  tPOCT6100_INSTANCE_API                    f_pApiInstance,
                  tPOCT6100_CONF_BRIDGE_CHAN_REMOVE   f_pConfBridgeRemove )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure.*/
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, f_pConfBridgeRemove );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanMute

Description:    This function mutes a participant present on a conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeMute       Pointer to conference bridge channel mute structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanMuteDef
UINT32 Oct6100ConfBridgeChanMuteDef(
                        tPOCT6100_CONF_BRIDGE_CHAN_MUTE           f_pConfBridgeMute )
{
      f_pConfBridgeMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK; 
}
#endif


#if !SKIP_Oct6100ConfBridgeChanMute
UINT32 Oct6100ConfBridgeChanMute(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_CHAN_MUTE           f_pConfBridgeMute )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure. */
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeChanMuteSer( f_pApiInstance, f_pConfBridgeMute );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanUnMute

Description:    This function unmutes a channel on a bridge. The other member 
                        of the conference will start to hear this participant again.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeUnMute           Pointer to conference bridge channel unmute structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanUnMuteDef
UINT32 Oct6100ConfBridgeChanUnMuteDef(
                        tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE   f_pConfBridgeUnMute )
{
      f_pConfBridgeUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK;
}
#endif

#if !SKIP_Oct6100ConfBridgeChanUnMute
UINT32 Oct6100ConfBridgeChanUnMute(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE   f_pConfBridgeUnMute )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure.*/
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeChanUnMuteSer( f_pApiInstance, f_pConfBridgeUnMute );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeDominantSpeakerSet

Description:    This function sets a participant present on a conference 
                        bridge as the dominant speaker.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to 
                                    keep the present state of the chip and all its 
                                    resources.

f_pConfBridgeDominant   Pointer to conference bridge dominant speaker 
                                    structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetDef
UINT32 Oct6100ConfBridgeDominantSpeakerSetDef(
                        tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET      f_pConfBridgeDominantSpeaker )
{
      f_pConfBridgeDominantSpeaker->ulChannelHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeDominantSpeaker->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK; 
}
#endif


#if !SKIP_Oct6100ConfBridgeDominantSpeakerSet
UINT32 Oct6100ConfBridgeDominantSpeakerSet(
                        tPOCT6100_INSTANCE_API                                f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET      f_pConfBridgeDominantSpeaker )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure.*/
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeDominantSpeakerSetSer( f_pApiInstance, f_pConfBridgeDominantSpeaker );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeMaskChange

Description:    This function changes the mask of a flexible bridge participant.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to 
                                          keep the present state of the chip and all its 
                                          resources.

f_pConfBridgeMaskChange       Pointer to conference bridge change of mask 
                                          structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeMaskChangeDef
UINT32 Oct6100ConfBridgeMaskChangeDef(
                        tPOCT6100_CONF_BRIDGE_MASK_CHANGE               f_pConfBridgeMaskChange )
{
      f_pConfBridgeMaskChange->ulChannelHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeMaskChange->ulNewListenerMask = 0x0;

      return cOCT6100_ERR_OK; 
}
#endif


#if !SKIP_Oct6100ConfBridgeMaskChange
UINT32 Oct6100ConfBridgeMaskChange(
                        tPOCT6100_INSTANCE_API                                f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_MASK_CHANGE               f_pConfBridgeMaskChange )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure. */
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeMaskChangeSer( f_pApiInstance, f_pConfBridgeMaskChange );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeGetStats

Description:    This function returns the stats for a conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeStats            Pointer to conference bridge channel stats structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeGetStatsDef
UINT32 Oct6100ConfBridgeGetStatsDef(
                        tPOCT6100_CONF_BRIDGE_STATS               f_pConfBridgeStats )
{
      f_pConfBridgeStats->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
      f_pConfBridgeStats->ulNumChannels = cOCT6100_INVALID_STAT;
      f_pConfBridgeStats->ulNumTappedChannels = cOCT6100_INVALID_STAT;
      f_pConfBridgeStats->fFlexibleConferencing = cOCT6100_INVALID_STAT;

      return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ConfBridgeGetStats
UINT32 Oct6100ConfBridgeGetStats(
                        tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        tPOCT6100_CONF_BRIDGE_STATS               f_pConfBridgeStats )
{
      tOCT6100_SEIZE_SERIALIZE_OBJECT           SeizeSerObj;
      tOCT6100_RELEASE_SERIALIZE_OBJECT   ReleaseSerObj;
      UINT32                                                ulSerRes = cOCT6100_ERR_OK;
      UINT32                                                ulFncRes = cOCT6100_ERR_OK;

      /* Set the process context of the serialize structure. */
      SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
      ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;

      /* Seize all list semaphores needed by this function. */
      SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
      ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
      if ( ulSerRes == cOCT6100_ERR_OK )
      {
            /* Call the serialized function. */
            ulFncRes = Oct6100ConfBridgeGetStatsSer( f_pApiInstance, f_pConfBridgeStats );
      }
      else
      {
            return ulSerRes;
      }

      /* Release the seized semaphores. */
      ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
      ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

      /* If an error occured then return the error code. */
      if ( ulSerRes != cOCT6100_ERR_OK )
            return ulSerRes;
      if ( ulFncRes != cOCT6100_ERR_OK )
            return ulFncRes;

      return cOCT6100_ERR_OK;
}
#endif

/****************************  PRIVATE FUNCTIONS  ****************************/


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiGetConfBridgeSwSizes

Description:    Gets the sizes of all portions of the API instance pertinent
                        to the management of conference bridges.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pOpenChip                   Pointer to chip configuration struct.
f_pInstSizes                  Pointer to struct containing instance sizes.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetConfBridgeSwSizes
UINT32 Oct6100ApiGetConfBridgeSwSizes(
                        IN          tPOCT6100_CHIP_OPEN                       f_pOpenChip,
                        OUT         tPOCT6100_API_INSTANCE_SIZES  f_pInstSizes )
{
      UINT32      ulTempVar;
      UINT32      ulResult;

      /* Calculate memory needed for conference bridge list. */
      if ( f_pOpenChip->ulMaxConfBridges == 0 && f_pOpenChip->fEnableChannelRecording == TRUE )
            f_pOpenChip->ulMaxConfBridges = 1;
      f_pInstSizes->ulConfBridgeList = f_pOpenChip->ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE );
      
      /* Calculate memory needed for conference bridge allocation software. */
      if ( f_pOpenChip->ulMaxConfBridges > 0 )
      {
            /* Get size of bridge allocation memory */
            ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxConfBridges, &f_pInstSizes->ulConfBridgeAlloc );
            if ( ulResult != cOCT6100_ERR_OK )
                  return cOCT6100_ERR_FATAL_1C;

            /* Check if the user wants to build flexible conference bridges. */
            if ( f_pOpenChip->ulMaxFlexibleConfParticipants > 0 )
            {
                  /* Allocate the lowest quantity according to what the user requested. */
                  if ( f_pOpenChip->ulMaxFlexibleConfParticipants < ( f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) )
                        f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxFlexibleConfParticipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT );
                  else
                  {
                        f_pOpenChip->ulMaxFlexibleConfParticipants = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE;
                        f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT );
                  }

                  /* Get size of flexible conferencing participants allocation memory */
                  ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxFlexibleConfParticipants, &f_pInstSizes->ulFlexConfParticipantsAlloc );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return cOCT6100_ERR_FATAL_1C;
            }
            else
            {
                  f_pInstSizes->ulFlexConfParticipantsList  = 0;
                  f_pInstSizes->ulFlexConfParticipantsAlloc  = 0;
            }
      }
      else
      {
            f_pInstSizes->ulMixerEventList = 0;       
            f_pInstSizes->ulMixerEventAlloc  = 0;
            f_pInstSizes->ulConfBridgeAlloc  = 0;

            /* Make sure flexible conferencing is not used. */
            f_pInstSizes->ulFlexConfParticipantsList  = 0;
            f_pInstSizes->ulFlexConfParticipantsAlloc  = 0;
      }

      /* Calculate memory needed for list and allocation software serialization. */
      mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeList, ulTempVar )
      mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeAlloc, ulTempVar )

      mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsList, ulTempVar )
      mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsAlloc, ulTempVar )

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiConfBridgeSwInit

Description:    Initializes all elements of the instance structure associated
                        to conference bridges.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep
                                    the present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiConfBridgeSwInit
UINT32 Oct6100ApiConfBridgeSwInit(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance )
{
      tPOCT6100_SHARED_INFO                     pSharedInfo;
      tPOCT6100_API_CONF_BRIDGE                 pConfBridgeList;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pFlexConfParticipantList;
      PVOID pFlexConfPartipantsAlloc;
      UINT32      ulMaxFlexConfParicipants;
      PVOID pConfBridgeAlloc;
      UINT32      ulMaxConfBridges;
      UINT32      ulResult;

      /* Get local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      /* Get the maximum number of conference bridges. */
      ulMaxConfBridges = pSharedInfo->ChipConfig.usMaxConfBridges;
      
      /*===================================================================*/
      /* Set all entries in the conference bridge list to unused. */

      mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pConfBridgeList );

      /* Initialize the conference bridge allocation software to "all free". */
      if ( ulMaxConfBridges > 0 )
      {
            /* Clear the bridge memory */ 
            Oct6100UserMemSet( pConfBridgeList, 0x00, ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE ));

            mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pConfBridgeAlloc )
            
            ulResult = OctapiLlmAllocInit( &pConfBridgeAlloc, ulMaxConfBridges );
            if ( ulResult != cOCT6100_ERR_OK )
                  return cOCT6100_ERR_FATAL_1E;
      }
      /*===================================================================*/


      /*===================================================================*/
      /* Set all entries in the flexible conferencing participant list to unused. */

      /* Get the maximum number of flexible conferencing participants. */
      ulMaxFlexConfParicipants = pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants;

      mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pFlexConfParticipantList );

      /* Initialize the flexible conferencing allocation software. */
      if ( ulMaxFlexConfParicipants > 0 )
      {
            UINT32 i, ulEventIndex;
            
            /* Clear the participants memory */ 
            Oct6100UserMemSet( pFlexConfParticipantList, 0x00, ulMaxFlexConfParicipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ));

            mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pFlexConfPartipantsAlloc )
            
            ulResult = OctapiLlmAllocInit( &pFlexConfPartipantsAlloc, ulMaxFlexConfParicipants );
            if ( ulResult != cOCT6100_ERR_OK )
                  return cOCT6100_ERR_FATAL_1E;

            /* Initialize the conferencing indexes. */
            for ( i = 0; i < ulMaxFlexConfParicipants; i ++ )
            {
                  for ( ulEventIndex = 0; ulEventIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulEventIndex ++ )
                        pFlexConfParticipantList[ i ].ausLoadOrAccumulateEventIndex[ ulEventIndex ] = cOCT6100_INVALID_INDEX;
            }
      }
      
      /*===================================================================*/
      
      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeOpenSer

Description:    Open a conference bridge. Note that no chip resources are 
                        allocated until a channel is added to the bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeOpen       Pointer to conference bridge configuration structure.  
                                    The handle identifying the conference bridge in all 
                                    future function calls is returned in this structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeOpenSer
UINT32 Oct6100ConfBridgeOpenSer(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN OUT      tPOCT6100_CONF_BRIDGE_OPEN          f_pConfBridgeOpen )
{
      UINT16      usBridgeIndex;
      UINT32      ulResult;

      /* Check the user's configuration of the conference bridge for errors. */
      ulResult = Oct6100ApiCheckBridgeParams( f_pApiInstance, f_pConfBridgeOpen );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Reserve all resources needed by the conference bridge. */
      ulResult = Oct6100ApiReserveBridgeResources( f_pApiInstance, &usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Update the new conference bridge's entry in the conference bridge list. */
      ulResult = Oct6100ApiUpdateBridgeEntry( f_pApiInstance, f_pConfBridgeOpen, usBridgeIndex);
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeParams

Description:    Checks the user's conference bridge open configuration for errors.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeOpen       Pointer to conference bridge configuration structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeParams
UINT32 Oct6100ApiCheckBridgeParams(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_OPEN          f_pConfBridgeOpen )
{
      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
      
      if ( f_pConfBridgeOpen->pulConfBridgeHndl == NULL )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
      
      if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencing == FALSE )
            return cOCT6100_ERR_NOT_SUPPORTED_CONF_BRIDGE;

      if ( f_pConfBridgeOpen->fFlexibleConferencing != FALSE
            && f_pConfBridgeOpen->fFlexibleConferencing != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReserveBridgeResources

Description:    Reserves all resources needed for the new conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.
      
f_pusBridgeIndex        Allocated entry in the API conference bridge list.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveBridgeResources
UINT32 Oct6100ApiReserveBridgeResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        OUT         PUINT16                                         f_pusBridgeIndex )
{
      tPOCT6100_SHARED_INFO   pSharedInfo;
      UINT32      ulResult;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      /* Reserve an entry in the conference bridge list. */
      ulResult = Oct6100ApiReserveBridgeEntry( f_pApiInstance, f_pusBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiUpdateBridgeEntry

Description:    Updates the new conference bridge's entry in the conference 
                        bridge list.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep
                                    the present state of the chip and all its resources.

f_pConfBridgeOpen       Pointer to conference bridge configuration structure.
f_usBridgeIndex               Allocated entry in API conference bridge list.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateBridgeEntry
UINT32 Oct6100ApiUpdateBridgeEntry(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN OUT      tPOCT6100_CONF_BRIDGE_OPEN          f_pConfBridgeOpen,
                        IN          UINT16                                          f_usBridgeIndex )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_CONF_BRIDGE     pTempBridgeEntry;

      /*================================================================================*/
      /* Obtain a pointer to the new conference bridge's list entry. */

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex )

      /* No clients are currently connected to the bridge. */
      pBridgeEntry->usNumClients = 0;
      /* Nobody is tapped for now. */
      pBridgeEntry->usNumTappedClients = 0;
      pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX;
      pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX;
      pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX;

      pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX;

      pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX;

      /* Now update the bridge pointer. */
      if ( f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened == 0 )
      {
            pBridgeEntry->usNextBridgePtr = cOCT6100_INVALID_INDEX;
            pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX;

            /* Set the global first bridge to this bridge. */
            f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex;
      }
      else  /* Insert this bridge at the head of the bridge list.*/
      {
            if ( f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_FATAL_22;

            mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge )
      
            if ( pTempBridgeEntry->fReserved != TRUE )
                  return cOCT6100_ERR_FATAL_23;

            /* Modify the old first entry. */
            pTempBridgeEntry->usPrevBridgePtr = f_usBridgeIndex;

            /* Modify current pointer. */
            pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX;
            pBridgeEntry->usNextBridgePtr = f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge;

            /* Set the new first bridge of the list. */
            f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex;
      }

      /* Form handle returned to user. */
      *f_pConfBridgeOpen->pulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBridgeIndex;

      /* Remember whether or not we are a flexible conference bridge. */
      pBridgeEntry->fFlexibleConferencing = (UINT8)( f_pConfBridgeOpen->fFlexibleConferencing & 0xFF );

      /* Finally, mark the conference bridge as opened. */
      pBridgeEntry->fReserved = TRUE;
      
      /* Increment the number of conference bridge opened. */
      f_pApiInstance->pSharedInfo->ChipStats.usNumberConfBridges++;
      f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened++;

      /*================================================================================*/

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeCloseSer

Description:    Closes a conference bridge. Note that no client must be present
                        on the bridge for the bridge to be closed.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeClose            Pointer to conference bridge close structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeCloseSer
UINT32 Oct6100ConfBridgeCloseSer(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CLOSE               f_pConfBridgeClose )
{
      UINT16      usBridgeIndex;
      UINT32      ulResult;

      /* Verify that all the parameters given match the state of the API. */
      ulResult = Oct6100ApiAssertBridgeParams( f_pApiInstance, f_pConfBridgeClose, &usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK  )
            return ulResult;

      /* Release all resources associated to the conference bridge. */
      ulResult = Oct6100ApiReleaseBridgeResources( f_pApiInstance, usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK  )
            return ulResult;

      /* Invalidate the handle. */
      f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiAssertBridgeParams

Description:    Checks the user's conference bridge close configuration for errors.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeClose            Pointer to conference bridge close structure.
f_pusBridgeIndex        Pointer to API instance conference bridge index.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiAssertBridgeParams
UINT32 Oct6100ApiAssertBridgeParams(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CLOSE               f_pConfBridgeClose,
                        OUT         PUINT16                                               f_pusBridgeIndex )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      UINT32                                    ulEntryOpenCnt;

      /* Check the provided handle. */
      if ( (f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      *f_pusBridgeIndex = (UINT16)( f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeClose->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( pBridgeEntry->usNumClients != 0 )
            return cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES;
      if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReleaseBridgeResources

Description:    Release all resources reserved for the conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_usBridgeIndex               Allocated external memory block for the conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReleaseBridgeResources
UINT32 Oct6100ApiReleaseBridgeResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex )
{
      tPOCT6100_SHARED_INFO         pSharedInfo;
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_CONF_BRIDGE     pTempBridgeEntry;
      UINT32      ulResult;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      /* Release the entry from the conference bridge list. */
      ulResult = Oct6100ApiReleaseBridgeEntry( f_pApiInstance, f_usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return cOCT6100_ERR_FATAL_24;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex );

      /* Remove the bridge entry from the bridge list. */
      if ( pSharedInfo->MiscVars.usNumBridgesOpened == 1 )
      {
            /* This bridge was the only one opened. */
            pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX;
      }
      else if ( pSharedInfo->MiscVars.usNumBridgesOpened > 1 )
      {
            /* There are more then one bridge open, must update the list. */
            if ( pBridgeEntry->usPrevBridgePtr != cOCT6100_INVALID_INDEX )
            {
                  /* There is a valid entry before this bridge, let's update this entry. */
                  mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usPrevBridgePtr );
                  
                  pTempBridgeEntry->usNextBridgePtr = pBridgeEntry->usNextBridgePtr;
            }

            if ( pBridgeEntry->usNextBridgePtr != cOCT6100_INVALID_INDEX )
            {
                  /* There is a valid entry after this bridge, let's update this entry. */
                  mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usNextBridgePtr );

                  pTempBridgeEntry->usPrevBridgePtr = pBridgeEntry->usPrevBridgePtr;
            }

            if ( pSharedInfo->MiscVars.usFirstBridge == f_usBridgeIndex )
            {
                  /* This entry was the first of the list, make the next one be the first now. */
                  pSharedInfo->MiscVars.usFirstBridge = pBridgeEntry->usNextBridgePtr;
            }
      }
      else
      {
            /* Variable has become out of sync. */
            return cOCT6100_ERR_FATAL_25;
      }

      /*=============================================================*/
      /* Update the conference bridge's list entry. */

      /* Mark the bridge as closed. */
      pBridgeEntry->fFlexibleConferencing = FALSE;
      pBridgeEntry->fReserved = FALSE;
      pBridgeEntry->byEntryOpenCnt++;

      /* Decrement the number of conference bridges opened. */
      pSharedInfo->MiscVars.usNumBridgesOpened--;
      pSharedInfo->ChipStats.usNumberConfBridges--;

      /*=============================================================*/

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanAddSer

Description:    Adds an echo channel (participant) to a conference bridge. 

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeAdd        Pointer to conference bridge channel add structure.  

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanAddSer
UINT32 Oct6100ConfBridgeChanAddSer(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_ADD      f_pConfBridgeAdd )
{
      UINT16      usBridgeIndex;
      UINT16      usChanIndex;
      UINT16      usLoadEventIndex;
      UINT16      usSubStoreEventIndex;
      UINT16      usCopyEventIndex;
      UINT32      ulInputPort;
      UINT8 fFlexibleConfBridge;
      UINT32      ulListenerMaskIndex;
      UINT32      ulListenerMask;
      UINT16      usTapChanIndex;
      UINT16      usTapBridgeIndex;
      UINT8 fMute;
      UINT8 fTap;
      UINT32      ulResult;

      /* Check the validity of the channel and conference bridge given. */
      ulResult = Oct6100ApiCheckBridgeAddParams( 
                                                      f_pApiInstance, 
                                                      f_pConfBridgeAdd, 
                                                      &usBridgeIndex, 
                                                      &usChanIndex, 
                                                      &fMute, 
                                                      &ulInputPort, 
                                                      &fFlexibleConfBridge, 
                                                      &ulListenerMaskIndex, 
                                                      &ulListenerMask,
                                                      &fTap,
                                                      &usTapChanIndex );
      if ( ulResult != cOCT6100_ERR_OK  )
            return ulResult;

      /* Reserve all resources needed by the conference bridge. */
      ulResult = Oct6100ApiReserveBridgeAddResources( 
                                                      f_pApiInstance, 
                                                      usBridgeIndex, 
                                                      usChanIndex, 
                                                      ulInputPort, 
                                                      fFlexibleConfBridge, 
                                                      ulListenerMaskIndex, 
                                                      ulListenerMask,
                                                      fTap,
                                                      &usLoadEventIndex, 
                                                      &usSubStoreEventIndex, 
                                                      &usCopyEventIndex,
                                                      &usTapBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Reserve all resources needed by the conference bridge. */
      ulResult = Oct6100ApiBridgeEventAdd( 
                                                      f_pApiInstance, 
                                                      usBridgeIndex, 
                                                      usChanIndex, 
                                                      fFlexibleConfBridge, 
                                                      usLoadEventIndex, 
                                                      usSubStoreEventIndex, 
                                                      usCopyEventIndex, 
                                                      ulInputPort, 
                                                      fMute, 
                                                      ulListenerMaskIndex, 
                                                      ulListenerMask,
                                                      fTap,
                                                      usTapBridgeIndex,
                                                      usTapChanIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeAddParams

Description:      Check the validity of the channel and conference bridge given.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.
f_pConfBridgeAdd        Pointer to conference bridge channenl add structure.  
f_pusBridgeIndex        Extracted bridge index where this channel should be 
                                    added.
f_pusChannelIndex       Extracted channel index related to the channel handle
                                    to be added to the bridge.
f_pfMute                      Whether to mute this channel in the bridge or not.
f_pulInputPort                Input port where the channel signal should be
                                    copied from.
f_pfFlexibleConfBridge  If this is a flexible conference bridge.
f_pulListenerMaskIndex  Index of the listener in this flexible conference bridge.
f_pulListenerMask       Mask of listeners in this flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeAddParams
UINT32 Oct6100ApiCheckBridgeAddParams(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_ADD            f_pConfBridgeAdd,
                        OUT         PUINT16                                               f_pusBridgeIndex, 
                        OUT         PUINT16                                               f_pusChannelIndex,
                        OUT         PUINT8                                                f_pfMute,
                        OUT         PUINT32                                               f_pulInputPort, 
                        OUT         PUINT8                                                f_pfFlexibleConfBridge,
                        OUT         PUINT32                                               f_pulListenerMaskIndex,
                        OUT         PUINT32                                               f_pulListenerMask,
                        OUT         PUINT8                                                f_pfTap,
                        OUT         PUINT16                                               f_pusTapChannelIndex )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_CHANNEL         pEchoChanEntry;
      UINT32      ulEntryOpenCnt;
      UINT8 byTapChannelLaw;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;

      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 1 &&
             f_pApiInstance->pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;

      if ( f_pConfBridgeAdd->ulConfBridgeHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      if ( f_pConfBridgeAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;
      
      if( f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_SOUT
            && f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_RIN )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_INPUT_PORT;

      if ( f_pConfBridgeAdd->fMute != TRUE && f_pConfBridgeAdd->fMute != FALSE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MUTE;

      /*=====================================================================*/
      /* Check the conference bridge handle. */

      if ( (f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      *f_pusBridgeIndex = (UINT16)( f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeAdd->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /* When we a flexible conference bridge, more things need to be checked. */
      if ( pBridgeEntry->fFlexibleConferencing == TRUE )
      {
            /* Check if flexible conferencing has been activated. */
            if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants == 0 )
                  return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_DISABLED;

            /* Check the number of clients on the bridge. */
            if ( pBridgeEntry->usNumClients >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE )
                  return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_PARTICIPANT_CNT;

            /* Check if the listener index in a flexible bridge is valid. */
            if ( f_pConfBridgeAdd->ulListenerMaskIndex == cOCT6100_INVALID_VALUE
                  || f_pConfBridgeAdd->ulListenerMaskIndex >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE )
                  return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_MASK_INDEX;
      }

      if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
      {
            if ( pBridgeEntry->fFlexibleConferencing == TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_TAP_NOT_SUPPORTED;
      }

      /*=====================================================================*/
      

      /*=====================================================================*/
      /* Check the channel handle. */

      if ( (f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;

      *f_pusChannelIndex = (UINT16)( f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pEchoChanEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
      if ( pEchoChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ALREADY_ON_BRIDGE;
      if ( pEchoChanEntry->fBiDirChannel == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_BIDIR;
      /* Law conversion is not allowed on a conference bridge. */
      if ( ( pEchoChanEntry->TdmConfig.usRinTimeslot != cOCT6100_UNASSIGNED )
            && ( pEchoChanEntry->TdmConfig.usRoutTimeslot != cOCT6100_UNASSIGNED ) )
      {
            if ( pEchoChanEntry->TdmConfig.byRinPcmLaw != pEchoChanEntry->TdmConfig.byRoutPcmLaw )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION;
      }
      if ( ( pEchoChanEntry->TdmConfig.usSinTimeslot != cOCT6100_UNASSIGNED )
            && ( pEchoChanEntry->TdmConfig.usSoutTimeslot != cOCT6100_UNASSIGNED ) )
      {
            if ( pEchoChanEntry->TdmConfig.bySinPcmLaw != pEchoChanEntry->TdmConfig.bySoutPcmLaw )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION;
      }
      if ( pEchoChanEntry->fRinRoutCodecActive == TRUE || pEchoChanEntry->fSinSoutCodecActive == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_CODEC_ACTIVE;
      if ( pEchoChanEntry->fEnableExtToneDetection == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_EXT_TONE_ENABLED;
      if ( pEchoChanEntry->usCopyEventCnt != 0x0 )
            return cOCT6100_ERR_CONF_BRIDGE_COPY_EVENTS;

      /* If the bridge is flexible, few more things need to be checked. */
      if ( pBridgeEntry->fFlexibleConferencing == TRUE )
      {
            tPOCT6100_SHARED_INFO   pSharedInfo;
            UINT16                              usChannelIndex;
            UINT32                              ulResult = cOCT6100_ERR_OK;

            /* Obtain local pointer to shared portion of instance. */
            pSharedInfo = f_pApiInstance->pSharedInfo;

            /* Check if the listener index has been used by another channel in the specified bridge. */
            for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex );
                  
                  /* Channel reserved? */
                  if ( ( usChannelIndex != ( *f_pusChannelIndex ) ) && ( pEchoChanEntry->fReserved == TRUE ) )
                  {
                        /* On current bridge? */
                        if ( pEchoChanEntry->usBridgeIndex == ( *f_pusBridgeIndex ) )
                        {
                              tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;

                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

                              /* Check if this participant has the same listener index. */
                              if ( f_pConfBridgeAdd->ulListenerMaskIndex == pCurrentParticipant->ulListenerMaskIndex )
                                    return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_INDEX_USED;
                        }
                  }
            }
      }

      if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
      {
            /* For internal logic, make sure the mute flag is set to false. */
            f_pConfBridgeAdd->fMute = FALSE;

            /* Force input port to Sout for logic below. */
            f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT;

            /* Keep law to check for conversion. */
            /* Check if the same law. */
            byTapChannelLaw = pEchoChanEntry->TdmConfig.bySoutPcmLaw;

            /* Check the tap handle. */
            if ( (f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;

            *f_pusTapChannelIndex = (UINT16)( f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_INDEX_MASK );
            if ( *f_pusTapChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;

            mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusTapChannelIndex )

            /* Extract the entry open count from the provided handle. */
            ulEntryOpenCnt = (f_pConfBridgeAdd->ulTappedChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

            /* Check for errors. */
            if ( pEchoChanEntry->fReserved != TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
            if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;
            if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_BRIDGE;
            if ( pEchoChanEntry->usBridgeIndex != *f_pusBridgeIndex )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_SAME_BRIDGE;

            /* We can only tap a channel added on the Sout port. */
            if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_TAP_SOUT_ONLY;

            /* Check if already tapped. */
            if ( pEchoChanEntry->fBeingTapped == TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_ALREADY_TAPPED;
      }

      /*=====================================================================*/

      /* Return the tap flag. */
      if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
      {
            *f_pfTap = TRUE;
      }
      else
      {
            *f_pfTap = FALSE;
      }

      /* Return the mute config specified. */
      *f_pfMute = (UINT8)( f_pConfBridgeAdd->fMute & 0xFF );

      /* Return the input port specified. */
      *f_pulInputPort = f_pConfBridgeAdd->ulInputPort;

      /* Return whether we are in the flexible conference bridge case. */
      *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;

      /* Return the listener mask index as specified. */
      *f_pulListenerMaskIndex = f_pConfBridgeAdd->ulListenerMaskIndex;

      /* Return the listener mask as specified. */
      *f_pulListenerMask = f_pConfBridgeAdd->ulListenerMask;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReserveBridgeAddResources

Description:    Reserves all resources needed for the addition of a channel to 
                        the conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_usBridgeIndex                     Bridge index of the bridge where this channel is added.
f_usChanIndex                       Channel index of the channel to be added to the bridge.
f_ulInputPort                       Input port where to copy samples from.
f_fFlexibleConfBridge         If this is a flexible conference bridge.
f_ulListenerMaskIndex         Index of the listener in this flexible conference bridge.
f_ulListenerMask              Mask of listeners in this flexible conference bridge.
f_pusLoadEventIndex                 Load event index within the API's list of mixer event.
f_pusSubStoreEventIndex       Sub-Store event index within the API's list of mixer event.
f_pusCopyEventIndex                 Copy event index within the API's list of mixer event.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveBridgeAddResources
UINT32 Oct6100ApiReserveBridgeAddResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex,
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT32                                          f_ulInputPort,
                        IN          UINT8                                     f_fFlexibleConfBridge,
                        IN          UINT32                                          f_ulListenerMaskIndex,
                        IN          UINT32                                          f_ulListenerMask,
                        IN          UINT8                                     f_fTap,
                        OUT         PUINT16                                         f_pusLoadEventIndex,
                        OUT         PUINT16                                         f_pusSubStoreEventIndex,
                        OUT         PUINT16                                         f_pusCopyEventIndex,
                        OUT         PUINT16                                         f_pusTapBridgeIndex )
{
      tPOCT6100_API_CHANNEL               pChanEntry;
      tPOCT6100_SHARED_INFO               pSharedInfo;
      tPOCT6100_API_CHANNEL               pTempEchoChanEntry;
      UINT32      ulResult;
      UINT32      ulTempVar;
      UINT16      usChannelIndex;
      BOOL  fLoadEventReserved = FALSE;
      BOOL  fStoreEventReserved = FALSE;
      BOOL  fCopyEventReserved = FALSE;
      BOOL  fExtraSinTsiReserved = FALSE;
      BOOL  fExtraRinTsiReserved = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      /* Get a pointer to the channel's list entry. */
      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex )

      /* Resources must be reserved according to the type of bridge we are adding to. */
      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;

            /*========================================================================*/
            /* If we are in the flexible conferencing case, things are a little       */
            /* different.  We create a mixer for every participant instead of the     */
            /* usual same mixer for everyone.  For example, if we have 3 participants */
            /* of type client - agent - coach, we build the mixers as follows:        */
            /*                                                                        */
            /*   Client:            - Load Agent                                      */
            /*                      - Store                                           */
            /*                                                                        */
            /*   Agent:             - Load Client                                     */
            /*                      - Accumulate Coach                                */
            /*                      - Store                                           */
            /*                                                                        */
            /*   Coach:             - Load Client                                     */
            /*                      - Accumulate Agent                                */
            /*                      - Store                                           */
            /*                                                                        */
            /*========================================================================*/

            /* First reserve a flexible conferencing participant entry. */
            ulResult = Oct6100ApiReserveFlexConfParticipantEntry( f_pApiInstance, &pChanEntry->usFlexConfParticipantIndex );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pChanEntry->usFlexConfParticipantIndex );

            /* Reserve an entry for the store event in the mixer memory. */
            ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex );
            if ( ulResult == cOCT6100_ERR_OK )
            {
                  /* If using the SOUT port, we must copy this entry */
                  if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
                  {
                        /* Reserve an entry for the copy event in the Mixer memory. */
                        ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex );
                        if ( ulResult == cOCT6100_ERR_OK )
                        {
                              fCopyEventReserved = TRUE;

                              /* Reserve a SIN copy entry if none were reserved before.*/
                              if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX )
                              {
                                    /* Reserve an entry for the extra tsi chariot memory. */
                                    ulResult = Oct6100ApiReserveTsiMemEntry(  f_pApiInstance, 
                                                                                                      &pChanEntry->usExtraSinTsiMemIndex );
                                    if ( ulResult == cOCT6100_ERR_OK )
                                          fExtraSinTsiReserved = TRUE;
                              }
                        }
                  }
                  else /* if( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
                  {
                        /* Reserve a RIN copy entry if none were reserved before.*/
                        if ( pChanEntry->usExtraRinTsiMemIndex == cOCT6100_INVALID_INDEX )
                        {
                              /* Reserve an entry for the extra tsi chariot memory. */
                              ulResult = Oct6100ApiReserveTsiMemEntry(  f_pApiInstance, 
                                                                                                &pChanEntry->usExtraRinTsiMemIndex );
                              if ( ulResult == cOCT6100_ERR_OK )
                                    fExtraRinTsiReserved = TRUE;
                        }                       
                  }

                  /* Must travel all clients of this conference and reserve a load or accumulate event for */
                  /* all participants which can hear us. */

                  /* Search through the list of API channel entry for the ones on to this bridge.*/
                  for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                        
                        /* Channel reserved? */
                        if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                        {
                              /* On current bridge? */
                              if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                              {
                                    mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                    /* Check if we can hear this participant. */
                                    if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                    {
                                          /* Must reserve a load or accumulate entry mixer event here! */
                                          ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                /* Most probably, the hardware is out of mixer events. */
                                                break;
                                          }
                                    }

                                    /* Check if this participant can hear us. */
                                    if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 )
                                    {
                                          /* Must reserve a load or accumulate entry mixer event here! */
                                          ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                /* Most probably, the hardware is out of mixer events. */
                                                break;
                                          }
                                    }
                              }
                        }
                  }

                  /* If an error is returned, make sure everything is cleaned up properly. */
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        /* Release the flexible conferencing participant entry. */
                        ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;
                        
                        pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;

                        /* Release the substore event in the mixer memory. */
                        ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;

                        if ( fCopyEventReserved == TRUE )
                        {
                              /* Release the copy event in the mixer memory. */
                              ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex );
                              if ( ulTempVar != cOCT6100_ERR_OK )
                                    return ulTempVar;
                        }

                        if ( fExtraSinTsiReserved == TRUE )
                        {
                              /* Release the extra Sin TSI in TSI memory. */
                              ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex );
                              if ( ulTempVar != cOCT6100_ERR_OK )
                                    return ulTempVar;

                              pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                        }

                        if ( fExtraRinTsiReserved == TRUE )
                        {
                              /* Release the extra Rin TSI in TSI memory. */
                              ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraRinTsiMemIndex );
                              if ( ulTempVar != cOCT6100_ERR_OK )
                                    return ulTempVar;

                              pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX;
                        }
                        
                        /* Search through the list of API channel entry for the ones on to this bridge. */
                        for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                        {
                              mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                              
                              /* Channel reserved? */
                              if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                              {
                                    /* On current bridge? */
                                    if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                                    {
                                          mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                          /* Check if we can hear this participant. */
                                          if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                          {
                                                /* If the load or event entry in the mixer memory was reserved. */
                                                if ( pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
                                                {
                                                      /* Must release the load or accumulate entry mixer event. */
                                                      ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] );
                                                      if ( ulTempVar != cOCT6100_ERR_OK )
                                                            return ulTempVar;

                                                      pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                                }
                                          }

                                          /* Check this participant can hear us. */
                                          if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 )
                                          {
                                                /* If the load or event entry in the mixer memory was reserved. */
                                                if ( pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
                                                {
                                                      /* Must release the load or accumulate entry mixer event. */
                                                      ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] );
                                                      if ( ulTempVar != cOCT6100_ERR_OK )
                                                            return ulTempVar;

                                                      pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                                }
                                          }
                                    }
                              }
                        }

                        return ulResult;
                  }
            }
            else /* if ( ulResult != cOCT6100_ERR_OK ) */
            {
                  ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex );
                  if ( ulTempVar != cOCT6100_ERR_OK )
                        return ulTempVar;

                  pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;
                  
                  /* Return the error code to the user.  The mixer event allocation failed. */
                  return ulResult;
            }

            /*=======================================================================*/
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            /*=======================================================================*/
            /* Normal conferencing. */          

            /* Reserve an entry for the load event in the mixer memory. */
            ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusLoadEventIndex );
            if ( ulResult == cOCT6100_ERR_OK )
            {
                  fLoadEventReserved = TRUE;
                  /* Reserve an entry for the substract and store event in the mixer memory. */
                  ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex );
                  if ( ulResult == cOCT6100_ERR_OK )
                  {
                        fStoreEventReserved = TRUE;

                        /* If using the SOUT port, we must copy this entry */
                        if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
                        {
                              /* Reserve an entry for the copy event in the mixer memory. */
                              ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex );
                              if ( ulResult == cOCT6100_ERR_OK )
                              {
                                    fCopyEventReserved = TRUE;

                                    /* Reserve a SIN copy entry if none were reserved before. */
                                    if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX )
                                    {
                                          /* Reserve an entry for the extra tsi chariot memory. */
                                          ulResult = Oct6100ApiReserveTsiMemEntry(  f_pApiInstance, 
                                                                                                            &pChanEntry->usExtraSinTsiMemIndex );

                                          if ( ulResult == cOCT6100_ERR_OK )
                                                fExtraSinTsiReserved = TRUE;
                                    }
                              }
                        }
                  }
            }

            if ( ( ulResult == cOCT6100_ERR_OK ) && ( f_fTap == TRUE ) )
            {
                  /* Reserve a "tap" bridge. */
                  tOCT6100_CONF_BRIDGE_OPEN     ConfBridgeOpen;
                  UINT32                                    ulTapBridgeHndl = 0;

                  Oct6100ConfBridgeOpenDef( &ConfBridgeOpen );

                  ConfBridgeOpen.pulConfBridgeHndl = &ulTapBridgeHndl;

                  ulResult = Oct6100ConfBridgeOpenSer( f_pApiInstance, &ConfBridgeOpen );

                  *f_pusTapBridgeIndex = (UINT16)( ulTapBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
            }

            if ( ulResult != cOCT6100_ERR_OK )
            {
                  if ( fLoadEventReserved == TRUE )
                  {
                        ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusLoadEventIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;
                  }
            
                  if ( fStoreEventReserved == TRUE )
                  {
                        ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;
                  }
                  
                  if ( fCopyEventReserved == TRUE )
                  {
                        ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;
                  }

                  if ( fExtraSinTsiReserved == TRUE )
                  {
                        ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex );
                        if ( ulTempVar != cOCT6100_ERR_OK )
                              return ulTempVar;

                        pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                  }

                  return ulResult;
            }

            /*=======================================================================*/
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeEventAdd

Description:    Add the event into the global event list of the chip and update
                        the bridge and channel structures.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to 
                                          keep the present state of the chip and all its 
                                          resources.
f_usBridgeIndex                     Index of the current bridge in the API list.
f_usChanIndex                       Index of the current channel in the API list.
f_fFlexibleConfBridge         If this is a flexible conference bridge.
f_usLoadEventIndex                  Allocated entry for the Load event of the 
                                          channel.
f_usSubStoreEventIndex        Allocated entry for the substract and store 
                                          event of the channel.
f_usCopyEventIndex                  Allocated entry for the copy event of the 
                                          channel.
f_ulInputPort                       Input port where to copy samples from.
f_fMute                                   Mute flag indicating if the channel is added in 
                                          a mute state.
f_ulListenerMaskIndex         Index of the listener in this flexible conference bridge.
f_ulListenerMask              Mask of listeners in this flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeEventAdd
UINT32 Oct6100ApiBridgeEventAdd(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex, 
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT8                                     f_fFlexibleConfBridge,
                        IN          UINT16                                          f_usLoadEventIndex,
                        IN          UINT16                                          f_usSubStoreEventIndex,
                        IN          UINT16                                          f_usCopyEventIndex,
                        IN          UINT32                                          f_ulInputPort,
                        IN          UINT8                                     f_fMute, 
                        IN          UINT32                                          f_ulListenerMaskIndex,
                        IN          UINT32                                          f_ulListenerMask,
                        IN          UINT8                                     f_fTap,
                        IN          UINT16                                          f_usTapBridgeIndex,
                        IN          UINT16                                          f_usTapChanIndex )
{
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT           pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT           pSubStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT           pTempEntry;

      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      tPOCT6100_API_CHANNEL               pTapEchoChanEntry = NULL;
      tPOCT6100_API_CHANNEL               pTempEchoChanEntry;

      tPOCT6100_SHARED_INFO               pSharedInfo;
      tOCT6100_WRITE_PARAMS               WriteParams;

      UINT32      ulResult;
      UINT16      usChannelIndex;
      UINT16      usLastSubStoreEventIndex;
      UINT16      usLastLoadEventIndex;

      BOOL  fAddSinCopy = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      /* Get the bridge and channel entries of interest. */
      if ( f_fTap == FALSE )
      {
            mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex );
      }
      else
      {
            mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usTapBridgeIndex );
            mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapEchoChanEntry, f_usTapChanIndex );
      }
      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );

      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;

            mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

            /* Search through the list of API channel entry for the ones onto this bridge. */
            for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                  
                  /* Channel reserved? */
                  if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                  {
                        /* On current bridge? */
                        if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                        {
                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                              /* Check if we can hear this participant. */
                              if ( ( pTempEchoChanEntry->fMute == FALSE ) && ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) )
                              {
                                    /* First create/update the current channel's mixer. */
                                    ulResult = Oct6100ApiBridgeAddParticipantToChannel(
                                                                              f_pApiInstance,
                                                                              f_usBridgeIndex,
                                                                              usChannelIndex,
                                                                              f_usChanIndex,
                                                                              pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ],
                                                                              f_usSubStoreEventIndex,
                                                                              f_usCopyEventIndex,
                                                                              pCurrentParticipant->ulInputPort,
                                                                              f_ulInputPort );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }

                              /* Check if this participant can hear us. */
                              if ( ( f_fMute == FALSE ) && ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) )
                              {
                                    /* Then create/update this channel's mixer. */
                                    ulResult = Oct6100ApiBridgeAddParticipantToChannel(
                                                                              f_pApiInstance,
                                                                              f_usBridgeIndex,
                                                                              f_usChanIndex,
                                                                              usChannelIndex,
                                                                              pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ],
                                                                              pTempEchoChanEntry->usSubStoreEventIndex,
                                                                              pTempEchoChanEntry->usSinCopyEventIndex,
                                                                              f_ulInputPort,
                                                                              pCurrentParticipant->ulInputPort );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    /* Check if the Rin silence event can be cleared now that the */
                                    /* channel has been added to a conference. */
                                    if ( ( pCurrentParticipant->fFlexibleMixerCreated == TRUE )
                                          && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) )
                                    {
                                          /* Remove the event from the list. */
                                          ulResult = Oct6100ApiMixerEventRemove(    f_pApiInstance,
                                                                                                      pTempEchoChanEntry->usRinSilenceEventIndex,
                                                                                                      cOCT6100_EVENT_TYPE_SOUT_COPY );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex );
                                          if ( ulResult != cOCT6100_ERR_OK  )
                                                return cOCT6100_ERR_FATAL_DF;

                                          pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
                                    }
                              }
                        }
                  }
            }

            /* Check if the mixer for the destination channel has been created. */
            if ( pNewParticipant->fFlexibleMixerCreated == FALSE )
            {
                  /* Save store event index that might be used for next channel added. */
                  pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex;
            }
            else
            {
                  /* Check if the Rin silence event can be cleared now that the */
                  /* channel has been added to a conference. */
                  if ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        /* Remove the event from the list.*/
                        ulResult = Oct6100ApiMixerEventRemove(    f_pApiInstance,
                                                                                    pEchoChanEntry->usRinSilenceEventIndex,
                                                                                    cOCT6100_EVENT_TYPE_SOUT_COPY );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return cOCT6100_ERR_FATAL_DF;

                        pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
                  }
            }

            pNewParticipant->ulListenerMaskIndex = f_ulListenerMaskIndex;
            pNewParticipant->ulListenerMask = f_ulListenerMask;

            /* Remember this channel's input port. */
            pNewParticipant->ulInputPort = f_ulInputPort;

            /*=======================================================================*/
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */
            if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) )
            {
                  if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
                  {
                        ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                  pEchoChanEntry->usSinTsstIndex,
                                                                                                  pEchoChanEntry->usExtraSinTsiMemIndex,
                                                                                                  pEchoChanEntry->TdmConfig.bySinPcmLaw );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }

                  /* If the silence TSI is loaded on this port, update with the extra sin TSI. */
                  if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                        WriteParams.ulWriteAddress += 2;
                        WriteParams.usWriteData = pEchoChanEntry->usExtraSinTsiMemIndex;

                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }
            }

            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex );
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );

            /*=======================================================================*/
            /* Program the Load event.*/
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            if ( ( f_fMute == FALSE ) || ( f_fTap == TRUE ) )
            {
                  if ( pBridgeEntry->usLoadIndex != cOCT6100_INVALID_INDEX )
                  {
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;

                        /* Set the event type. */
                        pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;

                        if ( f_fTap == TRUE )
                              return cOCT6100_ERR_FATAL_D1;
                  }
                  else /* pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX */
                  {
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;

                        /* Modify the bridge entry to show store the new load index.*/
                        pBridgeEntry->usLoadIndex = f_usLoadEventIndex;

                        /* Set the event type.*/
                        pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                  }

                  /* Select the TSI memory index according to the source port. */
                  if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
                  {
                        if ( f_fTap == FALSE )
                        {
                              WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
                        }
                        else
                        {
                              tPOCT6100_API_CONF_BRIDGE     pTempBridgeEntry;
                              UINT16                                    usTempWriteData;
                              UINT32                                    ulTempWriteAddress;

                              /* Save temp write data before trying to clear the Rin TSST. */
                              usTempWriteData = WriteParams.usWriteData;
                              ulTempWriteAddress = WriteParams.ulWriteAddress;
                              
                              /* Clear the Rin TSST if used. */
                              if ( pTapEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
                              {
                                    /* Deactivate the TSST entry.*/
                                    WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pTapEchoChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE );
                                    WriteParams.usWriteData  = 0x0000;

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }

                              /* Reassign write data that might have been cleared by write above. */
                              WriteParams.usWriteData = usTempWriteData;
                              WriteParams.ulWriteAddress = ulTempWriteAddress;
                              WriteParams.usWriteData |= pTapEchoChanEntry->usRinRoutTsiMemIndex;

                              /* Remember that this channel is being tapped by us. */
                              pTapEchoChanEntry->fBeingTapped = TRUE;
                              pTapEchoChanEntry->usTapChanIndex = f_usChanIndex;

                              mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex );

                              pTempBridgeEntry->usNumTappedClients++;
                        }
                  }
                  else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
                  {
                        WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
                  }
            }
            else /* f_fMute == TRUE */
            {
                  /* Do not load the sample if the channel is muted. */
                  if ( pBridgeEntry->usNumClients == 0 )
                  {
                        /* If the participant to be added is muted, and it would cause the conference to */
                        /* be completely muted, load the silence TSI. */
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                        WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */

                        /* We know for sure that the load of the bridge will be the silence one. */
                        pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex;
                  }
                  else
                  {
                        /* Do nothing! */
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                  }
                  
                  /* Set the event type. */
                  pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
            }
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/
            
            /*=======================================================================*/
            /* Program the Substract and store event.*/
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            if ( ( f_fMute == FALSE ) && ( f_fTap == FALSE ) )
            {
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
                  /* Select the TSI memory index and PCM law according to the source port. */
                  if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
                  {
                        WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                        WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
                  }
                  else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
                  {
                        WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                        WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
                  }
                  
                  /* Set the event type. */
                  pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
            }
            else /* f_fMute == TRUE */
            {
                  /* Do not substore the sample if the channel is muted. */
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE;

                  /* Select the PCM law according to the source port. */
                  if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
                  {
                        WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  }
                  else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
                  {
                        WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  }
                  /* Set the event type. */
                  pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE;
            }

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            WriteParams.ulWriteAddress += 2;
            WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Program the Copy event - if using the SOUT port */
            if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) )
            {
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY;
                  WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex;
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK  )
                        return ulResult;

                  WriteParams.ulWriteAddress += 2;
                  WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK  )
                        return ulResult;

                  /* Set add copy event flag. */
                  fAddSinCopy = TRUE;

                  /* For sure. */
                  pEchoChanEntry->fCopyEventCreated = TRUE;
            }
            else if ( f_fTap == TRUE )
            {
                  /* Accumulate the tapped channel's voice instead of building a copy event. */
                  
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
                  WriteParams.usWriteData |= pTapEchoChanEntry->usSinSoutTsiMemIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* Link to next operation. */
                  WriteParams.ulWriteAddress += 4;
                  WriteParams.usWriteData = f_usSubStoreEventIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* Update the software model. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, f_usCopyEventIndex );

                  pTempEntry->usSourceChanIndex = f_usTapChanIndex;
                  pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
                  pTempEntry->usNextEventPtr = f_usSubStoreEventIndex;
                  pTempEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX;
                  pTempEntry->fReserved = TRUE;
            }
            /*=======================================================================*/

            /*=======================================================================*/
            /* Now insert the event into the list.*/
            if ( pBridgeEntry->usNumClients == 0 )
            {
                  /* This is the first entry for this bridge. Insert the two events at the head
                     of the list just after the last sub-store event.*/
                  if ( f_fTap == FALSE )
                  {
                        ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usLastSubStoreEventIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND )
                              {
                                    if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
                                    {
                                          usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE;
                                    }
                                    else
                                    {
                                          usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
                                    }
                              }
                              else
                              {
                                    return cOCT6100_ERR_FATAL_26;
                              }
                        }
                  }
                  else
                  {
                        if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
                        {
                              usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE;
                        }
                        else
                        {
                              usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
                        }
                  }

                  /* An Entry was found, now, modify it's value.*/
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex );

                  /* Set the Sub-Store event first.*/
                  pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
                  pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;

                  /*=======================================================================*/
                  /* Program the Sub-Store event. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;
                  WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/

                  /* Set the load/accumulate event now.*/
                  if ( f_fTap == FALSE )
                  {
                        pLoadEventEntry->usNextEventPtr = f_usSubStoreEventIndex;
                  }
                  else
                  {
                        /* This is a little tricky, we use the copy event index for accumulating the tapped channel's voice. */
                        pLoadEventEntry->usNextEventPtr = f_usCopyEventIndex;
                  }

                  /*=======================================================================*/
                  /* Program the load/accumulate event. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/

                  /* Now modify the previous last Sub Store event from another bridge. */
                  pTempEntry->usNextEventPtr = f_usLoadEventIndex;

                  /*=======================================================================*/
                  /* Modify the last node of the other bridge. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/
                  
                  /* Set the event pointer info in the bridge stucture. */
                  pBridgeEntry->usFirstLoadEventPtr = f_usLoadEventIndex;
                  pBridgeEntry->usFirstSubStoreEventPtr = f_usSubStoreEventIndex;
                  pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex;

                  /* Update the global mixer pointers. */
                  if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX )
                  {
                        /* This bridge is the first to generate mixer event. */
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex;
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr      = f_usSubStoreEventIndex;    
                  }
                  else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex )
                  {
                        /* The two entries were added at the end of the bridge section, */
                        /* change only the last pointer. */
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr  = f_usSubStoreEventIndex;
                  }
                  else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE ||
                                usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr )
                  {
                        /* The two entries were added at the start of the bridge section, */
                        /* change only the first pointer. */
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex;
                  }
            }
            else /* pBridgeEntry->usNumClients != 0 */
            {
                  /* For sanity. */
                  if ( f_fTap == TRUE )
                        return cOCT6100_ERR_FATAL_D2;
                  
                  /*=======================================================================*/
                  /* Program the Load event. */

                  /* Now find the last load entry of this bridge. */
                  ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, pBridgeEntry->usFirstSubStoreEventPtr, 0, &usLastLoadEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* Add the load/accumulate event to the list. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex  );
                  
                  /* Set the load event now. */
                  pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;

                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Modify the previous last load event. */

                  /* Now modify the previous last load event. */
                  pTempEntry->usNextEventPtr = f_usLoadEventIndex;

                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Program the Sub-Store event. */

                  usLastSubStoreEventIndex = pBridgeEntry->usLastSubStoreEventPtr;

                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex );

                  /* Set the Sub-Store event first. */
                  pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;

                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Modify the previous last sub store event of the bridge. */

                  /* Now modify the last Load event of the bridge. */
                  pTempEntry->usNextEventPtr = f_usSubStoreEventIndex;

                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/

                  /* Update the bridge pointers. */
                  pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex;

                  /* Check if modification to the global mixer pointer are required. */
                  if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex )
                  {
                        /* We have a new last bridge pointer. */
                         pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex;
                  }     
            }

            if ( f_fTap == TRUE )
            {
                  if ( pEchoChanEntry->usRinTsstIndex == cOCT6100_INVALID_INDEX )
                  {
                        /* Remove the mute on the Rin port. */

                        UINT32 ulTempData;
                        UINT32 ulMask;
                        UINT32 ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst;

                        /* Configure the level control. */

                        UINT32 ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4;
                        UINT32 ulFeatureBitOffset      = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset;
                        UINT32 ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize;

                        mOCT6100_RETRIEVE_NLP_CONF_DWORD(   f_pApiInstance,
                                                                              pEchoChanEntry,
                                                                              ulBaseAddress + ulFeatureBytesOffset,
                                                                              &ulTempData,
                                                                              ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        /* Clear previous value set in the feature field.*/
                        mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask );

                        ulTempData &= (~ulMask);

                        /* Set the DC filter to pass through.*/
                        ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset );

                        /* First read the DWORD where the field is located. */
                        mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
                                                                        pEchoChanEntry,
                                                                        ulBaseAddress + ulFeatureBytesOffset,
                                                                        ulTempData,
                                                                        ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }
            }

            /* Set the event entries as reserved. */
            pLoadEventEntry->fReserved = TRUE;
            pSubStoreEventEntry->fReserved = TRUE;

            /* Store the event indexes into the channel structure. */
            pEchoChanEntry->usLoadEventIndex = f_usLoadEventIndex;
            pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex;

            /* Check if must insert the Sin copy event in the list. */
            if ( fAddSinCopy == TRUE )
            {
                  /* Now insert the Sin copy event into the list. */
                  ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance,
                                                                        f_usCopyEventIndex,
                                                                        cOCT6100_EVENT_TYPE_SIN_COPY,
                                                                        f_usChanIndex );
            }

            /* Check if the Rin silence event can be cleared now that the */
            /* channel has been added to a conference. */
            if ( ( f_fTap == FALSE ) && ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) )
            {
                  /* Remove the event from the list. */
                  ulResult = Oct6100ApiMixerEventRemove(    f_pApiInstance,
                                                                              pEchoChanEntry->usRinSilenceEventIndex,
                                                                              cOCT6100_EVENT_TYPE_SOUT_COPY );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return cOCT6100_ERR_FATAL_DF;

                  pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
            }
      }

      /* Configure the RIN copy mixer entry and memory - if using the RIN port. */
      if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) )
      {
            if ( pEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
            {
                  ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                            pEchoChanEntry->usRinTsstIndex,
                                                                                            pEchoChanEntry->usExtraRinTsiMemIndex,
                                                                                            pEchoChanEntry->TdmConfig.byRinPcmLaw );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }
      }

      if ( pBridgeEntry->fDominantSpeakerSet == TRUE )
      {
            /* Dominant speaker is another channel.  Set accordingly for this new conference channel. */
            ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, pBridgeEntry->usDominantSpeakerChanIndex );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;
      }
      else
      {
            /* No dominant speaker set on this bridge yet. */
            ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;
      }

      /* Update the bridge entry. */
      pBridgeEntry->usNumClients++;

      /* Store the bridge index into the channel structure. */
      pEchoChanEntry->usBridgeIndex = f_usBridgeIndex;

      /* Store the copy event index into the channel structure. */
      if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
      {
            pEchoChanEntry->usSinCopyEventIndex = f_usCopyEventIndex;
      }
      else
      {
            pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX;
      }

      /* Remember if the channel is muted in the conference. */
      pEchoChanEntry->fMute = f_fMute;

      /* Remember if the channel is a tap in a conference. */
      pEchoChanEntry->fTap = f_fTap;

      /* We start by not being tapped. */
      pEchoChanEntry->fBeingTapped = FALSE;
      pEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX;

      /* Remember the tap bridge index if necessary. */
      if ( pEchoChanEntry->fTap == TRUE )
      {
            pEchoChanEntry->usTapBridgeIndex = f_usTapBridgeIndex;
      }
      else
      {
            pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX;
      }

      /* Indicate that the extra SIN TSI is currently in used by the conference bridge. */
      if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
      {
            pEchoChanEntry->usExtraSinTsiDependencyCnt++;
      }

      /* Indicate that the extra RIN TSI is currently in used by the conference bridge. */
      if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) )
      {
            pEchoChanEntry->usExtraRinTsiDependencyCnt++;
      }

      /* Update the chip stats structure. */
      pSharedInfo->ChipStats.usNumEcChanUsingMixer++;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeAddParticipantToChannel

Description:    Used for the flexible conference bridges.  Insert a participant
                        onto a channel that is on a conference.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                            Pointer to API instance. This memory is used to keep the
                                                present state of the chip and all its resources.
f_usBridgeIndex                           Bridge index where this channel is located.
f_usSourceChannelIndex              Source channel to copy voice from.
f_usDestinationChannelIndex         Destination channel to store resulting voice to.
f_usLoadOrAccumulateEventIndex      Load or Accumulate allocated event index.
f_usStoreEventIndex                       Store allocated event index.
f_usCopyEventIndex                        Copy allocated event index.
f_ulSourceInputPort                       Source input port of the conference for this channel.
f_ulDestinationInputPort            Destination input port of the conference for this channel.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeAddParticipantToChannel
UINT32      Oct6100ApiBridgeAddParticipantToChannel(
                        IN OUT      tPOCT6100_INSTANCE_API  f_pApiInstance,
                        IN          UINT16                              f_usBridgeIndex, 
                        IN          UINT16                              f_usSourceChannelIndex,
                        IN          UINT16                              f_usDestinationChannelIndex,
                        IN          UINT16                              f_usLoadOrAccumulateEventIndex,
                        IN          UINT16                              f_usStoreEventIndex,
                        IN          UINT16                              f_usCopyEventIndex,
                        IN          UINT32                              f_ulSourceInputPort,
                        IN          UINT32                              f_ulDestinationInputPort )
{
      tPOCT6100_API_CONF_BRIDGE                 pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT                 pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pTempEntry;

      tPOCT6100_API_CHANNEL                     pSourceChanEntry;
      tPOCT6100_API_CHANNEL                     pDestinationChanEntry;

      tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant;

      tPOCT6100_SHARED_INFO               pSharedInfo;
      tOCT6100_WRITE_PARAMS               WriteParams;

      UINT32                                          ulResult;
      UINT16                                          usLastSubStoreEventIndex;
      UINT16                                          usLastLoadEventIndex;
      BOOL                                      fInsertCopy = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex );

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex );
      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex );
      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex );
      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex );

      mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadOrAccumulateEventIndex );
      mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, f_usStoreEventIndex );

      /* Check if we are creating the first event for this channel. */
      if ( pDestinationParticipant->fFlexibleMixerCreated == FALSE )
      {
            /*=======================================================================*/
            /* Before creating the participant's flexible mixer, make sure the extra Sin */
            /* mixer event is programmed correctly for sending the voice stream to the right place. */

            /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */
            if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT )
            {
                  if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
                  {
                        ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                  pDestinationChanEntry->usSinTsstIndex,
                                                                                                  pDestinationChanEntry->usExtraSinTsiMemIndex,
                                                                                                  pDestinationChanEntry->TdmConfig.bySinPcmLaw );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }

                  /* If the silence TSI is loaded on this port, update with the extra sin TSI. */
                  if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                        WriteParams.ulWriteAddress += 2;
                        WriteParams.usWriteData = pDestinationChanEntry->usExtraSinTsiMemIndex;

                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }
            }
            /*=======================================================================*/

            
            /*=======================================================================*/
            /* Program the load event.  This is the first event for this new destination channel. */

            /* First set the TSI buffer where the resulting stream should be written to. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

            /* For sure, we are loading. */
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;

            /* Select the TSI memory index according to the source port. */
            if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT )
            {
                  WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex;
            }
            else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
            {
                  WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex;
            }

            /* Set the event type. */
            pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;

            /* Set the source channel index. */
            pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/



            /*=======================================================================*/
            /* Program the store event. */

            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE;

            /* Select the TSI memory index and PCM law according to the source port. */
            if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT )
            {
                  WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  WriteParams.usWriteData |= pDestinationChanEntry->usSinSoutTsiMemIndex;
            }
            else /* if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
            {
                  WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  WriteParams.usWriteData |= pDestinationChanEntry->usRinRoutTsiMemIndex;
            }
            
            /* Set the event type. */
            pStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE;

            /* Set the destination channel index. */
            pStoreEventEntry->usDestinationChanIndex = f_usDestinationChannelIndex;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            WriteParams.ulWriteAddress += 2;
            WriteParams.usWriteData = pDestinationChanEntry->usRinRoutTsiMemIndex;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/



            /*=======================================================================*/
            /* Program the Copy event - if using the SOUT port */

            if ( ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pDestinationChanEntry->fCopyEventCreated == FALSE ) )
            {
                  /* The copy event has not been created, create it once for the life of the participant on the bridge. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY;
                  WriteParams.usWriteData |= pDestinationChanEntry->usExtraSinTsiMemIndex;
                  WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  WriteParams.ulWriteAddress += 2;
                  WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  pDestinationChanEntry->fCopyEventCreated = TRUE;

                  /* Set insert copy flag. */
                  fInsertCopy = TRUE;
            }
            
            /*=======================================================================*/



            /*=======================================================================*/
            /*=======================================================================*/
            /* Now, insert the events into the current list. */
            /*=======================================================================*/
            /*=======================================================================*/

            /* This is the first entry for this channel. Insert the two events at the head */
            /* of the list just after the last Sub-Store or Store event. */
            ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, f_usLoadOrAccumulateEventIndex, &usLastSubStoreEventIndex );
            if ( ulResult != cOCT6100_ERR_OK )
            {
                  if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND )
                  {
                        if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
                        {
                              usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE;
                        }
                        else
                        {
                              usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
                        }
                  }
                  else
                  {
                        return cOCT6100_ERR_FATAL_26;
                  }
            }

            /* An entry was found, now, modify it's value. */
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex );

            /*=======================================================================*/


            /*=======================================================================*/
            /* Link the store event first. */
            
            pStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;

            /* Link the store event. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.ulWriteAddress += 4;
            WriteParams.usWriteData = (UINT16)( pStoreEventEntry->usNextEventPtr );
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Link the load event now.*/

            pLoadEventEntry->usNextEventPtr = f_usStoreEventIndex;

            /* Link the load event.*/
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.ulWriteAddress += 4;

            WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Now modify the previous last Sub-Store or Store event from another bridge, */
            /* such that it links to us. */

            pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex;

            /* Modify the last node of the other bridge. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.ulWriteAddress += 4;

            WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Set the event pointer info in the bridge stucture. */

            if ( pBridgeEntry->usFirstLoadEventPtr == cOCT6100_INVALID_INDEX )
            {
                  /* We only do this once in case of the flexible conference bridges. */
                  pBridgeEntry->usFirstLoadEventPtr = f_usLoadOrAccumulateEventIndex;
                  pBridgeEntry->usFirstSubStoreEventPtr = f_usStoreEventIndex;
            }

            pBridgeEntry->usLastSubStoreEventPtr = f_usStoreEventIndex;

            /* Update the global mixer pointers. */
            if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX )
            {
                  /* This bridge is the first to generate mixer event. */
                  pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex;
                  pSharedInfo->MixerInfo.usLastBridgeEventPtr      = f_usStoreEventIndex; 
            }
            else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex )
            {
                  /* The two entries were added at the end of the bridge section, */
                  /* change only the last pointer. */
                  pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usStoreEventIndex;
            }
            else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE ||
                          usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr )
            {
                  /* The two entries were added at the start of the bridge section, */
                  /* change only the first pointer.*/
                  pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex;
            }

            /*=======================================================================*/


            /*=======================================================================*/
            /* Insert the copy event if needed in the mixer's list. */

            if ( fInsertCopy == TRUE )
            {
                  /* Now insert the Sin copy event into the list. */
                  ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance,
                                                                        f_usCopyEventIndex,
                                                                        cOCT6100_EVENT_TYPE_SIN_COPY,
                                                                        f_usDestinationChannelIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }

            /*=======================================================================*/


            /*=======================================================================*/
            /* Update the status of the instance structures. */

            pDestinationParticipant->fFlexibleMixerCreated = TRUE;

            /* Set the event entries as reserved. */
            pLoadEventEntry->fReserved = TRUE;
            pStoreEventEntry->fReserved = TRUE;

            /* Store the event indexes into the channel structure. */
            pDestinationChanEntry->usLoadEventIndex = f_usLoadOrAccumulateEventIndex;
            pDestinationChanEntry->usSubStoreEventIndex = f_usStoreEventIndex;

            /*=======================================================================*/
      }
      else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == TRUE ) */
      {
            /*=======================================================================*/
            /* Program the Accumulate event. */

            /* First set the TSI buffer where the resulting stream should be written to. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

            /* For sure, we are accumulating. */
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;

            /* Select the TSI memory index according to the source port. */
            if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT )
            {
                  WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex;
            }
            else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
            {
                  WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex;
            }

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/



            /*=======================================================================*/
            /*=======================================================================*/
            /* Now, insert the Accumulate event into the current list. */
            /*=======================================================================*/
            /*=======================================================================*/

            /* Use the Load entry of this channel. */
            usLastLoadEventIndex = pDestinationChanEntry->usLoadEventIndex;

            /* Add the Accumulate event to the list. */
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex );
            
            /* Set the accumulate event now. */
            pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;

            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.ulWriteAddress += 4;

            WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/



            /*=======================================================================*/
            /* Modify the previous Load event. */

            /* Now modify the previous Load event. */
            pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex;

            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.ulWriteAddress += 4;

            WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /*=======================================================================*/


            
            /*=======================================================================*/
            /* Update the status of the instance structures. */

            /* Set the Accumulate event entry as reserved. */
            pLoadEventEntry->fReserved = TRUE;
            /* Set the Event type. */
            pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
            /* Set the source channel index. */
            pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex;

            /*=======================================================================*/
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanRemoveSer

Description:    Removes an echo channel from a conference bridge. 

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeRemove           Pointer to conference bridge channel remove structure.  

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanRemoveSer
UINT32 Oct6100ConfBridgeChanRemoveSer(
                        IN OUT      tPOCT6100_INSTANCE_API                          f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_REMOVE         f_pConfBridgeRemove )
{
      UINT16      usBridgeIndex;
      UINT16      usChanIndex = 0;
      UINT16      usLoadEventIndex;
      UINT16      usSubStoreEventIndex;
      UINT16      usCopyEventIndex;
      UINT32      ulResult;
      UINT8 fFlexibleConfBridge;
      UINT8 fTap;

      /* Check the validity of the channel and conference bridge given. */
      ulResult = Oct6100ApiCheckChanRemoveParams(
                                                            f_pApiInstance, 
                                                            f_pConfBridgeRemove, 
                                                            &usBridgeIndex, 
                                                            &usChanIndex, 
                                                            &fFlexibleConfBridge, 
                                                            &fTap,
                                                            &usLoadEventIndex, 
                                                            &usSubStoreEventIndex, 
                                                            &usCopyEventIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Release all resources reserved for the conference bridge. */
      ulResult = Oct6100ApiReleaseChanEventResources( 
                                                            f_pApiInstance, 
                                                            f_pConfBridgeRemove, 
                                                            usBridgeIndex, 
                                                            usChanIndex, 
                                                            fFlexibleConfBridge, 
                                                            usLoadEventIndex, 
                                                            usSubStoreEventIndex, 
                                                            usCopyEventIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Clear the memory entry for this channel within the bridge. */
      ulResult = Oct6100ApiBridgeEventRemove( 
                                                            f_pApiInstance, 
                                                            f_pConfBridgeRemove, 
                                                            usBridgeIndex, 
                                                            usChanIndex, 
                                                            fFlexibleConfBridge, 
                                                            usLoadEventIndex, 
                                                            usSubStoreEventIndex, 
                                                            usCopyEventIndex,
                                                            fTap );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckChanRemoveParams

Description:      Check the validity of the channel and conference bridge given.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_pConfBridgeRemove                 Pointer to conference bridge channenl add structure.  
f_pusBridgeIndex              Pointer to the bridge index.
f_pfFlexibleConfBridge        If this is a flexible conference bridge
f_pusChannelIndex             Pointer to the channel index to be added to the bridge.
f_pusLoadEventIndex                 Pointer to the load mixer event.
f_pusSubStoreEventIndex       Pointer to the sub-store mixer event.
f_pusCopyEventIndex                 Pointer to the copy mixer event.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckChanRemoveParams
UINT32 Oct6100ApiCheckChanRemoveParams(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_REMOVE   f_pConfBridgeRemove,
                        OUT         PUINT16                                               f_pusBridgeIndex, 
                        OUT         PUINT16                                               f_pusChannelIndex,
                        OUT         PUINT8                                                f_pfFlexibleConfBridge,
                        OUT         PUINT8                                                f_pfTap,
                        OUT         PUINT16                                               f_pusLoadEventIndex,
                        OUT         PUINT16                                               f_pusSubStoreEventIndex,
                        OUT         PUINT16                                               f_pusCopyEventIndex )
{
      UINT32                                    ulEntryOpenCnt;
      tPOCT6100_API_CHANNEL         pEchoChanEntry;
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;

      /* Verify if the remove all flag is valid. */
      if ( f_pConfBridgeRemove->fRemoveAll != TRUE && 
             f_pConfBridgeRemove->fRemoveAll != FALSE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_ALL;

      /* Check the channel handle only if the remove all flag is set to FALSE. */
      if ( f_pConfBridgeRemove->fRemoveAll == FALSE )
      {
            /*=====================================================================*/
            /* Check the channel handle. */

            if ( (f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            *f_pusChannelIndex = (UINT16)( f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
            if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

            /* Extract the entry open count from the provided handle. */
            ulEntryOpenCnt = (f_pConfBridgeRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

            /* Check for errors. */
            if ( pEchoChanEntry->fReserved != TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
            if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
            if ( pEchoChanEntry->fBeingTapped == TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY;

            /*=====================================================================*/

            *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex;
            *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex;
            *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex;
            *f_pusCopyEventIndex = pEchoChanEntry->usSinCopyEventIndex;

            /* Check if the channel is really part of the bridge. */
            if ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE;

            mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

            /* Return whether this is a flexible bridge or not. */
            *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;

            /* Return whether this is a tap or not. */
            *f_pfTap = pEchoChanEntry->fTap;
      }
      else /* f_pConfBridgeRemove->fRemoveAll == TRUE */
      {
            /* Check the provided handle. */
            if ( (f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            *f_pusBridgeIndex = (UINT16)( f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
            if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

            /* Extract the entry open count from the provided handle. */
            ulEntryOpenCnt = (f_pConfBridgeRemove->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

            /* Check for errors. */
            if ( pBridgeEntry->fReserved != TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
            if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            /* This information is not currently available. */
            *f_pusLoadEventIndex = cOCT6100_INVALID_INDEX;
            *f_pusSubStoreEventIndex = cOCT6100_INVALID_INDEX;
            *f_pusCopyEventIndex = cOCT6100_INVALID_INDEX;

            /* Return whether this is a flexible bridge or not. */
            *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;

            *f_pfTap = FALSE;
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReleaseChanEventResources

Description:    Release all resources reserved to the channel part of the 
                        conference bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_pConfBridgeRemove                 Pointer to conference bridge channel add structure.  
f_usBridgeIndex                     Index of the bridge structure within the API's bridge list.
f_usChanIndex                       Index of the channel structure within the API's channel list
f_fFlexibleConfBridge         If this is a flexible conference bridge.
f_usLoadEventIndex                  Index of the load mixer event.
f_usSubStoreEventIndex        Index of the sub-store mixer event.
f_usCopyEventIndex                  Index of the copy mixer event.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReleaseChanEventResources
UINT32 Oct6100ApiReleaseChanEventResources(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_REMOVE   f_pConfBridgeRemove,
                        IN          UINT16                                                f_usBridgeIndex, 
                        IN          UINT16                                                f_usChanIndex,
                        IN          UINT8                                           f_fFlexibleConfBridge,
                        IN          UINT16                                                f_usLoadEventIndex,
                        IN          UINT16                                                f_usSubStoreEventIndex,
                        IN          UINT16                                                f_usCopyEventIndex )
{
      tPOCT6100_SHARED_INFO         pSharedInfo;
      tPOCT6100_API_CHANNEL         pEchoChanEntry;
      UINT32      ulResult;
      UINT32      i;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;

            if ( f_pConfBridgeRemove->fRemoveAll == FALSE )
            {
                  tPOCT6100_API_CHANNEL         pTempEchoChanEntry;

                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
                  mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

                  /* Release an entry for the store event in the mixer memory. */
                  ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        return ulResult;
                  }

                  /* Release an entry for the Sin copy event in the mixer memory. */
                  /* This value can be invalid if the Rin port was used - no need to release. */
                  if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              return ulResult;
                        }
                  }

                  /* This value can be 0 if the Rin port was used - no need to release. */
                  if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                  {
                        /* Release the extra TSI entry.*/
                        ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              return ulResult;
                        }
                  }

                  /* This value can be 0 if the Sout port was used - no need to release. */
                  if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 )
                  {
                        /* Release the extra TSI entry.*/
                        ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              return ulResult;
                        }
                  }

                  /* Must travel all clients of this conference and release the load or accumulate events for */
                  /* all participants which can hear us and vice versa. */

                  /* Search through the list of API channel entry for the ones on to this bridge. */
                  for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, i );
                  
                        /* Channel reserved? */
                        if ( ( i != f_usChanIndex ) && pTempEchoChanEntry->fReserved == TRUE )
                        {
                              /* On current bridge? */
                              if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                              {
                                    mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                    /* Check if we can hear this participant. */
                                    if ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                    {
                                          /* Must release the allocated mixer event. */
                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                          
                                          pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                    }

                                    /* Check if this participant can hear us. */
                                    if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                    {
                                          /* Must release the allocated mixer event. */
                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }

                                          pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                    }
                              }
                        }
                  }
            }
            else /* f_pConfBridgeRemove->fRemoveAll == TRUE */
            {
                  UINT32 ulListenerMaskIndex;

                  ulResult = cOCT6100_ERR_OK;
                  
                  /* Search through the list of API channel entry for the ones on to this bridge.*/
                  for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i );
                        
                        /* Channel reserved? */
                        if ( pEchoChanEntry->fReserved == TRUE )
                        {
                              /* On current bridge? */
                              if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                              {
                                    mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

                                    /* Release an entry for the Store event in the Mixer memory. */
                                    ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSubStoreEventIndex );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                    {
                                          return ulResult;
                                    }

                                    /* Release an entry for the Sin copy event in the Mixer memory. */
                                    /* This value can be invalid if the Rin port was used - no need to release. */
                                    if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                                    {
                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                    }

                                    /* This value can be 0 if the Rin port was used - no need to release. */
                                    if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                                    {
                                          /* Release the extra TSI entry.*/
                                          ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                    }

                                    /* This value can be 0 if the Sout port was used - no need to release. */
                                    if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 )
                                    {
                                          /* Release the extra TSI entry.*/
                                          ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                    }

                                    /* Check if something can be freed. */
                                    for ( ulListenerMaskIndex = 0; ulListenerMaskIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulListenerMaskIndex ++ )
                                    {
                                          if ( pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
                                          {
                                                /* Must release the allocated mixer event. */
                                                ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] );
                                                if ( ulResult != cOCT6100_ERR_OK )
                                                {
                                                      return ulResult;
                                                }
                                                
                                                pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                          }
                                    }
                              }
                        }
                  }

                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            if ( f_pConfBridgeRemove->fRemoveAll == FALSE )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
                  
                  /* Release the entry for the load event in the mixer memory. */
                  ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usLoadEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        return ulResult;
                  }

                  /* Release an entry for the substract and store event in the mixer memory. */
                  ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        return ulResult;
                  }

                  /* Release an entry for the Sin copy event in the Mixer memory. */
                  /* This value can be invalid if the Rin port was used - no need to release. */
                  if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              return ulResult;
                        }
                  }

                  /* This value can be 0 if the Rin port was used - no need to release. */
                  if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                  {
                        /* Release the extra TSI entry. */
                        ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex );
                        if ( ulResult != cOCT6100_ERR_OK )
                        {
                              return ulResult;
                        }
                  }
            }
            else /* f_pConfBridgeRemove->fRemoveAll == TRUE */
            {
                  /* Search through the list of API channel entry for the ones on to the specified bridge.*/
                  for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i );
                        
                        if ( pEchoChanEntry->fReserved == TRUE )
                        {
                              if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) )
                              {
                                    /* Release the entry for the load event in the mixer memory. */
                                    ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, 
                                                                                                        pEchoChanEntry->usLoadEventIndex );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                    {
                                          return ulResult;
                                    }

                                    /* Release an entry for the substract and store event in the Mixer memory. */
                                    ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, 
                                                                                                        pEchoChanEntry->usSubStoreEventIndex );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                    {
                                          return ulResult;
                                    }

                                    /* Release an entry for the Sin copy event in the Mixer memory. */
                                    /* This value can be invalid if the Rin port was used - no need to release. */
                                    if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                                    {
                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, 
                                                                                                              pEchoChanEntry->usSinCopyEventIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                    }

                                    /* This value can be 0 if the Rin port was used - no need to release. */
                                    if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                                    {
                                          /* Release the extra TSI entry.*/
                                          ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                          {
                                                return ulResult;
                                          }
                                    }
                              }
                        }
                  }
            }
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeEventRemove

Description:    Remove the event from the global event list of the chip and 
                        update the bridge and channel structures.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_pConfBridgeRemove                 Pointer to a conference bridge channel remove structure.
f_usBridgeIndex                     Index of the current bridge in the API list.
f_usChanIndex                       Index of the current channel in the API list.
f_fFlexibleConfBridge         If this is a flexible conference bridge.
f_usLoadEventIndex                  Allocated entry for the Load event of the channel.
f_usSubStoreEventIndex        Allocated entry for the substract and store event of the channel.
f_usCopyEventIndex                  Allocated entry for the copy event of the channel.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeEventRemove
UINT32 Oct6100ApiBridgeEventRemove (
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_REMOVE   f_pConfBridgeRemove,
                        IN          UINT16                                                f_usBridgeIndex, 
                        IN          UINT16                                                f_usChanIndex,
                        IN          UINT8                                           f_fFlexibleConfBridge,
                        IN          UINT16                                                f_usLoadEventIndex,
                        IN          UINT16                                                f_usSubStoreEventIndex,
                        IN          UINT16                                                f_usCopyEventIndex,
                        IN          UINT8                                           f_fTap )
{
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT           pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT           pSubStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT           pCopyEventEntry = NULL;
      tPOCT6100_API_MIXER_EVENT           pTempEntry;

      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      tPOCT6100_API_CHANNEL               pTempEchoChanEntry;

      tPOCT6100_SHARED_INFO               pSharedInfo;
      tOCT6100_WRITE_PARAMS               WriteParams;
      tOCT6100_READ_PARAMS                ReadParams;

      UINT32      ulResult;
      UINT16      usPreviousEventIndex;
      UINT16      usTempEventIndex;
      UINT32      ulLoopCount = 0;
      UINT16      usReadData;
      UINT16      usChannelIndex;
      UINT32      i;

      BOOL  fRemoveSinCopy = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

      ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
      ReadParams.pusReadData = &usReadData;
      
      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex );
      
      /* If no client on the bridge, and the remove all option is specified, return here. */
      if ( ( pBridgeEntry->usNumClients == 0 ) && ( f_pConfBridgeRemove->fRemoveAll == TRUE ) )
            return cOCT6100_ERR_OK;

      /* Make sure the dominant speaker feature is disabled first. */
      if ( pBridgeEntry->fDominantSpeakerSet == TRUE )
      {
            /* If all channels are to be removed or if the dominant speaker is the current channel to be removed. */
            if ( ( f_pConfBridgeRemove->fRemoveAll == TRUE )
                  || ( ( f_pConfBridgeRemove->fRemoveAll == FALSE ) && ( pBridgeEntry->usDominantSpeakerChanIndex == f_usChanIndex ) ) )
            {
                  /* Disable on all channels part of this conference. */

                  /* Search through the list of API channel entry for the ones on to this bridge. */
                  for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                        
                        if ( pTempEchoChanEntry->fReserved == TRUE )
                        {
                              if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                              {
                                    ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }
                        }
                  }

                  /* Save this in the conference bridge structure. */
                  pBridgeEntry->fDominantSpeakerSet = FALSE;
                  pBridgeEntry->usDominantSpeakerChanIndex = cOCT6100_INVALID_INDEX;
            }
            else
            {
                  /* Only disable this current channel. */
                  ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }
      }

      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;
            UINT16      ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ];
            UINT32      ulMutePortChannelIndex;

            for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                  ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX;

            if ( f_pConfBridgeRemove->fRemoveAll == FALSE )
            {
                  /* The channel index is valid. */
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
                  mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

                  /* Search through the list of API channel entry for the ones on to this bridge. */
                  for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );

                        if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                        {
                              if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                              {
                                    mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                    /* Check if we can hear this participant. */
                                    if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                          && ( pParticipant->fFlexibleMixerCreated == TRUE ) 
                                          && ( pTempEchoChanEntry->fMute == FALSE ) )
                                    {
                                          /* First update the current channel's mixer. */
                                          ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                                    f_pApiInstance,
                                                                                    f_usBridgeIndex,
                                                                                    usChannelIndex,
                                                                                    f_usChanIndex,
                                                                                    TRUE );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;
                                    }

                                    /* Check if this participant can hear us. */
                                    if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                          && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) 
                                          && ( pEchoChanEntry->fMute == FALSE ) )
                                    {
                                          /* Then update this channel's mixer. */
                                          ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                                    f_pApiInstance,
                                                                                    f_usBridgeIndex,
                                                                                    f_usChanIndex,
                                                                                    usChannelIndex,
                                                                                    TRUE );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          /* Remember to mute the port on this channel. */
                                          for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                                          {
                                                if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex )
                                                {
                                                      break;
                                                }
                                                else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX )
                                                {
                                                      ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex;
                                                      break;
                                                }
                                          }
                                    }
                              }
                        }
                  }

                  /* Check if must manually clear the Sin copy event. */
                  if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                        && ( pEchoChanEntry->fCopyEventCreated == TRUE ) )
                  {
                        /* Transform event into no-operation. */
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        /* Now remove the copy event from the event list. */
                        ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        pEchoChanEntry->fCopyEventCreated = FALSE;
                  }

                  /* Release an entry for the participant. */
                  ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        return ulResult;
                  }

                  /*=======================================================================*/
                  /* Update the event and channel API structure */
                  pEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX;

                  /* Indicate that the extra SIN TSI is not needed anymore by the mixer. */
                  if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                  {
                        pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                        pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                  }
                  else
                  {
                        /* Decrement the dependency count, but do not clear the mem index. */
                        pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                  }
                  
                  /* Indicate that the extra RIN TSI is not needed anymore by the mixer. */
                  if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 )
                  {
                        pEchoChanEntry->usExtraRinTsiDependencyCnt--;
                        pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX;
                  }

                  /* Update the chip stats structure. */
                  pSharedInfo->ChipStats.usNumEcChanUsingMixer--;

                  pBridgeEntry->usNumClients--;

                  /* For sure we have to mute the ports of this channel to be removed. */
                  ulResult = Oct6100ApiMutePorts( 
                                                      f_pApiInstance, 
                                                      f_usChanIndex, 
                                                      pEchoChanEntry->usRinTsstIndex, 
                                                      pEchoChanEntry->usSinTsstIndex,
                                                      FALSE );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */
                  for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                  {
                        if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX )
                        {
                              mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] );

                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
                              
                              if ( pTempParticipant->fFlexibleMixerCreated == FALSE )
                              {
                                    /* Check if the Rin port must be muted on this channel. */
                                    ulResult = Oct6100ApiMutePorts( 
                                                                        f_pApiInstance, 
                                                                        ausMutePortChannelIndexes[ ulMutePortChannelIndex ], 
                                                                        pTempEchoChanEntry->usRinTsstIndex, 
                                                                        pTempEchoChanEntry->usSinTsstIndex,
                                                                        FALSE );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }
                        }
                        else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */
                        {
                              /* No more channels to check for muting. */
                              break;
                        }
                  }
            }
            else /* if ( f_pConfBridgeRemove->fRemoveAll == TRUE ) */
            {
                  UINT16 usMainChannelIndex;

                  for ( usMainChannelIndex = 0 ; usMainChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ; usMainChannelIndex++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usMainChannelIndex );

                        /* If this channel is on the bridge we are closing all the channels. */
                        if ( ( pEchoChanEntry->fReserved == TRUE ) && ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) )
                        {
                              /* Remember to mute the port on this channel. */
                              for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                              {
                                    if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usMainChannelIndex )
                                    {
                                          break;
                                    }
                                    else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX )
                                    {
                                          ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usMainChannelIndex;
                                          break;
                                    }
                              }

                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

                              /* Search through the list of API channel entry for the ones on to this bridge. */
                              for ( usChannelIndex = (UINT16)( usMainChannelIndex + 1 ); usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                              {
                                    mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                                    if ( pTempEchoChanEntry->fReserved == TRUE )
                                    {
                                          if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                                          {
                                                mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                                /* Everyone that we can hear must be removed. */
                                                if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                                      && ( pParticipant->fFlexibleMixerCreated == TRUE ) 
                                                      && ( pTempEchoChanEntry->fMute == FALSE ) )
                                                {
                                                      /* First update the current channel's mixer. */
                                                      ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                                                f_pApiInstance,
                                                                                                f_usBridgeIndex,
                                                                                                usChannelIndex,
                                                                                                usMainChannelIndex,
                                                                                                TRUE );
                                                      if ( ulResult != cOCT6100_ERR_OK )
                                                            return ulResult;
                                                }

                                                /* Check if this participant can hear us. */
                                                if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                                      && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) 
                                                      && ( pEchoChanEntry->fMute == FALSE ) )
                                                {
                                                      /* Then update this channel's mixer. */
                                                      ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                                                f_pApiInstance,
                                                                                                f_usBridgeIndex,
                                                                                                usMainChannelIndex,
                                                                                                usChannelIndex,
                                                                                                TRUE );
                                                      if ( ulResult != cOCT6100_ERR_OK )
                                                            return ulResult;
                                                }
                                          }
                                    }
                              }

                              /* Check if must manually clear the Sin copy event. */
                              if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                                    && ( pEchoChanEntry->fCopyEventCreated == TRUE ) )
                              {
                                    /* Transform event into no-operation. */
                                    WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                    WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    /* Now remove the copy event from the event list. */
                                    ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    pEchoChanEntry->fCopyEventCreated = FALSE;
                              }

                              /* Release an entry for the participant. */
                              ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                              {
                                    return ulResult;
                              }

                              /*=======================================================================*/
                              /* Update the event and channel API structure */

                              pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX;

                              pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX;
                              pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX;
                              pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX;

                              /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */
                              if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                              {
                                    pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                                    pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                              }
                              else
                              {
                                    /* Decrement the dependency count, but do not clear the mem index. */
                                    pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                              }
                              
                              /* Indicate that the Extra RIN TSI is not needed anymore by the mixer. */
                              if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 )
                              {
                                    pEchoChanEntry->usExtraRinTsiDependencyCnt--;
                                    pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX;
                              }

                              /* Update the chip stats structure. */
                              pSharedInfo->ChipStats.usNumEcChanUsingMixer--;
                        }
                  }

                  /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */
                  for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                  {
                        if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX )
                        {
                              mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] );

                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
                              
                              if ( pTempParticipant->fFlexibleMixerCreated == FALSE )
                              {
                                    /* Check if the Rin port must be muted on this channel. */
                                    ulResult = Oct6100ApiMutePorts( 
                                                                        f_pApiInstance, 
                                                                        ausMutePortChannelIndexes[ ulMutePortChannelIndex ], 
                                                                        pTempEchoChanEntry->usRinTsstIndex, 
                                                                        pTempEchoChanEntry->usSinTsstIndex,
                                                                        FALSE );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }
                        }
                        else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */
                        {
                              /* No more channels to check for muting. */
                              break;
                        }

                        /* Clear the flexible conf bridge participant index. */
                        pTempEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;
                  }

                  /* No more clients on bridge. */
                  pBridgeEntry->usNumClients = 0;
            }
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            if ( f_pConfBridgeRemove->fRemoveAll == FALSE )
            {
                  /* The channel index is valid. */
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );

                  if ( f_fTap == TRUE )
                  {
                        mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, pEchoChanEntry->usTapBridgeIndex );
                  }

                  /* Get a pointer to the event entry. */
                  if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX )
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex );
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex );

                  /*=======================================================================*/
                  /* Check if have to modify the silence load event. */

                  if ( pBridgeEntry->usNumClients != 1 )
                  {
                        if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX )
                        {
                              if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex )
                              {
                                    /* Make sure the next event becomes the silence event. */
                                    WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadEventEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                                    WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                                    WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                                    
                                    /* Update the software model to remember the silence load. */
                                    pBridgeEntry->usSilenceLoadEventPtr = pLoadEventEntry->usNextEventPtr;
                              }
                              else
                              {
                                    /* Somebody else is the silence event, no need to worry. */
                              }
                        }
                  }

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Clear the Load event. */

                  /* First verify if the event to be removed was a load event. */
                  if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex )
                  {
                        /* Change the next entry if one is present to a load event to keep the bridge alive. */
                        if ( pBridgeEntry->usNumClients == 1 )
                        {
                              /* There is no other entry on the bridge, no need to search for an Accumulate event. */
                              pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX;

                              /* Clear the silence event, for sure it's invalid. */
                              pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX;
                        }
                        else
                        {
                              /* Search for an accumulate event to tranform into a Load event. */
                              usTempEventIndex = pLoadEventEntry->usNextEventPtr;
                              ulLoopCount = 0;

                              /* Find the copy entry before the entry to remove. */
                              mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                              while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && 
                                       pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE )
                              {
                                    if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE )
                                    {
                                          /* Change this entry into a load event. */
                                          ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                          mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          WriteParams.ulWriteAddress = ReadParams.ulReadAddress;
                                          WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD);

                                          mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;
                                          
                                          /* Set this entry as the load index. */
                                          pBridgeEntry->usLoadIndex = usTempEventIndex;

                                          /* Update the software model. */
                                          pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;

                                          /* Stop searching. */
                                          break;
                                    }
                                    
                                    /* Go to the next entry into the list. */
                                    usTempEventIndex = pTempEntry->usNextEventPtr;
                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                                    ulLoopCount++;
                                    if ( ulLoopCount == cOCT6100_MAX_LOOP )
                                          return cOCT6100_ERR_FATAL_9B;
                              }
                        }
                  }
                  
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/
                  
                  /*=======================================================================*/
                  /* Clear the substract and store event. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/

                  /*=======================================================================*/
                  /* Clear the Copy event - if needed. */

                  if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX )
                  {
                        /* Transform event into no-operation. */
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                        
                        if ( f_fTap == FALSE )
                        {
                              /* Set remove Sin copy event flag to remove the event from the mixer's list. */
                              fRemoveSinCopy = TRUE;

                              /* Clear the copy event created flag. */
                              pEchoChanEntry->fCopyEventCreated = FALSE;
                        }
                  }

                  /*=======================================================================*/
            
                  
                  /*=======================================================================*/
                  /* Now remove the event from the event list. */
                  
                  /* Look for the entry that is pointing at the first entry of our bridge. */
                  if ( f_fTap == FALSE )
                  {
                        ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex );
                  }
                  else
                  {
                        ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, pEchoChanEntry->usTapBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex );
                  }
                  
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        /* If the entry was not found, we now check for the Sout copy event section/list. */
                        if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND )
                        {
                              if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
                              {
                                    /* No Sout copy, it has to be the head node. */
                                    usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE;
                              }
                              else
                              {
                                    /* Use the last Sout copy event. */
                                    usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
                              }
                        }
                        else
                        {
                              return cOCT6100_ERR_FATAL_27;
                        }
                  }

                  if ( pBridgeEntry->usNumClients == 1 )
                  {
                        /* An entry was found, now, modify it's value. */
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex );

                        /* Now modify the previous last Sub Store event from another bridge. */
                        pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr;

                        /*=======================================================================*/
                        /* Modify the last node of the previous bridge to point to the next bridge. */
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                        WriteParams.ulWriteAddress += 4;

                        WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                        
                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        /*=======================================================================*/
                        
                        /* Set the event pointer info in the bridge stucture. */
                        pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX;
                        pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX;
                        pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX;

                        /*=======================================================================*/
                        /* Update the global mixer pointers. */
                        if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex &&
                               pSharedInfo->MixerInfo.usLastBridgeEventPtr  == f_usSubStoreEventIndex )
                        {
                              /* There is no more bridge entry in the mixer link list. */
                              pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX;
                              pSharedInfo->MixerInfo.usLastBridgeEventPtr  = cOCT6100_INVALID_INDEX;
                        }
                        else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex )
                        {
                              pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pSubStoreEventEntry->usNextEventPtr;
                        }
                        else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex )
                        {
                              pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex;
                        }
                        /*=======================================================================*/

                        if ( f_fTap == TRUE )
                        {
                              /* The channel being tapped is not tapped anymore.  */
                              /* There is no direct way of finding the tap, so loop through all channels and find the */
                              /* tapped channel index. */
                              for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                              {
                                    mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );

                                    if ( pTempEchoChanEntry->usTapChanIndex == f_usChanIndex )
                                    {
                                          tPOCT6100_API_CONF_BRIDGE     pTempBridgeEntry;

                                          pTempEchoChanEntry->fBeingTapped = FALSE;
                                          pTempEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX;

                                          mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex );

                                          pTempBridgeEntry->usNumTappedClients--;
                                          
                                          /* Re-assign Rin TSST for tapped channel. */
                                          if ( pTempEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
                                          {
                                                ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                                          pTempEchoChanEntry->usRinTsstIndex,
                                                                                                                          pTempEchoChanEntry->usRinRoutTsiMemIndex,
                                                                                                                          pTempEchoChanEntry->TdmConfig.byRinPcmLaw );
                                                if ( ulResult != cOCT6100_ERR_OK )
                                                      return ulResult;
                                          }

                                          break;
                                    }
                              }

                              /* Check if our model is broken. */
                              if ( usChannelIndex == pSharedInfo->ChipConfig.usMaxChannels )
                                    return cOCT6100_ERR_FATAL_D3;
                        }
                  }
                  else /* pBridgeEntry->usNumClients > 1 */
                  {
                        if ( pBridgeEntry->usFirstLoadEventPtr != f_usLoadEventIndex )
                        {
                              /* Now find the load entry of this bridge pointing at this load event */
                              ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usLoadEventIndex, 0, &usPreviousEventIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }

                        /* Remove the load event to the list. */
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex );
                        
                        /* Now modify the previous last Sub Store event from another bridge. */
                        pTempEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr;

                        /*=======================================================================*/
                        /* Modify the previous node. */
                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                        WriteParams.ulWriteAddress += 4;

                        WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                        
                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        /*=======================================================================*/

                        /* Now find the last load entry of this bridge ( the one pointing at the first sub-store event ). */
                        if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex )
                        {
                              /* Must start with the first load to get the entry before the first sub store. */
                              ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                        else
                        {
                              /* Must start with the first load to get the entry before the first sub store. */
                              ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstSubStoreEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }

                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex );
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );

                        /* Now modify the last load event of the bridge. */
                        pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr;

                        /*=======================================================================*/
                        /* Modify the last node of the other bridge. */

                        WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                        WriteParams.ulWriteAddress += 4;

                        WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
                        
                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        /*=======================================================================*/

                        /*=======================================================================*/
                        /* Update the bridge pointers. */

                        if ( pBridgeEntry->usFirstLoadEventPtr == f_usLoadEventIndex )
                              pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr;

                        if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex )
                              pBridgeEntry->usFirstSubStoreEventPtr = pSubStoreEventEntry->usNextEventPtr;

                        if ( pBridgeEntry->usLastSubStoreEventPtr == f_usSubStoreEventIndex )
                              pBridgeEntry->usLastSubStoreEventPtr = usPreviousEventIndex;
                  
                        /*=======================================================================*/


                        /*=======================================================================*/
                        /* Update the global mixer pointers. */

                        if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex )
                        {
                              pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr;
                        }

                        if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex )
                        {
                              pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex;
                        }
                        /*=======================================================================*/

                  }

                  /* Check if must remove the Sin copy event from the event list. */
                  if ( fRemoveSinCopy == TRUE )
                  {
                        /* Now remove the copy event from the event list. */
                        ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, f_usCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }

                  /* Get the channel. */
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );

                  /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released. */
                  if ( ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fTap == FALSE ) )
                  {
                        if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
                        {
                              ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                        pEchoChanEntry->usSinTsstIndex,
                                                                                                        pEchoChanEntry->usSinSoutTsiMemIndex,
                                                                                                        pEchoChanEntry->TdmConfig.bySinPcmLaw );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }

                        /* If the silence TSI is loaded on this port, update with the original sin TSI. */
                        if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                        {
                              WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                              WriteParams.ulWriteAddress += 2;
                              WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex;

                              mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                  }
                  /* Set the event entries as free. */
                  pLoadEventEntry->fReserved          = FALSE;
                  pLoadEventEntry->usEventType  = cOCT6100_INVALID_INDEX;
                  pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;

                  pSubStoreEventEntry->fReserved            = FALSE;
                  pSubStoreEventEntry->usEventType    = cOCT6100_INVALID_INDEX;
                  pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;

                  if ( pCopyEventEntry != NULL )
                  {
                        pCopyEventEntry->fReserved          = FALSE;
                        pCopyEventEntry->usEventType  = cOCT6100_INVALID_INDEX;
                        pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;
                  }

                  pBridgeEntry->usNumClients--;

                  /*=======================================================================*/
                  /* Update the event and channel API structure */
                  pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX;
                  pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX;

                  /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */
                  if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                  {
                        pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                        pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                  }
                  else
                  {
                        /* Decrement the dependency count, but do not clear the mem index. */
                        pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                  }

                  /* Update the chip stats structure. */
                  pSharedInfo->ChipStats.usNumEcChanUsingMixer--;

                  if ( f_fTap == TRUE )
                  {
                        /* Can now close the bridge. */
                        tOCT6100_CONF_BRIDGE_CLOSE    BridgeClose;

                        Oct6100ConfBridgeCloseDef( &BridgeClose );

                        BridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapBridgeIndex;

                        ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &BridgeClose );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;

                        pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX;
                        pEchoChanEntry->fTap = FALSE;
                  }

                  /* Check if the Rin port must be muted. */
                  ulResult = Oct6100ApiMutePorts( 
                                                      f_pApiInstance, 
                                                      f_usChanIndex, 
                                                      pEchoChanEntry->usRinTsstIndex, 
                                                      pEchoChanEntry->usSinTsstIndex,
                                                      FALSE );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/
            }
            else /* f_ulBridgeChanRemove->fRemoveAll == TRUE ) */
            {
                  UINT16 usNextEventPtr;

                  /* Save the next event pointer before invalidating everything. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pBridgeEntry->usLastSubStoreEventPtr );

                  usNextEventPtr = pSubStoreEventEntry->usNextEventPtr;

                  /* Search through the list of API channel entry for the ones on to the specified bridge. */
                  for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i );
                        
                        if ( pEchoChanEntry->fReserved == TRUE )
                        {
                              if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) )
                              {
                                    /* Check if we are being tapped.  If so, remove the channel that taps us from the conference. */
                                    /* The removal of the channel will make sure the Rin TSST is re-assigned. */
                                    if ( pEchoChanEntry->fBeingTapped == TRUE )
                                    {
                                          tOCT6100_CONF_BRIDGE_CHAN_REMOVE    ChanRemove;

                                          mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, pEchoChanEntry->usTapChanIndex );

                                          ulResult = Oct6100ConfBridgeChanRemoveDef( &ChanRemove );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;
                                          
                                          ChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pTempEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapChanIndex;

                                          ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &ChanRemove );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;
                                    }
                              
                                    /*=======================================================================*/
                                    /* Clear the Load event. */
                                    WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                    WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    /*=======================================================================*/
                                    
                                    /*=======================================================================*/
                                    /* Clear the Substract and store event. */
                                    WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                    WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                                    
                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                                    /*=======================================================================*/

                                    /*=======================================================================*/
                                    /* Clear the SIN copy event.*/
                                    
                                    if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                                    {
                                          /* Transform event into no-operation. */
                                          WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                          WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                                          
                                          mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          /* Get a pointer to the event entry. */
                                          mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pEchoChanEntry->usSinCopyEventIndex );

                                          /* Update the next event pointer if required. */
                                          if ( usNextEventPtr == pEchoChanEntry->usSinCopyEventIndex )
                                                usNextEventPtr = pCopyEventEntry->usNextEventPtr;

                                          /* Now remove the copy event from the event list. */
                                          ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          /* Clear the copy event created flag. */
                                          pEchoChanEntry->fCopyEventCreated = FALSE;
                                    }

                                    /*=======================================================================*/


                                    /*=======================================================================*/
                                    /* Update the event and channel API structure */

                                    /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released.*/
                                    if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                                    {
                                          if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
                                          {
                                                ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                                          pEchoChanEntry->usSinTsstIndex,
                                                                                                                          pEchoChanEntry->usSinSoutTsiMemIndex,
                                                                                                                          pEchoChanEntry->TdmConfig.bySinPcmLaw );
                                                if ( ulResult != cOCT6100_ERR_OK )
                                                      return ulResult;
                                          }

                                          /* If the silence TSI is loaded on this port, update with the original Sin TSI. */
                                          if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                                          {
                                                WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                                                WriteParams.ulWriteAddress += 2;
                                                WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex;

                                                mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                                if ( ulResult != cOCT6100_ERR_OK )
                                                      return ulResult;
                                          }
                                    }

                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, pEchoChanEntry->usLoadEventIndex );
                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pEchoChanEntry->usSubStoreEventIndex );

                                    /* Set the event entries as free. */
                                    pLoadEventEntry->fReserved          = FALSE;
                                    pLoadEventEntry->usEventType  = cOCT6100_INVALID_EVENT;
                                    pLoadEventEntry->usNextEventPtr     = cOCT6100_INVALID_INDEX;

                                    pSubStoreEventEntry->fReserved            = FALSE;
                                    pSubStoreEventEntry->usEventType    = cOCT6100_INVALID_EVENT;
                                    pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;

                                    if ( pCopyEventEntry != NULL )
                                    {
                                          pCopyEventEntry->fReserved          = FALSE;
                                          pCopyEventEntry->usEventType  = cOCT6100_INVALID_EVENT;
                                          pCopyEventEntry->usNextEventPtr     = cOCT6100_INVALID_INDEX;
                                    }

                                    /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */
                                    if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 )
                                    {
                                          pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                                          pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
                                    }
                                    else
                                    {
                                          /* Decrement the dependency count, but do not clear the mem index. */
                                          pEchoChanEntry->usExtraSinTsiDependencyCnt--;
                                    }

                                    /* Invalidate the channel entry. */
                                    pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX;
                                    pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX;
                                    pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX;

                                    /* Update the chip stats structure. */
                                    pSharedInfo->ChipStats.usNumEcChanUsingMixer--;

                                    /*=======================================================================*/
                              }
                        }
                  }
            
                  ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                  {
                        if ( cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND == ulResult )
                        {
                              if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
                              {
                                    usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE;
                              }
                              else
                              {
                                    usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
                              }
                        }
                        else
                        {
                              return cOCT6100_ERR_FATAL_28;
                        }
                  }

                  /* An Entry was found, now, modify it's value. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex );

                  /* Now modify the previous last Sub Store event from another bridge.*/
                  /* It will now point at the next bridge, or copy events. */
                  pTempEntry->usNextEventPtr = usNextEventPtr;

                  /*=======================================================================*/
                  /* Modify the last node of the other bridge. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = pTempEntry->usNextEventPtr;
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
                  /*=======================================================================*/
                  
                  /*=======================================================================*/
                  /* Update the global mixer pointers. */
                  if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr &&
                         pSharedInfo->MixerInfo.usLastBridgeEventPtr  == pBridgeEntry->usLastSubStoreEventPtr )
                  {
                        /* This bridge was the only one with event in the list. */
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX;
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr  = cOCT6100_INVALID_INDEX;
                  }
                  else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr )
                  {
                        /* This bridge was the first bridge. */
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = usNextEventPtr;
                  }
                  else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr )
                  {
                        /* This bridge was the last bridge.*/
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex;
                  }
                  /*=======================================================================*/

                  /* Set the event pointer info in the bridge stucture. */
                  pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX;
                  pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX;
                  pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX;
                  pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX;

                  pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX;

                  /* Set the number of clients to 0. */
                  pBridgeEntry->usNumClients = 0;

                  /* Search through the list of API channel entry for the ones on to the specified bridge. */
                  for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i );
                        
                        if ( pEchoChanEntry->fReserved == TRUE )
                        {
                              if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) )
                              {
                                    pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX;

                                    /* Check if the Rin port must be muted. */
                                    ulResult = Oct6100ApiMutePorts( 
                                                                        f_pApiInstance, 
                                                                        (UINT16)( i & 0xFFFF ), 
                                                                        pEchoChanEntry->usRinTsstIndex, 
                                                                        pEchoChanEntry->usSinTsstIndex,
                                                                        FALSE );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                              }
                        }
                  }
            }
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeRemoveParticipantFromChannel

Description:    This will remove a flexible conference participant from
                        a channel.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_usBridgeIndex                     Bridge index where this channel is located.
f_usSourceChannelIndex        Source channel to copy voice from.
f_usDestinationChannelIndex   Destination channel to store resulting voice to.
f_fRemovePermanently          Whether to remove permanently this participant.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeRemoveParticipantFromChannel
UINT32 Oct6100ApiBridgeRemoveParticipantFromChannel(
                        IN OUT      tPOCT6100_INSTANCE_API  f_pApiInstance, 
                        IN          UINT16                              f_usBridgeIndex,
                        IN          UINT16                              f_usSourceChannelIndex,
                        IN          UINT16                              f_usDestinationChannelIndex,
                        IN          UINT8                         f_fRemovePermanently )
{
      tPOCT6100_API_CONF_BRIDGE                 pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT                 pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pCopyEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pTempEntry;
      tPOCT6100_API_MIXER_EVENT                 pLoadTempEntry;
      tPOCT6100_API_MIXER_EVENT                 pLastEventEntry;
      tPOCT6100_API_MIXER_EVENT                 pLastLoadOrAccumulateEventEntry;

      tPOCT6100_API_CHANNEL                     pSourceChanEntry;
      tPOCT6100_API_CHANNEL                     pDestinationChanEntry;

      tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant;

      tPOCT6100_SHARED_INFO                     pSharedInfo;
      tOCT6100_WRITE_PARAMS                     WriteParams;
      tOCT6100_READ_PARAMS                      ReadParams;

      UINT32                                                ulResult;
      UINT32                                                ulLoopCount;
      UINT16                                                usLastLoadEventIndex;
      UINT16                                                usLoadOrAccumulateEventIndex;
      UINT16                                                usTempEventIndex;
      UINT16                                                usPreviousEventIndex;
      UINT16                                                usLastEventIndex;

      UINT16                                                usReadData;
      BOOL                                            fLastEvent = FALSE;
      BOOL                                            fSoutCopyEvent = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

      ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
      ReadParams.pusReadData = &usReadData;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex );

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex );
      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex );
      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex );
      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex );

      /* Check if the mixer has been created on this channel. */
      if ( pDestinationParticipant->fFlexibleMixerCreated == TRUE )
      {
            /*=======================================================================*/
            /* Clear the Load or Accumulate event.*/

            usTempEventIndex = pDestinationChanEntry->usLoadEventIndex;
            ulLoopCount = 0;

            /* Find the Load or Accumulate event entry. */
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usTempEventIndex );
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, pDestinationChanEntry->usSubStoreEventIndex );
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

            pLastEventEntry = pLoadEventEntry;
            pLastLoadOrAccumulateEventEntry = pLoadEventEntry;
            usLastLoadEventIndex = usTempEventIndex;
            usLastEventIndex = usTempEventIndex;

            while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && 
                     pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE )
            {
                  /* If this is the entry we are looking for. */
                  if ( pTempEntry->usSourceChanIndex == f_usSourceChannelIndex )
                  {
                        /* Check if this is a Load or Accumulate event. */
                        if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD )
                        {
                              /* This is the first entry.  Check if next entry is an accumulate. */
                              pLoadTempEntry = pTempEntry;
                              mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, pTempEntry->usNextEventPtr );

                              if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE )
                              {
                                    /* Change this entry into a Load event. */
                                    ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadTempEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                    mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    WriteParams.ulWriteAddress = ReadParams.ulReadAddress;
                                    WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD);

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                                    
                                    /* Update the channel information with this new load event. */
                                    pDestinationChanEntry->usLoadEventIndex = pLoadTempEntry->usNextEventPtr;

                                    /* Update the software model. */
                                    pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;

                                    /* Get the previous event. */
                                    ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex );
                                    usLastEventIndex = usPreviousEventIndex;

                                    /* Stop searching. */
                                    break;
                              }
                              else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE )
                              {
                                    /* Get back the event to remove. */
                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                                    /* This is the only event on this channel so we can clear everything up. */
                                    fLastEvent = TRUE;

                                    /* Get the previous event. */
                                    ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex );
                                    usLastEventIndex = usPreviousEventIndex;

                                    /* Stop searching. */
                                    break;
                              }
                              else
                              {
                                    /* Software model is broken. */
                                    return cOCT6100_ERR_FATAL_C5;
                              }
                              
                        }
                        else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE )
                        {
                              /* Simply remove the entry. */

                              /* Get the previous event. */
                              ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;

                              mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex );
                              usLastEventIndex = usPreviousEventIndex;

                              /* Stop searching. */
                              break;
                        }
                        else
                        {
                              /* Software model is broken. */
                              return cOCT6100_ERR_FATAL_C6;
                        }
                  }

                  pLastLoadOrAccumulateEventEntry = pTempEntry;
                  usLastLoadEventIndex = usTempEventIndex;

                  /* Go to the next entry into the list. */
                  usTempEventIndex = pTempEntry->usNextEventPtr;
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                  ulLoopCount++;
                  if ( ulLoopCount == cOCT6100_MAX_LOOP )
                        return cOCT6100_ERR_FATAL_C8;
            }

            /* Check if we found what we were looking for. */
            if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE 
                  || pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE )
            {
                  /* Software model is broken. */
                  return cOCT6100_ERR_FATAL_C7;
            }

            /*=======================================================================*/


            /*=======================================================================*/
            /* Clear the Store event - if needed. */

            if ( fLastEvent == TRUE )
            {
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }

            /*=======================================================================*/


            /*=======================================================================*/
            /* Clear the Load or Accumulate event. */

            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /* Save this event index.  It's the Load or Accumulate we want to remove from the list later. */
            usLoadOrAccumulateEventIndex = usTempEventIndex;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Clear the Copy event - if needed. */
            
            if ( ( fLastEvent == TRUE ) && ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) )
            {
                  /* Transform event into no-operation. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* The event remove from the list will be done below. */

                  /* Clear the copy event created flag. */
                  pDestinationChanEntry->fCopyEventCreated = FALSE;
            }

            /*=======================================================================*/


            /*=======================================================================*/
            /*=======================================================================*/
            /* Remove the events from the mixer event list.*/
            /*=======================================================================*/
            /*=======================================================================*/

            /*=======================================================================*/
            /* Remove the Load or Accumulate event from the event list. */
            
            if ( fLastEvent == FALSE )
            {
                  /*=======================================================================*/
                  /* Remove the Accumulate event from the event list. */

                  /* We saved the Load or Accumulate event above.  We also saved the previous event.  Use those. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usLoadOrAccumulateEventIndex );
                  
                  /* Now modify the previous last event. */
                  pLastEventEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr;

                  /* Modify the previous node. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = pLastEventEntry->usNextEventPtr;
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
                  
                  /* Check if this is the first load event on the bridge. */
                  if ( pBridgeEntry->usFirstLoadEventPtr == usLoadOrAccumulateEventIndex )
                  {
                        pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr;
                  }

                  /* Check if this was the first load of all bridges. */
                  if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex )
                  {
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr;
                  }

                  /*=======================================================================*/
            }
            else /* if ( fLastEvent == TRUE ) */
            {
                  /*=======================================================================*/
                  /* Remove the Load event from the event list. */

                  /* Look for the entry that is pointing at the first entry of our mixer. */
                  ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usLoadOrAccumulateEventIndex, 0, &usPreviousEventIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* An Entry was found, now, modify it's value. */
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex );

                  /* Check if this is a Sout copy event. */
                  if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_COPY )
                  {
                        /* No more previous bridges. */
                        fSoutCopyEvent = TRUE;
                  }

                  /* Now modify the previous last Store or Sub-Store or Head-Node event from another bridge/channel. */
                  pTempEntry->usNextEventPtr = pStoreEventEntry->usNextEventPtr;

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Modify the last node of the previous bridge/channel to point to the next bridge. */

                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  WriteParams.ulWriteAddress += 4;

                  WriteParams.usWriteData = pTempEntry->usNextEventPtr;
                  
                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /*=======================================================================*/
                  
                  
                  /*=======================================================================*/
                  /* Set the event pointer info in the bridge stucture. */

                  if ( pBridgeEntry->usFirstLoadEventPtr == pDestinationChanEntry->usLoadEventIndex )
                  {
                        UINT16                              usChannelIndex;
                        tPOCT6100_API_CHANNEL   pTempEchoChanEntry;

                        pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX;
                        pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX;

                        /* Find the next channel in this conference that could give us valid values. */
                        for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
                        {
                              mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );

                              if ( ( usChannelIndex != f_usDestinationChannelIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                              {
                                    if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                                    {
                                          tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;

                                          mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                                          if ( pTempParticipant->fFlexibleMixerCreated == TRUE )
                                          {
                                                pBridgeEntry->usFirstSubStoreEventPtr = pTempEchoChanEntry->usSubStoreEventIndex;
                                                pBridgeEntry->usFirstLoadEventPtr = pTempEchoChanEntry->usLoadEventIndex;
                                                break;
                                          }
                                    }
                              }
                        }
                  }

                  /* Reprogram the TSST entry correctly if the extra SIN TSI entry was released. */
                  if ( ( pDestinationChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) )
                  {
                        if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
                        {
                              ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                        pDestinationChanEntry->usSinTsstIndex,
                                                                                                        pDestinationChanEntry->usSinSoutTsiMemIndex,
                                                                                                        pDestinationChanEntry->TdmConfig.bySinPcmLaw );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }

                        /* If the silence TSI is loaded on this port, update with the original sin TSI. */
                        if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                        {
                              WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                              WriteParams.ulWriteAddress += 2;
                              WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex;

                              mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                  }

                  /* Reprogram the TSST entry correctly if the extra RIN TSI entry was released. */
                  if ( ( pDestinationChanEntry->usExtraRinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) )
                  {
                        if ( pDestinationChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
                        {
                              ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                                        pDestinationChanEntry->usRinTsstIndex,
                                                                                                        pDestinationChanEntry->usRinRoutTsiMemIndex,
                                                                                                        pDestinationChanEntry->TdmConfig.byRinPcmLaw );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                  }

                  /*=======================================================================*/
                  /* Update the global mixer pointers. */

                  if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex &&
                         pSharedInfo->MixerInfo.usLastBridgeEventPtr  == pDestinationChanEntry->usSubStoreEventIndex )
                  {
                        /* There is no more bridge entry in the mixer link list. */
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX;
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr  = cOCT6100_INVALID_INDEX;
                  }
                  else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex )
                  {
                        pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pStoreEventEntry->usNextEventPtr;
                  }
                  else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex )
                  {
                        pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex;
                  }

                  /*=======================================================================*/


                  /*=======================================================================*/
                  /* Check if must remove the Sin copy event from the list. */

                  if ( ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) )
                  {
                        /* Now remove the copy event from the event list. */
                        ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pDestinationChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                  }

                  /*=======================================================================*/



                  /*=======================================================================*/

                  if ( f_fRemovePermanently == TRUE )
                  {
                        /* Set the event entries as free. */
                        pLoadEventEntry->fReserved          = FALSE;
                        pLoadEventEntry->usEventType  = cOCT6100_INVALID_EVENT;
                        pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;

                        pStoreEventEntry->fReserved         = FALSE;
                        pStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT;
                        pStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;

                        if ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
                        {
                              mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pDestinationChanEntry->usSinCopyEventIndex );
                              
                              pCopyEventEntry->fReserved          = FALSE;
                              pCopyEventEntry->usEventType  = cOCT6100_INVALID_EVENT;
                              pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX;
                        }
                  }

                  /* Flexible mixer for this channel not created anymore. */
                  pDestinationParticipant->fFlexibleMixerCreated = FALSE;

                  /*=======================================================================*/
            }

            /*=======================================================================*/
      }
      else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == FALSE ) */
      {
            /* This point should never be reached. */
            return cOCT6100_ERR_FATAL_C9;
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanMuteSer

Description:    Mute an echo channel present on a conference bridge. 

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeMute       Pointer to conference bridge mute structure.  

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanMuteSer
UINT32 Oct6100ConfBridgeChanMuteSer(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_MUTE           f_pConfBridgeMute )
{
      UINT16      usChanIndex;
      UINT16      usLoadEventIndex;
      UINT16      usSubStoreEventIndex;
      UINT32      ulResult;
      UINT8 fFlexibleConferencing;

      /* Check the validity of the channel and conference bridge given. */
      ulResult = Oct6100ApiCheckBridgeMuteParams( 
                                                            f_pApiInstance, 
                                                            f_pConfBridgeMute, 
                                                            &usChanIndex, 
                                                            &usLoadEventIndex, 
                                                            &usSubStoreEventIndex, 
                                                            &fFlexibleConferencing );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Modify all resources needed by the conference bridge. */
      ulResult = Oct6100ApiUpdateBridgeMuteResources( 
                                                            f_pApiInstance, 
                                                            usChanIndex, 
                                                            usLoadEventIndex, 
                                                            usSubStoreEventIndex,
                                                            fFlexibleConferencing );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeMuteParams

Description:      Check the validity of the channel and conference bridge given.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_pConfBridgeMute             Pointer to conference bridge channel mute structure.  
f_pusChannelIndex       Pointer to a channel index.
f_pusLoadEventIndex           Pointer to a load mixer event index.
f_pusSubStoreEventIndex Pointer to a sub-store mixer event index.
f_pfFlexibleConfBridge  If this is a flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeMuteParams
UINT32 Oct6100ApiCheckBridgeMuteParams(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_MUTE           f_pConfBridgeMute,
                        OUT         PUINT16                                               f_pusChannelIndex,
                        OUT         PUINT16                                               f_pusLoadEventIndex,
                        OUT         PUINT16                                               f_pusSubStoreEventIndex, 
                        OUT         PUINT8                                                f_pfFlexibleConfBridge )
{
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;
      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      UINT32      ulEntryOpenCnt;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
      
      if ( f_pConfBridgeMute->ulChannelHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;

      /*=====================================================================*/
      /* Check the channel handle.*/

      if ( (f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      *f_pusChannelIndex = (UINT16)( f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pEchoChanEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /* Check if the channel is bound to a conference bridge. */
      if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;

      /* Check if channel is already muted. */
      if ( pEchoChanEntry->fMute == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_ALREADY_MUTED;

      /* Check if this is a tap channel, which is always mute. */
      if ( pEchoChanEntry->fTap == TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE;

      /*=====================================================================*/

      /*=====================================================================*/
      /* Check the conference bridge handle. */

      if ( pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex )

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;

      if ( pBridgeEntry->fFlexibleConferencing == FALSE )
      {
            /* Check the event entries.*/
            if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;

            if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;
      }

      /*=====================================================================*/

      /* Return the config of the channel and all other important information. */
      *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex;
      *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex;
      *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiUpdateBridgeMuteResources

Description:    Modify the conference bridge entry for this channel in order 
                        to mute the specified channel.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_usChanIndex                       Index of the channel to be muted.   
f_usLoadEventIndex                  Allocated entry for the Load event of the channel.
f_usSubStoreEventIndex        Allocated entry for the substract and store event of the channel.
f_fFlexibleConfBridge         If this is a flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateBridgeMuteResources
UINT32 Oct6100ApiUpdateBridgeMuteResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT16                                          f_usLoadEventIndex,
                        IN          UINT16                                          f_usSubStoreEventIndex, 
                        IN          UINT8                                     f_fFlexibleConfBridge )
{
      tOCT6100_WRITE_PARAMS               WriteParams;
      tOCT6100_READ_PARAMS                ReadParams;

      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      tPOCT6100_SHARED_INFO               pSharedInfo;

      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT           pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT           pSubStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT           pTempEntry;
      UINT32      ulResult;
      UINT16      usTempEventIndex;
      UINT32      ulLoopCount;
      UINT16      usReadData;

      BOOL  fCreateSilenceLoad = FALSE;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

      ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
      ReadParams.pusReadData = &usReadData;
      
      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry,  pEchoChanEntry->usBridgeIndex )

      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_CHANNEL                     pTempEchoChanEntry;
            UINT16                                                usChannelIndex;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;

            UINT16      ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ];
            UINT32      ulMutePortChannelIndex;

            for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                  ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX;

            mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

            /* Search through the list of API channel entry for the ones on to this bridge. */
            for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );

                  if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                  {
                        if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex )
                        {
                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                              /* Check if this participant can hear us. */
                              if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                    && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) )
                              {
                                    /* Then update this channel's mixer. */
                                    ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                              f_pApiInstance,
                                                                              pEchoChanEntry->usBridgeIndex,
                                                                              f_usChanIndex,
                                                                              usChannelIndex,
                                                                              FALSE );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    if ( pTempParticipant->fFlexibleMixerCreated == FALSE )
                                    {
                                          /* Remember to mute the port on this channel. */
                                          for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                                          {
                                                if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex )
                                                {
                                                      break;
                                                }
                                                else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX )
                                                {
                                                      ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex;
                                                      break;
                                                }
                                          }
                                    }
                              }
                        }
                  }
            }

            /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */
            for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
            {
                  if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] );

                        mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
                        
                        if ( pTempParticipant->fFlexibleMixerCreated == FALSE )
                        {
                              /* Check if the Rin port must be muted on this channel. */
                              ulResult = Oct6100ApiMutePorts( 
                                                                  f_pApiInstance, 
                                                                  ausMutePortChannelIndexes[ ulMutePortChannelIndex ], 
                                                                  pTempEchoChanEntry->usRinTsstIndex, 
                                                                  pTempEchoChanEntry->usSinTsstIndex,
                                                                  FALSE );
                              if ( ulResult != cOCT6100_ERR_OK )
                              {
                                    if ( ulResult == cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED )
                                    {
                                          UINT32 ulTempResult;

                                          /* Cleanup resources, unmute channel... */
                                          ulTempResult = Oct6100ApiUpdateBridgeUnMuteResources(
                                                                  f_pApiInstance,
                                                                  f_usChanIndex,
                                                                  f_usLoadEventIndex,
                                                                  f_usSubStoreEventIndex, 
                                                                  TRUE );
                                          if ( ulTempResult != cOCT6100_ERR_OK )
                                                return ulTempResult;
                                          else
                                                return ulResult;
                                    }
                                    else
                                    {
                                          return ulResult;
                                    }
                              }
                        }
                  }
                  else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */
                  {
                        /* No more channels to check for muting. */
                        break;
                  }
            }
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex );
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );

            /*=======================================================================*/
            /* Program the Load event. */

            /* Create silence load if this is the first event of the bridge. */
            if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr )
                  fCreateSilenceLoad = TRUE;

            /* First check if this event was a load or an accumulate event, if it's a load */
            /* we need to find a new load. */
            if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex )
            {
                  /* Change the next entry if one is present to a load event to keep the bridge alive. */
                  if ( pBridgeEntry->usNumClients == 1 )
                  {
                        /* There is no other entry on the bridge, no need to search for an Accumulate event. */
                        pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX;
                  }
                  else
                  {
                        /* Search for an accumulate event to tranform into a Load event. */
                        usTempEventIndex = pLoadEventEntry->usNextEventPtr;
                        ulLoopCount = 0;

                        /* Find the copy entry before the entry to remove. */
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                        while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && 
                                 pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE )
                        {
                              if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE )
                              {
                                    /* Change this entry into a load event. */
                                    ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                                    mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    WriteParams.ulWriteAddress = ReadParams.ulReadAddress;
                                    WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD);

                                    mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;
                                    
                                    /* Set this entry as the load index. */
                                    pBridgeEntry->usLoadIndex = usTempEventIndex;

                                    /* Update the software model. */
                                    pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;

                                    /* Stop searching. */
                                    break;
                              }
                              
                              /* Go to the next entry into the list. */
                              usTempEventIndex = pTempEntry->usNextEventPtr;
                              mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                              ulLoopCount++;
                              if ( ulLoopCount == cOCT6100_MAX_LOOP )
                                    return cOCT6100_ERR_FATAL_9B;
                        }
                  }
            }

            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

            /* Do not load the sample if the channel is muted. */
            if ( fCreateSilenceLoad == TRUE )
            {
                  if ( pBridgeEntry->usSilenceLoadEventPtr == cOCT6100_INVALID_INDEX )
                  {
                        /* Instead of No-oping, load the silence TSI, to make sure the other conferences before us are not heard. */
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                        WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */

                        /* Remember the silence load event. */
                        pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex;
                  }
                  else
                  {
                        /* Do nothing. */
                        WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
                  }
            }
            else
            {
                  /* Do nothing. */
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
            }

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /* Update the software model. */
            pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP;

            /*=======================================================================*/
            
            /*=======================================================================*/
            /* Program the Substract and store event. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            /* Do not load the sample if the channel is muted. */
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE;

            /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */
            if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
            {
                  /* Sout input. */
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
            }
            else /* if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX ) */
            {
                  /* Rin input. */
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
            }

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /* Update the software model. */
            pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE;

            /*=======================================================================*/
      }

      /* Update the channel entry API structure */
      pEchoChanEntry->fMute = TRUE;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeChanUnMuteSer

Description:    UnMute an echo channel present on a conference bridge. 

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeUnMute           Pointer to conference bridge channel unmute structure.  

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanUnMuteSer
UINT32 Oct6100ConfBridgeChanUnMuteSer(
                        IN OUT      tPOCT6100_INSTANCE_API                          f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE         f_pConfBridgeUnMute )
{
      UINT16      usChanIndex;
      UINT16      usLoadEventIndex;
      UINT16      usSubStoreEventIndex;
      UINT8 fFlexibleConfBridge;
      UINT32      ulResult;

      /* Check the validity of the channel and conference bridge given. */
      ulResult = Oct6100ApiCheckBridgeUnMuteParams( 
                                                                  f_pApiInstance, 
                                                                  f_pConfBridgeUnMute, 
                                                                  &usChanIndex, 
                                                                  &usLoadEventIndex, 
                                                                  &usSubStoreEventIndex, 
                                                                  &fFlexibleConfBridge );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Modify all resources needed by the conference bridge. */
      ulResult = Oct6100ApiUpdateBridgeUnMuteResources( 
                                                                  f_pApiInstance, 
                                                                  usChanIndex, 
                                                                  usLoadEventIndex, 
                                                                  usSubStoreEventIndex, 
                                                                  fFlexibleConfBridge );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeUnMuteParams

Description:      Check the validity of the channel and conference bridge given.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_pConfBridgeUnMute                 Pointer to conference bridge channel unmute structure.  
f_pusChannelIndex             Pointer to the channel index fo the channel to be unmuted.
f_pusLoadEventIndex                 Pointer to the load index of the channel.
f_pusSubStoreEventIndex       Pointer to the sub-store event of the channel.
f_pfFlexibleConfBridge        If this is a flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeUnMuteParams
UINT32 Oct6100ApiCheckBridgeUnMuteParams(
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE   f_pConfBridgeUnMute,
                        OUT         PUINT16                                               f_pusChannelIndex,
                        OUT         PUINT16                                               f_pusLoadEventIndex,
                        OUT         PUINT16                                               f_pusSubStoreEventIndex, 
                        OUT         PUINT8                                                f_pfFlexibleConfBridge )
{
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;
      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      UINT32      ulEntryOpenCnt;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
      
      if ( f_pConfBridgeUnMute->ulChannelHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;

      /*=====================================================================*/
      /* Check the channel handle.*/

      if ( (f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      *f_pusChannelIndex = (UINT16)( f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pEchoChanEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /* Check if the channel is bound to a conference bridge.*/
      if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;

      /* Check if channel is already muted.*/
      if ( pEchoChanEntry->fMute == FALSE )
            return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_NOT_MUTED;

      /*=====================================================================*/

      /*=====================================================================*/
      /* Check the conference bridge handle. */

      if (  pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry,  pEchoChanEntry->usBridgeIndex )

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      
      /* Check the event entries.*/
      if ( pBridgeEntry->fFlexibleConferencing == FALSE )
      {
            if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;

            /* Check the event entries.*/
            if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE;
      }

      /*=====================================================================*/

      /* Return the config of the channel and all other important information.*/
      *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex;
      *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex;
      *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiUpdateBridgeUnMuteResources

Description:    Modify the conference bridge entry for this channel in order 
                        to un-mute the specified channel.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_usChanIndex                       Index of the channel to be unmuted. 
f_usLoadEventIndex                  Allocated entry for the Load event of the channel.
f_usSubStoreEventIndex        Allocated entry for the substract and store event of the channel.
f_fFlexibleConfBridge         If this is a flexible conference bridge.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateBridgeUnMuteResources
UINT32 Oct6100ApiUpdateBridgeUnMuteResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT16                                          f_usLoadEventIndex,
                        IN          UINT16                                          f_usSubStoreEventIndex, 
                        IN          UINT8                                     f_fFlexibleConfBridge )
{
      tOCT6100_WRITE_PARAMS               WriteParams;
      tOCT6100_READ_PARAMS                ReadParams;

      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      tPOCT6100_SHARED_INFO               pSharedInfo;

      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;

      tPOCT6100_API_MIXER_EVENT           pLoadEventEntry;
      tPOCT6100_API_MIXER_EVENT           pSubStoreEventEntry;
      tPOCT6100_API_MIXER_EVENT           pTempEntry;
      UINT32      ulResult;
      UINT16      usTempEventIndex;
      UINT32      ulLoopCount;
      UINT16      usReadData;
      
      UINT16      usLoadEventType         = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
      UINT16      usPreviousLoadIndex = cOCT6100_INVALID_INDEX;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;
      
      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

      ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
      ReadParams.pusReadData = &usReadData;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry,  pEchoChanEntry->usBridgeIndex )
      
      if ( f_fFlexibleConfBridge == TRUE )
      {
            tPOCT6100_API_CHANNEL                     pTempEchoChanEntry;
            UINT16                                                usChannelIndex;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
            tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;

            mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex );

            /* Before doing anything, check if the copy events must be created. */
            if ( ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChanEntry->fCopyEventCreated == FALSE ) )
            {
                  /* The copy event has not been created, create it once for the life of the participant on the bridge. */
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  
                  WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY;
                  WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex;
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  WriteParams.ulWriteAddress += 2;
                  WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  /* Now insert the Sin copy event into the list. */
                  ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance,
                                                                        pEchoChanEntry->usSinCopyEventIndex,
                                                                        cOCT6100_EVENT_TYPE_SIN_COPY,
                                                                        f_usChanIndex );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;

                  pEchoChanEntry->fCopyEventCreated = TRUE;
            }
            
            /* Search through the list of API channel entry for the ones onto this bridge. */
            for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                  
                  /* Channel reserved? */
                  if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                  {
                        /* On current bridge? */
                        if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex )
                        {
                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                              /* Check if this participant can hear us. */
                              if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 )
                              {
                                    /* Then create/update this channel's mixer. */
                                    ulResult = Oct6100ApiBridgeAddParticipantToChannel(
                                                                              f_pApiInstance,
                                                                              pEchoChanEntry->usBridgeIndex,
                                                                              f_usChanIndex,
                                                                              usChannelIndex,
                                                                              pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ],
                                                                              pTempEchoChanEntry->usSubStoreEventIndex,
                                                                              pTempEchoChanEntry->usSinCopyEventIndex,
                                                                              pParticipant->ulInputPort,
                                                                              pTempParticipant->ulInputPort );
                                    if ( ulResult != cOCT6100_ERR_OK )
                                          return ulResult;

                                    /* Check if the Rin silence event can be cleared now that the */
                                    /* channel has unmuted. */
                                    if ( ( pTempParticipant->fFlexibleMixerCreated == TRUE )
                                          && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) )
                                    {
                                          /* Remove the event from the list. */
                                          ulResult = Oct6100ApiMixerEventRemove(    f_pApiInstance,
                                                                                                      pTempEchoChanEntry->usRinSilenceEventIndex,
                                                                                                      cOCT6100_EVENT_TYPE_SOUT_COPY );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return cOCT6100_ERR_FATAL_DF;

                                          pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
                                    }
                              }
                        }
                  }
            }
      }
      else /* if ( f_fFlexibleConfBridge == FALSE ) */
      {
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex );
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );

            /*=======================================================================*/
            /* Program the Load event. */

            /* Before reactivating this event, check what type of event this event must be. */
            if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr ||
                   pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX )
            {
                  /* This event must become a Load event. */
                  usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                  pBridgeEntry->usLoadIndex = f_usLoadEventIndex;
            }

            usTempEventIndex = pBridgeEntry->usFirstLoadEventPtr;
            mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

            ulLoopCount = 0;

            while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && 
                     pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE )
            {
                  if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD )
                  {
                        usPreviousLoadIndex = usTempEventIndex;
                  }

                  /* Check if the previous load event is before or after the event about to be unmuted. */
                  if ( pTempEntry->usNextEventPtr == f_usLoadEventIndex )
                  {
                        if ( usPreviousLoadIndex == cOCT6100_INVALID_INDEX )
                        {
                              /* We did not find a load event before our node, this mean this one */
                              /* is about to become the new load event. */
                              usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;
                        }
                  }
                  
                  /* Go to the next entry into the list. */
                  usTempEventIndex = pTempEntry->usNextEventPtr;
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex );

                  ulLoopCount++;
                  if ( ulLoopCount == cOCT6100_MAX_LOOP )
                        return cOCT6100_ERR_FATAL_9B;
            }     
            
            /* Now program the current event node. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            WriteParams.usWriteData = usLoadEventType;

            /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */
            if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
            {
                  /* Sout source */
                  WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
            }
            else
            {
                  /* Rin source */
                  WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
            }
            
            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;
            
            /* Update the software event to reflect the hardware. */
            pLoadEventEntry->usEventType = usLoadEventType;

            /* Check if we need to change another node. */
            if ( usLoadEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD )
            {
                  if ( usPreviousLoadIndex != cOCT6100_INVALID_INDEX )
                  {
                        /* Now program the old load event. */
                        ReadParams.ulReadAddress =  cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousLoadIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
                  
                        mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
                        
                        WriteParams.ulWriteAddress = ReadParams.ulReadAddress;
                        WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE );
                        
                        mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                        if ( ulResult != cOCT6100_ERR_OK )
                              return ulResult;
            
                        /* Update the software event to reflect the hardware. */
                        mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousLoadIndex );
                        pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
                  }
            }

            /*=======================================================================*/
            
            /*=======================================================================*/
            /* Program the Substract and store event. */
            WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
            
            WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
            /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */
            if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX )
            {
                  /* Sout port source */
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
            }
            else
            {
                  /* Rin port source */
                  WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
                  WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
            }

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            WriteParams.ulWriteAddress += 2;
            WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex;

            mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;

            /* Update the software event to reflect the hardware. */
            pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;

            /*=======================================================================*/


            /*=======================================================================*/
            /* Check if have to remove silence load event. */

            if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX )
            {
                  if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex )
                  {
                        /* Clear the silence load event ptr. */
                        pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX;
                  }
            }
      }

      /* Update the channel entry API structure */
      pEchoChanEntry->fMute = FALSE;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeDominantSpeakerSetSer

Description:    This function sets the dominant speaker of a bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to 
                                    keep the present state of the chip and all its 
                                    resources.

f_pConfBridgeDominant   Pointer to conference bridge dominant speaker 
                                    structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetSer
UINT32 Oct6100ConfBridgeDominantSpeakerSetSer(
                        IN OUT      tPOCT6100_INSTANCE_API                                f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET      f_pConfBridgeDominantSpeaker )
{
      UINT16      usChanIndex;
      UINT16      usBridgeIndex;
      UINT32      ulResult;

      /* Check the validity of the channel handle given. */
      ulResult = Oct6100ApiCheckBridgeDominantSpeakerParams( f_pApiInstance, f_pConfBridgeDominantSpeaker, &usChanIndex, &usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Modify all resources needed by the conference bridge. */
      ulResult = Oct6100ApiUpdateBridgeDominantSpeakerResources( f_pApiInstance, usChanIndex, usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeDominantSpeakerParams

Description:      Check the validity of the channel given for setting the
                        dominant speaker.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.
f_pConfBridgeDominant   Pointer to conference bridge channel dominant speaker structure.  
f_pusChannelIndex       Pointer to a channel index.
f_pusChannelIndex       Pointer to a bridge index.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeDominantSpeakerParams
UINT32 Oct6100ApiCheckBridgeDominantSpeakerParams(
                        IN OUT      tPOCT6100_INSTANCE_API                                f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET      f_pConfBridgeDominantSpeaker,
                        OUT         PUINT16                                                           f_pusChannelIndex,
                        OUT         PUINT16                                                           f_pusBridgeIndex )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_CHANNEL         pEchoChanEntry;
      UINT32      ulEntryOpenCnt;
      BOOL  fCheckEntryOpenCnt = FALSE;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
      
      if ( f_pConfBridgeDominantSpeaker->ulChannelHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /*=====================================================================*/
      /* Check the channel handle. */

      if ( f_pConfBridgeDominantSpeaker->ulChannelHndl != cOCT6100_CONF_NO_DOMINANT_SPEAKER_HNDL )
      {
            if ( (f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            *f_pusChannelIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
            if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

            /* Extract the entry open count from the provided handle. */
            ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

            /* Check for errors. */
            if ( pEchoChanEntry->fReserved != TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
            if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            /* Check if the channel is bound to a conference bridge. */
            if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
                  return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE;

            /* Check if the NLP is enabled on this channel. */
            if ( pEchoChanEntry->VqeConfig.fEnableNlp == FALSE )
                  return cOCT6100_ERR_CONF_BRIDGE_NLP_MUST_BE_ENABLED;

            /* Check if conferencing noise reduction is enabled on this channel. */
            if ( pEchoChanEntry->VqeConfig.fSoutConferencingNoiseReduction == FALSE )
                  return cOCT6100_ERR_CONF_BRIDGE_CNR_MUST_BE_ENABLED;

            /* Check if this is a tap channel.  If it is, it will never be the dominant speaker! */
            if ( pEchoChanEntry->fTap == TRUE )
                  return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE;

            /* Set the bridge index. */
            *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex;
      }
      else
      {
            /* Set this such that there is no dominant speaker on this conference bridge. */
            *f_pusChannelIndex = cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED;

            /* Check the conference bridge handle. */
            if ( (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

            /* Set the bridge index. */
            *f_pusBridgeIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );

            /* Extract the entry open count from the provided handle. */
            ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
            fCheckEntryOpenCnt = TRUE;
      }

      /*=====================================================================*/

      /*=====================================================================*/

      if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( fCheckEntryOpenCnt == TRUE )
      {
            if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
                  return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
      }

      /*=====================================================================*/
      /* Check if dominant speaker is supported in this firmware version. */
      
      if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == FALSE )
            return cOCT6100_ERR_NOT_SUPPORTED_DOMINANT_SPEAKER;

      /*=====================================================================*/

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiUpdateBridgeDominantSpeakerResources

Description:    Modify the conference bridge such that the new dominant
                        speaker is the one specified by the index.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
                                          
f_usChanIndex                       Index of the channel to be set as the dominant speaker.     
f_usBridgeIndex                     Index of the bridge where this channel is on.   

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateBridgeDominantSpeakerResources
UINT32 Oct6100ApiUpdateBridgeDominantSpeakerResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT16                                          f_usBridgeIndex )
{
      tPOCT6100_API_CHANNEL               pEchoChanEntry;
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;
      tPOCT6100_SHARED_INFO               pSharedInfo;

      UINT16      usChannelIndex;
      UINT32      ulResult;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      /* Get the bridge entry for this channel. */
      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex )

      /* Set the dominant speaker index for all channels in this conference. */

      /* Search through the list of API channel entry for the ones on to this bridge.*/
      for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
      {
            mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex );
            
            if ( pEchoChanEntry->fReserved == TRUE )
            {
                  if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                  {
                        /* If we are unsetting the dominant speaker, of if it is not our channel index. */
                        if ( ( f_usChanIndex == cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED )
                              || ( f_usChanIndex != usChannelIndex ) )
                        {
                              ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, f_usChanIndex );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                  }
            }
      }

      /* Make sure this channel is disabled. */
      if ( f_usChanIndex != cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED )
      {
            ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED );
            if ( ulResult != cOCT6100_ERR_OK )
                  return ulResult;
      }

      /* Save this in the conference bridge structure. */
      /* This will be needed later when removing the channel. */
      pBridgeEntry->fDominantSpeakerSet = TRUE;
      pBridgeEntry->usDominantSpeakerChanIndex = f_usChanIndex;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeMaskChangeSer

Description:    This function changes the mask of flexible bridge
                        participant.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to 
                                    keep the present state of the chip and all its 
                                    resources.

f_pConfBridgeMaskChange Pointer to conference bridge participant mask
                                    change structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeMaskChangeSer
UINT32 Oct6100ConfBridgeMaskChangeSer(
                        IN OUT      tPOCT6100_INSTANCE_API                                f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_MASK_CHANGE               f_pConfBridgeMaskChange )
{
      UINT16      usChanIndex;
      UINT16      usBridgeIndex;
      UINT32      ulResult;
      UINT32      ulNewParticipantMask;

      /* Check the validity of the channel handle given. */
      ulResult = Oct6100ApiCheckBridgeMaskChangeParams( f_pApiInstance, f_pConfBridgeMaskChange, &usChanIndex, &usBridgeIndex, &ulNewParticipantMask );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Update all resources needed by the new mask. */
      ulResult = Oct6100ApiUpdateMaskModifyResources( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Commit the changes to the chip's internal memories. */
      ulResult = Oct6100ApiBridgeUpdateMask( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiCheckBridgeMaskChangeParams

Description:      Check the validity of the channel given for setting the
                        mask.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_pConfBridgeMaskChange       Pointer to conference bridge channel mask change structure.  
f_pusChannelIndex             Pointer to a channel index.
f_pusBridgeIndex              Pointer to a bridge index.
f_pulNewParticipantMask       New mask to apply for this participant.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeMaskChangeParams
UINT32 Oct6100ApiCheckBridgeMaskChangeParams(
                        IN OUT      tPOCT6100_INSTANCE_API                          f_pApiInstance,
                        IN          tPOCT6100_CONF_BRIDGE_MASK_CHANGE         f_pConfBridgeMaskChange,
                        OUT         PUINT16                                                     f_pusChannelIndex,
                        OUT         PUINT16                                                     f_pusBridgeIndex,
                        OUT         PUINT32                                                     f_pulNewParticipantMask )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_CHANNEL         pEchoChanEntry;
      UINT32      ulEntryOpenCnt;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
      
      if ( f_pConfBridgeMaskChange->ulChannelHndl == cOCT6100_INVALID_HANDLE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /*=====================================================================*/
      /* Check the channel handle.*/

      if ( (f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      *f_pusChannelIndex = (UINT16)( f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeMaskChange->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pEchoChanEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /* Check if the channel is bound to a conference bridge. */
      if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
            return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE;

      /* Set the bridge index. */
      *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex;

      /*=====================================================================*/

      /*=====================================================================*/

      if ( ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX )
            || ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;

      /* Check if this is bridge is a flexible conference bridge. */
      if ( pBridgeEntry->fFlexibleConferencing == FALSE )
            return cOCT6100_ERR_CONF_BRIDGE_SIMPLE_BRIDGE;
      
      /*=====================================================================*/

      /* Return new mask to apply. */
      *f_pulNewParticipantMask = f_pConfBridgeMaskChange->ulNewListenerMask;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiUpdateMaskModifyResources

Description:    Modify/reserve all resources needed for the modification of
                        the participant's mask.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_usBridgeIndex                     Bridge index of the bridge where this channel is residing.
f_usChanIndex                       Channel index of the channel to be modified.
f_ulNewListenerMask                 New mask to apply to the selected participant.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateMaskModifyResources
UINT32 Oct6100ApiUpdateMaskModifyResources(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex,
                        IN          UINT16                                          f_usChanIndex,
                        IN          UINT32                                          f_ulNewListenerMask )
{
      tPOCT6100_API_CHANNEL                     pChanEntry;
      tPOCT6100_API_CHANNEL                     pTempEchoChanEntry;
      tPOCT6100_SHARED_INFO                     pSharedInfo;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;

      UINT32      ulResult = cOCT6100_ERR_OK;
      UINT32      ulTempVar;
      UINT32      ulOldListenerMask;
      UINT16      usChannelIndex;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      /* Get a pointer to the channel's list entry. */
      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex )

      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex );

      /* Must travel all clients of this conference and reserve a load or accumulate event for */
      /* all participants which could not hear us but now can. While at it, check for events that */
      /* could be released, for example a participant that we cannot hear anymore. */

      ulOldListenerMask = pParticipant->ulListenerMask;

      /* Search through the list of API channel entry for the ones on to this bridge.*/
      for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ )
      {
            mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
            
            /* Channel reserved? */
            if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
            {
                  /* On current bridge? */
                  if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                  {
                        mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                        /* Check if we can now hear this participant, but could not before. */
                        if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                              && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) )
                        {
                              /* Must reserve a load or accumulate entry mixer event here! */
                              ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] );
                              if ( ulResult != cOCT6100_ERR_OK )
                              {
                                    /* Most probably, the hardware is out of mixer events. */
                                    break;
                              }
                        }

                        /* Check if we can now NOT hear this participant, but could before. */
                        if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 )
                              && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) )
                        {
                              /* Must release the load or accumulate entry mixer event. */
                              ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] );
                              if ( ulResult != cOCT6100_ERR_OK )
                              {
                                    break;
                              }
                        }
                  }
            }
      }

      /* If an error is returned, make sure everything is cleaned up properly. */
      if ( ulResult != cOCT6100_ERR_OK )
      {
            /* Search through the list of API channel entry for the ones on to this bridge.*/
            for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
            {
                  mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
                  
                  /* Channel reserved? */
                  if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
                  {
                        /* On current bridge? */
                        if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                        {
                              mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                              /* Check if we can now hear this participant, but could not before. */
                              if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                                    && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) )
                              {
                                    /* If the load or event entry in the mixer memory was reserved. */
                                    if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
                                    {
                                          /* Must release the load or accumulate entry mixer event. */
                                          ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] );
                                          if ( ulTempVar != cOCT6100_ERR_OK )
                                                return ulTempVar;

                                          pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                                    }
                              }

                              /* Check if we can now NOT hear this participant, but could before. */
                              if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 )
                                    && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) )
                              {
                                    /* If the load or event entry in the mixer memory was reserved. */
                                    if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] == cOCT6100_INVALID_INDEX )
                                    {
                                          /* Must release the load or accumulate entry mixer event. */
                                          ulTempVar = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ) );
                                          if ( ulTempVar != cOCT6100_ERR_OK )
                                                return ulTempVar;
                                    }
                              }
                        }
                  }
            }

            return ulResult;
      }

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeUpdateMask

Description:    Update the participant's mask.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.
f_usBridgeIndex                     Bridge index of the bridge where this channel is residing.
f_usChanIndex                       Channel index of the channel to be modified.
f_ulNewListenerMask                 New mask to apply to the selected participant.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeUpdateMask
UINT32 Oct6100ApiBridgeUpdateMask( 
                        IN OUT      tPOCT6100_INSTANCE_API                    f_pApiInstance, 
                        IN          UINT16                                                f_usBridgeIndex, 
                        IN          UINT16                                                f_usChanIndex, 
                        IN          UINT32                                                f_ulNewListenerMask )
{
      tPOCT6100_API_CHANNEL                     pChanEntry;
      tPOCT6100_API_CHANNEL                     pTempEchoChanEntry;
      tPOCT6100_SHARED_INFO                     pSharedInfo;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant;
      tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant;
      tOCT6100_WRITE_PARAMS                     WriteParams;

      UINT32      ulResult;
      UINT32      ulOldListenerMask;
      UINT16      usChannelIndex;

      UINT16      ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ];
      UINT32      ulMutePortChannelIndex;

      for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
            ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX;

      /* Obtain local pointer to shared portion of instance. */
      pSharedInfo = f_pApiInstance->pSharedInfo;

      WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

      WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

      /* Get a pointer to the channel's list entry. */
      mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex )

      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex );

      ulOldListenerMask = pParticipant->ulListenerMask;

      /* Search through the list of API channel entry for the ones onto this bridge. */
      for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
      {
            mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
            
            /* Channel reserved? */
            if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
            {
                  /* On current bridge? */
                  if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
                  {
                        mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );

                        /* Check if we can now hear this participant, but could not before. */
                        if ( ( pTempEchoChanEntry->fMute == FALSE ) 
                              && ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                              && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) )
                        {
                              /* First create/update the current channel's mixer. */
                              ulResult = Oct6100ApiBridgeAddParticipantToChannel(
                                                                        f_pApiInstance,
                                                                        f_usBridgeIndex,
                                                                        usChannelIndex,
                                                                        f_usChanIndex,
                                                                        pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ],
                                                                        pChanEntry->usSubStoreEventIndex,
                                                                        pChanEntry->usSinCopyEventIndex,
                                                                        pTempParticipant->ulInputPort,
                                                                        pParticipant->ulInputPort );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;

                              if ( pParticipant->fFlexibleMixerCreated == TRUE )
                              {
                                    /* Check if the Rin silence event can be cleared now that the */
                                    /* channel has been added to a conference. */
                                    if ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX )
                                    {
                                          /* Remove the event from the list.*/
                                          ulResult = Oct6100ApiMixerEventRemove(    f_pApiInstance,
                                                                                                      pChanEntry->usRinSilenceEventIndex,
                                                                                                      cOCT6100_EVENT_TYPE_SOUT_COPY );
                                          if ( ulResult != cOCT6100_ERR_OK )
                                                return ulResult;

                                          ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex );
                                          if ( ulResult != cOCT6100_ERR_OK  )
                                                return cOCT6100_ERR_FATAL_DF;

                                          pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
                                    }
                              }
                        }

                        /* Check if we can now NOT hear this participant, but could before. */
                        if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 )
                              && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 )
                              && ( pParticipant->fFlexibleMixerCreated == TRUE ) 
                              && ( pTempEchoChanEntry->fMute == FALSE ) )
                        {
                              /* First update the current channel's mixer. */
                              ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel(
                                                                        f_pApiInstance,
                                                                        f_usBridgeIndex,
                                                                        usChannelIndex,
                                                                        f_usChanIndex,
                                                                        TRUE );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                              
                              if ( pParticipant->fFlexibleMixerCreated == FALSE )
                              {
                                    /* Remember to mute the port on this channel. */
                                    for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
                                    {
                                          if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == f_usChanIndex )
                                          {
                                                break;
                                          }
                                          else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX )
                                          {
                                                ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = f_usChanIndex;
                                                break;
                                          }
                                    }
                              }
                        }

                        /* Clear the load or accumulate event index for this participant. */
                        if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 )
                              && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) )
                        {
                              pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
                        }
                  }
            }

            /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */
            for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ )
            {
                  if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX )
                  {
                        mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] );

                        mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
                        
                        if ( pTempParticipant->fFlexibleMixerCreated == FALSE )
                        {
                              /* Check if the Rin port must be muted on this channel. */
                              ulResult = Oct6100ApiMutePorts( 
                                                                  f_pApiInstance, 
                                                                  ausMutePortChannelIndexes[ ulMutePortChannelIndex ], 
                                                                  pTempEchoChanEntry->usRinTsstIndex, 
                                                                  pTempEchoChanEntry->usSinTsstIndex,
                                                                  FALSE );
                              if ( ulResult != cOCT6100_ERR_OK )
                                    return ulResult;
                        }
                  }
                  else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */
                  {
                        /* No more channels to check for muting. */
                        break;
                  }
            }
      }
      
      /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */
      if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
      {
            if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
            {
                  ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                            pChanEntry->usSinTsstIndex,
                                                                                            pChanEntry->usExtraSinTsiMemIndex,
                                                                                            pChanEntry->TdmConfig.bySinPcmLaw );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }

            /* If the silence TSI is loaded on this port, update with the extra sin TSI. */
            if ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
            {
                  WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );

                  WriteParams.ulWriteAddress += 2;
                  WriteParams.usWriteData = pChanEntry->usExtraSinTsiMemIndex;

                  mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
                  if ( ulResult != cOCT6100_ERR_OK  )
                        return ulResult;
            }
      }

      /* Configure the RIN copy mixer entry and memory - if using the RIN port. */
      if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_RIN )
      {
            if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
            {
                  ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
                                                                                            pChanEntry->usRinTsstIndex,
                                                                                            pChanEntry->usExtraRinTsiMemIndex,
                                                                                            pChanEntry->TdmConfig.byRinPcmLaw );
                  if ( ulResult != cOCT6100_ERR_OK )
                        return ulResult;
            }
      }

      /* Save the new mask permanently in the API instance. */
      pParticipant->ulListenerMask = f_ulNewListenerMask;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ConfBridgeGetStatsSer

Description:    This function returns the statistics from the specified bridge.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_pConfBridgeStats            Pointer to conference bridge stats structure.  

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeGetStatsSer
UINT32 Oct6100ConfBridgeGetStatsSer(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN OUT      tPOCT6100_CONF_BRIDGE_STATS         f_pConfBridgeStats )
{
      tPOCT6100_API_CONF_BRIDGE           pBridgeEntry;
      UINT16      usConfBridgeIndex;
      UINT32      ulEntryOpenCnt;

      /* Check for errors. */
      if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
            return cOCT6100_ERR_CONF_BRIDGE_DISABLED;

      /*=====================================================================*/
      /* Check the conference bridge handle. */

      /* Check the provided handle. */
      if ( (f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      usConfBridgeIndex = (UINT16)( f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
      if ( usConfBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, usConfBridgeIndex )

      /* Extract the entry open count from the provided handle. */
      ulEntryOpenCnt = (f_pConfBridgeStats->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;

      /* Check for errors. */
      if ( pBridgeEntry->fReserved != TRUE )
            return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
      if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
            return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;

      /*=====================================================================*/

      /* Return the stats.*/
      f_pConfBridgeStats->ulNumChannels = pBridgeEntry->usNumClients;
      f_pConfBridgeStats->ulNumTappedChannels = pBridgeEntry->usNumTappedClients;
      f_pConfBridgeStats->fFlexibleConferencing = pBridgeEntry->fFlexibleConferencing;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReserveBridgeEntry

Description:    Reserves a free entry in the Bridge list.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.
f_pusBridgeIndex        List entry reserved.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveBridgeEntry
UINT32 Oct6100ApiReserveBridgeEntry(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        OUT         PUINT16                                         f_pusBridgeIndex )
{
      PVOID pBridgeAlloc;
      UINT32      ulResult;
      UINT32      ulBridgeIndex;

      mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc )

      ulResult = OctapiLlmAllocAlloc( pBridgeAlloc, &ulBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK  )
      {
            if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT )
                  return cOCT6100_ERR_CONF_BRIDGE_ALL_BUFFERS_OPEN;
            else
                  return cOCT6100_ERR_FATAL_29;
      }

      *f_pusBridgeIndex = (UINT16)( ulBridgeIndex & 0xFFFF );

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReleaseBridgeEntry

Description:    Release an entry from the bridge list.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance          Pointer to API instance. This memory is used to keep the
                              present state of the chip and all its resources.

f_usBridgeIndex         List entry reserved.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReleaseBridgeEntry
UINT32 Oct6100ApiReleaseBridgeEntry(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex )
{
      PVOID pBridgeAlloc;
      UINT32      ulResult;

      mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc )

      ulResult = OctapiLlmAllocDealloc( pBridgeAlloc, f_usBridgeIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return cOCT6100_ERR_FATAL_2A;

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiGetPrevLastSubStoreEvent

Description:    This function will search for the first valid LastSubStoreEvent 
                        in a bridge located before the current bridge in the bridge 
                        link list.
                        
                        If the function does not find an event before reaching the end
                        of the mixers list, then the event head node will be used as the
                        last Store or SubStore event.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                      Pointer to API instance. This memory is used to keep the
                                          present state of the chip and all its resources.

f_pusBridgeEntry              Bridge entry.
f_usBridgeFirstLoadEventPtr   Load index to check against.
First                               valid sub store index.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetPrevLastSubStoreEvent
UINT32 Oct6100ApiGetPrevLastSubStoreEvent(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usBridgeIndex,
                        IN          UINT16                                          f_usBridgeFirstLoadEventPtr,
                        OUT         PUINT16                                         f_pusLastSubStoreEventIndex )
{
      tPOCT6100_API_CONF_BRIDGE     pBridgeEntry;
      tPOCT6100_API_MIXER_EVENT     pTempMixerEntry;
      UINT16                                    usNextEventPtr;
      UINT16                                    usHeadEventPtr;
      UINT16                                    usLastSubStoreEventPtr;
      UINT32                                    ulLoopCount = 0;
      UINT16                                    usCurrentPtr;
      UINT32                                    ulResult = cOCT6100_ERR_OK;

      /* Get current entry to obtain the link to the previous entry.*/
      mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex );

      /* Since we have flexible bridges, we have to */
      /* run down the list and check for the appropriate event. */

      /* Travel down the list for the last Store or Sub/Store event before the bridge. */

      if ( f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
      {
            /* The only node in the list then is the head node.*/
            usHeadEventPtr = cOCT6100_MIXER_HEAD_NODE;
      }
      else
      {
            usHeadEventPtr = f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
      }

      mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usHeadEventPtr );
      usLastSubStoreEventPtr = usHeadEventPtr;
      usNextEventPtr = pTempMixerEntry->usNextEventPtr;
      usCurrentPtr = usHeadEventPtr;
      while( usCurrentPtr != f_usBridgeFirstLoadEventPtr )
      {
            if ( ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE )
                  || ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) )
            {
                  usLastSubStoreEventPtr = usNextEventPtr;
            }

            /* Next pointer. */
            usCurrentPtr = usNextEventPtr;
            usNextEventPtr = pTempMixerEntry->usNextEventPtr;

            /* Check if next event pointer is valid. */
            if ( ( ( f_usBridgeFirstLoadEventPtr != usCurrentPtr ) 
                  && ( pTempMixerEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) )
                        || ( pTempMixerEntry->usNextEventPtr == cOCT6100_MIXER_HEAD_NODE ) )
                  return cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND;

            if ( usNextEventPtr != cOCT6100_INVALID_INDEX )
                  mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usNextEventPtr );
            
            ulLoopCount++;
            if ( ulLoopCount == cOCT6100_MAX_LOOP )
                  return cOCT6100_ERR_FATAL_CA;
      }
      
      /* Return the result to the user. */
      *f_pusLastSubStoreEventIndex = usLastSubStoreEventPtr;

      return ulResult;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiGetPreviousEvent

Description:    This is a recursive function, it requires an entry event index and 
                        will run down the list until it finds the node just before the one
                        required.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_usEntryIndex                Event entry index.
f_pusBridgeEntry        Bridge entry.
f_pusPreviousIndex            Previous index.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetPreviousEvent
UINT32 Oct6100ApiGetPreviousEvent(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usEntryIndex,
                        IN          UINT16                                          f_usSearchedIndex,
                        IN          UINT16                                          f_usLoopCnt,
                        OUT         PUINT16                                         f_pusPreviousIndex )
{
      tPOCT6100_API_MIXER_EVENT     pCurrentEntry;
      UINT32      ulResult;

      /* Get current entry to obtain the link to the previous entry. */
      mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pCurrentEntry, f_usEntryIndex );

      /* Avoid stack overflows. */
      if ( f_usLoopCnt == cOCT6100_MAX_MIXER_EVENTS )
            return cOCT6100_ERR_FATAL_E3;

      if ( pCurrentEntry->usNextEventPtr == cOCT6100_INVALID_INDEX )
      {
            /* Event not found. */
            ulResult = cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND;
      }
      else if ( pCurrentEntry->usNextEventPtr == f_usSearchedIndex )
      {
            /* We found our node. */
            *f_pusPreviousIndex = f_usEntryIndex;
            ulResult = cOCT6100_ERR_OK; 
      }
      else
      {
            /* Keep searching.*/
            f_usLoopCnt++;
            ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pCurrentEntry->usNextEventPtr, f_usSearchedIndex, f_usLoopCnt, f_pusPreviousIndex );
      }

      return ulResult;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiBridgeSetDominantSpeaker

Description:    This function will set the index of the dominant speaker
                        for the channel index specified.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                            Pointer to API instance. This memory is used to 
                                                keep the present state of the chip and all its 
                                                resources.

f_usChannelIndex                    Index of the channel where the API must set the
                                                current dominant speaker for the conference.
f_usDominantSpeakerIndex            Index of the channel which is the dominant
                                                speaker in the conference.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeSetDominantSpeaker
UINT32 Oct6100ApiBridgeSetDominantSpeaker(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usChannelIndex,
                        IN          UINT16                                          f_usDominantSpeakerIndex )
{
      UINT32      ulBaseAddress;
      UINT32      ulFeatureBytesOffset;
      UINT32      ulFeatureBitOffset;
      UINT32      ulFeatureFieldLength;
      UINT32      ulResult;
      UINT32      ulTempData;
      UINT32      ulMask;

      tPOCT6100_API_CHANNEL   pEchoChanEntry;

      mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, f_usChannelIndex );

      ulBaseAddress            = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst;
      ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.usDwordOffset * 4;
      ulFeatureBitOffset       = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byBitOffset;
      ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byFieldSize;

      /* Retrieve the current configuration. */
      mOCT6100_RETRIEVE_NLP_CONF_DWORD(   f_pApiInstance,
                                                            pEchoChanEntry,
                                                            ulBaseAddress + ulFeatureBytesOffset,
                                                            &ulTempData,
                                                            ulResult );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;

      /* Clear previous value set in the feature field.*/
      mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask );

      ulTempData &= (~ulMask);
      ulTempData |= ( ( f_usDominantSpeakerIndex ) << ulFeatureBitOffset );

      /* Save the new dominant speaker. */
      mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance,
                                                      pEchoChanEntry,
                                                      ulBaseAddress + ulFeatureBytesOffset,
                                                      ulTempData,
                                                      ulResult );
      if ( ulResult != cOCT6100_ERR_OK )
            return ulResult;  

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReserveFlexConfParticipantEntry

Description:    Reserves a free entry in the participant list.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.
f_pusParticipantIndex   List entry reserved.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveFlexConfParticipantEntry
UINT32 Oct6100ApiReserveFlexConfParticipantEntry(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        OUT         PUINT16                                         f_pusParticipantIndex )
{
      PVOID pParticipantAlloc;
      UINT32      ulResult;
      UINT32      ulParticipantIndex;

      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc )

      ulResult = OctapiLlmAllocAlloc( pParticipantAlloc, &ulParticipantIndex );
      if ( ulResult != cOCT6100_ERR_OK )
      {
            if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT )
                  return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_ALL_BUFFERS_OPEN;
            else
                  return cOCT6100_ERR_FATAL_29;
      }

      *f_pusParticipantIndex = (UINT16)( ulParticipantIndex & 0xFFFF );

      return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:         Oct6100ApiReleaseFlexConfParticipantEntry

Description:    Release an entry from the flexible conferencing participant 
                        list.

-------------------------------------------------------------------------------
|     Argument          |     Description
-------------------------------------------------------------------------------
f_pApiInstance                Pointer to API instance. This memory is used to keep the
                                    present state of the chip and all its resources.

f_usParticipantIndex    List entry reserved.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReleaseFlexConfParticipantEntry
UINT32 Oct6100ApiReleaseFlexConfParticipantEntry(
                        IN OUT      tPOCT6100_INSTANCE_API              f_pApiInstance,
                        IN          UINT16                                          f_usParticipantIndex )
{
      PVOID pParticipantAlloc;
      UINT32      ulResult;

      mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc )

      ulResult = OctapiLlmAllocDealloc( pParticipantAlloc, f_usParticipantIndex );
      if ( ulResult != cOCT6100_ERR_OK )
            return cOCT6100_ERR_FATAL_2A;

      return cOCT6100_ERR_OK;
}
#endif

Generated by  Doxygen 1.6.0   Back to index