From 94f5ca620248b21b13763d4d1838c6a45e2e9165 Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Sun, 10 Jul 2011 16:10:32 +0000 Subject: xpp: A copy of oct612x in dahdi-tools Include a copy of the oct612x Octasic echo canceller interface to be used by astribank_hexload to load the echo canceller firmware to a Xorcom Astribank. git-svn-id: http://svn.asterisk.org/svn/dahdi/tools/trunk@10030 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- .../oct6100api/oct6100_api/oct6100_conf_bridge.c | 7683 ++++++++++++++++++++ 1 file changed, 7683 insertions(+) create mode 100644 xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c (limited to 'xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c') diff --git a/xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c b/xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c new file mode 100644 index 0000000..1fc539e --- /dev/null +++ b/xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c @@ -0,0 +1,7683 @@ +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +File: oct6100_conf_bridge.c + + Copyright (c) 2001-2007 Octasic Inc. + +Description: + + This file contains all functions related to a conference bridge. Procedures + needed to open/close a bridge, add/remove a participant to a conference + bridge, mute/unmute a participant, etc.. are all present in this source + file. + +This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is +free software; you can redistribute it and/or modify it under the terms of +the GNU General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later version. + +The OCT6100 GPL API is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with the OCT6100 GPL API; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + +$Octasic_Release: OCT612xAPI-01.00-PR49 $ + +$Octasic_Revision: 146 $ + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + +/***************************** INCLUDE FILES *******************************/ + +#include "octdef.h" + +#include "oct6100api/oct6100_defines.h" +#include "oct6100api/oct6100_errors.h" +#include "oct6100api/oct6100_apiud.h" + +#include "apilib/octapi_llman.h" + +#include "oct6100api/oct6100_tlv_inst.h" +#include "oct6100api/oct6100_chip_open_inst.h" +#include "oct6100api/oct6100_chip_stats_inst.h" +#include "oct6100api/oct6100_interrupts_inst.h" +#include "oct6100api/oct6100_remote_debug_inst.h" +#include "oct6100api/oct6100_debug_inst.h" +#include "oct6100api/oct6100_api_inst.h" +#include "oct6100api/oct6100_channel_inst.h" +#include "oct6100api/oct6100_mixer_inst.h" +#include "oct6100api/oct6100_conf_bridge_inst.h" + +#include "oct6100api/oct6100_interrupts_pub.h" +#include "oct6100api/oct6100_chip_open_pub.h" +#include "oct6100api/oct6100_channel_pub.h" +#include "oct6100api/oct6100_mixer_pub.h" +#include "oct6100api/oct6100_conf_bridge_pub.h" + +#include "oct6100_chip_open_priv.h" +#include "oct6100_miscellaneous_priv.h" +#include "oct6100_memory_priv.h" +#include "oct6100_tsst_priv.h" +#include "oct6100_channel_priv.h" +#include "oct6100_mixer_priv.h" +#include "oct6100_conf_bridge_priv.h" + + +/**************************** PUBLIC FUNCTIONS *****************************/ + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeOpen + +Description: This function opens a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeOpen Pointer to conference bridge open structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeOpenDef +UINT32 Oct6100ConfBridgeOpenDef( + tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) +{ + f_pConfBridgeOpen->pulConfBridgeHndl = NULL; + f_pConfBridgeOpen->fFlexibleConferencing = FALSE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeOpen +UINT32 Oct6100ConfBridgeOpen( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeOpenSer( f_pApiInstance, f_pConfBridgeOpen ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeClose + +Description: This function closes a conference bridge. A conference + bridge can only be closed if no participants are present on + the bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeClose Pointer to conference bridge close structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeCloseDef +UINT32 Oct6100ConfBridgeCloseDef( + tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) +{ + f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeClose +UINT32 Oct6100ConfBridgeClose( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure. */ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeCloseSer( f_pApiInstance, f_pConfBridgeClose ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanAdd + +Description: This function adds an echo channel (participant) to a + conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeAdd Pointer to conference bridge channel addition structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanAddDef +UINT32 Oct6100ConfBridgeChanAddDef( + tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) +{ + f_pConfBridgeAdd->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT; + f_pConfBridgeAdd->ulListenerMaskIndex = cOCT6100_INVALID_VALUE; + f_pConfBridgeAdd->ulListenerMask = 0; + f_pConfBridgeAdd->fMute = FALSE; + f_pConfBridgeAdd->ulTappedChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeChanAdd +UINT32 Oct6100ConfBridgeChanAdd( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure. */ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeChanAddSer( f_pApiInstance, f_pConfBridgeAdd ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanRemove + +Description: This function removes an echo channel (participant) from a + conference bridge. All participants can be removed from + the bridge if a special flag (fRemoveAll) is set to TRUE. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeRemove Pointer to conference bridge channel removal structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanRemoveDef +UINT32 Oct6100ConfBridgeChanRemoveDef( + tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) +{ + f_pConfBridgeRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeRemove->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeRemove->fRemoveAll = FALSE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeChanRemove +UINT32 Oct6100ConfBridgeChanRemove( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, f_pConfBridgeRemove ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanMute + +Description: This function mutes a participant present on a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeMute Pointer to conference bridge channel mute structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanMuteDef +UINT32 Oct6100ConfBridgeChanMuteDef( + tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) +{ + f_pConfBridgeMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeChanMute +UINT32 Oct6100ConfBridgeChanMute( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure. */ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeChanMuteSer( f_pApiInstance, f_pConfBridgeMute ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanUnMute + +Description: This function unmutes a channel on a bridge. The other member + of the conference will start to hear this participant again. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanUnMuteDef +UINT32 Oct6100ConfBridgeChanUnMuteDef( + tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) +{ + f_pConfBridgeUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + +#if !SKIP_Oct6100ConfBridgeChanUnMute +UINT32 Oct6100ConfBridgeChanUnMute( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeChanUnMuteSer( f_pApiInstance, f_pConfBridgeUnMute ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeDominantSpeakerSet + +Description: This function sets a participant present on a conference + bridge as the dominant speaker. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. + +f_pConfBridgeDominant Pointer to conference bridge dominant speaker + structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetDef +UINT32 Oct6100ConfBridgeDominantSpeakerSetDef( + tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) +{ + f_pConfBridgeDominantSpeaker->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeDominantSpeaker->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeDominantSpeakerSet +UINT32 Oct6100ConfBridgeDominantSpeakerSet( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure.*/ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeDominantSpeakerSetSer( f_pApiInstance, f_pConfBridgeDominantSpeaker ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeMaskChange + +Description: This function changes the mask of a flexible bridge participant. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. + +f_pConfBridgeMaskChange Pointer to conference bridge change of mask + structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeMaskChangeDef +UINT32 Oct6100ConfBridgeMaskChangeDef( + tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) +{ + f_pConfBridgeMaskChange->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeMaskChange->ulNewListenerMask = 0x0; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeMaskChange +UINT32 Oct6100ConfBridgeMaskChange( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure. */ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeMaskChangeSer( f_pApiInstance, f_pConfBridgeMaskChange ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeGetStats + +Description: This function returns the stats for a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeStats Pointer to conference bridge channel stats structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeGetStatsDef +UINT32 Oct6100ConfBridgeGetStatsDef( + tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) +{ + f_pConfBridgeStats->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + f_pConfBridgeStats->ulNumChannels = cOCT6100_INVALID_STAT; + f_pConfBridgeStats->ulNumTappedChannels = cOCT6100_INVALID_STAT; + f_pConfBridgeStats->fFlexibleConferencing = cOCT6100_INVALID_STAT; + + return cOCT6100_ERR_OK; +} +#endif + + +#if !SKIP_Oct6100ConfBridgeGetStats +UINT32 Oct6100ConfBridgeGetStats( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) +{ + tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; + tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; + UINT32 ulSerRes = cOCT6100_ERR_OK; + UINT32 ulFncRes = cOCT6100_ERR_OK; + + /* Set the process context of the serialize structure. */ + SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; + ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; + + /* Seize all list semaphores needed by this function. */ + SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; + ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); + if ( ulSerRes == cOCT6100_ERR_OK ) + { + /* Call the serialized function. */ + ulFncRes = Oct6100ConfBridgeGetStatsSer( f_pApiInstance, f_pConfBridgeStats ); + } + else + { + return ulSerRes; + } + + /* Release the seized semaphores. */ + ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; + ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); + + /* If an error occured then return the error code. */ + if ( ulSerRes != cOCT6100_ERR_OK ) + return ulSerRes; + if ( ulFncRes != cOCT6100_ERR_OK ) + return ulFncRes; + + return cOCT6100_ERR_OK; +} +#endif + +/**************************** PRIVATE FUNCTIONS ****************************/ + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiGetConfBridgeSwSizes + +Description: Gets the sizes of all portions of the API instance pertinent + to the management of conference bridges. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pOpenChip Pointer to chip configuration struct. +f_pInstSizes Pointer to struct containing instance sizes. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiGetConfBridgeSwSizes +UINT32 Oct6100ApiGetConfBridgeSwSizes( + IN tPOCT6100_CHIP_OPEN f_pOpenChip, + OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) +{ + UINT32 ulTempVar; + UINT32 ulResult; + + /* Calculate memory needed for conference bridge list. */ + if ( f_pOpenChip->ulMaxConfBridges == 0 && f_pOpenChip->fEnableChannelRecording == TRUE ) + f_pOpenChip->ulMaxConfBridges = 1; + f_pInstSizes->ulConfBridgeList = f_pOpenChip->ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE ); + + /* Calculate memory needed for conference bridge allocation software. */ + if ( f_pOpenChip->ulMaxConfBridges > 0 ) + { + /* Get size of bridge allocation memory */ + ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxConfBridges, &f_pInstSizes->ulConfBridgeAlloc ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_1C; + + /* Check if the user wants to build flexible conference bridges. */ + if ( f_pOpenChip->ulMaxFlexibleConfParticipants > 0 ) + { + /* Allocate the lowest quantity according to what the user requested. */ + if ( f_pOpenChip->ulMaxFlexibleConfParticipants < ( f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) ) + f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxFlexibleConfParticipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); + else + { + f_pOpenChip->ulMaxFlexibleConfParticipants = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; + f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); + } + + /* Get size of flexible conferencing participants allocation memory */ + ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxFlexibleConfParticipants, &f_pInstSizes->ulFlexConfParticipantsAlloc ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_1C; + } + else + { + f_pInstSizes->ulFlexConfParticipantsList = 0; + f_pInstSizes->ulFlexConfParticipantsAlloc = 0; + } + } + else + { + f_pInstSizes->ulMixerEventList = 0; + f_pInstSizes->ulMixerEventAlloc = 0; + f_pInstSizes->ulConfBridgeAlloc = 0; + + /* Make sure flexible conferencing is not used. */ + f_pInstSizes->ulFlexConfParticipantsList = 0; + f_pInstSizes->ulFlexConfParticipantsAlloc = 0; + } + + /* Calculate memory needed for list and allocation software serialization. */ + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeList, ulTempVar ) + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeAlloc, ulTempVar ) + + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsList, ulTempVar ) + mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsAlloc, ulTempVar ) + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiConfBridgeSwInit + +Description: Initializes all elements of the instance structure associated + to conference bridges. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiConfBridgeSwInit +UINT32 Oct6100ApiConfBridgeSwInit( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CONF_BRIDGE pConfBridgeList; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pFlexConfParticipantList; + PVOID pFlexConfPartipantsAlloc; + UINT32 ulMaxFlexConfParicipants; + PVOID pConfBridgeAlloc; + UINT32 ulMaxConfBridges; + UINT32 ulResult; + + /* Get local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Get the maximum number of conference bridges. */ + ulMaxConfBridges = pSharedInfo->ChipConfig.usMaxConfBridges; + + /*===================================================================*/ + /* Set all entries in the conference bridge list to unused. */ + + mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pConfBridgeList ); + + /* Initialize the conference bridge allocation software to "all free". */ + if ( ulMaxConfBridges > 0 ) + { + /* Clear the bridge memory */ + Oct6100UserMemSet( pConfBridgeList, 0x00, ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE )); + + mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pConfBridgeAlloc ) + + ulResult = OctapiLlmAllocInit( &pConfBridgeAlloc, ulMaxConfBridges ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_1E; + } + /*===================================================================*/ + + + /*===================================================================*/ + /* Set all entries in the flexible conferencing participant list to unused. */ + + /* Get the maximum number of flexible conferencing participants. */ + ulMaxFlexConfParicipants = pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pFlexConfParticipantList ); + + /* Initialize the flexible conferencing allocation software. */ + if ( ulMaxFlexConfParicipants > 0 ) + { + UINT32 i, ulEventIndex; + + /* Clear the participants memory */ + Oct6100UserMemSet( pFlexConfParticipantList, 0x00, ulMaxFlexConfParicipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT )); + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pFlexConfPartipantsAlloc ) + + ulResult = OctapiLlmAllocInit( &pFlexConfPartipantsAlloc, ulMaxFlexConfParicipants ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_1E; + + /* Initialize the conferencing indexes. */ + for ( i = 0; i < ulMaxFlexConfParicipants; i ++ ) + { + for ( ulEventIndex = 0; ulEventIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulEventIndex ++ ) + pFlexConfParticipantList[ i ].ausLoadOrAccumulateEventIndex[ ulEventIndex ] = cOCT6100_INVALID_INDEX; + } + } + + /*===================================================================*/ + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeOpenSer + +Description: Open a conference bridge. Note that no chip resources are + allocated until a channel is added to the bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeOpen Pointer to conference bridge configuration structure. + The handle identifying the conference bridge in all + future function calls is returned in this structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeOpenSer +UINT32 Oct6100ConfBridgeOpenSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) +{ + UINT16 usBridgeIndex; + UINT32 ulResult; + + /* Check the user's configuration of the conference bridge for errors. */ + ulResult = Oct6100ApiCheckBridgeParams( f_pApiInstance, f_pConfBridgeOpen ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the conference bridge. */ + ulResult = Oct6100ApiReserveBridgeResources( f_pApiInstance, &usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new conference bridge's entry in the conference bridge list. */ + ulResult = Oct6100ApiUpdateBridgeEntry( f_pApiInstance, f_pConfBridgeOpen, usBridgeIndex); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeParams + +Description: Checks the user's conference bridge open configuration for errors. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeOpen Pointer to conference bridge configuration structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeParams +UINT32 Oct6100ApiCheckBridgeParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) +{ + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeOpen->pulConfBridgeHndl == NULL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencing == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_CONF_BRIDGE; + + if ( f_pConfBridgeOpen->fFlexibleConferencing != FALSE + && f_pConfBridgeOpen->fFlexibleConferencing != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBridgeResources + +Description: Reserves all resources needed for the new conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pusBridgeIndex Allocated entry in the API conference bridge list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReserveBridgeResources +UINT32 Oct6100ApiReserveBridgeResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusBridgeIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Reserve an entry in the conference bridge list. */ + ulResult = Oct6100ApiReserveBridgeEntry( f_pApiInstance, f_pusBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBridgeEntry + +Description: Updates the new conference bridge's entry in the conference + bridge list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep + the present state of the chip and all its resources. + +f_pConfBridgeOpen Pointer to conference bridge configuration structure. +f_usBridgeIndex Allocated entry in API conference bridge list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiUpdateBridgeEntry +UINT32 Oct6100ApiUpdateBridgeEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen, + IN UINT16 f_usBridgeIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; + + /*================================================================================*/ + /* Obtain a pointer to the new conference bridge's list entry. */ + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ) + + /* No clients are currently connected to the bridge. */ + pBridgeEntry->usNumClients = 0; + /* Nobody is tapped for now. */ + pBridgeEntry->usNumTappedClients = 0; + pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; + + pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; + + pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; + + /* Now update the bridge pointer. */ + if ( f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened == 0 ) + { + pBridgeEntry->usNextBridgePtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX; + + /* Set the global first bridge to this bridge. */ + f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex; + } + else /* Insert this bridge at the head of the bridge list.*/ + { + if ( f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_FATAL_22; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge ) + + if ( pTempBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_FATAL_23; + + /* Modify the old first entry. */ + pTempBridgeEntry->usPrevBridgePtr = f_usBridgeIndex; + + /* Modify current pointer. */ + pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usNextBridgePtr = f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge; + + /* Set the new first bridge of the list. */ + f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex; + } + + /* Form handle returned to user. */ + *f_pConfBridgeOpen->pulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBridgeIndex; + + /* Remember whether or not we are a flexible conference bridge. */ + pBridgeEntry->fFlexibleConferencing = (UINT8)( f_pConfBridgeOpen->fFlexibleConferencing & 0xFF ); + + /* Finally, mark the conference bridge as opened. */ + pBridgeEntry->fReserved = TRUE; + + /* Increment the number of conference bridge opened. */ + f_pApiInstance->pSharedInfo->ChipStats.usNumberConfBridges++; + f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened++; + + /*================================================================================*/ + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeCloseSer + +Description: Closes a conference bridge. Note that no client must be present + on the bridge for the bridge to be closed. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeClose Pointer to conference bridge close structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeCloseSer +UINT32 Oct6100ConfBridgeCloseSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) +{ + UINT16 usBridgeIndex; + UINT32 ulResult; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertBridgeParams( f_pApiInstance, f_pConfBridgeClose, &usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the conference bridge. */ + ulResult = Oct6100ApiReleaseBridgeResources( f_pApiInstance, usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Invalidate the handle. */ + f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertBridgeParams + +Description: Checks the user's conference bridge close configuration for errors. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeClose Pointer to conference bridge close structure. +f_pusBridgeIndex Pointer to API instance conference bridge index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiAssertBridgeParams +UINT32 Oct6100ApiAssertBridgeParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose, + OUT PUINT16 f_pusBridgeIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + UINT32 ulEntryOpenCnt; + + /* Check the provided handle. */ + if ( (f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusBridgeIndex = (UINT16)( f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeClose->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( pBridgeEntry->usNumClients != 0 ) + return cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES; + if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBridgeResources + +Description: Release all resources reserved for the conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usBridgeIndex Allocated external memory block for the conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReleaseBridgeResources +UINT32 Oct6100ApiReleaseBridgeResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; + UINT32 ulResult; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Release the entry from the conference bridge list. */ + ulResult = Oct6100ApiReleaseBridgeEntry( f_pApiInstance, f_usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_24; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + + /* Remove the bridge entry from the bridge list. */ + if ( pSharedInfo->MiscVars.usNumBridgesOpened == 1 ) + { + /* This bridge was the only one opened. */ + pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX; + } + else if ( pSharedInfo->MiscVars.usNumBridgesOpened > 1 ) + { + /* There are more then one bridge open, must update the list. */ + if ( pBridgeEntry->usPrevBridgePtr != cOCT6100_INVALID_INDEX ) + { + /* There is a valid entry before this bridge, let's update this entry. */ + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usPrevBridgePtr ); + + pTempBridgeEntry->usNextBridgePtr = pBridgeEntry->usNextBridgePtr; + } + + if ( pBridgeEntry->usNextBridgePtr != cOCT6100_INVALID_INDEX ) + { + /* There is a valid entry after this bridge, let's update this entry. */ + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usNextBridgePtr ); + + pTempBridgeEntry->usPrevBridgePtr = pBridgeEntry->usPrevBridgePtr; + } + + if ( pSharedInfo->MiscVars.usFirstBridge == f_usBridgeIndex ) + { + /* This entry was the first of the list, make the next one be the first now. */ + pSharedInfo->MiscVars.usFirstBridge = pBridgeEntry->usNextBridgePtr; + } + } + else + { + /* Variable has become out of sync. */ + return cOCT6100_ERR_FATAL_25; + } + + /*=============================================================*/ + /* Update the conference bridge's list entry. */ + + /* Mark the bridge as closed. */ + pBridgeEntry->fFlexibleConferencing = FALSE; + pBridgeEntry->fReserved = FALSE; + pBridgeEntry->byEntryOpenCnt++; + + /* Decrement the number of conference bridges opened. */ + pSharedInfo->MiscVars.usNumBridgesOpened--; + pSharedInfo->ChipStats.usNumberConfBridges--; + + /*=============================================================*/ + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanAddSer + +Description: Adds an echo channel (participant) to a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeAdd Pointer to conference bridge channel add structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanAddSer +UINT32 Oct6100ConfBridgeChanAddSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) +{ + UINT16 usBridgeIndex; + UINT16 usChanIndex; + UINT16 usLoadEventIndex; + UINT16 usSubStoreEventIndex; + UINT16 usCopyEventIndex; + UINT32 ulInputPort; + UINT8 fFlexibleConfBridge; + UINT32 ulListenerMaskIndex; + UINT32 ulListenerMask; + UINT16 usTapChanIndex; + UINT16 usTapBridgeIndex; + UINT8 fMute; + UINT8 fTap; + UINT32 ulResult; + + /* Check the validity of the channel and conference bridge given. */ + ulResult = Oct6100ApiCheckBridgeAddParams( + f_pApiInstance, + f_pConfBridgeAdd, + &usBridgeIndex, + &usChanIndex, + &fMute, + &ulInputPort, + &fFlexibleConfBridge, + &ulListenerMaskIndex, + &ulListenerMask, + &fTap, + &usTapChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the conference bridge. */ + ulResult = Oct6100ApiReserveBridgeAddResources( + f_pApiInstance, + usBridgeIndex, + usChanIndex, + ulInputPort, + fFlexibleConfBridge, + ulListenerMaskIndex, + ulListenerMask, + fTap, + &usLoadEventIndex, + &usSubStoreEventIndex, + &usCopyEventIndex, + &usTapBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the conference bridge. */ + ulResult = Oct6100ApiBridgeEventAdd( + f_pApiInstance, + usBridgeIndex, + usChanIndex, + fFlexibleConfBridge, + usLoadEventIndex, + usSubStoreEventIndex, + usCopyEventIndex, + ulInputPort, + fMute, + ulListenerMaskIndex, + ulListenerMask, + fTap, + usTapBridgeIndex, + usTapChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeAddParams + +Description: Check the validity of the channel and conference bridge given. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pConfBridgeAdd Pointer to conference bridge channenl add structure. +f_pusBridgeIndex Extracted bridge index where this channel should be + added. +f_pusChannelIndex Extracted channel index related to the channel handle + to be added to the bridge. +f_pfMute Whether to mute this channel in the bridge or not. +f_pulInputPort Input port where the channel signal should be + copied from. +f_pfFlexibleConfBridge If this is a flexible conference bridge. +f_pulListenerMaskIndex Index of the listener in this flexible conference bridge. +f_pulListenerMask Mask of listeners in this flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeAddParams +UINT32 Oct6100ApiCheckBridgeAddParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd, + OUT PUINT16 f_pusBridgeIndex, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT8 f_pfMute, + OUT PUINT32 f_pulInputPort, + OUT PUINT8 f_pfFlexibleConfBridge, + OUT PUINT32 f_pulListenerMaskIndex, + OUT PUINT32 f_pulListenerMask, + OUT PUINT8 f_pfTap, + OUT PUINT16 f_pusTapChannelIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulEntryOpenCnt; + UINT8 byTapChannelLaw; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 1 && + f_pApiInstance->pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeAdd->ulConfBridgeHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + if ( f_pConfBridgeAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; + + if( f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_SOUT + && f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_RIN ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_INPUT_PORT; + + if ( f_pConfBridgeAdd->fMute != TRUE && f_pConfBridgeAdd->fMute != FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MUTE; + + /*=====================================================================*/ + /* Check the conference bridge handle. */ + + if ( (f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusBridgeIndex = (UINT16)( f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeAdd->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* When we a flexible conference bridge, more things need to be checked. */ + if ( pBridgeEntry->fFlexibleConferencing == TRUE ) + { + /* Check if flexible conferencing has been activated. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_DISABLED; + + /* Check the number of clients on the bridge. */ + if ( pBridgeEntry->usNumClients >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_PARTICIPANT_CNT; + + /* Check if the listener index in a flexible bridge is valid. */ + if ( f_pConfBridgeAdd->ulListenerMaskIndex == cOCT6100_INVALID_VALUE + || f_pConfBridgeAdd->ulListenerMaskIndex >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_MASK_INDEX; + } + + if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) + { + if ( pBridgeEntry->fFlexibleConferencing == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_TAP_NOT_SUPPORTED; + } + + /*=====================================================================*/ + + + /*=====================================================================*/ + /* Check the channel handle. */ + + if ( (f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + if ( pEchoChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ALREADY_ON_BRIDGE; + if ( pEchoChanEntry->fBiDirChannel == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_BIDIR; + /* Law conversion is not allowed on a conference bridge. */ + if ( ( pEchoChanEntry->TdmConfig.usRinTimeslot != cOCT6100_UNASSIGNED ) + && ( pEchoChanEntry->TdmConfig.usRoutTimeslot != cOCT6100_UNASSIGNED ) ) + { + if ( pEchoChanEntry->TdmConfig.byRinPcmLaw != pEchoChanEntry->TdmConfig.byRoutPcmLaw ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION; + } + if ( ( pEchoChanEntry->TdmConfig.usSinTimeslot != cOCT6100_UNASSIGNED ) + && ( pEchoChanEntry->TdmConfig.usSoutTimeslot != cOCT6100_UNASSIGNED ) ) + { + if ( pEchoChanEntry->TdmConfig.bySinPcmLaw != pEchoChanEntry->TdmConfig.bySoutPcmLaw ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION; + } + if ( pEchoChanEntry->fRinRoutCodecActive == TRUE || pEchoChanEntry->fSinSoutCodecActive == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_CODEC_ACTIVE; + if ( pEchoChanEntry->fEnableExtToneDetection == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_EXT_TONE_ENABLED; + if ( pEchoChanEntry->usCopyEventCnt != 0x0 ) + return cOCT6100_ERR_CONF_BRIDGE_COPY_EVENTS; + + /* If the bridge is flexible, few more things need to be checked. */ + if ( pBridgeEntry->fFlexibleConferencing == TRUE ) + { + tPOCT6100_SHARED_INFO pSharedInfo; + UINT16 usChannelIndex; + UINT32 ulResult = cOCT6100_ERR_OK; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Check if the listener index has been used by another channel in the specified bridge. */ + for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != ( *f_pusChannelIndex ) ) && ( pEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pEchoChanEntry->usBridgeIndex == ( *f_pusBridgeIndex ) ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if this participant has the same listener index. */ + if ( f_pConfBridgeAdd->ulListenerMaskIndex == pCurrentParticipant->ulListenerMaskIndex ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_INDEX_USED; + } + } + } + } + + if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) + { + /* For internal logic, make sure the mute flag is set to false. */ + f_pConfBridgeAdd->fMute = FALSE; + + /* Force input port to Sout for logic below. */ + f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT; + + /* Keep law to check for conversion. */ + /* Check if the same law. */ + byTapChannelLaw = pEchoChanEntry->TdmConfig.bySoutPcmLaw; + + /* Check the tap handle. */ + if ( (f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; + + *f_pusTapChannelIndex = (UINT16)( f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusTapChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusTapChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeAdd->ulTappedChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; + if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_BRIDGE; + if ( pEchoChanEntry->usBridgeIndex != *f_pusBridgeIndex ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_SAME_BRIDGE; + + /* We can only tap a channel added on the Sout port. */ + if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_TAP_SOUT_ONLY; + + /* Check if already tapped. */ + if ( pEchoChanEntry->fBeingTapped == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_ALREADY_TAPPED; + } + + /*=====================================================================*/ + + /* Return the tap flag. */ + if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) + { + *f_pfTap = TRUE; + } + else + { + *f_pfTap = FALSE; + } + + /* Return the mute config specified. */ + *f_pfMute = (UINT8)( f_pConfBridgeAdd->fMute & 0xFF ); + + /* Return the input port specified. */ + *f_pulInputPort = f_pConfBridgeAdd->ulInputPort; + + /* Return whether we are in the flexible conference bridge case. */ + *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; + + /* Return the listener mask index as specified. */ + *f_pulListenerMaskIndex = f_pConfBridgeAdd->ulListenerMaskIndex; + + /* Return the listener mask as specified. */ + *f_pulListenerMask = f_pConfBridgeAdd->ulListenerMask; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBridgeAddResources + +Description: Reserves all resources needed for the addition of a channel to + the conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_usBridgeIndex Bridge index of the bridge where this channel is added. +f_usChanIndex Channel index of the channel to be added to the bridge. +f_ulInputPort Input port where to copy samples from. +f_fFlexibleConfBridge If this is a flexible conference bridge. +f_ulListenerMaskIndex Index of the listener in this flexible conference bridge. +f_ulListenerMask Mask of listeners in this flexible conference bridge. +f_pusLoadEventIndex Load event index within the API's list of mixer event. +f_pusSubStoreEventIndex Sub-Store event index within the API's list of mixer event. +f_pusCopyEventIndex Copy event index within the API's list of mixer event. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReserveBridgeAddResources +UINT32 Oct6100ApiReserveBridgeAddResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT32 f_ulInputPort, + IN UINT8 f_fFlexibleConfBridge, + IN UINT32 f_ulListenerMaskIndex, + IN UINT32 f_ulListenerMask, + IN UINT8 f_fTap, + OUT PUINT16 f_pusLoadEventIndex, + OUT PUINT16 f_pusSubStoreEventIndex, + OUT PUINT16 f_pusCopyEventIndex, + OUT PUINT16 f_pusTapBridgeIndex ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + UINT32 ulResult; + UINT32 ulTempVar; + UINT16 usChannelIndex; + BOOL fLoadEventReserved = FALSE; + BOOL fStoreEventReserved = FALSE; + BOOL fCopyEventReserved = FALSE; + BOOL fExtraSinTsiReserved = FALSE; + BOOL fExtraRinTsiReserved = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + /* Resources must be reserved according to the type of bridge we are adding to. */ + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; + + /*========================================================================*/ + /* If we are in the flexible conferencing case, things are a little */ + /* different. We create a mixer for every participant instead of the */ + /* usual same mixer for everyone. For example, if we have 3 participants */ + /* of type client - agent - coach, we build the mixers as follows: */ + /* */ + /* Client: - Load Agent */ + /* - Store */ + /* */ + /* Agent: - Load Client */ + /* - Accumulate Coach */ + /* - Store */ + /* */ + /* Coach: - Load Client */ + /* - Accumulate Agent */ + /* - Store */ + /* */ + /*========================================================================*/ + + /* First reserve a flexible conferencing participant entry. */ + ulResult = Oct6100ApiReserveFlexConfParticipantEntry( f_pApiInstance, &pChanEntry->usFlexConfParticipantIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pChanEntry->usFlexConfParticipantIndex ); + + /* Reserve an entry for the store event in the mixer memory. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + /* If using the SOUT port, we must copy this entry */ + if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + /* Reserve an entry for the copy event in the Mixer memory. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fCopyEventReserved = TRUE; + + /* Reserve a SIN copy entry if none were reserved before.*/ + if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) + { + /* Reserve an entry for the extra tsi chariot memory. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &pChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fExtraSinTsiReserved = TRUE; + } + } + } + else /* if( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + /* Reserve a RIN copy entry if none were reserved before.*/ + if ( pChanEntry->usExtraRinTsiMemIndex == cOCT6100_INVALID_INDEX ) + { + /* Reserve an entry for the extra tsi chariot memory. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &pChanEntry->usExtraRinTsiMemIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + fExtraRinTsiReserved = TRUE; + } + } + + /* Must travel all clients of this conference and reserve a load or accumulate event for */ + /* all participants which can hear us. */ + + /* Search through the list of API channel entry for the ones on to this bridge.*/ + for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can hear this participant. */ + if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) + { + /* Must reserve a load or accumulate entry mixer event here! */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Most probably, the hardware is out of mixer events. */ + break; + } + } + + /* Check if this participant can hear us. */ + if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) + { + /* Must reserve a load or accumulate entry mixer event here! */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Most probably, the hardware is out of mixer events. */ + break; + } + } + } + } + } + + /* If an error is returned, make sure everything is cleaned up properly. */ + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Release the flexible conferencing participant entry. */ + ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; + + /* Release the substore event in the mixer memory. */ + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + if ( fCopyEventReserved == TRUE ) + { + /* Release the copy event in the mixer memory. */ + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fExtraSinTsiReserved == TRUE ) + { + /* Release the extra Sin TSI in TSI memory. */ + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + + if ( fExtraRinTsiReserved == TRUE ) + { + /* Release the extra Rin TSI in TSI memory. */ + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraRinTsiMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can hear this participant. */ + if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) + { + /* If the load or event entry in the mixer memory was reserved. */ + if ( pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) + { + /* Must release the load or accumulate entry mixer event. */ + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + + /* Check this participant can hear us. */ + if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) + { + /* If the load or event entry in the mixer memory was reserved. */ + if ( pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) + { + /* Must release the load or accumulate entry mixer event. */ + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + } + } + } + + return ulResult; + } + } + else /* if ( ulResult != cOCT6100_ERR_OK ) */ + { + ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; + + /* Return the error code to the user. The mixer event allocation failed. */ + return ulResult; + } + + /*=======================================================================*/ + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + /*=======================================================================*/ + /* Normal conferencing. */ + + /* Reserve an entry for the load event in the mixer memory. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusLoadEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fLoadEventReserved = TRUE; + /* Reserve an entry for the substract and store event in the mixer memory. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fStoreEventReserved = TRUE; + + /* If using the SOUT port, we must copy this entry */ + if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + /* Reserve an entry for the copy event in the mixer memory. */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex ); + if ( ulResult == cOCT6100_ERR_OK ) + { + fCopyEventReserved = TRUE; + + /* Reserve a SIN copy entry if none were reserved before. */ + if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) + { + /* Reserve an entry for the extra tsi chariot memory. */ + ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, + &pChanEntry->usExtraSinTsiMemIndex ); + + if ( ulResult == cOCT6100_ERR_OK ) + fExtraSinTsiReserved = TRUE; + } + } + } + } + } + + if ( ( ulResult == cOCT6100_ERR_OK ) && ( f_fTap == TRUE ) ) + { + /* Reserve a "tap" bridge. */ + tOCT6100_CONF_BRIDGE_OPEN ConfBridgeOpen; + UINT32 ulTapBridgeHndl = 0; + + Oct6100ConfBridgeOpenDef( &ConfBridgeOpen ); + + ConfBridgeOpen.pulConfBridgeHndl = &ulTapBridgeHndl; + + ulResult = Oct6100ConfBridgeOpenSer( f_pApiInstance, &ConfBridgeOpen ); + + *f_pusTapBridgeIndex = (UINT16)( ulTapBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + } + + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( fLoadEventReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusLoadEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fStoreEventReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fCopyEventReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + + if ( fExtraSinTsiReserved == TRUE ) + { + ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + + return ulResult; + } + + /*=======================================================================*/ + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeEventAdd + +Description: Add the event into the global event list of the chip and update + the bridge and channel structures. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. +f_usBridgeIndex Index of the current bridge in the API list. +f_usChanIndex Index of the current channel in the API list. +f_fFlexibleConfBridge If this is a flexible conference bridge. +f_usLoadEventIndex Allocated entry for the Load event of the + channel. +f_usSubStoreEventIndex Allocated entry for the substract and store + event of the channel. +f_usCopyEventIndex Allocated entry for the copy event of the + channel. +f_ulInputPort Input port where to copy samples from. +f_fMute Mute flag indicating if the channel is added in + a mute state. +f_ulListenerMaskIndex Index of the listener in this flexible conference bridge. +f_ulListenerMask Mask of listeners in this flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeEventAdd +UINT32 Oct6100ApiBridgeEventAdd( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT8 f_fFlexibleConfBridge, + IN UINT16 f_usLoadEventIndex, + IN UINT16 f_usSubStoreEventIndex, + IN UINT16 f_usCopyEventIndex, + IN UINT32 f_ulInputPort, + IN UINT8 f_fMute, + IN UINT32 f_ulListenerMaskIndex, + IN UINT32 f_ulListenerMask, + IN UINT8 f_fTap, + IN UINT16 f_usTapBridgeIndex, + IN UINT16 f_usTapChanIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pTempEntry; + + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_API_CHANNEL pTapEchoChanEntry = NULL; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + + UINT32 ulResult; + UINT16 usChannelIndex; + UINT16 usLastSubStoreEventIndex; + UINT16 usLastLoadEventIndex; + + BOOL fAddSinCopy = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Get the bridge and channel entries of interest. */ + if ( f_fTap == FALSE ) + { + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + } + else + { + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usTapBridgeIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapEchoChanEntry, f_usTapChanIndex ); + } + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Search through the list of API channel entry for the ones onto this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can hear this participant. */ + if ( ( pTempEchoChanEntry->fMute == FALSE ) && ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) + { + /* First create/update the current channel's mixer. */ + ulResult = Oct6100ApiBridgeAddParticipantToChannel( + f_pApiInstance, + f_usBridgeIndex, + usChannelIndex, + f_usChanIndex, + pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ], + f_usSubStoreEventIndex, + f_usCopyEventIndex, + pCurrentParticipant->ulInputPort, + f_ulInputPort ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Check if this participant can hear us. */ + if ( ( f_fMute == FALSE ) && ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) ) + { + /* Then create/update this channel's mixer. */ + ulResult = Oct6100ApiBridgeAddParticipantToChannel( + f_pApiInstance, + f_usBridgeIndex, + f_usChanIndex, + usChannelIndex, + pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ], + pTempEchoChanEntry->usSubStoreEventIndex, + pTempEchoChanEntry->usSinCopyEventIndex, + f_ulInputPort, + pCurrentParticipant->ulInputPort ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if the Rin silence event can be cleared now that the */ + /* channel has been added to a conference. */ + if ( ( pCurrentParticipant->fFlexibleMixerCreated == TRUE ) + && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) + { + /* Remove the event from the list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pTempEchoChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + } + } + } + } + + /* Check if the mixer for the destination channel has been created. */ + if ( pNewParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Save store event index that might be used for next channel added. */ + pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex; + } + else + { + /* Check if the Rin silence event can be cleared now that the */ + /* channel has been added to a conference. */ + if ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pEchoChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + } + + pNewParticipant->ulListenerMaskIndex = f_ulListenerMaskIndex; + pNewParticipant->ulListenerMask = f_ulListenerMask; + + /* Remember this channel's input port. */ + pNewParticipant->ulInputPort = f_ulInputPort; + + /*=======================================================================*/ + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ + if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) ) + { + if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pEchoChanEntry->usSinTsstIndex, + pEchoChanEntry->usExtraSinTsiMemIndex, + pEchoChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ + if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usExtraSinTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); + + /*=======================================================================*/ + /* Program the Load event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + if ( ( f_fMute == FALSE ) || ( f_fTap == TRUE ) ) + { + if ( pBridgeEntry->usLoadIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + + /* Set the event type. */ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + + if ( f_fTap == TRUE ) + return cOCT6100_ERR_FATAL_D1; + } + else /* pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX */ + { + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Modify the bridge entry to show store the new load index.*/ + pBridgeEntry->usLoadIndex = f_usLoadEventIndex; + + /* Set the event type.*/ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + } + + /* Select the TSI memory index according to the source port. */ + if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + if ( f_fTap == FALSE ) + { + WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; + } + else + { + tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; + UINT16 usTempWriteData; + UINT32 ulTempWriteAddress; + + /* Save temp write data before trying to clear the Rin TSST. */ + usTempWriteData = WriteParams.usWriteData; + ulTempWriteAddress = WriteParams.ulWriteAddress; + + /* Clear the Rin TSST if used. */ + if ( pTapEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + /* Deactivate the TSST entry.*/ + WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pTapEchoChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = 0x0000; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Reassign write data that might have been cleared by write above. */ + WriteParams.usWriteData = usTempWriteData; + WriteParams.ulWriteAddress = ulTempWriteAddress; + WriteParams.usWriteData |= pTapEchoChanEntry->usRinRoutTsiMemIndex; + + /* Remember that this channel is being tapped by us. */ + pTapEchoChanEntry->fBeingTapped = TRUE; + pTapEchoChanEntry->usTapChanIndex = f_usChanIndex; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex ); + + pTempBridgeEntry->usNumTappedClients++; + } + } + else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; + } + } + else /* f_fMute == TRUE */ + { + /* Do not load the sample if the channel is muted. */ + if ( pBridgeEntry->usNumClients == 0 ) + { + /* If the participant to be added is muted, and it would cause the conference to */ + /* be completely muted, load the silence TSI. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; + WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ + + /* We know for sure that the load of the bridge will be the silence one. */ + pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex; + } + else + { + /* Do nothing! */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + } + + /* Set the event type. */ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Program the Substract and store event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + if ( ( f_fMute == FALSE ) && ( f_fTap == FALSE ) ) + { + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; + /* Select the TSI memory index and PCM law according to the source port. */ + if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; + } + else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; + } + + /* Set the event type. */ + pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; + } + else /* f_fMute == TRUE */ + { + /* Do not substore the sample if the channel is muted. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; + + /* Select the PCM law according to the source port. */ + if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + } + else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + } + /* Set the event type. */ + pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Program the Copy event - if using the SOUT port */ + if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex; + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set add copy event flag. */ + fAddSinCopy = TRUE; + + /* For sure. */ + pEchoChanEntry->fCopyEventCreated = TRUE; + } + else if ( f_fTap == TRUE ) + { + /* Accumulate the tapped channel's voice instead of building a copy event. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + WriteParams.usWriteData |= pTapEchoChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Link to next operation. */ + WriteParams.ulWriteAddress += 4; + WriteParams.usWriteData = f_usSubStoreEventIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software model. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, f_usCopyEventIndex ); + + pTempEntry->usSourceChanIndex = f_usTapChanIndex; + pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + pTempEntry->usNextEventPtr = f_usSubStoreEventIndex; + pTempEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX; + pTempEntry->fReserved = TRUE; + } + /*=======================================================================*/ + + /*=======================================================================*/ + /* Now insert the event into the list.*/ + if ( pBridgeEntry->usNumClients == 0 ) + { + /* This is the first entry for this bridge. Insert the two events at the head + of the list just after the last sub-store event.*/ + if ( f_fTap == FALSE ) + { + ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usLastSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) + { + if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; + } + else + { + usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + } + else + { + return cOCT6100_ERR_FATAL_26; + } + } + } + else + { + if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; + } + else + { + usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + } + + /* An Entry was found, now, modify it's value.*/ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); + + /* Set the Sub-Store event first.*/ + pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; + pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; + + /*=======================================================================*/ + /* Program the Sub-Store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Set the load/accumulate event now.*/ + if ( f_fTap == FALSE ) + { + pLoadEventEntry->usNextEventPtr = f_usSubStoreEventIndex; + } + else + { + /* This is a little tricky, we use the copy event index for accumulating the tapped channel's voice. */ + pLoadEventEntry->usNextEventPtr = f_usCopyEventIndex; + } + + /*=======================================================================*/ + /* Program the load/accumulate event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Now modify the previous last Sub Store event from another bridge. */ + pTempEntry->usNextEventPtr = f_usLoadEventIndex; + + /*=======================================================================*/ + /* Modify the last node of the other bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Set the event pointer info in the bridge stucture. */ + pBridgeEntry->usFirstLoadEventPtr = f_usLoadEventIndex; + pBridgeEntry->usFirstSubStoreEventPtr = f_usSubStoreEventIndex; + pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex; + + /* Update the global mixer pointers. */ + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX ) + { + /* This bridge is the first to generate mixer event. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex; + pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; + } + else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) + { + /* The two entries were added at the end of the bridge section, */ + /* change only the last pointer. */ + pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; + } + else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE || + usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) + { + /* The two entries were added at the start of the bridge section, */ + /* change only the first pointer. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex; + } + } + else /* pBridgeEntry->usNumClients != 0 */ + { + /* For sanity. */ + if ( f_fTap == TRUE ) + return cOCT6100_ERR_FATAL_D2; + + /*=======================================================================*/ + /* Program the Load event. */ + + /* Now find the last load entry of this bridge. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, pBridgeEntry->usFirstSubStoreEventPtr, 0, &usLastLoadEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Add the load/accumulate event to the list. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex ); + + /* Set the load event now. */ + pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Modify the previous last load event. */ + + /* Now modify the previous last load event. */ + pTempEntry->usNextEventPtr = f_usLoadEventIndex; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Program the Sub-Store event. */ + + usLastSubStoreEventIndex = pBridgeEntry->usLastSubStoreEventPtr; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); + + /* Set the Sub-Store event first. */ + pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Modify the previous last sub store event of the bridge. */ + + /* Now modify the last Load event of the bridge. */ + pTempEntry->usNextEventPtr = f_usSubStoreEventIndex; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Update the bridge pointers. */ + pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex; + + /* Check if modification to the global mixer pointer are required. */ + if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) + { + /* We have a new last bridge pointer. */ + pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; + } + } + + if ( f_fTap == TRUE ) + { + if ( pEchoChanEntry->usRinTsstIndex == cOCT6100_INVALID_INDEX ) + { + /* Remove the mute on the Rin port. */ + + UINT32 ulTempData; + UINT32 ulMask; + UINT32 ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + /* Configure the level control. */ + + UINT32 ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4; + UINT32 ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset; + UINT32 ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize; + + ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, + pEchoChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData); + 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. */ + ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, + pEchoChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Set the event entries as reserved. */ + pLoadEventEntry->fReserved = TRUE; + pSubStoreEventEntry->fReserved = TRUE; + + /* Store the event indexes into the channel structure. */ + pEchoChanEntry->usLoadEventIndex = f_usLoadEventIndex; + pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex; + + /* Check if must insert the Sin copy event in the list. */ + if ( fAddSinCopy == TRUE ) + { + /* Now insert the Sin copy event into the list. */ + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_usChanIndex ); + } + + /* Check if the Rin silence event can be cleared now that the */ + /* channel has been added to a conference. */ + if ( ( f_fTap == FALSE ) && ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) + { + /* Remove the event from the list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pEchoChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + } + + /* Configure the RIN copy mixer entry and memory - if using the RIN port. */ + if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) ) + { + if ( pEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pEchoChanEntry->usRinTsstIndex, + pEchoChanEntry->usExtraRinTsiMemIndex, + pEchoChanEntry->TdmConfig.byRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + if ( pBridgeEntry->fDominantSpeakerSet == TRUE ) + { + /* Dominant speaker is another channel. Set accordingly for this new conference channel. */ + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, pBridgeEntry->usDominantSpeakerChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + /* No dominant speaker set on this bridge yet. */ + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Update the bridge entry. */ + pBridgeEntry->usNumClients++; + + /* Store the bridge index into the channel structure. */ + pEchoChanEntry->usBridgeIndex = f_usBridgeIndex; + + /* Store the copy event index into the channel structure. */ + if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + pEchoChanEntry->usSinCopyEventIndex = f_usCopyEventIndex; + } + else + { + pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + } + + /* Remember if the channel is muted in the conference. */ + pEchoChanEntry->fMute = f_fMute; + + /* Remember if the channel is a tap in a conference. */ + pEchoChanEntry->fTap = f_fTap; + + /* We start by not being tapped. */ + pEchoChanEntry->fBeingTapped = FALSE; + pEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; + + /* Remember the tap bridge index if necessary. */ + if ( pEchoChanEntry->fTap == TRUE ) + { + pEchoChanEntry->usTapBridgeIndex = f_usTapBridgeIndex; + } + else + { + pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; + } + + /* Indicate that the extra SIN TSI is currently in used by the conference bridge. */ + if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + pEchoChanEntry->usExtraSinTsiDependencyCnt++; + } + + /* Indicate that the extra RIN TSI is currently in used by the conference bridge. */ + if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) ) + { + pEchoChanEntry->usExtraRinTsiDependencyCnt++; + } + + /* Update the chip stats structure. */ + pSharedInfo->ChipStats.usNumEcChanUsingMixer++; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeAddParticipantToChannel + +Description: Used for the flexible conference bridges. Insert a participant + onto a channel that is on a conference. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_usBridgeIndex Bridge index where this channel is located. +f_usSourceChannelIndex Source channel to copy voice from. +f_usDestinationChannelIndex Destination channel to store resulting voice to. +f_usLoadOrAccumulateEventIndex Load or Accumulate allocated event index. +f_usStoreEventIndex Store allocated event index. +f_usCopyEventIndex Copy allocated event index. +f_ulSourceInputPort Source input port of the conference for this channel. +f_ulDestinationInputPort Destination input port of the conference for this channel. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeAddParticipantToChannel +UINT32 Oct6100ApiBridgeAddParticipantToChannel( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usSourceChannelIndex, + IN UINT16 f_usDestinationChannelIndex, + IN UINT16 f_usLoadOrAccumulateEventIndex, + IN UINT16 f_usStoreEventIndex, + IN UINT16 f_usCopyEventIndex, + IN UINT32 f_ulSourceInputPort, + IN UINT32 f_ulDestinationInputPort ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pTempEntry; + + tPOCT6100_API_CHANNEL pSourceChanEntry; + tPOCT6100_API_CHANNEL pDestinationChanEntry; + + tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant; + + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + + UINT32 ulResult; + UINT16 usLastSubStoreEventIndex; + UINT16 usLastLoadEventIndex; + BOOL fInsertCopy = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex ); + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadOrAccumulateEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, f_usStoreEventIndex ); + + /* Check if we are creating the first event for this channel. */ + if ( pDestinationParticipant->fFlexibleMixerCreated == FALSE ) + { + /*=======================================================================*/ + /* Before creating the participant's flexible mixer, make sure the extra Sin */ + /* mixer event is programmed correctly for sending the voice stream to the right place. */ + + /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ + if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pDestinationChanEntry->usSinTsstIndex, + pDestinationChanEntry->usExtraSinTsiMemIndex, + pDestinationChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ + if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pDestinationChanEntry->usExtraSinTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Program the load event. This is the first event for this new destination channel. */ + + /* First set the TSI buffer where the resulting stream should be written to. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + /* For sure, we are loading. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Select the TSI memory index according to the source port. */ + if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex; + } + else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex; + } + + /* Set the event type. */ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Set the source channel index. */ + pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /* Program the store event. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; + + /* Select the TSI memory index and PCM law according to the source port. */ + if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pDestinationChanEntry->usSinSoutTsiMemIndex; + } + else /* if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pDestinationChanEntry->usRinRoutTsiMemIndex; + } + + /* Set the event type. */ + pStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; + + /* Set the destination channel index. */ + pStoreEventEntry->usDestinationChanIndex = f_usDestinationChannelIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pDestinationChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /* Program the Copy event - if using the SOUT port */ + + if ( ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pDestinationChanEntry->fCopyEventCreated == FALSE ) ) + { + /* The copy event has not been created, create it once for the life of the participant on the bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= pDestinationChanEntry->usExtraSinTsiMemIndex; + WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + pDestinationChanEntry->fCopyEventCreated = TRUE; + + /* Set insert copy flag. */ + fInsertCopy = TRUE; + } + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /*=======================================================================*/ + /* Now, insert the events into the current list. */ + /*=======================================================================*/ + /*=======================================================================*/ + + /* This is the first entry for this channel. Insert the two events at the head */ + /* of the list just after the last Sub-Store or Store event. */ + ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, f_usLoadOrAccumulateEventIndex, &usLastSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) + { + if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; + } + else + { + usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + } + else + { + return cOCT6100_ERR_FATAL_26; + } + } + + /* An entry was found, now, modify it's value. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Link the store event first. */ + + pStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; + + /* Link the store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + WriteParams.usWriteData = (UINT16)( pStoreEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Link the load event now.*/ + + pLoadEventEntry->usNextEventPtr = f_usStoreEventIndex; + + /* Link the load event.*/ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now modify the previous last Sub-Store or Store event from another bridge, */ + /* such that it links to us. */ + + pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex; + + /* Modify the last node of the other bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Set the event pointer info in the bridge stucture. */ + + if ( pBridgeEntry->usFirstLoadEventPtr == cOCT6100_INVALID_INDEX ) + { + /* We only do this once in case of the flexible conference bridges. */ + pBridgeEntry->usFirstLoadEventPtr = f_usLoadOrAccumulateEventIndex; + pBridgeEntry->usFirstSubStoreEventPtr = f_usStoreEventIndex; + } + + pBridgeEntry->usLastSubStoreEventPtr = f_usStoreEventIndex; + + /* Update the global mixer pointers. */ + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX ) + { + /* This bridge is the first to generate mixer event. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex; + pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usStoreEventIndex; + } + else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) + { + /* The two entries were added at the end of the bridge section, */ + /* change only the last pointer. */ + pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usStoreEventIndex; + } + else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE || + usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) + { + /* The two entries were added at the start of the bridge section, */ + /* change only the first pointer.*/ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Insert the copy event if needed in the mixer's list. */ + + if ( fInsertCopy == TRUE ) + { + /* Now insert the Sin copy event into the list. */ + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + f_usCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_usDestinationChannelIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Update the status of the instance structures. */ + + pDestinationParticipant->fFlexibleMixerCreated = TRUE; + + /* Set the event entries as reserved. */ + pLoadEventEntry->fReserved = TRUE; + pStoreEventEntry->fReserved = TRUE; + + /* Store the event indexes into the channel structure. */ + pDestinationChanEntry->usLoadEventIndex = f_usLoadOrAccumulateEventIndex; + pDestinationChanEntry->usSubStoreEventIndex = f_usStoreEventIndex; + + /*=======================================================================*/ + } + else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == TRUE ) */ + { + /*=======================================================================*/ + /* Program the Accumulate event. */ + + /* First set the TSI buffer where the resulting stream should be written to. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + /* For sure, we are accumulating. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + + /* Select the TSI memory index according to the source port. */ + if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex; + } + else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ + { + WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /*=======================================================================*/ + /* Now, insert the Accumulate event into the current list. */ + /*=======================================================================*/ + /*=======================================================================*/ + + /* Use the Load entry of this channel. */ + usLastLoadEventIndex = pDestinationChanEntry->usLoadEventIndex; + + /* Add the Accumulate event to the list. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex ); + + /* Set the accumulate event now. */ + pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /* Modify the previous Load event. */ + + /* Now modify the previous Load event. */ + pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex; + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + + /*=======================================================================*/ + /* Update the status of the instance structures. */ + + /* Set the Accumulate event entry as reserved. */ + pLoadEventEntry->fReserved = TRUE; + /* Set the Event type. */ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + /* Set the source channel index. */ + pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex; + + /*=======================================================================*/ + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanRemoveSer + +Description: Removes an echo channel from a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeRemove Pointer to conference bridge channel remove structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanRemoveSer +UINT32 Oct6100ConfBridgeChanRemoveSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) +{ + UINT16 usBridgeIndex; + UINT16 usChanIndex = 0; + UINT16 usLoadEventIndex; + UINT16 usSubStoreEventIndex; + UINT16 usCopyEventIndex; + UINT32 ulResult; + UINT8 fFlexibleConfBridge; + UINT8 fTap; + + /* Check the validity of the channel and conference bridge given. */ + ulResult = Oct6100ApiCheckChanRemoveParams( + f_pApiInstance, + f_pConfBridgeRemove, + &usBridgeIndex, + &usChanIndex, + &fFlexibleConfBridge, + &fTap, + &usLoadEventIndex, + &usSubStoreEventIndex, + &usCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources reserved for the conference bridge. */ + ulResult = Oct6100ApiReleaseChanEventResources( + f_pApiInstance, + f_pConfBridgeRemove, + usBridgeIndex, + usChanIndex, + fFlexibleConfBridge, + usLoadEventIndex, + usSubStoreEventIndex, + usCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear the memory entry for this channel within the bridge. */ + ulResult = Oct6100ApiBridgeEventRemove( + f_pApiInstance, + f_pConfBridgeRemove, + usBridgeIndex, + usChanIndex, + fFlexibleConfBridge, + usLoadEventIndex, + usSubStoreEventIndex, + usCopyEventIndex, + fTap ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckChanRemoveParams + +Description: Check the validity of the channel and conference bridge given. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pConfBridgeRemove Pointer to conference bridge channenl add structure. +f_pusBridgeIndex Pointer to the bridge index. +f_pfFlexibleConfBridge If this is a flexible conference bridge +f_pusChannelIndex Pointer to the channel index to be added to the bridge. +f_pusLoadEventIndex Pointer to the load mixer event. +f_pusSubStoreEventIndex Pointer to the sub-store mixer event. +f_pusCopyEventIndex Pointer to the copy mixer event. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckChanRemoveParams +UINT32 Oct6100ApiCheckChanRemoveParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, + OUT PUINT16 f_pusBridgeIndex, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT8 f_pfFlexibleConfBridge, + OUT PUINT8 f_pfTap, + OUT PUINT16 f_pusLoadEventIndex, + OUT PUINT16 f_pusSubStoreEventIndex, + OUT PUINT16 f_pusCopyEventIndex ) +{ + UINT32 ulEntryOpenCnt; + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + /* Verify if the remove all flag is valid. */ + if ( f_pConfBridgeRemove->fRemoveAll != TRUE && + f_pConfBridgeRemove->fRemoveAll != FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_ALL; + + /* Check the channel handle only if the remove all flag is set to FALSE. */ + if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) + { + /*=====================================================================*/ + /* Check the channel handle. */ + + if ( (f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + if ( pEchoChanEntry->fBeingTapped == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY; + + /*=====================================================================*/ + + *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; + *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; + *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; + *f_pusCopyEventIndex = pEchoChanEntry->usSinCopyEventIndex; + + /* Check if the channel is really part of the bridge. */ + if ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Return whether this is a flexible bridge or not. */ + *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; + + /* Return whether this is a tap or not. */ + *f_pfTap = pEchoChanEntry->fTap; + } + else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ + { + /* Check the provided handle. */ + if ( (f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusBridgeIndex = (UINT16)( f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeRemove->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* This information is not currently available. */ + *f_pusLoadEventIndex = cOCT6100_INVALID_INDEX; + *f_pusSubStoreEventIndex = cOCT6100_INVALID_INDEX; + *f_pusCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Return whether this is a flexible bridge or not. */ + *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; + + *f_pfTap = FALSE; + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseChanEventResources + +Description: Release all resources reserved to the channel part of the + conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pConfBridgeRemove Pointer to conference bridge channel add structure. +f_usBridgeIndex Index of the bridge structure within the API's bridge list. +f_usChanIndex Index of the channel structure within the API's channel list +f_fFlexibleConfBridge If this is a flexible conference bridge. +f_usLoadEventIndex Index of the load mixer event. +f_usSubStoreEventIndex Index of the sub-store mixer event. +f_usCopyEventIndex Index of the copy mixer event. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReleaseChanEventResources +UINT32 Oct6100ApiReleaseChanEventResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT8 f_fFlexibleConfBridge, + IN UINT16 f_usLoadEventIndex, + IN UINT16 f_usSubStoreEventIndex, + IN UINT16 f_usCopyEventIndex ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulResult; + UINT32 i; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + + if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) + { + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Release an entry for the store event in the mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the Sin copy event in the mixer memory. */ + /* This value can be invalid if the Rin port was used - no need to release. */ + if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Sout port was used - no need to release. */ + if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* Must travel all clients of this conference and release the load or accumulate events for */ + /* all participants which can hear us and vice versa. */ + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, i ); + + /* Channel reserved? */ + if ( ( i != f_usChanIndex ) && pTempEchoChanEntry->fReserved == TRUE ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can hear this participant. */ + if ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + { + /* Must release the allocated mixer event. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + + /* Check if this participant can hear us. */ + if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) + { + /* Must release the allocated mixer event. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + } + } + } + else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ + { + UINT32 ulListenerMaskIndex; + + ulResult = cOCT6100_ERR_OK; + + /* Search through the list of API channel entry for the ones on to this bridge.*/ + for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); + + /* Channel reserved? */ + if ( pEchoChanEntry->fReserved == TRUE ) + { + /* On current bridge? */ + if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Release an entry for the Store event in the Mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the Sin copy event in the Mixer memory. */ + /* This value can be invalid if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Sout port was used - no need to release. */ + if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* Check if something can be freed. */ + for ( ulListenerMaskIndex = 0; ulListenerMaskIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulListenerMaskIndex ++ ) + { + if ( pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) + { + /* Must release the allocated mixer event. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + } + } + } + + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + + /* Release the entry for the load event in the mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usLoadEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the substract and store event in the mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the Sin copy event in the Mixer memory. */ + /* This value can be invalid if the Rin port was used - no need to release. */ + if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry. */ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + } + else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ + { + /* Search through the list of API channel entry for the ones on to the specified bridge.*/ + for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); + + if ( pEchoChanEntry->fReserved == TRUE ) + { + if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) + { + /* Release the entry for the load event in the mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + pEchoChanEntry->usLoadEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the substract and store event in the Mixer memory. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + pEchoChanEntry->usSubStoreEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /* Release an entry for the Sin copy event in the Mixer memory. */ + /* This value can be invalid if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, + pEchoChanEntry->usSinCopyEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + + /* This value can be 0 if the Rin port was used - no need to release. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + /* Release the extra TSI entry.*/ + ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + } + } + } + } + } + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeEventRemove + +Description: Remove the event from the global event list of the chip and + update the bridge and channel structures. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pConfBridgeRemove Pointer to a conference bridge channel remove structure. +f_usBridgeIndex Index of the current bridge in the API list. +f_usChanIndex Index of the current channel in the API list. +f_fFlexibleConfBridge If this is a flexible conference bridge. +f_usLoadEventIndex Allocated entry for the Load event of the channel. +f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. +f_usCopyEventIndex Allocated entry for the copy event of the channel. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeEventRemove +UINT32 Oct6100ApiBridgeEventRemove ( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT8 f_fFlexibleConfBridge, + IN UINT16 f_usLoadEventIndex, + IN UINT16 f_usSubStoreEventIndex, + IN UINT16 f_usCopyEventIndex, + IN UINT8 f_fTap ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pCopyEventEntry = NULL; + tPOCT6100_API_MIXER_EVENT pTempEntry; + + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_READ_PARAMS ReadParams; + + UINT32 ulResult; + UINT16 usPreviousEventIndex; + UINT16 usTempEventIndex; + UINT32 ulLoopCount = 0; + UINT16 usReadData; + UINT16 usChannelIndex; + UINT32 i; + + BOOL fRemoveSinCopy = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + + /* If no client on the bridge, and the remove all option is specified, return here. */ + if ( ( pBridgeEntry->usNumClients == 0 ) && ( f_pConfBridgeRemove->fRemoveAll == TRUE ) ) + return cOCT6100_ERR_OK; + + /* Make sure the dominant speaker feature is disabled first. */ + if ( pBridgeEntry->fDominantSpeakerSet == TRUE ) + { + /* If all channels are to be removed or if the dominant speaker is the current channel to be removed. */ + if ( ( f_pConfBridgeRemove->fRemoveAll == TRUE ) + || ( ( f_pConfBridgeRemove->fRemoveAll == FALSE ) && ( pBridgeEntry->usDominantSpeakerChanIndex == f_usChanIndex ) ) ) + { + /* Disable on all channels part of this conference. */ + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + if ( pTempEchoChanEntry->fReserved == TRUE ) + { + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Save this in the conference bridge structure. */ + pBridgeEntry->fDominantSpeakerSet = FALSE; + pBridgeEntry->usDominantSpeakerChanIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Only disable this current channel. */ + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; + UINT32 ulMutePortChannelIndex; + + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; + + if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) + { + /* The channel index is valid. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can hear this participant. */ + if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pParticipant->fFlexibleMixerCreated == TRUE ) + && ( pTempEchoChanEntry->fMute == FALSE ) ) + { + /* First update the current channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + f_usBridgeIndex, + usChannelIndex, + f_usChanIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Check if this participant can hear us. */ + if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) + && ( pEchoChanEntry->fMute == FALSE ) ) + { + /* Then update this channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + f_usBridgeIndex, + f_usChanIndex, + usChannelIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Remember to mute the port on this channel. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex ) + { + break; + } + else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) + { + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex; + break; + } + } + } + } + } + } + + /* Check if must manually clear the Sin copy event. */ + if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) + { + /* Transform event into no-operation. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now remove the copy event from the event list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + pEchoChanEntry->fCopyEventCreated = FALSE; + } + + /* Release an entry for the participant. */ + ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /*=======================================================================*/ + /* Update the event and channel API structure */ + pEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Indicate that the extra SIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Decrement the dependency count, but do not clear the mem index. */ + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + } + + /* Indicate that the extra RIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraRinTsiDependencyCnt--; + pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + + /* Update the chip stats structure. */ + pSharedInfo->ChipStats.usNumEcChanUsingMixer--; + + pBridgeEntry->usNumClients--; + + /* For sure we have to mute the ports of this channel to be removed. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + f_usChanIndex, + pEchoChanEntry->usRinTsstIndex, + pEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Check if the Rin port must be muted on this channel. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + ausMutePortChannelIndexes[ ulMutePortChannelIndex ], + pTempEchoChanEntry->usRinTsstIndex, + pTempEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ + { + /* No more channels to check for muting. */ + break; + } + } + } + else /* if ( f_pConfBridgeRemove->fRemoveAll == TRUE ) */ + { + UINT16 usMainChannelIndex; + + for ( usMainChannelIndex = 0 ; usMainChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ; usMainChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usMainChannelIndex ); + + /* If this channel is on the bridge we are closing all the channels. */ + if ( ( pEchoChanEntry->fReserved == TRUE ) && ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ) + { + /* Remember to mute the port on this channel. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usMainChannelIndex ) + { + break; + } + else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) + { + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usMainChannelIndex; + break; + } + } + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( usChannelIndex = (UINT16)( usMainChannelIndex + 1 ); usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + if ( pTempEchoChanEntry->fReserved == TRUE ) + { + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Everyone that we can hear must be removed. */ + if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pParticipant->fFlexibleMixerCreated == TRUE ) + && ( pTempEchoChanEntry->fMute == FALSE ) ) + { + /* First update the current channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + f_usBridgeIndex, + usChannelIndex, + usMainChannelIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Check if this participant can hear us. */ + if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) + && ( pEchoChanEntry->fMute == FALSE ) ) + { + /* Then update this channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + f_usBridgeIndex, + usMainChannelIndex, + usChannelIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + } + + /* Check if must manually clear the Sin copy event. */ + if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) + { + /* Transform event into no-operation. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now remove the copy event from the event list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + pEchoChanEntry->fCopyEventCreated = FALSE; + } + + /* Release an entry for the participant. */ + ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + return ulResult; + } + + /*=======================================================================*/ + /* Update the event and channel API structure */ + + pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; + + pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Decrement the dependency count, but do not clear the mem index. */ + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + } + + /* Indicate that the Extra RIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraRinTsiDependencyCnt--; + pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + + /* Update the chip stats structure. */ + pSharedInfo->ChipStats.usNumEcChanUsingMixer--; + } + } + + /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Check if the Rin port must be muted on this channel. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + ausMutePortChannelIndexes[ ulMutePortChannelIndex ], + pTempEchoChanEntry->usRinTsstIndex, + pTempEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ + { + /* No more channels to check for muting. */ + break; + } + + /* Clear the flexible conf bridge participant index. */ + pTempEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; + } + + /* No more clients on bridge. */ + pBridgeEntry->usNumClients = 0; + } + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) + { + /* The channel index is valid. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + + if ( f_fTap == TRUE ) + { + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, pEchoChanEntry->usTapBridgeIndex ); + } + + /* Get a pointer to the event entry. */ + if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); + + /*=======================================================================*/ + /* Check if have to modify the silence load event. */ + + if ( pBridgeEntry->usNumClients != 1 ) + { + if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX ) + { + if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex ) + { + /* Make sure the next event becomes the silence event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadEventEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; + WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software model to remember the silence load. */ + pBridgeEntry->usSilenceLoadEventPtr = pLoadEventEntry->usNextEventPtr; + } + else + { + /* Somebody else is the silence event, no need to worry. */ + } + } + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Clear the Load event. */ + + /* First verify if the event to be removed was a load event. */ + if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex ) + { + /* Change the next entry if one is present to a load event to keep the bridge alive. */ + if ( pBridgeEntry->usNumClients == 1 ) + { + /* There is no other entry on the bridge, no need to search for an Accumulate event. */ + pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; + + /* Clear the silence event, for sure it's invalid. */ + pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; + } + else + { + /* Search for an accumulate event to tranform into a Load event. */ + usTempEventIndex = pLoadEventEntry->usNextEventPtr; + ulLoopCount = 0; + + /* Find the copy entry before the entry to remove. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && + pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) + { + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) + { + /* Change this entry into a load event. */ + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set this entry as the load index. */ + pBridgeEntry->usLoadIndex = usTempEventIndex; + + /* Update the software model. */ + pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Stop searching. */ + break; + } + + /* Go to the next entry into the list. */ + usTempEventIndex = pTempEntry->usNextEventPtr; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + ulLoopCount++; + if ( ulLoopCount == cOCT6100_MAX_LOOP ) + return cOCT6100_ERR_FATAL_9B; + } + } + } + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Clear the substract and store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Clear the Copy event - if needed. */ + + if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Transform event into no-operation. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( f_fTap == FALSE ) + { + /* Set remove Sin copy event flag to remove the event from the mixer's list. */ + fRemoveSinCopy = TRUE; + + /* Clear the copy event created flag. */ + pEchoChanEntry->fCopyEventCreated = FALSE; + } + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now remove the event from the event list. */ + + /* Look for the entry that is pointing at the first entry of our bridge. */ + if ( f_fTap == FALSE ) + { + ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); + } + else + { + ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, pEchoChanEntry->usTapBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); + } + + if ( ulResult != cOCT6100_ERR_OK ) + { + /* If the entry was not found, we now check for the Sout copy event section/list. */ + if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) + { + if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + /* No Sout copy, it has to be the head node. */ + usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; + } + else + { + /* Use the last Sout copy event. */ + usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + } + else + { + return cOCT6100_ERR_FATAL_27; + } + } + + if ( pBridgeEntry->usNumClients == 1 ) + { + /* An entry was found, now, modify it's value. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); + + /* Now modify the previous last Sub Store event from another bridge. */ + pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; + + /*=======================================================================*/ + /* Modify the last node of the previous bridge to point to the next bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Set the event pointer info in the bridge stucture. */ + pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; + + /*=======================================================================*/ + /* Update the global mixer pointers. */ + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex && + pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) + { + /* There is no more bridge entry in the mixer link list. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; + pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; + } + else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) + { + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pSubStoreEventEntry->usNextEventPtr; + } + else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) + { + pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; + } + /*=======================================================================*/ + + if ( f_fTap == TRUE ) + { + /* The channel being tapped is not tapped anymore. */ + /* There is no direct way of finding the tap, so loop through all channels and find the */ + /* tapped channel index. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + if ( pTempEchoChanEntry->usTapChanIndex == f_usChanIndex ) + { + tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; + + pTempEchoChanEntry->fBeingTapped = FALSE; + pTempEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex ); + + pTempBridgeEntry->usNumTappedClients--; + + /* Re-assign Rin TSST for tapped channel. */ + if ( pTempEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pTempEchoChanEntry->usRinTsstIndex, + pTempEchoChanEntry->usRinRoutTsiMemIndex, + pTempEchoChanEntry->TdmConfig.byRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + break; + } + } + + /* Check if our model is broken. */ + if ( usChannelIndex == pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_FATAL_D3; + } + } + else /* pBridgeEntry->usNumClients > 1 */ + { + if ( pBridgeEntry->usFirstLoadEventPtr != f_usLoadEventIndex ) + { + /* Now find the load entry of this bridge pointing at this load event */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usLoadEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Remove the load event to the list. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); + + /* Now modify the previous last Sub Store event from another bridge. */ + pTempEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; + + /*=======================================================================*/ + /* Modify the previous node. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /* Now find the last load entry of this bridge ( the one pointing at the first sub-store event ). */ + if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) + { + /* Must start with the first load to get the entry before the first sub store. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + else + { + /* Must start with the first load to get the entry before the first sub store. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstSubStoreEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); + + /* Now modify the last load event of the bridge. */ + pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; + + /*=======================================================================*/ + /* Modify the last node of the other bridge. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the bridge pointers. */ + + if ( pBridgeEntry->usFirstLoadEventPtr == f_usLoadEventIndex ) + pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; + + if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) + pBridgeEntry->usFirstSubStoreEventPtr = pSubStoreEventEntry->usNextEventPtr; + + if ( pBridgeEntry->usLastSubStoreEventPtr == f_usSubStoreEventIndex ) + pBridgeEntry->usLastSubStoreEventPtr = usPreviousEventIndex; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Update the global mixer pointers. */ + + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) + { + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; + } + + if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) + { + pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; + } + /*=======================================================================*/ + + } + + /* Check if must remove the Sin copy event from the event list. */ + if ( fRemoveSinCopy == TRUE ) + { + /* Now remove the copy event from the event list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, f_usCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Get the channel. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + + /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released. */ + if ( ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fTap == FALSE ) ) + { + if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pEchoChanEntry->usSinTsstIndex, + pEchoChanEntry->usSinSoutTsiMemIndex, + pEchoChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the original sin TSI. */ + if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + /* Set the event entries as free. */ + pLoadEventEntry->fReserved = FALSE; + pLoadEventEntry->usEventType = cOCT6100_INVALID_INDEX; + pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + pSubStoreEventEntry->fReserved = FALSE; + pSubStoreEventEntry->usEventType = cOCT6100_INVALID_INDEX; + pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + if ( pCopyEventEntry != NULL ) + { + pCopyEventEntry->fReserved = FALSE; + pCopyEventEntry->usEventType = cOCT6100_INVALID_INDEX; + pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + } + + pBridgeEntry->usNumClients--; + + /*=======================================================================*/ + /* Update the event and channel API structure */ + pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Decrement the dependency count, but do not clear the mem index. */ + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + } + + /* Update the chip stats structure. */ + pSharedInfo->ChipStats.usNumEcChanUsingMixer--; + + if ( f_fTap == TRUE ) + { + /* Can now close the bridge. */ + tOCT6100_CONF_BRIDGE_CLOSE BridgeClose; + + Oct6100ConfBridgeCloseDef( &BridgeClose ); + + BridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapBridgeIndex; + + ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &BridgeClose ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->fTap = FALSE; + } + + /* Check if the Rin port must be muted. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + f_usChanIndex, + pEchoChanEntry->usRinTsstIndex, + pEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + } + else /* f_ulBridgeChanRemove->fRemoveAll == TRUE ) */ + { + UINT16 usNextEventPtr; + + /* Save the next event pointer before invalidating everything. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pBridgeEntry->usLastSubStoreEventPtr ); + + usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; + + /* Search through the list of API channel entry for the ones on to the specified bridge. */ + for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); + + if ( pEchoChanEntry->fReserved == TRUE ) + { + if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) + { + /* Check if we are being tapped. If so, remove the channel that taps us from the conference. */ + /* The removal of the channel will make sure the Rin TSST is re-assigned. */ + if ( pEchoChanEntry->fBeingTapped == TRUE ) + { + tOCT6100_CONF_BRIDGE_CHAN_REMOVE ChanRemove; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, pEchoChanEntry->usTapChanIndex ); + + ulResult = Oct6100ConfBridgeChanRemoveDef( &ChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pTempEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapChanIndex; + + ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &ChanRemove ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*=======================================================================*/ + /* Clear the Load event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Clear the Substract and store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*=======================================================================*/ + + /*=======================================================================*/ + /* Clear the SIN copy event.*/ + + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Transform event into no-operation. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Get a pointer to the event entry. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pEchoChanEntry->usSinCopyEventIndex ); + + /* Update the next event pointer if required. */ + if ( usNextEventPtr == pEchoChanEntry->usSinCopyEventIndex ) + usNextEventPtr = pCopyEventEntry->usNextEventPtr; + + /* Now remove the copy event from the event list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Clear the copy event created flag. */ + pEchoChanEntry->fCopyEventCreated = FALSE; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Update the event and channel API structure */ + + /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released.*/ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pEchoChanEntry->usSinTsstIndex, + pEchoChanEntry->usSinSoutTsiMemIndex, + pEchoChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the original Sin TSI. */ + if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, pEchoChanEntry->usLoadEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pEchoChanEntry->usSubStoreEventIndex ); + + /* Set the event entries as free. */ + pLoadEventEntry->fReserved = FALSE; + pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + pSubStoreEventEntry->fReserved = FALSE; + pSubStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + if ( pCopyEventEntry != NULL ) + { + pCopyEventEntry->fReserved = FALSE; + pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + } + + /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ + if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) + { + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Decrement the dependency count, but do not clear the mem index. */ + pEchoChanEntry->usExtraSinTsiDependencyCnt--; + } + + /* Invalidate the channel entry. */ + pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; + pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; + + /* Update the chip stats structure. */ + pSharedInfo->ChipStats.usNumEcChanUsingMixer--; + + /*=======================================================================*/ + } + } + } + + ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND == ulResult ) + { + if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; + } + else + { + usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + } + else + { + return cOCT6100_ERR_FATAL_28; + } + } + + /* An Entry was found, now, modify it's value. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); + + /* Now modify the previous last Sub Store event from another bridge.*/ + /* It will now point at the next bridge, or copy events. */ + pTempEntry->usNextEventPtr = usNextEventPtr; + + /*=======================================================================*/ + /* Modify the last node of the other bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = pTempEntry->usNextEventPtr; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + /*=======================================================================*/ + + /*=======================================================================*/ + /* Update the global mixer pointers. */ + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr && + pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) + { + /* This bridge was the only one with event in the list. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; + pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; + } + else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr ) + { + /* This bridge was the first bridge. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = usNextEventPtr; + } + else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) + { + /* This bridge was the last bridge.*/ + pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; + } + /*=======================================================================*/ + + /* Set the event pointer info in the bridge stucture. */ + pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; + + pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; + + /* Set the number of clients to 0. */ + pBridgeEntry->usNumClients = 0; + + /* Search through the list of API channel entry for the ones on to the specified bridge. */ + for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); + + if ( pEchoChanEntry->fReserved == TRUE ) + { + if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) + { + pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; + + /* Check if the Rin port must be muted. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + (UINT16)( i & 0xFFFF ), + pEchoChanEntry->usRinTsstIndex, + pEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + } + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeRemoveParticipantFromChannel + +Description: This will remove a flexible conference participant from + a channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_usBridgeIndex Bridge index where this channel is located. +f_usSourceChannelIndex Source channel to copy voice from. +f_usDestinationChannelIndex Destination channel to store resulting voice to. +f_fRemovePermanently Whether to remove permanently this participant. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeRemoveParticipantFromChannel +UINT32 Oct6100ApiBridgeRemoveParticipantFromChannel( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usSourceChannelIndex, + IN UINT16 f_usDestinationChannelIndex, + IN UINT8 f_fRemovePermanently ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pCopyEventEntry; + tPOCT6100_API_MIXER_EVENT pTempEntry; + tPOCT6100_API_MIXER_EVENT pLoadTempEntry; + tPOCT6100_API_MIXER_EVENT pLastEventEntry; + tPOCT6100_API_MIXER_EVENT pLastLoadOrAccumulateEventEntry; + + tPOCT6100_API_CHANNEL pSourceChanEntry; + tPOCT6100_API_CHANNEL pDestinationChanEntry; + + tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant; + + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_READ_PARAMS ReadParams; + + UINT32 ulResult; + UINT32 ulLoopCount; + UINT16 usLastLoadEventIndex; + UINT16 usLoadOrAccumulateEventIndex; + UINT16 usTempEventIndex; + UINT16 usPreviousEventIndex; + UINT16 usLastEventIndex; + + UINT16 usReadData; + BOOL fLastEvent = FALSE; + BOOL fSoutCopyEvent = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex ); + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex ); + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex ); + + /* Check if the mixer has been created on this channel. */ + if ( pDestinationParticipant->fFlexibleMixerCreated == TRUE ) + { + /*=======================================================================*/ + /* Clear the Load or Accumulate event.*/ + + usTempEventIndex = pDestinationChanEntry->usLoadEventIndex; + ulLoopCount = 0; + + /* Find the Load or Accumulate event entry. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usTempEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, pDestinationChanEntry->usSubStoreEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + pLastEventEntry = pLoadEventEntry; + pLastLoadOrAccumulateEventEntry = pLoadEventEntry; + usLastLoadEventIndex = usTempEventIndex; + usLastEventIndex = usTempEventIndex; + + while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && + pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) + { + /* If this is the entry we are looking for. */ + if ( pTempEntry->usSourceChanIndex == f_usSourceChannelIndex ) + { + /* Check if this is a Load or Accumulate event. */ + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) + { + /* This is the first entry. Check if next entry is an accumulate. */ + pLoadTempEntry = pTempEntry; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, pTempEntry->usNextEventPtr ); + + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) + { + /* Change this entry into a Load event. */ + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadTempEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the channel information with this new load event. */ + pDestinationChanEntry->usLoadEventIndex = pLoadTempEntry->usNextEventPtr; + + /* Update the software model. */ + pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Get the previous event. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); + usLastEventIndex = usPreviousEventIndex; + + /* Stop searching. */ + break; + } + else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) + { + /* Get back the event to remove. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + /* This is the only event on this channel so we can clear everything up. */ + fLastEvent = TRUE; + + /* Get the previous event. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); + usLastEventIndex = usPreviousEventIndex; + + /* Stop searching. */ + break; + } + else + { + /* Software model is broken. */ + return cOCT6100_ERR_FATAL_C5; + } + + } + else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) + { + /* Simply remove the entry. */ + + /* Get the previous event. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); + usLastEventIndex = usPreviousEventIndex; + + /* Stop searching. */ + break; + } + else + { + /* Software model is broken. */ + return cOCT6100_ERR_FATAL_C6; + } + } + + pLastLoadOrAccumulateEventEntry = pTempEntry; + usLastLoadEventIndex = usTempEventIndex; + + /* Go to the next entry into the list. */ + usTempEventIndex = pTempEntry->usNextEventPtr; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + ulLoopCount++; + if ( ulLoopCount == cOCT6100_MAX_LOOP ) + return cOCT6100_ERR_FATAL_C8; + } + + /* Check if we found what we were looking for. */ + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE + || pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) + { + /* Software model is broken. */ + return cOCT6100_ERR_FATAL_C7; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Clear the Store event - if needed. */ + + if ( fLastEvent == TRUE ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Clear the Load or Accumulate event. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Save this event index. It's the Load or Accumulate we want to remove from the list later. */ + usLoadOrAccumulateEventIndex = usTempEventIndex; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Clear the Copy event - if needed. */ + + if ( ( fLastEvent == TRUE ) && ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) + { + /* Transform event into no-operation. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* The event remove from the list will be done below. */ + + /* Clear the copy event created flag. */ + pDestinationChanEntry->fCopyEventCreated = FALSE; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /*=======================================================================*/ + /* Remove the events from the mixer event list.*/ + /*=======================================================================*/ + /*=======================================================================*/ + + /*=======================================================================*/ + /* Remove the Load or Accumulate event from the event list. */ + + if ( fLastEvent == FALSE ) + { + /*=======================================================================*/ + /* Remove the Accumulate event from the event list. */ + + /* We saved the Load or Accumulate event above. We also saved the previous event. Use those. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usLoadOrAccumulateEventIndex ); + + /* Now modify the previous last event. */ + pLastEventEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; + + /* Modify the previous node. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = pLastEventEntry->usNextEventPtr; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if this is the first load event on the bridge. */ + if ( pBridgeEntry->usFirstLoadEventPtr == usLoadOrAccumulateEventIndex ) + { + pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; + } + + /* Check if this was the first load of all bridges. */ + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) + { + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; + } + + /*=======================================================================*/ + } + else /* if ( fLastEvent == TRUE ) */ + { + /*=======================================================================*/ + /* Remove the Load event from the event list. */ + + /* Look for the entry that is pointing at the first entry of our mixer. */ + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usLoadOrAccumulateEventIndex, 0, &usPreviousEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* An Entry was found, now, modify it's value. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); + + /* Check if this is a Sout copy event. */ + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_COPY ) + { + /* No more previous bridges. */ + fSoutCopyEvent = TRUE; + } + + /* Now modify the previous last Store or Sub-Store or Head-Node event from another bridge/channel. */ + pTempEntry->usNextEventPtr = pStoreEventEntry->usNextEventPtr; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Modify the last node of the previous bridge/channel to point to the next bridge. */ + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + WriteParams.ulWriteAddress += 4; + + WriteParams.usWriteData = pTempEntry->usNextEventPtr; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Set the event pointer info in the bridge stucture. */ + + if ( pBridgeEntry->usFirstLoadEventPtr == pDestinationChanEntry->usLoadEventIndex ) + { + UINT16 usChannelIndex; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + + pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; + pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; + + /* Find the next channel in this conference that could give us valid values. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + if ( ( usChannelIndex != f_usDestinationChannelIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + if ( pTempParticipant->fFlexibleMixerCreated == TRUE ) + { + pBridgeEntry->usFirstSubStoreEventPtr = pTempEchoChanEntry->usSubStoreEventIndex; + pBridgeEntry->usFirstLoadEventPtr = pTempEchoChanEntry->usLoadEventIndex; + break; + } + } + } + } + } + + /* Reprogram the TSST entry correctly if the extra SIN TSI entry was released. */ + if ( ( pDestinationChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) + { + if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pDestinationChanEntry->usSinTsstIndex, + pDestinationChanEntry->usSinSoutTsiMemIndex, + pDestinationChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the original sin TSI. */ + if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Reprogram the TSST entry correctly if the extra RIN TSI entry was released. */ + if ( ( pDestinationChanEntry->usExtraRinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) + { + if ( pDestinationChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pDestinationChanEntry->usRinTsstIndex, + pDestinationChanEntry->usRinRoutTsiMemIndex, + pDestinationChanEntry->TdmConfig.byRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /*=======================================================================*/ + /* Update the global mixer pointers. */ + + if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex && + pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) + { + /* There is no more bridge entry in the mixer link list. */ + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; + pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; + } + else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) + { + pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pStoreEventEntry->usNextEventPtr; + } + else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) + { + pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Check if must remove the Sin copy event from the list. */ + + if ( ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) + { + /* Now remove the copy event from the event list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pDestinationChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /*=======================================================================*/ + + + + /*=======================================================================*/ + + if ( f_fRemovePermanently == TRUE ) + { + /* Set the event entries as free. */ + pLoadEventEntry->fReserved = FALSE; + pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + pStoreEventEntry->fReserved = FALSE; + pStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + + if ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pDestinationChanEntry->usSinCopyEventIndex ); + + pCopyEventEntry->fReserved = FALSE; + pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; + pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; + } + } + + /* Flexible mixer for this channel not created anymore. */ + pDestinationParticipant->fFlexibleMixerCreated = FALSE; + + /*=======================================================================*/ + } + + /*=======================================================================*/ + } + else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == FALSE ) */ + { + /* This point should never be reached. */ + return cOCT6100_ERR_FATAL_C9; + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanMuteSer + +Description: Mute an echo channel present on a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeMute Pointer to conference bridge mute structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanMuteSer +UINT32 Oct6100ConfBridgeChanMuteSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) +{ + UINT16 usChanIndex; + UINT16 usLoadEventIndex; + UINT16 usSubStoreEventIndex; + UINT32 ulResult; + UINT8 fFlexibleConferencing; + + /* Check the validity of the channel and conference bridge given. */ + ulResult = Oct6100ApiCheckBridgeMuteParams( + f_pApiInstance, + f_pConfBridgeMute, + &usChanIndex, + &usLoadEventIndex, + &usSubStoreEventIndex, + &fFlexibleConferencing ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Modify all resources needed by the conference bridge. */ + ulResult = Oct6100ApiUpdateBridgeMuteResources( + f_pApiInstance, + usChanIndex, + usLoadEventIndex, + usSubStoreEventIndex, + fFlexibleConferencing ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeMuteParams + +Description: Check the validity of the channel and conference bridge given. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeMute Pointer to conference bridge channel mute structure. +f_pusChannelIndex Pointer to a channel index. +f_pusLoadEventIndex Pointer to a load mixer event index. +f_pusSubStoreEventIndex Pointer to a sub-store mixer event index. +f_pfFlexibleConfBridge If this is a flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeMuteParams +UINT32 Oct6100ApiCheckBridgeMuteParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT16 f_pusLoadEventIndex, + OUT PUINT16 f_pusSubStoreEventIndex, + OUT PUINT8 f_pfFlexibleConfBridge ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeMute->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; + + /*=====================================================================*/ + /* Check the channel handle.*/ + + if ( (f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* Check if the channel is bound to a conference bridge. */ + if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + + /* Check if channel is already muted. */ + if ( pEchoChanEntry->fMute == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_ALREADY_MUTED; + + /* Check if this is a tap channel, which is always mute. */ + if ( pEchoChanEntry->fTap == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE; + + /*=====================================================================*/ + + /*=====================================================================*/ + /* Check the conference bridge handle. */ + + if ( pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + + if ( pBridgeEntry->fFlexibleConferencing == FALSE ) + { + /* Check the event entries.*/ + if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + + if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + } + + /*=====================================================================*/ + + /* Return the config of the channel and all other important information. */ + *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; + *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; + *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBridgeMuteResources + +Description: Modify the conference bridge entry for this channel in order + to mute the specified channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usChanIndex Index of the channel to be muted. +f_usLoadEventIndex Allocated entry for the Load event of the channel. +f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. +f_fFlexibleConfBridge If this is a flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiUpdateBridgeMuteResources +UINT32 Oct6100ApiUpdateBridgeMuteResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChanIndex, + IN UINT16 f_usLoadEventIndex, + IN UINT16 f_usSubStoreEventIndex, + IN UINT8 f_fFlexibleConfBridge ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_READ_PARAMS ReadParams; + + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pTempEntry; + UINT32 ulResult; + UINT16 usTempEventIndex; + UINT32 ulLoopCount; + UINT16 usReadData; + + BOOL fCreateSilenceLoad = FALSE; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) + + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + UINT16 usChannelIndex; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + + UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; + UINT32 ulMutePortChannelIndex; + + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Search through the list of API channel entry for the ones on to this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if this participant can hear us. */ + if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ) + { + /* Then update this channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + pEchoChanEntry->usBridgeIndex, + f_usChanIndex, + usChannelIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Remember to mute the port on this channel. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex ) + { + break; + } + else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) + { + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex; + break; + } + } + } + } + } + } + } + + /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Check if the Rin port must be muted on this channel. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + ausMutePortChannelIndexes[ ulMutePortChannelIndex ], + pTempEchoChanEntry->usRinTsstIndex, + pTempEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED ) + { + UINT32 ulTempResult; + + /* Cleanup resources, unmute channel... */ + ulTempResult = Oct6100ApiUpdateBridgeUnMuteResources( + f_pApiInstance, + f_usChanIndex, + f_usLoadEventIndex, + f_usSubStoreEventIndex, + TRUE ); + if ( ulTempResult != cOCT6100_ERR_OK ) + return ulTempResult; + else + return ulResult; + } + else + { + return ulResult; + } + } + } + } + else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ + { + /* No more channels to check for muting. */ + break; + } + } + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); + + /*=======================================================================*/ + /* Program the Load event. */ + + /* Create silence load if this is the first event of the bridge. */ + if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr ) + fCreateSilenceLoad = TRUE; + + /* First check if this event was a load or an accumulate event, if it's a load */ + /* we need to find a new load. */ + if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex ) + { + /* Change the next entry if one is present to a load event to keep the bridge alive. */ + if ( pBridgeEntry->usNumClients == 1 ) + { + /* There is no other entry on the bridge, no need to search for an Accumulate event. */ + pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; + } + else + { + /* Search for an accumulate event to tranform into a Load event. */ + usTempEventIndex = pLoadEventEntry->usNextEventPtr; + ulLoopCount = 0; + + /* Find the copy entry before the entry to remove. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && + pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) + { + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) + { + /* Change this entry into a load event. */ + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Set this entry as the load index. */ + pBridgeEntry->usLoadIndex = usTempEventIndex; + + /* Update the software model. */ + pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + + /* Stop searching. */ + break; + } + + /* Go to the next entry into the list. */ + usTempEventIndex = pTempEntry->usNextEventPtr; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + ulLoopCount++; + if ( ulLoopCount == cOCT6100_MAX_LOOP ) + return cOCT6100_ERR_FATAL_9B; + } + } + } + + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + /* Do not load the sample if the channel is muted. */ + if ( fCreateSilenceLoad == TRUE ) + { + if ( pBridgeEntry->usSilenceLoadEventPtr == cOCT6100_INVALID_INDEX ) + { + /* Instead of No-oping, load the silence TSI, to make sure the other conferences before us are not heard. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; + WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ + + /* Remember the silence load event. */ + pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex; + } + else + { + /* Do nothing. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + } + } + else + { + /* Do nothing. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software model. */ + pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Program the Substract and store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + /* Do not load the sample if the channel is muted. */ + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; + + /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Sout input. */ + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + } + else /* if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX ) */ + { + /* Rin input. */ + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software model. */ + pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; + + /*=======================================================================*/ + } + + /* Update the channel entry API structure */ + pEchoChanEntry->fMute = TRUE; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeChanUnMuteSer + +Description: UnMute an echo channel present on a conference bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeChanUnMuteSer +UINT32 Oct6100ConfBridgeChanUnMuteSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) +{ + UINT16 usChanIndex; + UINT16 usLoadEventIndex; + UINT16 usSubStoreEventIndex; + UINT8 fFlexibleConfBridge; + UINT32 ulResult; + + /* Check the validity of the channel and conference bridge given. */ + ulResult = Oct6100ApiCheckBridgeUnMuteParams( + f_pApiInstance, + f_pConfBridgeUnMute, + &usChanIndex, + &usLoadEventIndex, + &usSubStoreEventIndex, + &fFlexibleConfBridge ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Modify all resources needed by the conference bridge. */ + ulResult = Oct6100ApiUpdateBridgeUnMuteResources( + f_pApiInstance, + usChanIndex, + usLoadEventIndex, + usSubStoreEventIndex, + fFlexibleConfBridge ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeUnMuteParams + +Description: Check the validity of the channel and conference bridge given. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. +f_pusChannelIndex Pointer to the channel index fo the channel to be unmuted. +f_pusLoadEventIndex Pointer to the load index of the channel. +f_pusSubStoreEventIndex Pointer to the sub-store event of the channel. +f_pfFlexibleConfBridge If this is a flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeUnMuteParams +UINT32 Oct6100ApiCheckBridgeUnMuteParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT16 f_pusLoadEventIndex, + OUT PUINT16 f_pusSubStoreEventIndex, + OUT PUINT8 f_pfFlexibleConfBridge ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeUnMute->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; + + /*=====================================================================*/ + /* Check the channel handle.*/ + + if ( (f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* Check if the channel is bound to a conference bridge.*/ + if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + + /* Check if channel is already muted.*/ + if ( pEchoChanEntry->fMute == FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_NOT_MUTED; + + /*=====================================================================*/ + + /*=====================================================================*/ + /* Check the conference bridge handle. */ + + if ( pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + + /* Check the event entries.*/ + if ( pBridgeEntry->fFlexibleConferencing == FALSE ) + { + if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + + /* Check the event entries.*/ + if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; + } + + /*=====================================================================*/ + + /* Return the config of the channel and all other important information.*/ + *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; + *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; + *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBridgeUnMuteResources + +Description: Modify the conference bridge entry for this channel in order + to un-mute the specified channel. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usChanIndex Index of the channel to be unmuted. +f_usLoadEventIndex Allocated entry for the Load event of the channel. +f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. +f_fFlexibleConfBridge If this is a flexible conference bridge. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiUpdateBridgeUnMuteResources +UINT32 Oct6100ApiUpdateBridgeUnMuteResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChanIndex, + IN UINT16 f_usLoadEventIndex, + IN UINT16 f_usSubStoreEventIndex, + IN UINT8 f_fFlexibleConfBridge ) +{ + tOCT6100_WRITE_PARAMS WriteParams; + tOCT6100_READ_PARAMS ReadParams; + + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + + tPOCT6100_API_MIXER_EVENT pLoadEventEntry; + tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; + tPOCT6100_API_MIXER_EVENT pTempEntry; + UINT32 ulResult; + UINT16 usTempEventIndex; + UINT32 ulLoopCount; + UINT16 usReadData; + + UINT16 usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + UINT16 usPreviousLoadIndex = cOCT6100_INVALID_INDEX; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) + + if ( f_fFlexibleConfBridge == TRUE ) + { + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + UINT16 usChannelIndex; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); + + /* Before doing anything, check if the copy events must be created. */ + if ( ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChanEntry->fCopyEventCreated == FALSE ) ) + { + /* The copy event has not been created, create it once for the life of the participant on the bridge. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; + WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex; + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Now insert the Sin copy event into the list. */ + ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, + pEchoChanEntry->usSinCopyEventIndex, + cOCT6100_EVENT_TYPE_SIN_COPY, + f_usChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + pEchoChanEntry->fCopyEventCreated = TRUE; + } + + /* Search through the list of API channel entry for the ones onto this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if this participant can hear us. */ + if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) + { + /* Then create/update this channel's mixer. */ + ulResult = Oct6100ApiBridgeAddParticipantToChannel( + f_pApiInstance, + pEchoChanEntry->usBridgeIndex, + f_usChanIndex, + usChannelIndex, + pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ], + pTempEchoChanEntry->usSubStoreEventIndex, + pTempEchoChanEntry->usSinCopyEventIndex, + pParticipant->ulInputPort, + pTempParticipant->ulInputPort ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if the Rin silence event can be cleared now that the */ + /* channel has unmuted. */ + if ( ( pTempParticipant->fFlexibleMixerCreated == TRUE ) + && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) + { + /* Remove the event from the list. */ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pTempEchoChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + } + } + } + } + } + else /* if ( f_fFlexibleConfBridge == FALSE ) */ + { + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); + + /*=======================================================================*/ + /* Program the Load event. */ + + /* Before reactivating this event, check what type of event this event must be. */ + if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr || + pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX ) + { + /* This event must become a Load event. */ + usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + pBridgeEntry->usLoadIndex = f_usLoadEventIndex; + } + + usTempEventIndex = pBridgeEntry->usFirstLoadEventPtr; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + ulLoopCount = 0; + + while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && + pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) + { + if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) + { + usPreviousLoadIndex = usTempEventIndex; + } + + /* Check if the previous load event is before or after the event about to be unmuted. */ + if ( pTempEntry->usNextEventPtr == f_usLoadEventIndex ) + { + if ( usPreviousLoadIndex == cOCT6100_INVALID_INDEX ) + { + /* We did not find a load event before our node, this mean this one */ + /* is about to become the new load event. */ + usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; + } + } + + /* Go to the next entry into the list. */ + usTempEventIndex = pTempEntry->usNextEventPtr; + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); + + ulLoopCount++; + if ( ulLoopCount == cOCT6100_MAX_LOOP ) + return cOCT6100_ERR_FATAL_9B; + } + + /* Now program the current event node. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = usLoadEventType; + + /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Sout source */ + WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; + } + else + { + /* Rin source */ + WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software event to reflect the hardware. */ + pLoadEventEntry->usEventType = usLoadEventType; + + /* Check if we need to change another node. */ + if ( usLoadEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) + { + if ( usPreviousLoadIndex != cOCT6100_INVALID_INDEX ) + { + /* Now program the old load event. */ + ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousLoadIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress = ReadParams.ulReadAddress; + WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ); + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software event to reflect the hardware. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousLoadIndex ); + pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; + } + } + + /*=======================================================================*/ + + /*=======================================================================*/ + /* Program the Substract and store event. */ + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; + /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ + if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Sout port source */ + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; + } + else + { + /* Rin port source */ + WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; + WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; + } + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the software event to reflect the hardware. */ + pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Check if have to remove silence load event. */ + + if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX ) + { + if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex ) + { + /* Clear the silence load event ptr. */ + pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; + } + } + } + + /* Update the channel entry API structure */ + pEchoChanEntry->fMute = FALSE; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeDominantSpeakerSetSer + +Description: This function sets the dominant speaker of a bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. + +f_pConfBridgeDominant Pointer to conference bridge dominant speaker + structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetSer +UINT32 Oct6100ConfBridgeDominantSpeakerSetSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) +{ + UINT16 usChanIndex; + UINT16 usBridgeIndex; + UINT32 ulResult; + + /* Check the validity of the channel handle given. */ + ulResult = Oct6100ApiCheckBridgeDominantSpeakerParams( f_pApiInstance, f_pConfBridgeDominantSpeaker, &usChanIndex, &usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Modify all resources needed by the conference bridge. */ + ulResult = Oct6100ApiUpdateBridgeDominantSpeakerResources( f_pApiInstance, usChanIndex, usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeDominantSpeakerParams + +Description: Check the validity of the channel given for setting the + dominant speaker. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pConfBridgeDominant Pointer to conference bridge channel dominant speaker structure. +f_pusChannelIndex Pointer to a channel index. +f_pusChannelIndex Pointer to a bridge index. +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeDominantSpeakerParams +UINT32 Oct6100ApiCheckBridgeDominantSpeakerParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT16 f_pusBridgeIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulEntryOpenCnt; + BOOL fCheckEntryOpenCnt = FALSE; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeDominantSpeaker->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /*=====================================================================*/ + /* Check the channel handle. */ + + if ( f_pConfBridgeDominantSpeaker->ulChannelHndl != cOCT6100_CONF_NO_DOMINANT_SPEAKER_HNDL ) + { + if ( (f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* Check if the channel is bound to a conference bridge. */ + if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; + + /* Check if the NLP is enabled on this channel. */ + if ( pEchoChanEntry->VqeConfig.fEnableNlp == FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_NLP_MUST_BE_ENABLED; + + /* Check if conferencing noise reduction is enabled on this channel. */ + if ( pEchoChanEntry->VqeConfig.fSoutConferencingNoiseReduction == FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_CNR_MUST_BE_ENABLED; + + /* Check if this is a tap channel. If it is, it will never be the dominant speaker! */ + if ( pEchoChanEntry->fTap == TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE; + + /* Set the bridge index. */ + *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; + } + else + { + /* Set this such that there is no dominant speaker on this conference bridge. */ + *f_pusChannelIndex = cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED; + + /* Check the conference bridge handle. */ + if ( (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* Set the bridge index. */ + *f_pusBridgeIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + fCheckEntryOpenCnt = TRUE; + } + + /*=====================================================================*/ + + /*=====================================================================*/ + + if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( fCheckEntryOpenCnt == TRUE ) + { + if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + } + + /*=====================================================================*/ + /* Check if dominant speaker is supported in this firmware version. */ + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_DOMINANT_SPEAKER; + + /*=====================================================================*/ + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBridgeDominantSpeakerResources + +Description: Modify the conference bridge such that the new dominant + speaker is the one specified by the index. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usChanIndex Index of the channel to be set as the dominant speaker. +f_usBridgeIndex Index of the bridge where this channel is on. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiUpdateBridgeDominantSpeakerResources +UINT32 Oct6100ApiUpdateBridgeDominantSpeakerResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChanIndex, + IN UINT16 f_usBridgeIndex ) +{ + tPOCT6100_API_CHANNEL pEchoChanEntry; + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + + UINT16 usChannelIndex; + UINT32 ulResult; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Get the bridge entry for this channel. */ + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ) + + /* Set the dominant speaker index for all channels in this conference. */ + + /* Search through the list of API channel entry for the ones on to this bridge.*/ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex ); + + if ( pEchoChanEntry->fReserved == TRUE ) + { + if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + /* If we are unsetting the dominant speaker, of if it is not our channel index. */ + if ( ( f_usChanIndex == cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ) + || ( f_usChanIndex != usChannelIndex ) ) + { + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, f_usChanIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + } + + /* Make sure this channel is disabled. */ + if ( f_usChanIndex != cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ) + { + ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Save this in the conference bridge structure. */ + /* This will be needed later when removing the channel. */ + pBridgeEntry->fDominantSpeakerSet = TRUE; + pBridgeEntry->usDominantSpeakerChanIndex = f_usChanIndex; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeMaskChangeSer + +Description: This function changes the mask of flexible bridge + participant. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. + +f_pConfBridgeMaskChange Pointer to conference bridge participant mask + change structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeMaskChangeSer +UINT32 Oct6100ConfBridgeMaskChangeSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) +{ + UINT16 usChanIndex; + UINT16 usBridgeIndex; + UINT32 ulResult; + UINT32 ulNewParticipantMask; + + /* Check the validity of the channel handle given. */ + ulResult = Oct6100ApiCheckBridgeMaskChangeParams( f_pApiInstance, f_pConfBridgeMaskChange, &usChanIndex, &usBridgeIndex, &ulNewParticipantMask ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update all resources needed by the new mask. */ + ulResult = Oct6100ApiUpdateMaskModifyResources( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Commit the changes to the chip's internal memories. */ + ulResult = Oct6100ApiBridgeUpdateMask( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBridgeMaskChangeParams + +Description: Check the validity of the channel given for setting the + mask. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeMaskChange Pointer to conference bridge channel mask change structure. +f_pusChannelIndex Pointer to a channel index. +f_pusBridgeIndex Pointer to a bridge index. +f_pulNewParticipantMask New mask to apply for this participant. +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiCheckBridgeMaskChangeParams +UINT32 Oct6100ApiCheckBridgeMaskChangeParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange, + OUT PUINT16 f_pusChannelIndex, + OUT PUINT16 f_pusBridgeIndex, + OUT PUINT32 f_pulNewParticipantMask ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_CHANNEL pEchoChanEntry; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + if ( f_pConfBridgeMaskChange->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /*=====================================================================*/ + /* Check the channel handle.*/ + + if ( (f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + *f_pusChannelIndex = (UINT16)( f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeMaskChange->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pEchoChanEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /* Check if the channel is bound to a conference bridge. */ + if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) + return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; + + /* Set the bridge index. */ + *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; + + /*=====================================================================*/ + + /*=====================================================================*/ + + if ( ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX ) + || ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + + /* Check if this is bridge is a flexible conference bridge. */ + if ( pBridgeEntry->fFlexibleConferencing == FALSE ) + return cOCT6100_ERR_CONF_BRIDGE_SIMPLE_BRIDGE; + + /*=====================================================================*/ + + /* Return new mask to apply. */ + *f_pulNewParticipantMask = f_pConfBridgeMaskChange->ulNewListenerMask; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateMaskModifyResources + +Description: Modify/reserve all resources needed for the modification of + the participant's mask. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usBridgeIndex Bridge index of the bridge where this channel is residing. +f_usChanIndex Channel index of the channel to be modified. +f_ulNewListenerMask New mask to apply to the selected participant. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiUpdateMaskModifyResources +UINT32 Oct6100ApiUpdateMaskModifyResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT32 f_ulNewListenerMask ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + + UINT32 ulResult = cOCT6100_ERR_OK; + UINT32 ulTempVar; + UINT32 ulOldListenerMask; + UINT16 usChannelIndex; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex ); + + /* Must travel all clients of this conference and reserve a load or accumulate event for */ + /* all participants which could not hear us but now can. While at it, check for events that */ + /* could be released, for example a participant that we cannot hear anymore. */ + + ulOldListenerMask = pParticipant->ulListenerMask; + + /* Search through the list of API channel entry for the ones on to this bridge.*/ + for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can now hear this participant, but could not before. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) + { + /* Must reserve a load or accumulate entry mixer event here! */ + ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Most probably, the hardware is out of mixer events. */ + break; + } + } + + /* Check if we can now NOT hear this participant, but could before. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) + { + /* Must release the load or accumulate entry mixer event. */ + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); + if ( ulResult != cOCT6100_ERR_OK ) + { + break; + } + } + } + } + } + + /* If an error is returned, make sure everything is cleaned up properly. */ + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Search through the list of API channel entry for the ones on to this bridge.*/ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can now hear this participant, but could not before. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) + { + /* If the load or event entry in the mixer memory was reserved. */ + if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) + { + /* Must release the load or accumulate entry mixer event. */ + ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + + pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + + /* Check if we can now NOT hear this participant, but could before. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) + { + /* If the load or event entry in the mixer memory was reserved. */ + if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] == cOCT6100_INVALID_INDEX ) + { + /* Must release the load or accumulate entry mixer event. */ + ulTempVar = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ) ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + } + } + } + } + + return ulResult; + } + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeUpdateMask + +Description: Update the participant's mask. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_usBridgeIndex Bridge index of the bridge where this channel is residing. +f_usChanIndex Channel index of the channel to be modified. +f_ulNewListenerMask New mask to apply to the selected participant. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeUpdateMask +UINT32 Oct6100ApiBridgeUpdateMask( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usChanIndex, + IN UINT32 f_ulNewListenerMask ) +{ + tPOCT6100_API_CHANNEL pChanEntry; + tPOCT6100_API_CHANNEL pTempEchoChanEntry; + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; + tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; + tOCT6100_WRITE_PARAMS WriteParams; + + UINT32 ulResult; + UINT32 ulOldListenerMask; + UINT16 usChannelIndex; + + UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; + UINT32 ulMutePortChannelIndex; + + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Get a pointer to the channel's list entry. */ + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex ); + + ulOldListenerMask = pParticipant->ulListenerMask; + + /* Search through the list of API channel entry for the ones onto this bridge. */ + for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); + + /* Channel reserved? */ + if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) + { + /* On current bridge? */ + if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) + { + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + /* Check if we can now hear this participant, but could not before. */ + if ( ( pTempEchoChanEntry->fMute == FALSE ) + && ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) + { + /* First create/update the current channel's mixer. */ + ulResult = Oct6100ApiBridgeAddParticipantToChannel( + f_pApiInstance, + f_usBridgeIndex, + usChannelIndex, + f_usChanIndex, + pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ], + pChanEntry->usSubStoreEventIndex, + pChanEntry->usSinCopyEventIndex, + pTempParticipant->ulInputPort, + pParticipant->ulInputPort ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( pParticipant->fFlexibleMixerCreated == TRUE ) + { + /* Check if the Rin silence event can be cleared now that the */ + /* channel has been added to a conference. */ + if ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + /* Remove the event from the list.*/ + ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, + pChanEntry->usRinSilenceEventIndex, + cOCT6100_EVENT_TYPE_SOUT_COPY ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_DF; + + pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; + } + } + } + + /* Check if we can now NOT hear this participant, but could before. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) + && ( pParticipant->fFlexibleMixerCreated == TRUE ) + && ( pTempEchoChanEntry->fMute == FALSE ) ) + { + /* First update the current channel's mixer. */ + ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( + f_pApiInstance, + f_usBridgeIndex, + usChannelIndex, + f_usChanIndex, + TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + if ( pParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Remember to mute the port on this channel. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == f_usChanIndex ) + { + break; + } + else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) + { + ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = f_usChanIndex; + break; + } + } + } + } + + /* Clear the load or accumulate event index for this participant. */ + if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) + && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) + { + pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; + } + } + } + + /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ + for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) + { + if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) + { + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); + + if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) + { + /* Check if the Rin port must be muted on this channel. */ + ulResult = Oct6100ApiMutePorts( + f_pApiInstance, + ausMutePortChannelIndexes[ ulMutePortChannelIndex ], + pTempEchoChanEntry->usRinTsstIndex, + pTempEchoChanEntry->usSinTsstIndex, + FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ + { + /* No more channels to check for muting. */ + break; + } + } + } + + /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ + if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) + { + if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usSinTsstIndex, + pChanEntry->usExtraSinTsiMemIndex, + pChanEntry->TdmConfig.bySinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ + if ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) + { + WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); + + WriteParams.ulWriteAddress += 2; + WriteParams.usWriteData = pChanEntry->usExtraSinTsiMemIndex; + + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Configure the RIN copy mixer entry and memory - if using the RIN port. */ + if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) + { + if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) + { + ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, + pChanEntry->usRinTsstIndex, + pChanEntry->usExtraRinTsiMemIndex, + pChanEntry->TdmConfig.byRinPcmLaw ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Save the new mask permanently in the API instance. */ + pParticipant->ulListenerMask = f_ulNewListenerMask; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ConfBridgeGetStatsSer + +Description: This function returns the statistics from the specified bridge. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pConfBridgeStats Pointer to conference bridge stats structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ConfBridgeGetStatsSer +UINT32 Oct6100ConfBridgeGetStatsSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + UINT16 usConfBridgeIndex; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) + return cOCT6100_ERR_CONF_BRIDGE_DISABLED; + + /*=====================================================================*/ + /* Check the conference bridge handle. */ + + /* Check the provided handle. */ + if ( (f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + usConfBridgeIndex = (UINT16)( f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); + if ( usConfBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, usConfBridgeIndex ) + + /* Extract the entry open count from the provided handle. */ + ulEntryOpenCnt = (f_pConfBridgeStats->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; + + /* Check for errors. */ + if ( pBridgeEntry->fReserved != TRUE ) + return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; + if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) + return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; + + /*=====================================================================*/ + + /* Return the stats.*/ + f_pConfBridgeStats->ulNumChannels = pBridgeEntry->usNumClients; + f_pConfBridgeStats->ulNumTappedChannels = pBridgeEntry->usNumTappedClients; + f_pConfBridgeStats->fFlexibleConferencing = pBridgeEntry->fFlexibleConferencing; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBridgeEntry + +Description: Reserves a free entry in the Bridge list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pusBridgeIndex List entry reserved. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReserveBridgeEntry +UINT32 Oct6100ApiReserveBridgeEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusBridgeIndex ) +{ + PVOID pBridgeAlloc; + UINT32 ulResult; + UINT32 ulBridgeIndex; + + mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc ) + + ulResult = OctapiLlmAllocAlloc( pBridgeAlloc, &ulBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) + return cOCT6100_ERR_CONF_BRIDGE_ALL_BUFFERS_OPEN; + else + return cOCT6100_ERR_FATAL_29; + } + + *f_pusBridgeIndex = (UINT16)( ulBridgeIndex & 0xFFFF ); + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBridgeEntry + +Description: Release an entry from the bridge list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usBridgeIndex List entry reserved. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReleaseBridgeEntry +UINT32 Oct6100ApiReleaseBridgeEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex ) +{ + PVOID pBridgeAlloc; + UINT32 ulResult; + + mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc ) + + ulResult = OctapiLlmAllocDealloc( pBridgeAlloc, f_usBridgeIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_2A; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiGetPrevLastSubStoreEvent + +Description: This function will search for the first valid LastSubStoreEvent + in a bridge located before the current bridge in the bridge + link list. + + If the function does not find an event before reaching the end + of the mixers list, then the event head node will be used as the + last Store or SubStore event. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_pusBridgeEntry Bridge entry. +f_usBridgeFirstLoadEventPtr Load index to check against. +First valid sub store index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiGetPrevLastSubStoreEvent +UINT32 Oct6100ApiGetPrevLastSubStoreEvent( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usBridgeIndex, + IN UINT16 f_usBridgeFirstLoadEventPtr, + OUT PUINT16 f_pusLastSubStoreEventIndex ) +{ + tPOCT6100_API_CONF_BRIDGE pBridgeEntry; + tPOCT6100_API_MIXER_EVENT pTempMixerEntry; + UINT16 usNextEventPtr; + UINT16 usHeadEventPtr; + UINT16 usLastSubStoreEventPtr; + UINT32 ulLoopCount = 0; + UINT16 usCurrentPtr; + UINT32 ulResult = cOCT6100_ERR_OK; + + /* Get current entry to obtain the link to the previous entry.*/ + mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); + + /* Since we have flexible bridges, we have to */ + /* run down the list and check for the appropriate event. */ + + /* Travel down the list for the last Store or Sub/Store event before the bridge. */ + + if ( f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) + { + /* The only node in the list then is the head node.*/ + usHeadEventPtr = cOCT6100_MIXER_HEAD_NODE; + } + else + { + usHeadEventPtr = f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; + } + + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usHeadEventPtr ); + usLastSubStoreEventPtr = usHeadEventPtr; + usNextEventPtr = pTempMixerEntry->usNextEventPtr; + usCurrentPtr = usHeadEventPtr; + while( usCurrentPtr != f_usBridgeFirstLoadEventPtr ) + { + if ( ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) + || ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) ) + { + usLastSubStoreEventPtr = usNextEventPtr; + } + + /* Next pointer. */ + usCurrentPtr = usNextEventPtr; + usNextEventPtr = pTempMixerEntry->usNextEventPtr; + + /* Check if next event pointer is valid. */ + if ( ( ( f_usBridgeFirstLoadEventPtr != usCurrentPtr ) + && ( pTempMixerEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) ) + || ( pTempMixerEntry->usNextEventPtr == cOCT6100_MIXER_HEAD_NODE ) ) + return cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; + + if ( usNextEventPtr != cOCT6100_INVALID_INDEX ) + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usNextEventPtr ); + + ulLoopCount++; + if ( ulLoopCount == cOCT6100_MAX_LOOP ) + return cOCT6100_ERR_FATAL_CA; + } + + /* Return the result to the user. */ + *f_pusLastSubStoreEventIndex = usLastSubStoreEventPtr; + + return ulResult; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiGetPreviousEvent + +Description: This is a recursive function, it requires an entry event index and + will run down the list until it finds the node just before the one + required. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usEntryIndex Event entry index. +f_pusBridgeEntry Bridge entry. +f_pusPreviousIndex Previous index. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiGetPreviousEvent +UINT32 Oct6100ApiGetPreviousEvent( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usEntryIndex, + IN UINT16 f_usSearchedIndex, + IN UINT16 f_usLoopCnt, + OUT PUINT16 f_pusPreviousIndex ) +{ + tPOCT6100_API_MIXER_EVENT pCurrentEntry; + UINT32 ulResult; + + /* Get current entry to obtain the link to the previous entry. */ + mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pCurrentEntry, f_usEntryIndex ); + + /* Avoid stack overflows. */ + if ( f_usLoopCnt == cOCT6100_MAX_MIXER_EVENTS ) + return cOCT6100_ERR_FATAL_E3; + + if ( pCurrentEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) + { + /* Event not found. */ + ulResult = cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; + } + else if ( pCurrentEntry->usNextEventPtr == f_usSearchedIndex ) + { + /* We found our node. */ + *f_pusPreviousIndex = f_usEntryIndex; + ulResult = cOCT6100_ERR_OK; + } + else + { + /* Keep searching.*/ + f_usLoopCnt++; + ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pCurrentEntry->usNextEventPtr, f_usSearchedIndex, f_usLoopCnt, f_pusPreviousIndex ); + } + + return ulResult; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiBridgeSetDominantSpeaker + +Description: This function will set the index of the dominant speaker + for the channel index specified. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to + keep the present state of the chip and all its + resources. + +f_usChannelIndex Index of the channel where the API must set the + current dominant speaker for the conference. +f_usDominantSpeakerIndex Index of the channel which is the dominant + speaker in the conference. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiBridgeSetDominantSpeaker +UINT32 Oct6100ApiBridgeSetDominantSpeaker( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usChannelIndex, + IN UINT16 f_usDominantSpeakerIndex ) +{ + UINT32 ulBaseAddress; + UINT32 ulFeatureBytesOffset; + UINT32 ulFeatureBitOffset; + UINT32 ulFeatureFieldLength; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulMask; + + tPOCT6100_API_CHANNEL pEchoChanEntry; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, f_usChannelIndex ); + + ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst; + ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.usDwordOffset * 4; + ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byBitOffset; + ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byFieldSize; + + /* Retrieve the current configuration. */ + ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, + pEchoChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + &ulTempData); + 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. */ + ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, + pEchoChanEntry, + ulBaseAddress + ulFeatureBytesOffset, + ulTempData); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveFlexConfParticipantEntry + +Description: Reserves a free entry in the participant list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. +f_pusParticipantIndex List entry reserved. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReserveFlexConfParticipantEntry +UINT32 Oct6100ApiReserveFlexConfParticipantEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT16 f_pusParticipantIndex ) +{ + PVOID pParticipantAlloc; + UINT32 ulResult; + UINT32 ulParticipantIndex; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc ) + + ulResult = OctapiLlmAllocAlloc( pParticipantAlloc, &ulParticipantIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) + return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_ALL_BUFFERS_OPEN; + else + return cOCT6100_ERR_FATAL_29; + } + + *f_pusParticipantIndex = (UINT16)( ulParticipantIndex & 0xFFFF ); + + return cOCT6100_ERR_OK; +} +#endif + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseFlexConfParticipantEntry + +Description: Release an entry from the flexible conferencing participant + list. + +------------------------------------------------------------------------------- +| Argument | Description +------------------------------------------------------------------------------- +f_pApiInstance Pointer to API instance. This memory is used to keep the + present state of the chip and all its resources. + +f_usParticipantIndex List entry reserved. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +#if !SKIP_Oct6100ApiReleaseFlexConfParticipantEntry +UINT32 Oct6100ApiReleaseFlexConfParticipantEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT16 f_usParticipantIndex ) +{ + PVOID pParticipantAlloc; + UINT32 ulResult; + + mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc ) + + ulResult = OctapiLlmAllocDealloc( pParticipantAlloc, f_usParticipantIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_2A; + + return cOCT6100_ERR_OK; +} +#endif -- cgit v1.2.3