dahdi-tools/xpp/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c
Tzafrir Cohen d3cadf5352 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.astersk.org/svn/dahdi/tools/trunk@10030 17933a7a-c749-41c5-a318-cba88f637d49
2011-07-10 16:10:32 +00:00

7684 lines
289 KiB
C

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
File: oct6100_conf_bridge.c
Copyright (c) 2001-2007 Octasic Inc.
Description:
This file contains all functions related to a conference bridge. Procedures
needed to open/close a bridge, add/remove a participant to a conference
bridge, mute/unmute a participant, etc.. are all present in this source
file.
This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is
free software; you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
The OCT6100 GPL API is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with the OCT6100 GPL API; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
$Octasic_Release: OCT612xAPI-01.00-PR49 $
$Octasic_Revision: 146 $
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/***************************** INCLUDE FILES *******************************/
#include "octdef.h"
#include "oct6100api/oct6100_defines.h"
#include "oct6100api/oct6100_errors.h"
#include "oct6100api/oct6100_apiud.h"
#include "apilib/octapi_llman.h"
#include "oct6100api/oct6100_tlv_inst.h"
#include "oct6100api/oct6100_chip_open_inst.h"
#include "oct6100api/oct6100_chip_stats_inst.h"
#include "oct6100api/oct6100_interrupts_inst.h"
#include "oct6100api/oct6100_remote_debug_inst.h"
#include "oct6100api/oct6100_debug_inst.h"
#include "oct6100api/oct6100_api_inst.h"
#include "oct6100api/oct6100_channel_inst.h"
#include "oct6100api/oct6100_mixer_inst.h"
#include "oct6100api/oct6100_conf_bridge_inst.h"
#include "oct6100api/oct6100_interrupts_pub.h"
#include "oct6100api/oct6100_chip_open_pub.h"
#include "oct6100api/oct6100_channel_pub.h"
#include "oct6100api/oct6100_mixer_pub.h"
#include "oct6100api/oct6100_conf_bridge_pub.h"
#include "oct6100_chip_open_priv.h"
#include "oct6100_miscellaneous_priv.h"
#include "oct6100_memory_priv.h"
#include "oct6100_tsst_priv.h"
#include "oct6100_channel_priv.h"
#include "oct6100_mixer_priv.h"
#include "oct6100_conf_bridge_priv.h"
/**************************** PUBLIC FUNCTIONS *****************************/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeOpen
Description: This function opens a conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeOpen Pointer to conference bridge open structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeOpenDef
UINT32 Oct6100ConfBridgeOpenDef(
tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen )
{
f_pConfBridgeOpen->pulConfBridgeHndl = NULL;
f_pConfBridgeOpen->fFlexibleConferencing = FALSE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeOpen
UINT32 Oct6100ConfBridgeOpen(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure.*/
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeOpenSer( f_pApiInstance, f_pConfBridgeOpen );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeClose
Description: This function closes a conference bridge. A conference
bridge can only be closed if no participants are present on
the bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeClose Pointer to conference bridge close structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeCloseDef
UINT32 Oct6100ConfBridgeCloseDef(
tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose )
{
f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeClose
UINT32 Oct6100ConfBridgeClose(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure. */
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeCloseSer( f_pApiInstance, f_pConfBridgeClose );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeChanAdd
Description: This function adds an echo channel (participant) to a
conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeAdd Pointer to conference bridge channel addition structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanAddDef
UINT32 Oct6100ConfBridgeChanAddDef(
tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd )
{
f_pConfBridgeAdd->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT;
f_pConfBridgeAdd->ulListenerMaskIndex = cOCT6100_INVALID_VALUE;
f_pConfBridgeAdd->ulListenerMask = 0;
f_pConfBridgeAdd->fMute = FALSE;
f_pConfBridgeAdd->ulTappedChannelHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeChanAdd
UINT32 Oct6100ConfBridgeChanAdd(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure. */
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeChanAddSer( f_pApiInstance, f_pConfBridgeAdd );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeChanRemove
Description: This function removes an echo channel (participant) from a
conference bridge. All participants can be removed from
the bridge if a special flag (fRemoveAll) is set to TRUE.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeRemove Pointer to conference bridge channel removal structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanRemoveDef
UINT32 Oct6100ConfBridgeChanRemoveDef(
tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove )
{
f_pConfBridgeRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeRemove->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeRemove->fRemoveAll = FALSE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeChanRemove
UINT32 Oct6100ConfBridgeChanRemove(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure.*/
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, f_pConfBridgeRemove );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeChanMute
Description: This function mutes a participant present on a conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeMute Pointer to conference bridge channel mute structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanMuteDef
UINT32 Oct6100ConfBridgeChanMuteDef(
tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute )
{
f_pConfBridgeMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeChanMute
UINT32 Oct6100ConfBridgeChanMute(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure. */
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeChanMuteSer( f_pApiInstance, f_pConfBridgeMute );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeChanUnMute
Description: This function unmutes a channel on a bridge. The other member
of the conference will start to hear this participant again.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanUnMuteDef
UINT32 Oct6100ConfBridgeChanUnMuteDef(
tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute )
{
f_pConfBridgeUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeChanUnMute
UINT32 Oct6100ConfBridgeChanUnMute(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure.*/
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeChanUnMuteSer( f_pApiInstance, f_pConfBridgeUnMute );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeDominantSpeakerSet
Description: This function sets a participant present on a conference
bridge as the dominant speaker.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to
keep the present state of the chip and all its
resources.
f_pConfBridgeDominant Pointer to conference bridge dominant speaker
structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetDef
UINT32 Oct6100ConfBridgeDominantSpeakerSetDef(
tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker )
{
f_pConfBridgeDominantSpeaker->ulChannelHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeDominantSpeaker->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeDominantSpeakerSet
UINT32 Oct6100ConfBridgeDominantSpeakerSet(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure.*/
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeDominantSpeakerSetSer( f_pApiInstance, f_pConfBridgeDominantSpeaker );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeMaskChange
Description: This function changes the mask of a flexible bridge participant.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to
keep the present state of the chip and all its
resources.
f_pConfBridgeMaskChange Pointer to conference bridge change of mask
structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeMaskChangeDef
UINT32 Oct6100ConfBridgeMaskChangeDef(
tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange )
{
f_pConfBridgeMaskChange->ulChannelHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeMaskChange->ulNewListenerMask = 0x0;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeMaskChange
UINT32 Oct6100ConfBridgeMaskChange(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure. */
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeMaskChangeSer( f_pApiInstance, f_pConfBridgeMaskChange );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeGetStats
Description: This function returns the stats for a conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeStats Pointer to conference bridge channel stats structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeGetStatsDef
UINT32 Oct6100ConfBridgeGetStatsDef(
tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats )
{
f_pConfBridgeStats->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
f_pConfBridgeStats->ulNumChannels = cOCT6100_INVALID_STAT;
f_pConfBridgeStats->ulNumTappedChannels = cOCT6100_INVALID_STAT;
f_pConfBridgeStats->fFlexibleConferencing = cOCT6100_INVALID_STAT;
return cOCT6100_ERR_OK;
}
#endif
#if !SKIP_Oct6100ConfBridgeGetStats
UINT32 Oct6100ConfBridgeGetStats(
tPOCT6100_INSTANCE_API f_pApiInstance,
tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats )
{
tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj;
tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj;
UINT32 ulSerRes = cOCT6100_ERR_OK;
UINT32 ulFncRes = cOCT6100_ERR_OK;
/* Set the process context of the serialize structure. */
SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext;
ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext;
/* Seize all list semaphores needed by this function. */
SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY;
ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj );
if ( ulSerRes == cOCT6100_ERR_OK )
{
/* Call the serialized function. */
ulFncRes = Oct6100ConfBridgeGetStatsSer( f_pApiInstance, f_pConfBridgeStats );
}
else
{
return ulSerRes;
}
/* Release the seized semaphores. */
ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );
/* If an error occured then return the error code. */
if ( ulSerRes != cOCT6100_ERR_OK )
return ulSerRes;
if ( ulFncRes != cOCT6100_ERR_OK )
return ulFncRes;
return cOCT6100_ERR_OK;
}
#endif
/**************************** PRIVATE FUNCTIONS ****************************/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiGetConfBridgeSwSizes
Description: Gets the sizes of all portions of the API instance pertinent
to the management of conference bridges.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pOpenChip Pointer to chip configuration struct.
f_pInstSizes Pointer to struct containing instance sizes.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetConfBridgeSwSizes
UINT32 Oct6100ApiGetConfBridgeSwSizes(
IN tPOCT6100_CHIP_OPEN f_pOpenChip,
OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes )
{
UINT32 ulTempVar;
UINT32 ulResult;
/* Calculate memory needed for conference bridge list. */
if ( f_pOpenChip->ulMaxConfBridges == 0 && f_pOpenChip->fEnableChannelRecording == TRUE )
f_pOpenChip->ulMaxConfBridges = 1;
f_pInstSizes->ulConfBridgeList = f_pOpenChip->ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE );
/* Calculate memory needed for conference bridge allocation software. */
if ( f_pOpenChip->ulMaxConfBridges > 0 )
{
/* Get size of bridge allocation memory */
ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxConfBridges, &f_pInstSizes->ulConfBridgeAlloc );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_1C;
/* Check if the user wants to build flexible conference bridges. */
if ( f_pOpenChip->ulMaxFlexibleConfParticipants > 0 )
{
/* Allocate the lowest quantity according to what the user requested. */
if ( f_pOpenChip->ulMaxFlexibleConfParticipants < ( f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) )
f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxFlexibleConfParticipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT );
else
{
f_pOpenChip->ulMaxFlexibleConfParticipants = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE;
f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT );
}
/* Get size of flexible conferencing participants allocation memory */
ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxFlexibleConfParticipants, &f_pInstSizes->ulFlexConfParticipantsAlloc );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_1C;
}
else
{
f_pInstSizes->ulFlexConfParticipantsList = 0;
f_pInstSizes->ulFlexConfParticipantsAlloc = 0;
}
}
else
{
f_pInstSizes->ulMixerEventList = 0;
f_pInstSizes->ulMixerEventAlloc = 0;
f_pInstSizes->ulConfBridgeAlloc = 0;
/* Make sure flexible conferencing is not used. */
f_pInstSizes->ulFlexConfParticipantsList = 0;
f_pInstSizes->ulFlexConfParticipantsAlloc = 0;
}
/* Calculate memory needed for list and allocation software serialization. */
mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeList, ulTempVar )
mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeAlloc, ulTempVar )
mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsList, ulTempVar )
mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsAlloc, ulTempVar )
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiConfBridgeSwInit
Description: Initializes all elements of the instance structure associated
to conference bridges.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep
the present state of the chip and all its resources.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiConfBridgeSwInit
UINT32 Oct6100ApiConfBridgeSwInit(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance )
{
tPOCT6100_SHARED_INFO pSharedInfo;
tPOCT6100_API_CONF_BRIDGE pConfBridgeList;
tPOCT6100_API_FLEX_CONF_PARTICIPANT pFlexConfParticipantList;
PVOID pFlexConfPartipantsAlloc;
UINT32 ulMaxFlexConfParicipants;
PVOID pConfBridgeAlloc;
UINT32 ulMaxConfBridges;
UINT32 ulResult;
/* Get local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
/* Get the maximum number of conference bridges. */
ulMaxConfBridges = pSharedInfo->ChipConfig.usMaxConfBridges;
/*===================================================================*/
/* Set all entries in the conference bridge list to unused. */
mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pConfBridgeList );
/* Initialize the conference bridge allocation software to "all free". */
if ( ulMaxConfBridges > 0 )
{
/* Clear the bridge memory */
Oct6100UserMemSet( pConfBridgeList, 0x00, ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE ));
mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pConfBridgeAlloc )
ulResult = OctapiLlmAllocInit( &pConfBridgeAlloc, ulMaxConfBridges );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_1E;
}
/*===================================================================*/
/*===================================================================*/
/* Set all entries in the flexible conferencing participant list to unused. */
/* Get the maximum number of flexible conferencing participants. */
ulMaxFlexConfParicipants = pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants;
mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pFlexConfParticipantList );
/* Initialize the flexible conferencing allocation software. */
if ( ulMaxFlexConfParicipants > 0 )
{
UINT32 i, ulEventIndex;
/* Clear the participants memory */
Oct6100UserMemSet( pFlexConfParticipantList, 0x00, ulMaxFlexConfParicipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ));
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pFlexConfPartipantsAlloc )
ulResult = OctapiLlmAllocInit( &pFlexConfPartipantsAlloc, ulMaxFlexConfParicipants );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_1E;
/* Initialize the conferencing indexes. */
for ( i = 0; i < ulMaxFlexConfParicipants; i ++ )
{
for ( ulEventIndex = 0; ulEventIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulEventIndex ++ )
pFlexConfParticipantList[ i ].ausLoadOrAccumulateEventIndex[ ulEventIndex ] = cOCT6100_INVALID_INDEX;
}
}
/*===================================================================*/
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeOpenSer
Description: Open a conference bridge. Note that no chip resources are
allocated until a channel is added to the bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeOpen Pointer to conference bridge configuration structure.
The handle identifying the conference bridge in all
future function calls is returned in this structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeOpenSer
UINT32 Oct6100ConfBridgeOpenSer(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen )
{
UINT16 usBridgeIndex;
UINT32 ulResult;
/* Check the user's configuration of the conference bridge for errors. */
ulResult = Oct6100ApiCheckBridgeParams( f_pApiInstance, f_pConfBridgeOpen );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Reserve all resources needed by the conference bridge. */
ulResult = Oct6100ApiReserveBridgeResources( f_pApiInstance, &usBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Update the new conference bridge's entry in the conference bridge list. */
ulResult = Oct6100ApiUpdateBridgeEntry( f_pApiInstance, f_pConfBridgeOpen, usBridgeIndex);
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiCheckBridgeParams
Description: Checks the user's conference bridge open configuration for errors.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeOpen Pointer to conference bridge configuration structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeParams
UINT32 Oct6100ApiCheckBridgeParams(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen )
{
/* Check for errors. */
if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
if ( f_pConfBridgeOpen->pulConfBridgeHndl == NULL )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencing == FALSE )
return cOCT6100_ERR_NOT_SUPPORTED_CONF_BRIDGE;
if ( f_pConfBridgeOpen->fFlexibleConferencing != FALSE
&& f_pConfBridgeOpen->fFlexibleConferencing != TRUE )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiReserveBridgeResources
Description: Reserves all resources needed for the new conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pusBridgeIndex Allocated entry in the API conference bridge list.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveBridgeResources
UINT32 Oct6100ApiReserveBridgeResources(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
OUT PUINT16 f_pusBridgeIndex )
{
tPOCT6100_SHARED_INFO pSharedInfo;
UINT32 ulResult;
/* Obtain local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
/* Reserve an entry in the conference bridge list. */
ulResult = Oct6100ApiReserveBridgeEntry( f_pApiInstance, f_pusBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiUpdateBridgeEntry
Description: Updates the new conference bridge's entry in the conference
bridge list.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep
the present state of the chip and all its resources.
f_pConfBridgeOpen Pointer to conference bridge configuration structure.
f_usBridgeIndex Allocated entry in API conference bridge list.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUpdateBridgeEntry
UINT32 Oct6100ApiUpdateBridgeEntry(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen,
IN UINT16 f_usBridgeIndex )
{
tPOCT6100_API_CONF_BRIDGE pBridgeEntry;
tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry;
/*================================================================================*/
/* Obtain a pointer to the new conference bridge's list entry. */
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex )
/* No clients are currently connected to the bridge. */
pBridgeEntry->usNumClients = 0;
/* Nobody is tapped for now. */
pBridgeEntry->usNumTappedClients = 0;
pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX;
/* Now update the bridge pointer. */
if ( f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened == 0 )
{
pBridgeEntry->usNextBridgePtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX;
/* Set the global first bridge to this bridge. */
f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex;
}
else /* Insert this bridge at the head of the bridge list.*/
{
if ( f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge == cOCT6100_INVALID_INDEX )
return cOCT6100_ERR_FATAL_22;
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge )
if ( pTempBridgeEntry->fReserved != TRUE )
return cOCT6100_ERR_FATAL_23;
/* Modify the old first entry. */
pTempBridgeEntry->usPrevBridgePtr = f_usBridgeIndex;
/* Modify current pointer. */
pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX;
pBridgeEntry->usNextBridgePtr = f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge;
/* Set the new first bridge of the list. */
f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex;
}
/* Form handle returned to user. */
*f_pConfBridgeOpen->pulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBridgeIndex;
/* Remember whether or not we are a flexible conference bridge. */
pBridgeEntry->fFlexibleConferencing = (UINT8)( f_pConfBridgeOpen->fFlexibleConferencing & 0xFF );
/* Finally, mark the conference bridge as opened. */
pBridgeEntry->fReserved = TRUE;
/* Increment the number of conference bridge opened. */
f_pApiInstance->pSharedInfo->ChipStats.usNumberConfBridges++;
f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened++;
/*================================================================================*/
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeCloseSer
Description: Closes a conference bridge. Note that no client must be present
on the bridge for the bridge to be closed.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeClose Pointer to conference bridge close structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeCloseSer
UINT32 Oct6100ConfBridgeCloseSer(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose )
{
UINT16 usBridgeIndex;
UINT32 ulResult;
/* Verify that all the parameters given match the state of the API. */
ulResult = Oct6100ApiAssertBridgeParams( f_pApiInstance, f_pConfBridgeClose, &usBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Release all resources associated to the conference bridge. */
ulResult = Oct6100ApiReleaseBridgeResources( f_pApiInstance, usBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Invalidate the handle. */
f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiAssertBridgeParams
Description: Checks the user's conference bridge close configuration for errors.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeClose Pointer to conference bridge close structure.
f_pusBridgeIndex Pointer to API instance conference bridge index.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiAssertBridgeParams
UINT32 Oct6100ApiAssertBridgeParams(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose,
OUT PUINT16 f_pusBridgeIndex )
{
tPOCT6100_API_CONF_BRIDGE pBridgeEntry;
UINT32 ulEntryOpenCnt;
/* Check the provided handle. */
if ( (f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
*f_pusBridgeIndex = (UINT16)( f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )
/* Extract the entry open count from the provided handle. */
ulEntryOpenCnt = (f_pConfBridgeClose->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
/* Check for errors. */
if ( pBridgeEntry->fReserved != TRUE )
return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
if ( pBridgeEntry->usNumClients != 0 )
return cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES;
if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiReleaseBridgeResources
Description: Release all resources reserved for the conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_usBridgeIndex Allocated external memory block for the conference bridge.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReleaseBridgeResources
UINT32 Oct6100ApiReleaseBridgeResources(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN UINT16 f_usBridgeIndex )
{
tPOCT6100_SHARED_INFO pSharedInfo;
tPOCT6100_API_CONF_BRIDGE pBridgeEntry;
tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry;
UINT32 ulResult;
/* Obtain local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
/* Release the entry from the conference bridge list. */
ulResult = Oct6100ApiReleaseBridgeEntry( f_pApiInstance, f_usBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_24;
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex );
/* Remove the bridge entry from the bridge list. */
if ( pSharedInfo->MiscVars.usNumBridgesOpened == 1 )
{
/* This bridge was the only one opened. */
pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX;
}
else if ( pSharedInfo->MiscVars.usNumBridgesOpened > 1 )
{
/* There are more then one bridge open, must update the list. */
if ( pBridgeEntry->usPrevBridgePtr != cOCT6100_INVALID_INDEX )
{
/* There is a valid entry before this bridge, let's update this entry. */
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usPrevBridgePtr );
pTempBridgeEntry->usNextBridgePtr = pBridgeEntry->usNextBridgePtr;
}
if ( pBridgeEntry->usNextBridgePtr != cOCT6100_INVALID_INDEX )
{
/* There is a valid entry after this bridge, let's update this entry. */
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usNextBridgePtr );
pTempBridgeEntry->usPrevBridgePtr = pBridgeEntry->usPrevBridgePtr;
}
if ( pSharedInfo->MiscVars.usFirstBridge == f_usBridgeIndex )
{
/* This entry was the first of the list, make the next one be the first now. */
pSharedInfo->MiscVars.usFirstBridge = pBridgeEntry->usNextBridgePtr;
}
}
else
{
/* Variable has become out of sync. */
return cOCT6100_ERR_FATAL_25;
}
/*=============================================================*/
/* Update the conference bridge's list entry. */
/* Mark the bridge as closed. */
pBridgeEntry->fFlexibleConferencing = FALSE;
pBridgeEntry->fReserved = FALSE;
pBridgeEntry->byEntryOpenCnt++;
/* Decrement the number of conference bridges opened. */
pSharedInfo->MiscVars.usNumBridgesOpened--;
pSharedInfo->ChipStats.usNumberConfBridges--;
/*=============================================================*/
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ConfBridgeChanAddSer
Description: Adds an echo channel (participant) to a conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeAdd Pointer to conference bridge channel add structure.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ConfBridgeChanAddSer
UINT32 Oct6100ConfBridgeChanAddSer(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd )
{
UINT16 usBridgeIndex;
UINT16 usChanIndex;
UINT16 usLoadEventIndex;
UINT16 usSubStoreEventIndex;
UINT16 usCopyEventIndex;
UINT32 ulInputPort;
UINT8 fFlexibleConfBridge;
UINT32 ulListenerMaskIndex;
UINT32 ulListenerMask;
UINT16 usTapChanIndex;
UINT16 usTapBridgeIndex;
UINT8 fMute;
UINT8 fTap;
UINT32 ulResult;
/* Check the validity of the channel and conference bridge given. */
ulResult = Oct6100ApiCheckBridgeAddParams(
f_pApiInstance,
f_pConfBridgeAdd,
&usBridgeIndex,
&usChanIndex,
&fMute,
&ulInputPort,
&fFlexibleConfBridge,
&ulListenerMaskIndex,
&ulListenerMask,
&fTap,
&usTapChanIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Reserve all resources needed by the conference bridge. */
ulResult = Oct6100ApiReserveBridgeAddResources(
f_pApiInstance,
usBridgeIndex,
usChanIndex,
ulInputPort,
fFlexibleConfBridge,
ulListenerMaskIndex,
ulListenerMask,
fTap,
&usLoadEventIndex,
&usSubStoreEventIndex,
&usCopyEventIndex,
&usTapBridgeIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Reserve all resources needed by the conference bridge. */
ulResult = Oct6100ApiBridgeEventAdd(
f_pApiInstance,
usBridgeIndex,
usChanIndex,
fFlexibleConfBridge,
usLoadEventIndex,
usSubStoreEventIndex,
usCopyEventIndex,
ulInputPort,
fMute,
ulListenerMaskIndex,
ulListenerMask,
fTap,
usTapBridgeIndex,
usTapChanIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiCheckBridgeAddParams
Description: Check the validity of the channel and conference bridge given.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_pConfBridgeAdd Pointer to conference bridge channenl add structure.
f_pusBridgeIndex Extracted bridge index where this channel should be
added.
f_pusChannelIndex Extracted channel index related to the channel handle
to be added to the bridge.
f_pfMute Whether to mute this channel in the bridge or not.
f_pulInputPort Input port where the channel signal should be
copied from.
f_pfFlexibleConfBridge If this is a flexible conference bridge.
f_pulListenerMaskIndex Index of the listener in this flexible conference bridge.
f_pulListenerMask Mask of listeners in this flexible conference bridge.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckBridgeAddParams
UINT32 Oct6100ApiCheckBridgeAddParams(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd,
OUT PUINT16 f_pusBridgeIndex,
OUT PUINT16 f_pusChannelIndex,
OUT PUINT8 f_pfMute,
OUT PUINT32 f_pulInputPort,
OUT PUINT8 f_pfFlexibleConfBridge,
OUT PUINT32 f_pulListenerMaskIndex,
OUT PUINT32 f_pulListenerMask,
OUT PUINT8 f_pfTap,
OUT PUINT16 f_pusTapChannelIndex )
{
tPOCT6100_API_CONF_BRIDGE pBridgeEntry;
tPOCT6100_API_CHANNEL pEchoChanEntry;
UINT32 ulEntryOpenCnt;
UINT8 byTapChannelLaw;
/* Check for errors. */
if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 )
return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 1 &&
f_pApiInstance->pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_DISABLED;
if ( f_pConfBridgeAdd->ulConfBridgeHndl == cOCT6100_INVALID_HANDLE )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
if ( f_pConfBridgeAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;
if( f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_SOUT
&& f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_RIN )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_INPUT_PORT;
if ( f_pConfBridgeAdd->fMute != TRUE && f_pConfBridgeAdd->fMute != FALSE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MUTE;
/*=====================================================================*/
/* Check the conference bridge handle. */
if ( (f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
*f_pusBridgeIndex = (UINT16)( f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex )
/* Extract the entry open count from the provided handle. */
ulEntryOpenCnt = (f_pConfBridgeAdd->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
/* Check for errors. */
if ( pBridgeEntry->fReserved != TRUE )
return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
/* When we a flexible conference bridge, more things need to be checked. */
if ( pBridgeEntry->fFlexibleConferencing == TRUE )
{
/* Check if flexible conferencing has been activated. */
if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants == 0 )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_DISABLED;
/* Check the number of clients on the bridge. */
if ( pBridgeEntry->usNumClients >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_PARTICIPANT_CNT;
/* Check if the listener index in a flexible bridge is valid. */
if ( f_pConfBridgeAdd->ulListenerMaskIndex == cOCT6100_INVALID_VALUE
|| f_pConfBridgeAdd->ulListenerMaskIndex >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_MASK_INDEX;
}
if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
{
if ( pBridgeEntry->fFlexibleConferencing == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_TAP_NOT_SUPPORTED;
}
/*=====================================================================*/
/*=====================================================================*/
/* Check the channel handle. */
if ( (f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;
*f_pusChannelIndex = (UINT16)( f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK );
if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE;
mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex )
/* Extract the entry open count from the provided handle. */
ulEntryOpenCnt = (f_pConfBridgeAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
/* Check for errors. */
if ( pEchoChanEntry->fReserved != TRUE )
return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE;
if ( pEchoChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ALREADY_ON_BRIDGE;
if ( pEchoChanEntry->fBiDirChannel == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_BIDIR;
/* Law conversion is not allowed on a conference bridge. */
if ( ( pEchoChanEntry->TdmConfig.usRinTimeslot != cOCT6100_UNASSIGNED )
&& ( pEchoChanEntry->TdmConfig.usRoutTimeslot != cOCT6100_UNASSIGNED ) )
{
if ( pEchoChanEntry->TdmConfig.byRinPcmLaw != pEchoChanEntry->TdmConfig.byRoutPcmLaw )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION;
}
if ( ( pEchoChanEntry->TdmConfig.usSinTimeslot != cOCT6100_UNASSIGNED )
&& ( pEchoChanEntry->TdmConfig.usSoutTimeslot != cOCT6100_UNASSIGNED ) )
{
if ( pEchoChanEntry->TdmConfig.bySinPcmLaw != pEchoChanEntry->TdmConfig.bySoutPcmLaw )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION;
}
if ( pEchoChanEntry->fRinRoutCodecActive == TRUE || pEchoChanEntry->fSinSoutCodecActive == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_CODEC_ACTIVE;
if ( pEchoChanEntry->fEnableExtToneDetection == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_EXT_TONE_ENABLED;
if ( pEchoChanEntry->usCopyEventCnt != 0x0 )
return cOCT6100_ERR_CONF_BRIDGE_COPY_EVENTS;
/* If the bridge is flexible, few more things need to be checked. */
if ( pBridgeEntry->fFlexibleConferencing == TRUE )
{
tPOCT6100_SHARED_INFO pSharedInfo;
UINT16 usChannelIndex;
UINT32 ulResult = cOCT6100_ERR_OK;
/* Obtain local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
/* Check if the listener index has been used by another channel in the specified bridge. */
for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ )
{
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex );
/* Channel reserved? */
if ( ( usChannelIndex != ( *f_pusChannelIndex ) ) && ( pEchoChanEntry->fReserved == TRUE ) )
{
/* On current bridge? */
if ( pEchoChanEntry->usBridgeIndex == ( *f_pusBridgeIndex ) )
{
tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pEchoChanEntry->usFlexConfParticipantIndex );
/* Check if this participant has the same listener index. */
if ( f_pConfBridgeAdd->ulListenerMaskIndex == pCurrentParticipant->ulListenerMaskIndex )
return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_INDEX_USED;
}
}
}
}
if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
{
/* For internal logic, make sure the mute flag is set to false. */
f_pConfBridgeAdd->fMute = FALSE;
/* Force input port to Sout for logic below. */
f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT;
/* Keep law to check for conversion. */
/* Check if the same law. */
byTapChannelLaw = pEchoChanEntry->TdmConfig.bySoutPcmLaw;
/* Check the tap handle. */
if ( (f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;
*f_pusTapChannelIndex = (UINT16)( f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_INDEX_MASK );
if ( *f_pusTapChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;
mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusTapChannelIndex )
/* Extract the entry open count from the provided handle. */
ulEntryOpenCnt = (f_pConfBridgeAdd->ulTappedChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK;
/* Check for errors. */
if ( pEchoChanEntry->fReserved != TRUE )
return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN;
if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE;
if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_BRIDGE;
if ( pEchoChanEntry->usBridgeIndex != *f_pusBridgeIndex )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_SAME_BRIDGE;
/* We can only tap a channel added on the Sout port. */
if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_TAP_SOUT_ONLY;
/* Check if already tapped. */
if ( pEchoChanEntry->fBeingTapped == TRUE )
return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_ALREADY_TAPPED;
}
/*=====================================================================*/
/* Return the tap flag. */
if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE )
{
*f_pfTap = TRUE;
}
else
{
*f_pfTap = FALSE;
}
/* Return the mute config specified. */
*f_pfMute = (UINT8)( f_pConfBridgeAdd->fMute & 0xFF );
/* Return the input port specified. */
*f_pulInputPort = f_pConfBridgeAdd->ulInputPort;
/* Return whether we are in the flexible conference bridge case. */
*f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing;
/* Return the listener mask index as specified. */
*f_pulListenerMaskIndex = f_pConfBridgeAdd->ulListenerMaskIndex;
/* Return the listener mask as specified. */
*f_pulListenerMask = f_pConfBridgeAdd->ulListenerMask;
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiReserveBridgeAddResources
Description: Reserves all resources needed for the addition of a channel to
the conference bridge.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to keep the
present state of the chip and all its resources.
f_usBridgeIndex Bridge index of the bridge where this channel is added.
f_usChanIndex Channel index of the channel to be added to the bridge.
f_ulInputPort Input port where to copy samples from.
f_fFlexibleConfBridge If this is a flexible conference bridge.
f_ulListenerMaskIndex Index of the listener in this flexible conference bridge.
f_ulListenerMask Mask of listeners in this flexible conference bridge.
f_pusLoadEventIndex Load event index within the API's list of mixer event.
f_pusSubStoreEventIndex Sub-Store event index within the API's list of mixer event.
f_pusCopyEventIndex Copy event index within the API's list of mixer event.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiReserveBridgeAddResources
UINT32 Oct6100ApiReserveBridgeAddResources(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN UINT16 f_usBridgeIndex,
IN UINT16 f_usChanIndex,
IN UINT32 f_ulInputPort,
IN UINT8 f_fFlexibleConfBridge,
IN UINT32 f_ulListenerMaskIndex,
IN UINT32 f_ulListenerMask,
IN UINT8 f_fTap,
OUT PUINT16 f_pusLoadEventIndex,
OUT PUINT16 f_pusSubStoreEventIndex,
OUT PUINT16 f_pusCopyEventIndex,
OUT PUINT16 f_pusTapBridgeIndex )
{
tPOCT6100_API_CHANNEL pChanEntry;
tPOCT6100_SHARED_INFO pSharedInfo;
tPOCT6100_API_CHANNEL pTempEchoChanEntry;
UINT32 ulResult;
UINT32 ulTempVar;
UINT16 usChannelIndex;
BOOL fLoadEventReserved = FALSE;
BOOL fStoreEventReserved = FALSE;
BOOL fCopyEventReserved = FALSE;
BOOL fExtraSinTsiReserved = FALSE;
BOOL fExtraRinTsiReserved = FALSE;
/* Obtain local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
/* Get a pointer to the channel's list entry. */
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex )
/* Resources must be reserved according to the type of bridge we are adding to. */
if ( f_fFlexibleConfBridge == TRUE )
{
tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant;
tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;
/*========================================================================*/
/* If we are in the flexible conferencing case, things are a little */
/* different. We create a mixer for every participant instead of the */
/* usual same mixer for everyone. For example, if we have 3 participants */
/* of type client - agent - coach, we build the mixers as follows: */
/* */
/* Client: - Load Agent */
/* - Store */
/* */
/* Agent: - Load Client */
/* - Accumulate Coach */
/* - Store */
/* */
/* Coach: - Load Client */
/* - Accumulate Agent */
/* - Store */
/* */
/*========================================================================*/
/* First reserve a flexible conferencing participant entry. */
ulResult = Oct6100ApiReserveFlexConfParticipantEntry( f_pApiInstance, &pChanEntry->usFlexConfParticipantIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pChanEntry->usFlexConfParticipantIndex );
/* Reserve an entry for the store event in the mixer memory. */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex );
if ( ulResult == cOCT6100_ERR_OK )
{
/* If using the SOUT port, we must copy this entry */
if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
{
/* Reserve an entry for the copy event in the Mixer memory. */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex );
if ( ulResult == cOCT6100_ERR_OK )
{
fCopyEventReserved = TRUE;
/* Reserve a SIN copy entry if none were reserved before.*/
if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX )
{
/* Reserve an entry for the extra tsi chariot memory. */
ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance,
&pChanEntry->usExtraSinTsiMemIndex );
if ( ulResult == cOCT6100_ERR_OK )
fExtraSinTsiReserved = TRUE;
}
}
}
else /* if( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
{
/* Reserve a RIN copy entry if none were reserved before.*/
if ( pChanEntry->usExtraRinTsiMemIndex == cOCT6100_INVALID_INDEX )
{
/* Reserve an entry for the extra tsi chariot memory. */
ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance,
&pChanEntry->usExtraRinTsiMemIndex );
if ( ulResult == cOCT6100_ERR_OK )
fExtraRinTsiReserved = TRUE;
}
}
/* Must travel all clients of this conference and reserve a load or accumulate event for */
/* all participants which can hear us. */
/* Search through the list of API channel entry for the ones on to this bridge.*/
for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ )
{
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
/* Channel reserved? */
if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
{
/* On current bridge? */
if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
{
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
/* Check if we can hear this participant. */
if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 )
{
/* Must reserve a load or accumulate entry mixer event here! */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] );
if ( ulResult != cOCT6100_ERR_OK )
{
/* Most probably, the hardware is out of mixer events. */
break;
}
}
/* Check if this participant can hear us. */
if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 )
{
/* Must reserve a load or accumulate entry mixer event here! */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] );
if ( ulResult != cOCT6100_ERR_OK )
{
/* Most probably, the hardware is out of mixer events. */
break;
}
}
}
}
}
/* If an error is returned, make sure everything is cleaned up properly. */
if ( ulResult != cOCT6100_ERR_OK )
{
/* Release the flexible conferencing participant entry. */
ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;
/* Release the substore event in the mixer memory. */
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
if ( fCopyEventReserved == TRUE )
{
/* Release the copy event in the mixer memory. */
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
}
if ( fExtraSinTsiReserved == TRUE )
{
/* Release the extra Sin TSI in TSI memory. */
ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
}
if ( fExtraRinTsiReserved == TRUE )
{
/* Release the extra Rin TSI in TSI memory. */
ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraRinTsiMemIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX;
}
/* Search through the list of API channel entry for the ones on to this bridge. */
for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
{
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
/* Channel reserved? */
if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
{
/* On current bridge? */
if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
{
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
/* Check if we can hear this participant. */
if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 )
{
/* If the load or event entry in the mixer memory was reserved. */
if ( pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
{
/* Must release the load or accumulate entry mixer event. */
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
}
}
/* Check this participant can hear us. */
if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 )
{
/* If the load or event entry in the mixer memory was reserved. */
if ( pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX )
{
/* Must release the load or accumulate entry mixer event. */
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX;
}
}
}
}
}
return ulResult;
}
}
else /* if ( ulResult != cOCT6100_ERR_OK ) */
{
ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX;
/* Return the error code to the user. The mixer event allocation failed. */
return ulResult;
}
/*=======================================================================*/
}
else /* if ( f_fFlexibleConfBridge == FALSE ) */
{
/*=======================================================================*/
/* Normal conferencing. */
/* Reserve an entry for the load event in the mixer memory. */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusLoadEventIndex );
if ( ulResult == cOCT6100_ERR_OK )
{
fLoadEventReserved = TRUE;
/* Reserve an entry for the substract and store event in the mixer memory. */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex );
if ( ulResult == cOCT6100_ERR_OK )
{
fStoreEventReserved = TRUE;
/* If using the SOUT port, we must copy this entry */
if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
{
/* Reserve an entry for the copy event in the mixer memory. */
ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex );
if ( ulResult == cOCT6100_ERR_OK )
{
fCopyEventReserved = TRUE;
/* Reserve a SIN copy entry if none were reserved before. */
if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX )
{
/* Reserve an entry for the extra tsi chariot memory. */
ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance,
&pChanEntry->usExtraSinTsiMemIndex );
if ( ulResult == cOCT6100_ERR_OK )
fExtraSinTsiReserved = TRUE;
}
}
}
}
}
if ( ( ulResult == cOCT6100_ERR_OK ) && ( f_fTap == TRUE ) )
{
/* Reserve a "tap" bridge. */
tOCT6100_CONF_BRIDGE_OPEN ConfBridgeOpen;
UINT32 ulTapBridgeHndl = 0;
Oct6100ConfBridgeOpenDef( &ConfBridgeOpen );
ConfBridgeOpen.pulConfBridgeHndl = &ulTapBridgeHndl;
ulResult = Oct6100ConfBridgeOpenSer( f_pApiInstance, &ConfBridgeOpen );
*f_pusTapBridgeIndex = (UINT16)( ulTapBridgeHndl & cOCT6100_HNDL_INDEX_MASK );
}
if ( ulResult != cOCT6100_ERR_OK )
{
if ( fLoadEventReserved == TRUE )
{
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusLoadEventIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
}
if ( fStoreEventReserved == TRUE )
{
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
}
if ( fCopyEventReserved == TRUE )
{
ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
}
if ( fExtraSinTsiReserved == TRUE )
{
ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex );
if ( ulTempVar != cOCT6100_ERR_OK )
return ulTempVar;
pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX;
}
return ulResult;
}
/*=======================================================================*/
}
return cOCT6100_ERR_OK;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
Function: Oct6100ApiBridgeEventAdd
Description: Add the event into the global event list of the chip and update
the bridge and channel structures.
-------------------------------------------------------------------------------
| Argument | Description
-------------------------------------------------------------------------------
f_pApiInstance Pointer to API instance. This memory is used to
keep the present state of the chip and all its
resources.
f_usBridgeIndex Index of the current bridge in the API list.
f_usChanIndex Index of the current channel in the API list.
f_fFlexibleConfBridge If this is a flexible conference bridge.
f_usLoadEventIndex Allocated entry for the Load event of the
channel.
f_usSubStoreEventIndex Allocated entry for the substract and store
event of the channel.
f_usCopyEventIndex Allocated entry for the copy event of the
channel.
f_ulInputPort Input port where to copy samples from.
f_fMute Mute flag indicating if the channel is added in
a mute state.
f_ulListenerMaskIndex Index of the listener in this flexible conference bridge.
f_ulListenerMask Mask of listeners in this flexible conference bridge.
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBridgeEventAdd
UINT32 Oct6100ApiBridgeEventAdd(
IN OUT tPOCT6100_INSTANCE_API f_pApiInstance,
IN UINT16 f_usBridgeIndex,
IN UINT16 f_usChanIndex,
IN UINT8 f_fFlexibleConfBridge,
IN UINT16 f_usLoadEventIndex,
IN UINT16 f_usSubStoreEventIndex,
IN UINT16 f_usCopyEventIndex,
IN UINT32 f_ulInputPort,
IN UINT8 f_fMute,
IN UINT32 f_ulListenerMaskIndex,
IN UINT32 f_ulListenerMask,
IN UINT8 f_fTap,
IN UINT16 f_usTapBridgeIndex,
IN UINT16 f_usTapChanIndex )
{
tPOCT6100_API_CONF_BRIDGE pBridgeEntry;
tPOCT6100_API_MIXER_EVENT pLoadEventEntry;
tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry;
tPOCT6100_API_MIXER_EVENT pTempEntry;
tPOCT6100_API_CHANNEL pEchoChanEntry;
tPOCT6100_API_CHANNEL pTapEchoChanEntry = NULL;
tPOCT6100_API_CHANNEL pTempEchoChanEntry;
tPOCT6100_SHARED_INFO pSharedInfo;
tOCT6100_WRITE_PARAMS WriteParams;
UINT32 ulResult;
UINT16 usChannelIndex;
UINT16 usLastSubStoreEventIndex;
UINT16 usLastLoadEventIndex;
BOOL fAddSinCopy = FALSE;
/* Obtain local pointer to shared portion of instance. */
pSharedInfo = f_pApiInstance->pSharedInfo;
WriteParams.pProcessContext = f_pApiInstance->pProcessContext;
WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
/* Get the bridge and channel entries of interest. */
if ( f_fTap == FALSE )
{
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex );
}
else
{
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usTapBridgeIndex );
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapEchoChanEntry, f_usTapChanIndex );
}
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex );
if ( f_fFlexibleConfBridge == TRUE )
{
tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant;
tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant;
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pEchoChanEntry->usFlexConfParticipantIndex );
/* Search through the list of API channel entry for the ones onto this bridge. */
for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ )
{
mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex );
/* Channel reserved? */
if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) )
{
/* On current bridge? */
if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex )
{
mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex );
/* Check if we can hear this participant. */
if ( ( pTempEchoChanEntry->fMute == FALSE ) && ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) )
{
/* First create/update the current channel's mixer. */
ulResult = Oct6100ApiBridgeAddParticipantToChannel(
f_pApiInstance,
f_usBridgeIndex,
usChannelIndex,
f_usChanIndex,
pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ],
f_usSubStoreEventIndex,
f_usCopyEventIndex,
pCurrentParticipant->ulInputPort,
f_ulInputPort );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
}
/* Check if this participant can hear us. */
if ( ( f_fMute == FALSE ) && ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) )
{
/* Then create/update this channel's mixer. */
ulResult = Oct6100ApiBridgeAddParticipantToChannel(
f_pApiInstance,
f_usBridgeIndex,
f_usChanIndex,
usChannelIndex,
pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ],
pTempEchoChanEntry->usSubStoreEventIndex,
pTempEchoChanEntry->usSinCopyEventIndex,
f_ulInputPort,
pCurrentParticipant->ulInputPort );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Check if the Rin silence event can be cleared now that the */
/* channel has been added to a conference. */
if ( ( pCurrentParticipant->fFlexibleMixerCreated == TRUE )
&& ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) )
{
/* Remove the event from the list. */
ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance,
pTempEchoChanEntry->usRinSilenceEventIndex,
cOCT6100_EVENT_TYPE_SOUT_COPY );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_DF;
pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
}
}
}
}
}
/* Check if the mixer for the destination channel has been created. */
if ( pNewParticipant->fFlexibleMixerCreated == FALSE )
{
/* Save store event index that might be used for next channel added. */
pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex;
}
else
{
/* Check if the Rin silence event can be cleared now that the */
/* channel has been added to a conference. */
if ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX )
{
/* Remove the event from the list.*/
ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance,
pEchoChanEntry->usRinSilenceEventIndex,
cOCT6100_EVENT_TYPE_SOUT_COPY );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex );
if ( ulResult != cOCT6100_ERR_OK )
return cOCT6100_ERR_FATAL_DF;
pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX;
}
}
pNewParticipant->ulListenerMaskIndex = f_ulListenerMaskIndex;
pNewParticipant->ulListenerMask = f_ulListenerMask;
/* Remember this channel's input port. */
pNewParticipant->ulInputPort = f_ulInputPort;
/*=======================================================================*/
}
else /* if ( f_fFlexibleConfBridge == FALSE ) */
{
/* Configure the SIN copy mixer entry and memory - if using the SOUT port. */
if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) )
{
if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX )
{
ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance,
pEchoChanEntry->usSinTsstIndex,
pEchoChanEntry->usExtraSinTsiMemIndex,
pEchoChanEntry->TdmConfig.bySinPcmLaw );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
}
/* If the silence TSI is loaded on this port, update with the extra sin TSI. */
if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX )
{
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 2;
WriteParams.usWriteData = pEchoChanEntry->usExtraSinTsiMemIndex;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
}
}
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex );
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex );
/*=======================================================================*/
/* Program the Load event.*/
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
if ( ( f_fMute == FALSE ) || ( f_fTap == TRUE ) )
{
if ( pBridgeEntry->usLoadIndex != cOCT6100_INVALID_INDEX )
{
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
/* Set the event type. */
pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
if ( f_fTap == TRUE )
return cOCT6100_ERR_FATAL_D1;
}
else /* pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX */
{
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;
/* Modify the bridge entry to show store the new load index.*/
pBridgeEntry->usLoadIndex = f_usLoadEventIndex;
/* Set the event type.*/
pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD;
}
/* Select the TSI memory index according to the source port. */
if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
{
if ( f_fTap == FALSE )
{
WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
}
else
{
tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry;
UINT16 usTempWriteData;
UINT32 ulTempWriteAddress;
/* Save temp write data before trying to clear the Rin TSST. */
usTempWriteData = WriteParams.usWriteData;
ulTempWriteAddress = WriteParams.ulWriteAddress;
/* Clear the Rin TSST if used. */
if ( pTapEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX )
{
/* Deactivate the TSST entry.*/
WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pTapEchoChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE );
WriteParams.usWriteData = 0x0000;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
}
/* Reassign write data that might have been cleared by write above. */
WriteParams.usWriteData = usTempWriteData;
WriteParams.ulWriteAddress = ulTempWriteAddress;
WriteParams.usWriteData |= pTapEchoChanEntry->usRinRoutTsiMemIndex;
/* Remember that this channel is being tapped by us. */
pTapEchoChanEntry->fBeingTapped = TRUE;
pTapEchoChanEntry->usTapChanIndex = f_usChanIndex;
mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex );
pTempBridgeEntry->usNumTappedClients++;
}
}
else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
{
WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
}
}
else /* f_fMute == TRUE */
{
/* Do not load the sample if the channel is muted. */
if ( pBridgeEntry->usNumClients == 0 )
{
/* If the participant to be added is muted, and it would cause the conference to */
/* be completely muted, load the silence TSI. */
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD;
WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */
/* We know for sure that the load of the bridge will be the silence one. */
pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex;
}
else
{
/* Do nothing! */
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
}
/* Set the event type. */
pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP;
}
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/*=======================================================================*/
/* Program the Substract and store event.*/
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
if ( ( f_fMute == FALSE ) && ( f_fTap == FALSE ) )
{
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
/* Select the TSI memory index and PCM law according to the source port. */
if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
{
WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex;
}
else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
{
WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex;
}
/* Set the event type. */
pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
}
else /* f_fMute == TRUE */
{
/* Do not substore the sample if the channel is muted. */
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE;
/* Select the PCM law according to the source port. */
if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT )
{
WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
}
else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */
{
WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
}
/* Set the event type. */
pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE;
}
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
WriteParams.ulWriteAddress += 2;
WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/*=======================================================================*/
/* Program the Copy event - if using the SOUT port */
if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) )
{
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY;
WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex;
WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
WriteParams.ulWriteAddress += 2;
WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Set add copy event flag. */
fAddSinCopy = TRUE;
/* For sure. */
pEchoChanEntry->fCopyEventCreated = TRUE;
}
else if ( f_fTap == TRUE )
{
/* Accumulate the tapped channel's voice instead of building a copy event. */
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
WriteParams.usWriteData |= pTapEchoChanEntry->usSinSoutTsiMemIndex;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Link to next operation. */
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = f_usSubStoreEventIndex;
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Update the software model. */
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, f_usCopyEventIndex );
pTempEntry->usSourceChanIndex = f_usTapChanIndex;
pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE;
pTempEntry->usNextEventPtr = f_usSubStoreEventIndex;
pTempEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX;
pTempEntry->fReserved = TRUE;
}
/*=======================================================================*/
/*=======================================================================*/
/* Now insert the event into the list.*/
if ( pBridgeEntry->usNumClients == 0 )
{
/* This is the first entry for this bridge. Insert the two events at the head
of the list just after the last sub-store event.*/
if ( f_fTap == FALSE )
{
ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usLastSubStoreEventIndex );
if ( ulResult != cOCT6100_ERR_OK )
{
if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND )
{
if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
{
usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE;
}
else
{
usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
}
}
else
{
return cOCT6100_ERR_FATAL_26;
}
}
}
else
{
if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX )
{
usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE;
}
else
{
usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr;
}
}
/* An Entry was found, now, modify it's value.*/
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex );
/* Set the Sub-Store event first.*/
pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE;
pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;
/*=======================================================================*/
/* Program the Sub-Store event. */
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/* Set the load/accumulate event now.*/
if ( f_fTap == FALSE )
{
pLoadEventEntry->usNextEventPtr = f_usSubStoreEventIndex;
}
else
{
/* This is a little tricky, we use the copy event index for accumulating the tapped channel's voice. */
pLoadEventEntry->usNextEventPtr = f_usCopyEventIndex;
}
/*=======================================================================*/
/* Program the load/accumulate event. */
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/* Now modify the previous last Sub Store event from another bridge. */
pTempEntry->usNextEventPtr = f_usLoadEventIndex;
/*=======================================================================*/
/* Modify the last node of the other bridge. */
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/* Set the event pointer info in the bridge stucture. */
pBridgeEntry->usFirstLoadEventPtr = f_usLoadEventIndex;
pBridgeEntry->usFirstSubStoreEventPtr = f_usSubStoreEventIndex;
pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex;
/* Update the global mixer pointers. */
if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX )
{
/* This bridge is the first to generate mixer event. */
pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex;
pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex;
}
else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex )
{
/* The two entries were added at the end of the bridge section, */
/* change only the last pointer. */
pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex;
}
else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE ||
usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr )
{
/* The two entries were added at the start of the bridge section, */
/* change only the first pointer. */
pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex;
}
}
else /* pBridgeEntry->usNumClients != 0 */
{
/* For sanity. */
if ( f_fTap == TRUE )
return cOCT6100_ERR_FATAL_D2;
/*=======================================================================*/
/* Program the Load event. */
/* Now find the last load entry of this bridge. */
ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, pBridgeEntry->usFirstSubStoreEventPtr, 0, &usLastLoadEventIndex );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/* Add the load/accumulate event to the list. */
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex );
/* Set the load event now. */
pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/*=======================================================================*/
/* Modify the previous last load event. */
/* Now modify the previous last load event. */
pTempEntry->usNextEventPtr = f_usLoadEventIndex;
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/*=======================================================================*/
/* Program the Sub-Store event. */
usLastSubStoreEventIndex = pBridgeEntry->usLastSubStoreEventPtr;
mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex );
/* Set the Sub-Store event first. */
pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr;
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/*=======================================================================*/
/* Modify the previous last sub store event of the bridge. */
/* Now modify the last Load event of the bridge. */
pTempEntry->usNextEventPtr = f_usSubStoreEventIndex;
WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
WriteParams.ulWriteAddress += 4;
WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr );
mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
if ( ulResult != cOCT6100_ERR_OK )
return ulResult;
/*=======================================================================*/
/* Update the bridge pointers. */
pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex;
/* Check if modification to the global mixer pointer are required. */
if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex )
{
/* We have a new last bridge pointer. */
pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex;
}
}
if ( f_fTap == TRUE )
{
if ( pEchoChanEntry->usRinTsstIndex == cOCT6100_INVALID_INDEX )
{
/* Remove the mute on the Rin port. */
UINT32 ulTempData;
UINT32 ulMask;
UINT32 ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst;
/* Configure the level control. */
UINT32 ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4;
UINT32 ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset;
UINT32 ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize;
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