summaryrefslogtreecommitdiff
path: root/software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c')
-rw-r--r--software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c7518
1 files changed, 7518 insertions, 0 deletions
diff --git a/software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c
new file mode 100644
index 0000000..43e57c8
--- /dev/null
+++ b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c
@@ -0,0 +1,7518 @@
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+File: oct6100_conf_bridge.c
+
+ Copyright (c) 2001-2005 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-PR38 $
+
+$Octasic_Revision: 145 $
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+
+
+/***************************** 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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeOpenDef(
+ tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen )
+{
+ f_pConfBridgeOpen->pulConfBridgeHndl = NULL;
+ f_pConfBridgeOpen->fFlexibleConferencing = FALSE;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeCloseDef(
+ tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose )
+{
+ f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeChanMuteDef(
+ tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute )
+{
+ f_pConfBridgeMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeChanUnMuteDef(
+ tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute )
+{
+ f_pConfBridgeUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+
+ return cOCT6100_ERR_OK;
+}
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeMaskChangeDef(
+ tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange )
+{
+ f_pConfBridgeMaskChange->ulChannelHndl = cOCT6100_INVALID_HANDLE;
+ f_pConfBridgeMaskChange->ulNewListenerMask = 0x0;
+
+ return cOCT6100_ERR_OK;
+}
+
+
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+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;
+}
+
+/**************************** 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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+
+ 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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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 );
+
+ /* 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;
+ }
+ }
+
+ 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 ) */
+ {
+ 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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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 )
+ {
+ /*=======================================================================*/
+ /* 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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+UINT32 Oct6100ConfBridgeChanRemoveSer(
+ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
+ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove )
+{
+ UINT16 usBridgeIndex;
+ UINT16 usChanIndex;
+ 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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}
+
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
+
+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.
+
+\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+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;
+}