windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/callcont/api_dwn.c
2020-09-26 16:20:57 +08:00

6323 lines
199 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
*
* INTEL Corporation Proprietary Information
* Copyright (c) 1994, 1995, 1996 Intel Corporation.
*
* This listing is supplied under the terms of a license agreement
* with INTEL Corporation and may not be used, copied, nor disclosed
* except in accordance with the terms of that agreement.
*
*****************************************************************************/
/******************************************************************************
*
* AUTHOR: cjutzi (Curt Jutzi) Intel Corporation
*
* $Workfile: api_dwn.c $
* $Revision: 1.45 $
* $Modtime: 05 Mar 1997 09:53:36 $
* $Log: S:/STURGEON/SRC/H245/SRC/VCS/api_dwn.c_v $
*
* Rev 1.45 05 Mar 1997 09:56:04 MANDREWS
* Fixed compiler warning in release mode.
*
* Rev 1.44 04 Mar 1997 17:33:26 MANDREWS
* H245CopyCap() and H245CopyCapDescriptor() now return HRESULTs.
*
* Rev 1.43 26 Feb 1997 11:12:06 MANDREWS
* Fixed problem in assigning dynamic term cap IDs; the dynamic IDs were
* overlapping with static IDs.
*
* Rev 1.42 Feb 24 1997 18:30:18 tomitowx
* multiple modedescriptor support
*
* Rev 1.41 07 Feb 1997 15:33:58 EHOWARDX
* Changed H245DelCapDescriptor to match changes to set_cap_descriptor.
*
* Rev 1.40 27 Jan 1997 12:40:16 MANDREWS
*
* Fixed warnings.
*
* Rev 1.39 09 Jan 1997 19:17:04 EHOWARDX
*
* Initialize lError to H245_ERROR_OK to prevent "may be uninitialized"
* warning.
*
* Rev 1.38 19 Dec 1996 17:18:50 EHOWARDX
* Changed to use h245asn1.h definitions instead of _setof3 and _setof8.
*
* Rev 1.37 12 Dec 1996 15:57:22 EHOWARDX
* Master Slave Determination kludge.
*
* Rev 1.36 11 Dec 1996 13:55:44 SBELL1
* Changed H245Init parameters.
*
* Rev 1.35 17 Oct 1996 18:17:36 EHOWARDX
* Changed general string to always be Unicode.
*
* Rev 1.34 14 Oct 1996 14:01:26 EHOWARDX
* Unicode changes.
*
* Rev 1.33 11 Oct 1996 15:19:56 EHOWARDX
* Fixed H245CopyCap() bug.
*
* Rev 1.32 28 Aug 1996 11:37:10 EHOWARDX
* const changes.
*
* Rev 1.31 19 Aug 1996 16:28:36 EHOWARDX
* H245CommunicationModeResponse/H245CommunicationModeCommand bug fixes.
*
* Rev 1.30 15 Aug 1996 15:19:46 EHOWARDX
* First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews.
* Use at your own risk!
*
* Rev 1.29 08 Aug 1996 16:02:58 EHOWARDX
*
* Eliminated api_vers.h.
* Changed H245Init Debug trace to eliminate API_VERSION.
*
* Rev 1.28 19 Jul 1996 12:48:22 EHOWARDX
*
* Multipoint clean-up.
*
* Rev 1.27 01 Jul 1996 22:13:42 EHOWARDX
*
* Added Conference and CommunicationMode structures and functions.
*
* Rev 1.26 18 Jun 1996 14:53:16 EHOWARDX
* Eliminated Channel parameter to MaintenanceLoopRelease.
* Made Multiplex Capability mandatory -- H245SendTermCaps now returns
* H245_ERROR_NO_MUX_CAPS if no Multiplex Capability has been defined.
*
* Rev 1.25 14 Jun 1996 18:57:38 EHOWARDX
* Geneva update.
*
* Rev 1.24 10 Jun 1996 16:59:02 EHOWARDX
* Moved init/shutdown of submodules to CreateInstance/InstanceUnlock.
*
* Rev 1.23 06 Jun 1996 18:50:10 EHOWARDX
* Equivalent of H.324 bugs #808 and 875 fixed.
*
* Rev 1.22 05 Jun 1996 17:16:48 EHOWARDX
* MaintenanceLoop bug fix.
*
* Rev 1.21 04 Jun 1996 13:56:42 EHOWARDX
* Fixed Release build warnings.
*
* Rev 1.20 30 May 1996 23:38:52 EHOWARDX
* Cleanup.
*
* Rev 1.19 29 May 1996 16:08:04 unknown
* Fixed bug in copying nonstandard identifiers.
*
* Rev 1.18 29 May 1996 15:19:48 EHOWARDX
* Change to use HRESULT.
*
* Rev 1.17 28 May 1996 14:25:12 EHOWARDX
* Tel Aviv update.
*
* Rev 1.16 21 May 1996 15:46:54 EHOWARDX
* Fixed bugs in NonStandard messages using object identifier.
*
* Rev 1.15 20 May 1996 22:17:54 EHOWARDX
* Completed NonStandard Message and H.225.0 Maximum Skew indication
* implementation. Added ASN.1 validation to H245SetLocalCap and
* H245SetCapDescriptor. Check-in from Microsoft drop on 17-May-96.
*
* Rev 1.14 20 May 1996 14:35:12 EHOWARDX
* Got rid of asynchronous H245EndConnection/H245ShutDown stuff...
*
* Rev 1.13 17 May 1996 14:53:38 EHOWARDX
* Added calls to StartSystemClose() and EndSystemClose().
*
* Rev 1.12 16 May 1996 19:40:30 EHOWARDX
* Fixed multiplex capability bug.
*
* Rev 1.11 16 May 1996 16:36:10 EHOWARDX
* Fixed typo in H245SetCapDescriptor.
*
* Rev 1.10 16 May 1996 16:14:06 EHOWARDX
* Fixed backwards-compatibility problem in H245SetLocalCap
* (CapId of zero should result in dynamically-allocated cap id being used)
*
* Rev 1.9 16 May 1996 16:03:44 EHOWARDX
* Fixed typo in H245SetCapDescriptor.
*
* Rev 1.8 16 May 1996 15:58:32 EHOWARDX
* Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/
* H245DelCapDescriptor behaviour.
*
* Rev 1.7 15 May 1996 21:49:46 unknown
* Added call to InstanceLock() to increment lock count before call
* to InstanceDelete() in H245EndConnectionPhase2().
*
* Rev 1.6 15 May 1996 19:54:02 unknown
* Fixed H245SetCapDescriptor.
*
* Rev 1.5 14 May 1996 16:56:22 EHOWARDX
* Last minute change from H245_IND_CAPDESC_T to H245_TOTCAPDESC_T.
* H245EnumCaps() callback now uses H245_TOTCAPDESC_T instead
* of separate H245_CAPDESCID_T and H245_CAPDESC_T for consistency.
*
* Rev 1.4 14 May 1996 15:55:44 EHOWARDX
* Added mux cap handling to H245DelLocalCap.
*
* Rev 1.3 14 May 1996 14:06:06 EHOWARDX
* Fixed abort from H245EnumCaps - if Cap Callback returns non-zero,
* Cap Desc Callback is never called.
*
* Rev 1.2 13 May 1996 23:16:42 EHOWARDX
* Fixed remote terminal capability handling.
*
* Rev 1.1 11 May 1996 20:32:52 EHOWARDX
* Checking in for the night...
*
* Rev 1.0 09 May 1996 21:06:06 EHOWARDX
* Initial revision.
*
* Rev 1.25.1.10 09 May 1996 19:31:02 EHOWARDX
* Redesigned thread locking logic.
* Added new API functions.
*
* Rev 1.25.1.9 01 May 1996 19:31:16 EHOWARDX
* Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux().
* Changed H2250_xxx definitions for H.225.0 address types to H245_xxx.
*
* Rev 1.25.1.8 27 Apr 1996 21:09:20 EHOWARDX
* Changed Channel Numbers to words, added H.225.0 support.
*
* Rev 1.25.1.7 25 Apr 1996 20:06:26 EHOWARDX
* Moved setting of EndSessionPdu in EndSessionPhase1 to before call to api_fs
*
* Rev 1.25.1.6 25 Apr 1996 17:57:00 EHOWARDX
* Added dwTxPort argument to H245OpenChannel().
*
* Rev 1.25.1.5 25 Apr 1996 16:51:00 EHOWARDX
* Function changes as per H.245 API Changes spec.
*
* Rev 1.25.1.4 24 Apr 1996 20:54:32 EHOWARDX
* Added new OpenLogicalChannelAck/OpenLogicalChannelReject support.
*
* Rev 1.25.1.3 19 Apr 1996 12:54:40 EHOWARDX
* Updated to 1.30
*
* Rev 1.25.1.2 15 Apr 1996 15:10:48 EHOWARDX
* Updated to match Curt's current version.
*
* Rev 1.25.1.1 03 Apr 1996 17:12:50 EHOWARDX
* Integrated latest H.323 changes.
*
* Rev 1.25.1.0 03 Apr 1996 15:53:42 cjutzi
* Branched for H.323.
*
* Rev 1.20 27 Mar 1996 15:25:34 cjutzi
* - fixed a bug from this morning checkin dynamically allocating
* pdu's.. free_mux_tbl was getting called after pdu was free'd..
* this was a problem since the mux table pointer was in the pdu
*
* Rev 1.19 27 Mar 1996 08:37:08 cjutzi
*
* - removed PDU from stack.. made them dynamically allocated
*
* Rev 1.18 20 Mar 1996 14:47:32 cjutzi
* - added ERROR H245_ERROR_NO_CAPDESC to SendTermCaps.
*
* Rev 1.17 18 Mar 1996 15:23:16 cjutzi
*
*
*
* Rev 1.16 13 Mar 1996 09:15:44 cjutzi
*
* - changed LLPCRITICAL_SECTION to CRITICAL_SECTION *
*
* Rev 1.15 12 Mar 1996 15:51:48 cjutzi
*
* - implemented locking
* - fixed callback bug w/ clenaup on term caps..
* - implemented End Session
* - fixed shutdown
*
* Rev 1.14 08 Mar 1996 14:02:48 cjutzi
*
* - removed H245SetSimultaneous stuff..
* - added H245SetCapDescriptor Stuff..
* - completeed MuxTable Entry Stuff.
* - required H223 -or- some portion of MuxCapbilities to be
* there before you issue SendCaps..
* - NOTE: need to inforce the Simultaneous capabilities in
* the same mannor..
*
* Rev 1.13 05 Mar 1996 17:35:38 cjutzi
*
* - implemented SendMultiplexTable..
* - removed bcopy/bzero and changed free call
* - added master slave indication
*
* Rev 1.12 01 Mar 1996 13:48:24 cjutzi
*
* - added hani's new fsm id's
* - added some support for release on close request.
*
* Rev 1.11 29 Feb 1996 17:27:10 cjutzi
*
* - bi-directional channel working..
*
* Rev 1.10 29 Feb 1996 08:35:52 cjutzi
*
* - added p_ossWorld to initialization
*
* Rev 1.9 27 Feb 1996 13:30:18 cjutzi
*
* - fixed master slave problem with conf_ind and tracker type
* - removed RSP_LCSE in close channel resp
*
* Rev 1.8 26 Feb 1996 17:23:18 cjutzi
*
* - MiscCommand API added
* - Fixed Assert for H245Init.. was not NULL'n out the pointers for the
* context blocks..
*
* Rev 1.7 26 Feb 1996 11:05:16 cjutzi
*
* - added simultaneous caps.. and fixed bugs..
* lot's of changes..
*
* Rev 1.6 16 Feb 1996 13:01:08 cjutzi
*
* - got open / close / request close working in both directions.
*
* Rev 1.5 15 Feb 1996 14:42:54 cjutzi
*
* - fixed trace level bind w/ Instance.. no other change but had to
* add when h245deb.c when in..
*
*
* Rev 1.4 15 Feb 1996 10:50:54 cjutzi
*
* - termcaps working
* - changed API interface for MUX_T
* - changed callback or IND_OPEN
* - changed constants IND_OPEN/IND_OPEN_NEEDRSP etc..
* - cleaned up the open.. (not complete yet.. )
*
* Rev 1.3 09 Feb 1996 16:58:36 cjutzi
*
* - cleanup.. and some fixes..
* - added and or changed headers to reflect the log of changes
*
*****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/**** *****/
/**** NOTES TO THE READER *****/
/**** *****/
/**** This program has been put together using a a screen which is *****/
/**** wider than 80 characters.. It is best if a similar screen size is *****/
/**** used.. Of course emacs is my preference but 80 col screens will *****/
/**** cause you much frustration.. *****/
/**** *****/
/**** Tabs are set to 8 *****/
/**** *****/
/**** NOTE: *****/
/**** Headers are documented, however they may or may not *****/
/**** coorispond to reality. See the H245Spec.doc from Intel for the *****/
/**** current :-> H245 specification *****/
/**** *****/
/**** DISCLAMER: *****/
/**** *****/
/**** Since this code wasn't developed in Word 7.0, I am fully *****/
/**** responsable for all spelling mistakes in the comments. Please *****/
/**** disregard the spelling mistakes.. or fix them, if you are *****/
/**** currently modifying the code. *****/
/**** *****/
/**** - Thankyou *****/
/**** *****/
/**** Curt Jutzi *****/
/**** Oregon, USA *****/
/**** *****/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
#ifndef STRICT
#define STRICT
#endif
#include "precomp.h"
/***********************/
/* H245 INCLUDES */
/***********************/
#define H245DLL_EXPORT
#include "h245api.h"
#include "h245com.h"
#include "h245sys.x"
#include "api_util.x"
#include "pdu.x"
#include "fsmexpor.h"
#include "api_debu.x"
#include "sr_api.h"
#include "h245deb.x"
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245Init
*
* DESCRIPTION
*
* H245_INST_T H245Init (
* H245_CONF_T Configuration,
* DWORD dwH245PhysId,
* DWORD dwLinkLayerPhysId,
* DWORD dwPreserved,
* H245_CONF_IND_CALLBACK_T Callback
* )
* Description:
*
* Called to create an H.245 instance and its related sublayers
* (e.g., SRP). This function must be called before any other
* API calls may be called The current H.245 implementation can
* only have, at most, one client. Therefore H245Init can only be
* called once per physical ID.
* Input
*
* Configuration Indicates the type of configuration the client
* wishes to establish, e.g. H.324, H.323, H.310,
* or DSVD.
* dwH245PhysId Parameter identifying the H245 entry
* pdwLinkLayerPhysId
* Output parameter identifying the linkLayer
* entry.
* dwPreserved Parameter that may be used by H.245 client to
* provide context, passed back to client in all
* confirms and indications.
* Callback Callback routine supplied by the client which
* will be used by the H.245 subsystem to convey
* confirm and indication messages back to the
* client.
* Call Type:
*
* Synchronous
*
* Return Values:
*
* Return value of 0 indicates Failure
* Return value of non 0 is a valid H245_INST_T
*
* Errors:
* N/A
*
* See Also:
* H245EndSession
* H245Shutdown
*
*
*****************************************************************************/
H245DLL H245_INST_T
H245Init (
H245_CONFIG_T Configuration,
unsigned long dwH245PhysId,
unsigned long *pdwLinkLayerPhysId,
DWORD_PTR dwPreserved,
H245_CONF_IND_CALLBACK_T CallBack,
unsigned char byTerminalType
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
H245TRACE(dwH245PhysId,4,"H245Init(%d, 0x%x, 0x%x, 0x%x, %d) <-",
Configuration, dwH245PhysId, dwPreserved, CallBack, byTerminalType);
switch (Configuration)
{
case H245_CONF_H324:
case H245_CONF_H323:
break;
default:
H245TRACE(dwH245PhysId,1,"H245Init -> Invalid Configuration %d", Configuration);
return H245_INVALID_ID;
} // switch
if (CallBack == NULL)
{
H245TRACE(dwH245PhysId,1,"H245Init -> Null CallBack");
return H245_INVALID_ID;
}
/* see if this physical identifier has been initialized already */
// Send down H245PhysId that was input.
pInstance = InstanceCreate(dwH245PhysId, Configuration);
if (pInstance == NULL)
{
return H245_INVALID_ID;
}
// Get the linkLayer PhysId.
*pdwLinkLayerPhysId = pInstance->SendReceive.hLinkLayerInstance;
// Initialize instance API structure
pInstance->API.dwPreserved = dwPreserved;
pInstance->API.ConfIndCallBack = CallBack;
// Initialize instance FSM structure
pInstance->StateMachine.sv_TT = byTerminalType;
pInstance->StateMachine.sv_STATUS = INDETERMINATE;
H245TRACE(pInstance->dwInst,4,"H245Init -> %d", pInstance->dwInst);
lError = pInstance->dwInst;
InstanceUnlock(pInstance);
return lError;
} // H245Init()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245EndSession
*
* DESCRIPTION
*
* Yes.. this should be explained.. Since Send Receive needs
* to flush some buffers and send out an End Session.. what we've
* hopefully done is a 2 phase shut down...
*
* call StartSessionClose which initiates the flush..
* when flush is complete EndSessionPhase1 is called..
* The end session pdu is then placed in the send queue..
* When the End Session Pdu is sent.. the EndSession Phase
* 2 is called, and the result is sent up to the client..
*
* Hope that helps..
*
*
* HRESULT H245EndSession ( H245_INST_T dwInst,
* H245_ENDSESSION_T Mode,
* H245_NONSTANDARD_T *pNonStd (*optional*)
* )
*
* Description:
* Called to shutdown the peer to peer session between this H.245
* session and the remote peers H.245 layer.
*
* It will terminate by issuing an EndSession command to the
* remote side and call end session for all the H.245 subsystems.
* All resources are returned; therefore no further action is
* permitted, except H245ShutDown until another H245Init API call
* is made.
*
* input
* dwInst Instance handle returned by H245Init
* Mode Mode which the client wishes to terminat
* the session
* pNonStd If the mode is non standard this is the non
* standard parameter passes to the remote client.
* This parameter is optional, and should be set
* to NULL if not used
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM
* H245_ERROR_INVALID_INST
* H245_ERROR_NOT_CONNECTED
* See Also:
* H245Shutdown
* H245Init
*
*****************************************************************************/
H245DLL HRESULT
H245EndSession (
H245_INST_T dwInst,
H245_ENDSESSION_T Mode,
const H245_NONSTANDARD_PARAMETER_T * pNonStd
)
{
register struct InstanceStruct *pInstance;
register MltmdSystmCntrlMssg *pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245EndSession <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in either connecting or connected */
switch (pInstance->API.SystemState)
{
case APIST_Connecting:
case APIST_Connected:
break;
default:
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
// Allocate the PDU buffer
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
// Build the PDU
lError = pdu_cmd_end_session (pPdu, Mode, pNonStd);
if (lError == H245_ERROR_OK)
{
// Send the PDU
lError = FsmOutgoing(pInstance, pPdu, 0);
}
// Free the PDU buffer
MemFree(pPdu);
if (lError != H245_ERROR_OK)
{
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(lError));
}
else
{
H245TRACE (dwInst,4,"H245EndSession -> OK");
pInstance->API.SystemState = APIST_Disconnected;
}
InstanceUnlock(pInstance);
return lError;
} // H245EndSession()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245ShutDown
*
* DESCRIPTION
*
* HRESULT H245Shutdown ( H245_INST_T dwInst);
*
* Description:
*
* Called to terminate the specified instance of H.245. If there
* is currently an active session (see H245Init) then the H.245
* subsystem will issue an EndSession to the other side and wait
* for H.245 sublayer termination notifications before it queues
* Callback confirm.
*
* This call will force the client to issue another H245Init
* before it can use any of the H.245 API functions.
*
* Input
* dwInst Instance handle returned by H245Init
*
* Call Type:
* asynchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
*
* See Also:
* H245Init
*
*****************************************************************************/
H245DLL HRESULT
H245ShutDown (H245_INST_T dwInst)
{
register struct InstanceStruct *pInstance;
register HRESULT lError;
H245TRACE (dwInst,4,"H245ShutDown <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245ShutDown -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
switch (pInstance->API.SystemState)
{
case APIST_Connecting:
case APIST_Connected:
lError = H245EndSession(dwInst,H245_ENDSESSION_DISCONNECT,NULL);
break;
default:
lError = H245_ERROR_OK;
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245ShutDown -> %s", map_api_error(lError));
else
H245TRACE (dwInst,4,"H245ShutDown -> OK");
InstanceDelete (pInstance);
return H245_ERROR_OK;
} // H245ShutDown()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245InitMasterSlave
*
* DESCRIPTION
*
* HRESULT H245InitMasterSlave ( H245_INST_T dwInst,
* DWORD dwTransId )
*
* Description:
* Called to initiate the H.245 master slave negotiation.
* Upon completion of the negotiation the local client will
* receive an H245_CONF_INIT_MSTSLV message indicating the
* result of the negotiation.
* Input
* dwInst Instance handle returned by
* H245GetInstanceId
* dwTransId User supplied object used to identify this
* request in the asynchronous response to
* this call.
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callbacks:
* H245_CONF_INIT_MSTSLV
*
* Errors:
* H245_ERROR_OK Master Slave Determination started
* H245_ERROR_INPROCESS Master Slave Determination currently
* in process
* H245_ERROR_NOMEM
* H245_ERROR_INPROCESS In process
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
*
* See Also:
* H245Init
*
* callbacks
* H245_IND_MSTSLV
*
*
*****************************************************************************/
H245DLL HRESULT
H245InitMasterSlave (
H245_INST_T dwInst,
DWORD_PTR dwTransId
)
{
struct InstanceStruct *pInstance;
Tracker_T *pTracker;
HRESULT lError;
MltmdSystmCntrlMssg *pPdu = NULL;
/* check for valid instance handle */
H245TRACE (dwInst,4,"H245InitMasterSlave <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* if the transaction is in process.. tell client */
if (pInstance->API.MasterSlave == APIMS_InProcess)
{
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INPROCESS));
InstanceUnlock(pInstance);
return H245_ERROR_INPROCESS;
}
/* if the transaction is already complete */
if (pInstance->API.MasterSlave != APIMS_Undef)
{
if (pInstance->API.ConfIndCallBack)
{
H245_CONF_IND_T confirm_ind_event;
confirm_ind_event.Kind = H245_CONF;
confirm_ind_event.u.Confirm.Confirm = H245_CONF_INIT_MSTSLV;
confirm_ind_event.u.Confirm.dwPreserved = pInstance->API.dwPreserved;
confirm_ind_event.u.Confirm.dwTransId = dwTransId;
confirm_ind_event.u.Confirm.Error = H245_ERROR_OK;
confirm_ind_event.u.Confirm.u.ConfMstSlv =
(pInstance->API.MasterSlave == APIMS_Master) ? H245_MASTER : H245_SLAVE;
(*pInstance->API.ConfIndCallBack)(&confirm_ind_event, NULL);
}
H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
InstanceUnlock(pInstance);
return H245_ERROR_OK;
}
/* get somthing to keep track of what the heck you're doing.. */
if (!(pTracker = alloc_link_tracker (pInstance,
API_MSTSLV_T,
dwTransId,
API_ST_WAIT_RMTACK,
API_CH_ALLOC_UNDEF,
API_CH_TYPE_UNDEF,
0,
H245_INVALID_CHANNEL,
H245_INVALID_CHANNEL,
0)))
{
H245TRACE(dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
/* set master slave in process */
pInstance->API.SystemState = APIST_Connecting;
pInstance->API.MasterSlave = APIMS_InProcess;
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = masterSlaveDetermination_chosen;
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
MemFree(pPdu);
if (lError != H245_ERROR_OK)
{
unlink_dealloc_tracker (pInstance, pTracker);
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(lError));
}
else
H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245InitMasterSlave()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245SetLocalCap
*
* DESCRIPTION
*
* HRESULT H245SetLocalCap (
* H245_INST_T dwInst,
* H245_TOTCAP_T *pTotCap,
* H245_CAPID_T *pCapId
* )
*
* Description:
* This function allows the client to define a specific
* capability to the H.245 subsystem. When this function is
* called a new capability entry is made in the local capability
* table. The returned value in *pCapId can be used by the client
* to refer to that registered capability. NULL in the *pCapId
* is valid.
*
* This call is used for both client (Audio / Video / Data / Mux)
* capabilities. It is not used for setting capability descriptors.
*
* Note:
* 7 This function does not communicate this update to the
* remote peer until the client calls H245SendTermCaps.
* 7 pTotCap->CapId is of no significance in this call.
*
* pTotCap->CapId is of no significance in this call and should
* be set to 0
*
* if DataType of H245_DATA_MUX is used (i.e. in setting the
* mux table capabilities) No capid is returned, and it can not
* be used in H245SetCapDescritptor api call.
*
* Input
* dwInst Instance handle returned by GetInstanceId
* pTotCap Capability set defining the capability
*
* Note: pTotCap->CapId is of no significance in this call.
*
* output
* pCapId Capability id which client can use to reference
* this capability in the H.245 subsystem. This can
* be NULL, in this case nothing is returned.
*
* Call Type:
* Synchronous
*
* Return Values:
* If pCap is not null, the local cap table id is returned
* to the client in this parameter.
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM There was an invalid parameter passed
* H245_ERROR_MAXTBL Entry not made because local cap table
* is full
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
*
* See Also:
* H245DelLocalCap
* H245EnumCaps
* H245SetCapDescriptor
*
*
* ASSUMPTION:
* pTotCap->CapId will be set to H245_INVALID_CAPID
* pTotCap->Dir will be set
*
*****************************************************************************/
H245DLL HRESULT
H245SetLocalCap (
H245_INST_T dwInst,
H245_TOTCAP_T * pTotCap,
H245_CAPID_T * pCapId
)
{
register struct InstanceStruct *pInstance;
struct TerminalCapabilitySet *pTermCapSet;
HRESULT lError;
H245TRACE (dwInst,4,"H245SetLocalCap <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* check for valid parameters */
if (pTotCap == NULL ||
pCapId == NULL ||
((*pCapId > H245_MAX_CAPID) && (*pCapId != H245_INVALID_CAPID)) ||
pTotCap->Dir < H245_CAPDIR_LCLRX ||
pTotCap->Dir > H245_CAPDIR_LCLRXTX ||
pTotCap->ClientType < H245_CLIENT_NONSTD ||
pTotCap->ClientType > H245_CLIENT_MUX_H2250)
{
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
// Don't trust the user filled-in data type!
pTotCap->DataType = DataTypeMap[pTotCap->ClientType];
/* if it's a MUX type handle here */
if (pTotCap->DataType == H245_DATA_MUX)
{
// Add multiplex capability
if (pTermCapSet->bit_mask & multiplexCapability_present)
{
del_mux_cap(pTermCapSet);
}
*pCapId = pTotCap->CapId = 0;
lError = set_mux_cap(pInstance, pTermCapSet, pTotCap);
#if defined(_DEBUG)
if (lError == H245_ERROR_OK)
{
// Validate mux capability
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
{
// Bad mux capability - delete it
del_mux_cap(pTermCapSet);
lError = H245_ERROR_ASN1;
}
}
#endif // (DEBUG)
}
else if (*pCapId == 0 || *pCapId == H245_INVALID_CAPID)
{
// Assign the next never-used cap id
if (pInstance->API.LocalCapIdNum == H245_INVALID_CAPID)
{
// All possible capability identifiers have been assigned
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_MAXTBL));
InstanceUnlock(pInstance);
return H245_ERROR_MAXTBL;
}
*pCapId = pInstance->API.LocalCapIdNum;
/* insert in the new capability in the local capability set table */
pTotCap->CapId = *pCapId;
lError = set_capability(pInstance, pTermCapSet, pTotCap);
#if defined(_DEBUG)
if (lError == H245_ERROR_OK)
{
// Validate capability
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
{
// Bad capability - delete it
H245DelLocalCap(dwInst, *pCapId);
lError = H245_ERROR_ASN1;
}
}
#endif // (DEBUG)
if (lError == H245_ERROR_OK)
pInstance->API.LocalCapIdNum++;
}
else
{
/* insert in the new capability in the local capability set table */
pTotCap->CapId = *pCapId;
lError = set_capability(pInstance, pTermCapSet, pTotCap);
#if defined(_DEBUG)
if (lError == H245_ERROR_OK)
{
// Validate capability
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
{
// Bad capability - delete it
H245DelLocalCap(dwInst, *pCapId);
lError = H245_ERROR_ASN1;
}
}
#endif // (DEBUG)
}
if (lError != H245_ERROR_OK)
{
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(lError));
pTotCap->CapId = *pCapId = H245_INVALID_CAPID;
}
else
{
H245TRACE (dwInst,4,"H245SetLocalCap -> OK");
}
InstanceUnlock(pInstance);
return lError;
} // H245SetLocalCap()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245DelLocalCap
*
* DESCRIPTION Delete Local Cap simply disables the cap.. it
* will not be updated until the client issues
* H245SendTermCaps
*
*
* HRESULT H245DelLocalCap(
* H245_INST_T dwInst,
* H245_CAPID_T CapId
* )
*
* Description:
* This function allows the client to delete a specific
* capability id in the H.245 subsystem.
*
* Note: This function does not communicate this update
* to the remote peer until the client calls H245SendTermCaps.
*
* Input
* dwInst Instance handle returned by H245GetInstanceId
* CapId Cap Id the client wishes to remove from the
* capability table.
*
* If an error occurs no action is taken and the CapId the
* client wished to delete is not changed.
*
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK Capability deleted
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
*
* See Also:
* H245SetLocalCap
* H245SendTermCaps
* H245EnumCaps
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245DelLocalCap (
H245_INST_T dwInst,
H245_CAPID_T CapId
)
{
register struct InstanceStruct *pInstance;
struct TerminalCapabilitySet *pTermCapSet;
CapabilityTableLink pCapLink;
HRESULT lError = H245_ERROR_OK;
H245TRACE (dwInst,4,"H245DelLocalCap <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
if (CapId == 0)
{
// Delete multiplex capability
del_mux_cap(pTermCapSet);
}
else
{
/* (TBC) if I delete my capability id.. what about simultaneous caps ?? */
/* should I go through the list and deactivate them ?? */
pCapLink = find_capid_by_entrynumber (pTermCapSet, CapId);
if (pCapLink)
{
// Delete terminal capability
disable_cap_link (pCapLink);
}
else
{
lError = H245_ERROR_PARAM;
}
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245DelLocalCap -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245DelLocalCap()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245SetCapDescriptor
*
* DESCRIPTION
*
* HRESULT H245SetCapDescriptor (
* H245_INST_T dwInst,
* H245_CAPDESC_T *pCapDesc,
* H245_CAPDESCID_T *pCapDescId (* Optional *)
* )
* Description:
* This procedure is called to set local capability descriptors.
* It will return a capability descriptor id in the parameter
* *pCapDescId if it is non null.
*
* Note:
* These capabilities are communicated via the H245SendTermCaps
* API call. Any updates to the CapDescriptor table (either
* additions or deletions ) will not be communicated to the
* remote side until the H245SendTermCaps call is made.
*
* Input
* dwInst Instance handle returned by H245Init
* CapDesc This is the capability Descriptor you wish
* to set
* Output
* pCapDescId optional: Capability id that will be returned.
*
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_INVALID_CAPID Capid used in CapDesc was not
* registred
* H245_ERROR_MAXTB Out of table space to store Descriptor
* H245_ERROR_PARAM Descriptor is too long or not valid
* H245_ERROR_NOMEM
* H245_ERROR_INVALID_INST
*
* See Also:
* H245DelCapDescriptor
* H245SendTermCaps
*
* ASSUMES:
* SimCapId is the array entry point in the apabilityDescriptors
* array.. this has a limitation, in that you can never wrap the
* array at 256.. this will be cleaned up when array is turned into
* linked list.
*
*****************************************************************************/
H245DLL HRESULT
H245SetCapDescriptor (
H245_INST_T dwInst,
H245_CAPDESC_T *pCapDesc,
H245_CAPDESCID_T *pCapDescId
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
H245TRACE (dwInst,4,"H245SetCapDescriptor <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* must have capdescriptor && */
/* length must be less than 256 */
if (pCapDesc == NULL ||
pCapDesc->Length >= 256 ||
pCapDescId == NULL)
{
H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
if (*pCapDescId >= 256)
{
// Assign the next never-used cap id
if (pInstance->API.LocalCapDescIdNum >= 256)
{
// All possible capability identifiers have been assigned
H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(H245_ERROR_MAXTBL));
InstanceUnlock(pInstance);
return H245_ERROR_MAXTBL;
}
*pCapDescId = pInstance->API.LocalCapDescIdNum;
/* insert in the new capability descriptor in the local capability descriptor table */
lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
#if defined(_DEBUG)
if (lError == H245_ERROR_OK)
{
// Validate Capability Descriptor
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
{
// Capability Descriptor Invalid - delete it
H245DelCapDescriptor(dwInst, *pCapDescId);
lError = H245_ERROR_ASN1;
}
}
#endif // (DEBUG)
if (lError == H245_ERROR_OK)
pInstance->API.LocalCapDescIdNum++;
}
else
{
/* insert in the new capability in the local capability set table */
lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
#if defined(_DEBUG)
if (lError == H245_ERROR_OK)
{
// Validate Capability Descriptor
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
{
// Capability Descriptor Invalid - delete it
H245DelCapDescriptor(dwInst, *pCapDescId);
lError = H245_ERROR_ASN1;
}
}
#endif // (DEBUG)
}
if (lError != H245_ERROR_OK)
{
H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(lError));
*pCapDescId = H245_INVALID_CAPDESCID;
}
else
{
H245TRACE (dwInst,4,"H245CapDescriptor -> OK");
}
InstanceUnlock(pInstance);
return lError;
} // H245SetCapDescriptor()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245DelCapDescriptor
*
* DESCRIPTION
*
* HRESULT H245DelCapDescriptor (
* H245_INST_T dwInst,
* H245_CAPDESCID_T CapDescId
* )
* Description:
* This procedure is called to delete local capability descriptors.
*
* Note:
* These capabilities are communicated via the
* H245SendTermCaps API call. Any updates to the
* CapDescriptor table (either additions or deletions )
* will not be communicated to the remote side until the
* H245SendTermCaps call is made.
*
* Input
* dwInst Instance handle returned by H245Init
* CapDescId This is the capability Descriptor you wish
* to delete
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
* Errors:
* H245_ERROR_OK
* H245_ERROR_INVALID_INST
*
* See Also:
* H245SetCapDescriptor
* H245SendTermCaps
*
* ASSUMES:
*
* SimCapId is the array entry point in the apabilityDescriptors
* array.. this has a limitation, in that you can never wrap the
* array at 256.. this will be cleaned up when array is turned into
* linked list.
*
*
*****************************************************************************/
H245DLL HRESULT
H245DelCapDescriptor (
H245_INST_T dwInst,
H245_CAPDESCID_T CapDescId
)
{
register struct InstanceStruct *pInstance;
CapabilityDescriptor *p_cap_desc;
struct TerminalCapabilitySet *pTermCapSet;
unsigned int uId;
H245TRACE (dwInst,4,"H245DelCapDescriptor <-");
if (CapDescId >= 256)
{
H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
return H245_ERROR_INVALID_CAPDESCID;
}
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"API:H24DelCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* get pointer to Capability Descriptor */
p_cap_desc = NULL;
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
for (uId = 0; uId < pTermCapSet->capabilityDescriptors.count; ++uId)
{
if (pTermCapSet->capabilityDescriptors.value[uId].capabilityDescriptorNumber == CapDescId)
{
p_cap_desc = &pTermCapSet->capabilityDescriptors.value[uId];
break;
}
}
if (p_cap_desc == NULL ||
p_cap_desc->smltnsCpblts == NULL ||
(p_cap_desc->bit_mask & smltnsCpblts_present) == 0)
{
H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_CAPDESCID;
}
/* free up the list */
dealloc_simultaneous_cap (p_cap_desc);
/* (TBC) what if you've removed the last simultaneous cap ? */
/* in this case.. the count does not go down.. it simply */
/* removes the cap descriptor bit from the table.. */
H245TRACE (dwInst,4,"H245DelCapDescriptor -> OK");
InstanceUnlock(pInstance);
return H245_ERROR_OK;
} // H245DelCapDescriptor()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245SendTermCaps
*
* DESCRIPTION
*
* HRESULT
* H245SendTermCaps (
* H245_INST_T dwInst,
* DWORD dwTransId
* )
*
* Description:
*
* Called to send terminal capabilities to the remote H.245 peer.
* When remote capabilities are receive the client will be
* notified by the H245_IND_CAP indication. When remote side has
* acknowledged the local terminal capabilities and has responded
* with their terminal capabilities the client will receive an
* H245_CONF_ TERMCAP. Between H245Init and H245SendTermCap the
* client may call H245SetLocalCap to register capabilities.
* These capabilities will not be registered to the remote side
* until H245SendTermCap has been called.
*
* Note: As required by the H245 specification, Mutliplex
* capabilities, and Capability descriptors must be
* loaded before the first capability PDU is sent.
*
* Once H245SendTermCap is called, any subsequent calls to
* H245SetLocalTermCap will result in that capability being
* communicated to the remote H.245 peer.
*
* Input
* dwInst Instance handle returned by
* H245GetInstanceId
* dwTransId User supplied object used to identify
* this request in the asynchronous
* response to this call.
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callbacks:
* H245_CONF_TERMCAP
*
* Errors:
* H245_ERROR_OK Function succeeded
* H245_ERROR_NOMEM
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
* H245_ERROR_NO_MUX_CAPS no Mux capabilities have been set yet
* H245_ERROR_NO_CAPDESC no Capability Descriptors have been set
*
* See Also:
* H245SetLocalCap
* H245Init
*
* callbacks
*
* H245_IND_CAP
* H245_IND_CAPDESC
* H245_IND_CAP_DEL
* H245_IND_CAPDESC_DEL
*
*
*****************************************************************************/
H245DLL HRESULT
H245SendTermCaps (
H245_INST_T dwInst,
DWORD_PTR dwTransId
)
{
struct InstanceStruct *pInstance;
Tracker_T *pTracker;
HRESULT lError;
unsigned char TermCapData = TRUE;
struct TerminalCapabilitySet_capabilityTable TermCap = {0};
H245TRACE(dwInst,4,"H245SendTermCaps <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* must have mux parameters set */
if ((pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & multiplexCapability_present) == 0)
{
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_MUX_CAPS));
InstanceUnlock(pInstance);
return H245_ERROR_NO_MUX_CAPS;
}
/* must have capability descriptors set */
if (!(pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & capabilityDescriptors_present))
{
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_CAPDESC));
InstanceUnlock(pInstance);
return H245_ERROR_NO_CAPDESC;
}
if (!(pTracker = alloc_link_tracker (pInstance,
API_TERMCAP_T,
dwTransId,
API_ST_WAIT_RMTACK,
API_CH_ALLOC_UNDEF,
API_CH_TYPE_UNDEF,
0,
H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
0)))
{
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
pdu_req_termcap_set (&pInstance->API.PDU_LocalTermCap, 0);
TermCap.next = pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable;
pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = &TermCap;
TermCap.value.bit_mask = capability_present;
TermCap.value.capabilityTableEntryNumber = pInstance->API.LocalCapIdNum;
TermCap.value.capability.choice = Capability_nonStandard_chosen;
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice = h221NonStandard_chosen;
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = 0xB5;
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension = 0x42;
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = 0x8080;
TermCap.value.capability.u.Capability_nonStandard.data.value = &TermCapData;
TermCap.value.capability.u.Capability_nonStandard.data.length = sizeof(TermCapData);
lError = FsmOutgoing(pInstance, &pInstance->API.PDU_LocalTermCap, (DWORD_PTR)pTracker);
pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = TermCap.next;
if (lError != H245_ERROR_OK)
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(lError));
else
H245TRACE(dwInst,4,"H245SendTermCaps -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245SendTermCaps()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245EnumCaps
*
* DESCRIPTION
*
* HRESULT H245EnumCaps (
* DWORD dwInst,
* DWORD dwTransId,
* H245_CAPDIR_T Direction,
* H245_DATA_T DataType,
* H245_CLIENT_T ClientType,
* H245_CAP_CALLBACK_T CallBack
* )
*
*
* Callback:
* CallBack (
* DWORD dwTransId,
* H245_TOTCAP_T *pTotCap,
* )
*
* Description:
*
* This function calls the H.245 client back for every
* capability as defined in the API call that complies with the
* request. If the DataType parameter is set to 0 all of the
* caps types are returned (either local or remote based on the
* Direction parameter) no mater what is in the ClientType
* parameter. If the ClientType parameter is 0, it will return
* all of the capabilities of the given DataType.
*
* The user supplied call back is called within the context of
* the call, therefor the call will be considered synchronous.
*
* Input
* dwInst Instance handle returned by H245Init
* Direction Local/Remote Receive, Transmit, or Receive and
* Transmit
* DataType Type of data (Audio, Video, Data, etc.)
* ClientType Client type (H.262, G.711. etc. ).
* dwTransId User supplied object used to identify this
* request in the callback.
*
* CallBack Output
* dwTransId Identical to dwTransId passed in H245EnumCaps
* pTotCap Pointer one of the capabilities.
*
* Note: TotCap parameter must be copied in the callback. This
* data structure is reused for each callback.
*
* Call Type:
* Synchronous Callback - i.e. called back in the context of
* the API call
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM One or more parameters were invalid
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle.
*
* See Also:
* H245SetLocalCap
* H245ReplLocalCap
*
* callback
*
* H245_IND_CAP
* H245_IND_CAPDESC
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245EnumCaps (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_CAPDIR_T Direction,
H245_DATA_T DataType,
H245_CLIENT_T ClientType,
H245_CAP_CALLBACK_T pfCapCallback,
H245_CAPDESC_CALLBACK_T pfCapDescCallback
)
{
register struct InstanceStruct *pInstance;
struct TerminalCapabilitySet *pTermCapSet;
CapabilityTableLink pCapLink;
int lcl_rmt;
H245_TOTCAP_T totcap;
int nResult = 0;
H245TRACE (dwInst,4,"H245EnumCaps <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* check for callback routine */
if (pfCapCallback == NULL && pfCapDescCallback == NULL)
{
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
/* ok... check the direction.. either remote or local caps.. */
switch (Direction)
{
case H245_CAPDIR_RMTRX:
case H245_CAPDIR_RMTTX:
case H245_CAPDIR_RMTRXTX:
pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
lcl_rmt = H245_REMOTE;
break;
case H245_CAPDIR_LCLRX:
case H245_CAPDIR_LCLTX:
case H245_CAPDIR_LCLRXTX:
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
lcl_rmt = H245_LOCAL;
break;
/* must be either local or remote */
// case H245_CAPDIR_DONTCARE:
default:
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
if (pfCapCallback)
{
if (pTermCapSet->bit_mask & multiplexCapability_present &&
build_totcap_from_mux(&totcap, &pTermCapSet->multiplexCapability, Direction) == H245_ERROR_OK)
{
(*pfCapCallback)(dwTransId, &totcap);
}
if (ClientType == H245_CLIENT_DONTCARE)
{
if (DataType == H245_DATA_DONTCARE)
{
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
{
/* if capability is present */
if (pCapLink->value.bit_mask & capability_present &&
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK)
{
nResult = (*pfCapCallback)(dwTransId, &totcap);
}
} // for
} // if
else
{
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
{
/* if capability is present */
if (pCapLink->value.bit_mask & capability_present &&
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
totcap.DataType == DataType)
{
nResult = (*pfCapCallback)(dwTransId, &totcap);
}
} // for
} // else
} // if
else
{
if (DataType == H245_DATA_DONTCARE)
{
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
{
/* if capability is present */
if (pCapLink->value.bit_mask & capability_present &&
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
totcap.ClientType == ClientType)
{
nResult = (*pfCapCallback)(dwTransId, &totcap);
} /* if cap match */
} // for
} // if
else
{
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
{
/* if capability is present */
if (pCapLink->value.bit_mask & capability_present &&
build_totcap_from_captbl(&totcap,pCapLink,lcl_rmt) == H245_ERROR_OK &&
totcap.ClientType == ClientType &&
totcap.DataType == DataType)
{
nResult = (*pfCapCallback)(dwTransId, &totcap);
}
} // for
} // else
} // else
} // if (pfCapCallback)
if (pfCapDescCallback)
{
// Convert CapabilityDescriptor format to H245_CAPDESC_T format
unsigned int uCapDesc;
register SmltnsCpbltsLink pSimCap;
register unsigned int uAltCap;
H245_TOTCAPDESC_T TotCapDesc;
for (uCapDesc = 0;
uCapDesc < pTermCapSet->capabilityDescriptors.count && nResult == 0;
++uCapDesc)
{
if (pTermCapSet->capabilityDescriptors.value[uCapDesc].bit_mask & smltnsCpblts_present)
{
ASSERT(pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber <= 256);
TotCapDesc.CapDesc.Length = 0;
pSimCap = pTermCapSet->capabilityDescriptors.value[uCapDesc].smltnsCpblts;
ASSERT(pSimCap != NULL);
while (pSimCap)
{
if (TotCapDesc.CapDesc.Length >= H245_MAX_SIMCAPS)
{
H245TRACE (dwInst,1,"H245EnumCaps -> Number of simutaneous capabilities exceeds H245_MAX_SIMCAPS");
InstanceUnlock(pInstance);
return H245_ERROR_MAXTBL;
}
if (pSimCap->value.count > H245_MAX_ALTCAPS)
{
H245TRACE (dwInst,1,"H245EnumCaps -> Number of alternative capabilities exceeds H245_MAX_ALTCAPS");
InstanceUnlock(pInstance);
return H245_ERROR_MAXTBL;
}
TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].Length = (WORD) pSimCap->value.count;
for (uAltCap = 0; uAltCap < pSimCap->value.count; ++uAltCap)
{
TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].AltCaps[uAltCap] = pSimCap->value.value[uAltCap];
}
TotCapDesc.CapDesc.Length++;
pSimCap = pSimCap->next;
} // while
TotCapDesc.CapDescId = pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber;
nResult = pfCapDescCallback(dwTransId, &TotCapDesc);
} // if
} // for
} // if (pfCapDescCallback)
H245TRACE (dwInst,4,"H245EnumCaps -> OK");
InstanceUnlock(pInstance);
return H245_ERROR_OK;
} // H245EnumCaps()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245GetCaps
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
static H245_TOTCAP_T * * ppTotCapGlobal;
static unsigned long dwTotCapLen;
static unsigned long dwTotCapMax;
static H245_TOTCAPDESC_T * * ppCapDescGlobal;
static unsigned long dwCapDescLen;
static unsigned long dwCapDescMax;
static HRESULT dwGetCapsError;
static int
GetCapsCapCallback(DWORD_PTR dwTransId, H245_TOTCAP_T *pTotCap)
{
H245_TOTCAP_T *pNewCap;
if (dwGetCapsError == H245_ERROR_OK)
{
if (dwTotCapLen >= dwTotCapMax)
{
dwGetCapsError = H245_ERROR_MAXTBL;
}
else
{
dwGetCapsError = H245CopyCap(&pNewCap, pTotCap);
if (dwGetCapsError == H245_ERROR_OK)
{
*ppTotCapGlobal++ = pNewCap;
++dwTotCapLen;
}
}
}
return 0;
} // GetCapsCapCallback()
static int
GetCapsCapDescCallback(DWORD_PTR dwTransId, H245_TOTCAPDESC_T *pCapDesc)
{
H245_TOTCAPDESC_T *pNewCapDesc;
if (dwGetCapsError == H245_ERROR_OK)
{
if (dwCapDescLen >= dwCapDescMax)
{
dwGetCapsError = H245_ERROR_MAXTBL;
}
else
{
dwGetCapsError = H245CopyCapDescriptor(&pNewCapDesc,pCapDesc);
{
*ppCapDescGlobal++ = pNewCapDesc;
++dwCapDescLen;
}
}
}
return 0;
} // GetCapsCapDescCallback()
H245DLL HRESULT
H245GetCaps (
H245_INST_T dwInst,
H245_CAPDIR_T Direction,
H245_DATA_T DataType,
H245_CLIENT_T ClientType,
H245_TOTCAP_T * * ppTotCap,
unsigned long * pdwTotCapLen,
H245_TOTCAPDESC_T * * ppCapDesc,
unsigned long * pdwCapDescLen
)
{
register struct InstanceStruct *pInstance;
H245_CAP_CALLBACK_T CapCallback;
H245_CAPDESC_CALLBACK_T CapDescCallback;
H245TRACE (dwInst,4,"H245GetCaps <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
dwTotCapLen = 0;
if (ppTotCap == NULL || pdwTotCapLen == NULL || *pdwTotCapLen == 0)
{
CapCallback = NULL;
}
else
{
CapCallback = GetCapsCapCallback;
ppTotCapGlobal = ppTotCap;
dwTotCapMax = *pdwTotCapLen;
}
dwCapDescLen = 0;
if (ppCapDesc == NULL || pdwCapDescLen == NULL || *pdwCapDescLen == 0)
{
CapDescCallback = NULL;
}
else
{
CapDescCallback = GetCapsCapDescCallback;
ppCapDescGlobal = ppCapDesc;
dwCapDescMax = *pdwCapDescLen;
}
/* check parameters */
if (CapCallback == NULL && CapDescCallback == NULL)
{
H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
dwGetCapsError = H245_ERROR_OK;
H245EnumCaps(dwInst,
0,
Direction,
DataType,
ClientType,
CapCallback,
CapDescCallback);
if (pdwTotCapLen)
*pdwTotCapLen = dwTotCapLen;
if (pdwCapDescLen)
*pdwCapDescLen = dwCapDescLen;
if (dwGetCapsError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245GetCaps -> %s", map_api_error(dwGetCapsError));
else
H245TRACE (dwInst,4,"H245GetCaps -> OK");
InstanceUnlock(pInstance);
return H245_ERROR_OK;
} // H245GetCaps()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CopyCap
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CopyCap (H245_TOTCAP_T **ppDestTotCap,
const H245_TOTCAP_T *pTotCap)
{
POBJECTID pObjectTo;
POBJECTID pObjectFrom;
HRESULT Status;
if (ppDestTotCap == NULL)
return H245_ERROR_PARAM;
*ppDestTotCap = NULL;
if (pTotCap == NULL)
return H245_ERROR_PARAM;
switch (pTotCap->ClientType)
{
case H245_CLIENT_NONSTD:
case H245_CLIENT_VID_NONSTD:
case H245_CLIENT_AUD_NONSTD:
case H245_CLIENT_MUX_NONSTD:
if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen)
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245_NonStd.data.length +
ObjectIdLength(&pTotCap->Cap.H245_NonStd.nonStandardIdentifier) * sizeof(OBJECTID));
}
else
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245_NonStd.data.length);
}
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
if (pTotCap->Cap.H245_NonStd.data.length != 0)
{
(*ppDestTotCap)->Cap.H245_NonStd.data.value = (unsigned char *)(*ppDestTotCap + 1);
memcpy((*ppDestTotCap)->Cap.H245_NonStd.data.value,
pTotCap->Cap.H245_NonStd.data.value,
pTotCap->Cap.H245_NonStd.data.length);
}
else
{
(*ppDestTotCap)->Cap.H245_NonStd.data.value = NULL;
}
if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen &&
pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object != NULL)
{
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
pTotCap->Cap.H245_NonStd.data.length);
(*ppDestTotCap)->Cap.H245_NonStd.nonStandardIdentifier.u.object = pObjectTo;
pObjectFrom = pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object;
do
{
pObjectTo->value = pObjectFrom->value;
pObjectTo->next = pObjectTo + 1;
++pObjectTo;
} while ((pObjectFrom = pObjectFrom->next) != NULL);
--pObjectTo;
pObjectTo->next = NULL;
}
break;
case H245_CLIENT_DAT_NONSTD:
if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen)
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length +
ObjectIdLength(&pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
}
else
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
}
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
if (pTotCap->Cap.H245_NonStd.data.length != 0)
{
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value =
(unsigned char *)(*ppDestTotCap + 1);
memcpy((*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
}
else
{
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value = NULL;
}
if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object != NULL)
{
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
pObjectFrom = pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object;
do
{
pObjectTo->value = pObjectFrom->value;
pObjectTo->next = pObjectTo + 1;
++pObjectTo;
} while ((pObjectFrom = pObjectFrom->next) != NULL);
--pObjectTo;
pObjectTo->next = NULL;
}
break;
case H245_CLIENT_DAT_T120:
case H245_CLIENT_DAT_DSMCC:
case H245_CLIENT_DAT_USERDATA:
case H245_CLIENT_DAT_T434:
case H245_CLIENT_DAT_H224:
case H245_CLIENT_DAT_H222:
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.choice == DtPrtclCpblty_nnStndrd_chosen)
{
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen)
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length +
ObjectIdLength(&pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
}
else
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
}
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
if (pTotCap->Cap.H245_NonStd.data.length != 0)
{
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value =
(unsigned char *)(*ppDestTotCap + 1);
memcpy((*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
}
else
{
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value = NULL;
}
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object != NULL)
{
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
pObjectFrom = pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object;
do
{
pObjectTo->value = pObjectFrom->value;
pObjectTo->next = pObjectTo + 1;
++pObjectTo;
} while ((pObjectFrom = pObjectFrom->next) != NULL);
--pObjectTo;
pObjectTo->next = NULL;
}
}
else
{
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
}
break;
case H245_CLIENT_CONFERENCE:
{
NonStandardDataLink pList;
NonStandardDataLink pFrom;
NonStandardDataLink pTo;
// Initialize Status here to prevent compiler warning "returning a possibly
// uninitialized value"
Status = H245_ERROR_NOMEM;
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
pList = NULL;
(*ppDestTotCap)->Cap.H245Conference.nonStandardData = NULL;
pFrom = pTotCap->Cap.H245Conference.nonStandardData;
while (pFrom)
{
pTo = MemAlloc(sizeof(*pTo));
if (pTo == NULL)
Status = H245_ERROR_NOMEM;
if (pTo != NULL)
{
Status = CopyNonStandardParameter(&pTo->value, &pFrom->value);
if (Status != H245_ERROR_OK)
{
MemFree(pTo);
pTo = NULL;
}
}
if (pTo == NULL)
{
while (pList)
{
pTo = pList;
pList = pList->next;
FreeNonStandardParameter(&pTo->value);
MemFree(pTo);
}
MemFree(*ppDestTotCap);
*ppDestTotCap = NULL;
return Status;
}
pTo->next = pList;
pList = pTo;
pFrom = pFrom->next;
} // while
while (pList)
{
pTo = pList;
pList = pList->next;
pTo->next = (*ppDestTotCap)->Cap.H245Conference.nonStandardData;
(*ppDestTotCap)->Cap.H245Conference.nonStandardData = pTo;
} // while
break;
}
case H245_CLIENT_MUX_H222:
{
VCCapabilityLink pList = NULL;
VCCapabilityLink pFrom;
VCCapabilityLink pTo;
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
(*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = NULL;
pFrom = pTotCap->Cap.H245Mux_H222.vcCapability;
while (pFrom)
{
pTo = MemAlloc(sizeof(*pTo));
if (pTo == NULL)
{
while (pList)
{
pTo = pList;
pList = pList->next;
MemFree(pTo);
}
MemFree(*ppDestTotCap);
*ppDestTotCap = NULL;
return H245_ERROR_NOMEM;
}
pTo->value = pFrom->value;
pTo->next = pList;
pList = pTo;
pFrom = pFrom->next;
} // while
while (pList)
{
pTo = pList;
pList = pList->next;
pTo->next = (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability;
(*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = pList;
} // while
break;
}
case H245_CLIENT_MUX_H2250:
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
Status = CopyH2250Cap(&(*ppDestTotCap)->Cap.H245Mux_H2250, &pTotCap->Cap.H245Mux_H2250);
if (Status != H245_ERROR_OK)
{
MemFree(*ppDestTotCap);
*ppDestTotCap = NULL;
return Status;
}
break;
default:
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
if (*ppDestTotCap == NULL)
return H245_ERROR_NOMEM;
**ppDestTotCap = *pTotCap;
} // switch
return H245_ERROR_OK;
} // H245CopyCap()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245FreeCap
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245FreeCap (H245_TOTCAP_T * pTotCap)
{
if (pTotCap == NULL)
{
return H245_ERROR_PARAM;
}
switch (pTotCap->ClientType)
{
case H245_CLIENT_CONFERENCE:
{
NonStandardDataLink pList;
NonStandardDataLink pTo;
pList = pTotCap->Cap.H245Conference.nonStandardData;
while (pList)
{
pTo = pList;
pList = pList->next;
FreeNonStandardParameter(&pTo->value);
MemFree(pTo);
}
}
break;
case H245_CLIENT_MUX_H222:
{
VCCapabilityLink pList;
VCCapabilityLink pTo;
pList = pTotCap->Cap.H245Mux_H222.vcCapability;
while (pList)
{
pTo = pList;
pList = pList->next;
MemFree(pTo);
}
}
break;
case H245_CLIENT_MUX_H2250:
FreeH2250Cap(&pTotCap->Cap.H245Mux_H2250);
break;
} // switch
MemFree(pTotCap);
return 0;
} // H245FreeCap()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CopyCapDescriptor
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CopyCapDescriptor (H245_TOTCAPDESC_T **ppDestCapDesc,
const H245_TOTCAPDESC_T *pCapDesc)
{
if (ppDestCapDesc == NULL)
return H245_ERROR_PARAM;
*ppDestCapDesc = NULL;
if (pCapDesc == NULL)
return H245_ERROR_PARAM;
*ppDestCapDesc = MemAlloc(sizeof(**ppDestCapDesc));
if (*ppDestCapDesc == NULL)
return H245_ERROR_NOMEM;
**ppDestCapDesc = *pCapDesc;
return H245_ERROR_OK;
} // H245CopyCapDescriptor()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245FreeCapDescriptor
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245FreeCapDescriptor (H245_TOTCAPDESC_T * pCapDesc)
{
if (pCapDesc == NULL)
{
return H245_ERROR_PARAM;
}
MemFree(pCapDesc);
return 0;
} // H245FreeCapDescriptor()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CopyMux
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL H245_MUX_T *
H245CopyMux (const H245_MUX_T * pMux)
{
register unsigned int uLength;
register H245_MUX_T *pNew;
H2250LCPs_nnStndrdLink pList;
H2250LCPs_nnStndrdLink pFrom;
H2250LCPs_nnStndrdLink pTo;
switch (pMux->Kind)
{
case H245_H222:
uLength = sizeof(*pMux) +
pMux->u.H222.programDescriptors.length +
pMux->u.H222.streamDescriptors.length;
pNew = MemAlloc(uLength);
if (pNew != NULL)
{
*pNew = *pMux;
if (pMux->u.H222.programDescriptors.length != 0)
{
pNew->u.H222.programDescriptors.value = (unsigned char *)(pNew + 1);
memcpy(pNew->u.H222.programDescriptors.value,
pMux->u.H222.programDescriptors.value,
pMux->u.H222.programDescriptors.length);
}
else
{
pNew->u.H222.programDescriptors.value = NULL;
}
if (pMux->u.H222.streamDescriptors.length != 0)
{
pNew->u.H222.streamDescriptors.value = ((unsigned char *)pNew) +
(uLength - pMux->u.H222.streamDescriptors.length);
memcpy(pNew->u.H222.streamDescriptors.value,
pMux->u.H222.streamDescriptors.value,
pMux->u.H222.streamDescriptors.length);
}
else
{
pNew->u.H222.streamDescriptors.value = NULL;
}
}
break;
case H245_H223:
pNew = MemAlloc(sizeof(*pMux) + pMux->u.H223.H223_NONSTD.data.length);
if (pNew != NULL)
{
*pNew = *pMux;
if (pMux->u.H223.H223_NONSTD.data.length != 0)
{
pNew->u.H223.H223_NONSTD.data.value = (unsigned char *)(pNew + 1);
memcpy(pNew->u.H223.H223_NONSTD.data.value,
pMux->u.H223.H223_NONSTD.data.value,
pMux->u.H223.H223_NONSTD.data.length);
}
else
{
pNew->u.H223.H223_NONSTD.data.value = NULL;
}
}
break;
case H245_H2250:
case H245_H2250ACK:
// Caveat: assumes nonstandard list, mediaChannel and mediaControlChannel
// in same place in both structures
if (pMux->u.H2250.mediaChannelPresent &&
(pMux->u.H2250.mediaChannel.type == H245_IPSSR_UNICAST ||
pMux->u.H2250.mediaChannel.type == H245_IPLSR_UNICAST) &&
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route != NULL &&
pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount != 0)
{
if (pMux->u.H2250.mediaControlChannelPresent &&
(pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
{
unsigned int uLength2;
uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
uLength2 = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
pNew = MemAlloc(sizeof(*pMux) + uLength + uLength2);
if (pNew != NULL)
{
*pNew = *pMux;
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route =
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route + uLength;
memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
uLength);
memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
uLength2);
}
}
else
{
uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
pNew = MemAlloc(sizeof(*pMux) + uLength);
if (pNew != NULL)
{
*pNew = *pMux;
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
uLength);
}
}
}
else if (pMux->u.H2250.mediaControlChannelPresent &&
(pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
{
uLength = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
pNew = MemAlloc(sizeof(*pMux) + uLength);
if (pNew != NULL)
{
*pNew = *pMux;
pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
uLength);
}
}
else
{
pNew = MemAlloc(sizeof(*pMux));
if (pNew != NULL)
{
*pNew = *pMux;
}
}
pList = NULL;
pNew->u.H2250.nonStandardList = NULL;
pFrom = pMux->u.H2250.nonStandardList;
while (pFrom)
{
pTo = MemAlloc(sizeof(*pTo));
if (pTo != NULL)
{
if (CopyNonStandardParameter(&pTo->value, &pFrom->value) != H245_ERROR_OK)
{
MemFree(pTo);
pTo = NULL;
}
}
if (pTo == NULL)
{
while (pList)
{
pTo = pList;
pList = pList->next;
FreeNonStandardParameter(&pTo->value);
MemFree(pTo);
}
MemFree(pNew);
return NULL;
}
pTo->next = pList;
pList = pTo;
pFrom = pFrom->next;
} // while
while (pList)
{
pTo = pList;
pList = pList->next;
pTo->next = pNew->u.H2250.nonStandardList;
pNew->u.H2250.nonStandardList = pTo;
} // while
break;
// case H245_VGMUX:
default:
pNew = MemAlloc(sizeof(*pMux));
if (pNew != NULL)
{
*pNew = *pMux;
}
} // switch
return pNew;
} // H245CopyMux()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245FreeMux
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245FreeMux (H245_MUX_T * pMux)
{
H2250LCPs_nnStndrdLink pLink;
if (pMux == NULL)
{
return H245_ERROR_PARAM;
}
switch (pMux->Kind)
{
case H245_H2250:
case H245_H2250ACK:
// Caveat: assumes nonstandard list is in same place in both structures
while (pMux->u.H2250.nonStandardList)
{
pLink = pMux->u.H2250.nonStandardList;
pMux->u.H2250.nonStandardList = pLink->next;
FreeNonStandardParameter(&pLink->value);
MemFree(pLink);
}
break;
} // switch
MemFree(pMux);
return 0;
} // H245FreeMux()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245OpenChannel
*
* DESCRIPTION
*
* HRESULT H245OpenChannel (
* H245_INST_T dwInst,
* DWORD dwTransId,
* DWORD dwTxChannel,
* H245_TOTCAP_T *pTxMode,
* H245_MUX_T *pTxMux,
* H245_TOTCAP_T *pRxMode, (* bi-dir only *)
* H245_MUX_T *pRxMux (* bi-dir only *)
* )
*
* Description:
* This function is called to open either a uni-directional,
* or a bi-directional channel. The mode to the remote peer
* will be designated by the *pTxMode.. To open a bi-directional
* channel the client selects a non-null receive mode ( *pRxMode).
* This mode indicates to the remote peer its transmit mode.
* For uni-directional channels the *pRxMode must be NULL.
*
* The dwTxChannel parameter indicates which forward logical
* channel the H.245 will open. If this is a bi-directional
* channel open, the confirm will indicate the logical channel
* specified in the open request by the remote terminal
*
* The pMux parameter will contain a pointer to H.223, H.222,
* VGMUX, or other logical channel parameters depending on the
* system configuration. (see H245_H223_LOGICAL_PARAM). This
* may be NULL for some clients.
*
* Note:
* 7 pTxMode->CapId is of no significance in this call.
* It is not used
* 7 pRxMode->CapId is of no significance in this call.
* It is not used
*
* Input
* dwInst Instance handle returned by H245Init
* dwTransId User supplied object used to identify this
* request in the asynchronous confirm to this
* call.
* dwTxChannel Logical Channel number for forward (Transmit)
* Channel
* pTxMode The capability (mode) used for transmission
* to the remote peer.
* Note: pTxMode->CapId is ignored
* pTxMux The formward logical channel parameters
* for H.223, H.222, VGMUX, etc.
* pRxMode Optional: Transmit mode specified for the
* remote terminal. This is used only for
* Bi-directional Channel opens and must be set
* to NULL if opening a Uni-directional channel.
* Note: pRxMode->CapId is ignored
* pRxMux Optional : The reverse logical channel
* parameters for H.223, H.222, VGMUX, etc. or
* NULL.
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callback:
* H245_CONF_OPEN
* H245_CONF_NEEDRSP_OPEN Bi-Directional Channels only
* waiting for confirm.
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM One or more parameters were
* invalid
* H245_ERROR_BANDWIDTH_OVERFLOW Open would exceed bandwidth
* limitations
* H245_ERROR_NOMEM
* H245_ERROR_NORESOURCE Out of resources, too many
* open channels or outside scope
* of simultaneous capabilities.
* H245_ERROR_INVALID_INST dwInst is not a valid instance
* handle
* H245_ERROR_INVALID_STATE Not in the proper state to
* issue open
* H245_ERROR_CHANNEL_INUSE Channel is currently open
*
* See Also:
* H245CloseChannel
* H245OpenChannelIndResp
* H245OpenChannelConfResp
*
* callback
*
* H245_CONF_OPEN
* H245_CONF_NEEDRSP_OPEN
* H245_IND_OPEN_CONF
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245OpenChannel (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_CHANNEL_T wTxChannel,
const H245_TOTCAP_T * pTxMode,
const H245_MUX_T * pTxMux,
H245_PORT_T dwTxPort, // optional
const H245_TOTCAP_T * pRxMode, // bi-dir only
const H245_MUX_T * pRxMux, // bi-dir only
const H245_ACCESS_T * pSeparateStack // optional
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
Tracker_T *pTracker;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245OpenChannel <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* must have performed Master Slave Negotiation at this point */
if (pInstance->Configuration == H245_CONF_H324 &&
pInstance->API.MasterSlave != APIMS_Master &&
pInstance->API.MasterSlave != APIMS_Slave)
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_STATE));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_STATE;
}
pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
/* channel is currently in use */
if (pTracker)
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_CHANNEL_INUSE));
InstanceUnlock(pInstance);
return H245_ERROR_CHANNEL_INUSE;
}
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(*pPdu));
/* lock in the transmit side.. */
/* wait until OpenChannelConfResp to setup RxChannel */
lError = pdu_req_open_channel(pPdu,
wTxChannel,
dwTxPort, /* forward port */
pTxMode,
pTxMux,
pRxMode,
pRxMux,
pSeparateStack);
if (lError != H245_ERROR_OK)
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
InstanceUnlock(pInstance);
return lError;
}
/* if allocation error */
if (!(pTracker = alloc_link_tracker (pInstance,
API_OPEN_CHANNEL_T,
dwTransId,
API_ST_WAIT_RMTACK,
API_CH_ALLOC_LCL,
(pRxMode?API_CH_TYPE_BI:API_CH_TYPE_UNI),
pTxMode->DataType,
wTxChannel, H245_INVALID_CHANNEL,
0)))
{
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
if (lError != H245_ERROR_OK)
{
unlink_dealloc_tracker (pInstance, pTracker);
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
}
else
H245TRACE (dwInst,4,"H245OpenChannel -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245OpenChannel()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245OpenChannelAccept
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245OpenChannelAccept (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
const H245_MUX_T * pRxMux, // optional H2250LogicalChannelAckParameters
H245_CHANNEL_T wTxChannel, // bi-dir only
const H245_MUX_T * pTxMux, // bi-dir only optional H2250LogicalChannelParameters
H245_PORT_T dwTxPort, // bi-dir only optional
const H245_ACCESS_T * pSeparateStack // optional
)
{
register struct InstanceStruct *pInstance;
Tracker_T * pTracker;
MltmdSystmCntrlMssg * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245OpenChannelAccept <- wRxChannel=%d wTxChannel=%d",
wRxChannel, wTxChannel);
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if channel not found in tracker list */
/* note that it looks for given channel given who alloced it */
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
/* not locking tracker.. since no indication will come in until I issue the request */
if (!pTracker)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* if not open.. invalid op */
if (pTracker->TrackerType != API_OPEN_CHANNEL_T)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* if was uni open w/ TxChannel set.. error */
/* -or - */
/* if was bi open w/ !TxChannel set.. error */
/* AND it wasn't a reject */
if (pTracker->u.Channel.ChannelType == API_CH_TYPE_BI && wTxChannel == 0)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
/* for debug */
ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
/* check state.. must be returning.. */
if (pTracker->State != API_ST_WAIT_LCLACK)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_STATE));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_STATE;
}
/* setup tracker object for new transaction */
pTracker->TransId = dwTransId;
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(*pPdu));
switch (pTracker->u.Channel.ChannelType)
{
case API_CH_TYPE_UNI:
pTracker->State = API_ST_IDLE;
pTracker->u.Channel.TxChannel = 0;
lError = pdu_rsp_open_logical_channel_ack(pPdu,
wRxChannel,
pRxMux,
0,
NULL,
dwTxPort,
pSeparateStack);
if (lError != H245_ERROR_OK)
{
// If parameter error, we don't want to deallocate tracker
MemFree (pPdu);
InstanceUnlock(pInstance);
return lError;
}
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
break;
case API_CH_TYPE_BI:
pTracker->State = API_ST_WAIT_CONF; /* waiting for confirmation */
pTracker->u.Channel.TxChannel = wTxChannel;
lError = pdu_rsp_open_logical_channel_ack(pPdu,
wRxChannel,
pRxMux,
wTxChannel,
pTxMux,
dwTxPort,
pSeparateStack);
if (lError != H245_ERROR_OK)
{
// If parameter error, we don't want to deallocate tracker
MemFree (pPdu);
InstanceUnlock(pInstance);
return lError;
}
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
break;
default:
H245TRACE (dwInst,1,"H245OpenChannelAccept: Invalid Tracker Channel Type %d",
pTracker->u.Channel.ChannelType);
lError = H245_ERROR_FATAL;
} // switch
MemFree (pPdu);
switch (lError)
{
case H245_ERROR_OK:
H245TRACE (dwInst,4,"H245OpenChannelAccept -> OK");
break;
default:
// Deallocate tracker object for all errors except parameter error
unlink_dealloc_tracker (pInstance, pTracker);
// Fall-through to next case is intentional
case H245_ERROR_PARAM:
// If parameter error, we don't want to deallocate tracker
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(lError));
} // switch
InstanceUnlock(pInstance);
return lError;
} // H245OpenChannelAccept()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245OpenChannelReject
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245OpenChannelReject (
H245_INST_T dwInst,
H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
unsigned short wCause
)
{
register struct InstanceStruct *pInstance;
Tracker_T * pTracker;
MltmdSystmCntrlMssg * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245OpenChannelReject <- wRxChannel=%d", wRxChannel);
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if channel not found in tracker list */
/* note that it looks for given channel given who alloced it */
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
/* not locking tracker.. since no indication will come in until I issue the request */
/* if not open.. invalid op */
if (pTracker == NULL || pTracker->TrackerType != API_OPEN_CHANNEL_T)
{
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* for debug */
ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
/* check state.. must be returning.. */
if (pTracker->State != API_ST_WAIT_LCLACK)
{
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_STATE));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_STATE;
}
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(*pPdu));
pdu_rsp_open_logical_channel_rej(pPdu, wRxChannel, wCause);
switch (pTracker->u.Channel.ChannelType)
{
case API_CH_TYPE_UNI:
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
break;
case API_CH_TYPE_BI:
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
break;
default:
H245TRACE (dwInst,1,"H245OpenChannelReject: Invalid Tracker Channel Type %d",
pTracker->u.Channel.ChannelType);
lError = H245_ERROR_FATAL;
} // switch
MemFree (pPdu);
unlink_dealloc_tracker (pInstance, pTracker);
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245OpenChannelReject -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245OpenChannelReject()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245CloseChannel
*
* DESCRIPTION
*
* HRESULT H245CloseChannel (
* H245_INST_T dwInst,
* DWORD dwTransId,
* DWORD wTxChannel,
* )
* Description:
* Called to close a channel upon which the client previously
* issued an OpenChannel request.
*
* Input
* dwInst Instance handle returned by H245Init
* dwTransId User supplied object used to identify this
* request in the asynchronous confirm to this
* call.
* wChannel Logical Channel Number to close
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callbacks:
* H245_CONF_CLOSE
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM wChannel is not a locally opened
* channel
* H245_ERROR_INVALID_INST dwInst is not a valid intance handle
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_INVALID_CHANNEL
* H245_ERROR_INVALID_OP Can not perform this operation on
* this channel.(See H245CloseChannelReq)
* See Also:
* H245OpenChannel
* H245OpenChannelIndResp
* H245OpenChannelConfResp
* H245CloseChannelReq
*
* callback
* H245_CONF_CLOSE
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CloseChannel (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_CHANNEL_T wTxChannel
)
{
register struct InstanceStruct *pInstance;
Tracker_T *pTracker;
DWORD error;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245CloseChannel <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if channel not found in tracker list */
/* note that it looks for given channel given who alloced it */
pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
/* not locking tracker.. since no indication will come in until I issue the request */
if (!pTracker)
{
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_CHANNEL;
}
/* setup new tracker state */
pTracker->State = API_ST_WAIT_RMTACK;
pTracker->TrackerType = API_CLOSE_CHANNEL_T;
pTracker->TransId = dwTransId;
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* ok.. get pdu */
pdu_req_close_logical_channel(pPdu, wTxChannel, 0/* user */);
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
MemFree (pPdu);
/* error.. so deallocate tracker structure */
if (error != H245_ERROR_OK)
{
unlink_dealloc_tracker (pInstance, pTracker);
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(error));
}
else
{
H245TRACE (dwInst,4,"H245CloseChannel -> OK");
}
InstanceUnlock(pInstance);
return H245_ERROR_OK;
} // H245CloseChannel()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245CloseChannelReq
*
* DESCRIPTION
*
* HRESULT H245CloseChannelReq (
* H245_INST_T dwInst,
* DWORD dwTransId,
* DWORD wChannel,
* )
* Description:
* Called to request the remote peer to close a logical channel
* it previously opened
*
* Input
* dwInst Instance handle returned by H245Init
* dwTransId User supplied object used to identify this
* request in the asynchronous confirm to this
* call
* wChannel Logical Channel Number to close
*
* Note: This is only asking permission. Even if the Close
* Request is accepted the channel still has to be closed from
* the remote side. (i.e. this does not close the channel it
* only asked the remote side it issue a close)
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callbacks:
* H245_CONF_CLOSE
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM wChannel is not a channel
* opened by remote peer
* H245_ERROR_INVALID_INST dwInst is not a valid instance
* handle
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_INVALID_CHANNEL
* H245_ERROR_INVALID_OP Can not perform this operation
* on this channel
* (see H245CloseChannel)
* See Also:
* H245OpenChannel
* H245OpenChannelIndResp
* H245OpenChannelConfResp
* H245CloseChannel
*
* callback
*
* H245_CONF_CLOSE
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CloseChannelReq (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_CHANNEL_T wRxChannel
)
{
register struct InstanceStruct *pInstance;
Tracker_T *pTracker;
DWORD error;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245CloseChannelReq <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if channel not found in tracker list */
/* note that it looks for given channel given who alloced it */
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
/* not locking tracker.. since no indication will come in until I issue the request */
if (!pTracker)
{
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* verify state of tracker */
pTracker->State = API_ST_WAIT_RMTACK;
pTracker->TrackerType = API_CLOSE_CHANNEL_T;
pTracker->TransId = dwTransId;
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* ok.. get pdu */
pdu_req_request_close_channel(pPdu, wRxChannel);
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
MemFree (pPdu);
if (error != H245_ERROR_OK)
{
unlink_dealloc_tracker (pInstance, pTracker);
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(error));
}
else
H245TRACE (dwInst,4,"H245CloseChannelReq -> OK");
InstanceUnlock(pInstance);
return error;
} // H245CloseChannelReq()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245CloseChannelReqResp
*
* DESCRIPTION
*
* HRESULT H245CloseChannelReqResp (
* H245_INST_T dwInst,
* H245_ACC_REJ_T AccRej,
* DWORD wChannel
* )
*
* Description:
* This routine is called to accept or reject a
* RequestChannelClose (H245_IND_REQ_CLOSE indication) from the
* remote peer. The channel must have been locally opened. The
* parameter AccRej is H245_ACC to accept or H245_REJ to reject
* the close. The local client should follow this response with
* a H245CloseChannel call.
*
* If there was a Release CloseChannelRequest event that
* occurred during this transaction there error code returned
* will be H245_ERROR_CANCELED. This indicates to the H.245
* client that no action should be taken.
*
* Input
* dwInst Instance handle returned by H245GetInstanceId
* AccRej this parameter contains either H245_ACC or
* H245_REJ. This indicates to H.245 which
* action to take.
* wChannel Logical Channel Number to close
*
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
* Errors:
* H245_ERROR_OK
* H245_ERROR_PARAM
* H245_ERROR_NOMEM
* H245_ERROR_INVALID_CHANNEL
* H245_ERROR_INVALID_OP Can not perform this operation on this
* channel (see H245CloseChannel)
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
* H245_ERROR_CANCELED if release was received during the
* processing of this request..
* See Also:
* H245CloseChannel
*
* callback
*
* H245_IND_REQ_CLOSE
* H245_IND_CLOSE
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CloseChannelReqResp (
H245_INST_T dwInst,
H245_ACC_REJ_T AccRej,
H245_CHANNEL_T wChannel
)
{
register struct InstanceStruct *pInstance;
Tracker_T *pTracker;
DWORD error;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245CloseChannelReqResp <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if channel not found in tracker list */
/* note that it looks for given channel given who alloced it */
pTracker = find_tracker_by_txchannel (pInstance, wChannel, API_CH_ALLOC_LCL);
/* not locking tracker.. since no indication will come in until I issue the request */
if (!pTracker)
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* if the request was canceled.. tell useer */
if (pTracker->State == API_ST_WAIT_LCLACK_CANCEL)
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_CANCELED));
InstanceUnlock(pInstance);
return H245_ERROR_CANCELED;
}
/* verify state of tracker */
if ((pTracker->State != API_ST_WAIT_LCLACK) ||
(pTracker->TrackerType != API_CLOSE_CHANNEL_T))
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
/* set the state to idle.. expect this side to close the channel next */
pTracker->State = API_ST_IDLE;
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* ok.. get pdu */
if (AccRej == H245_ACC)
{
pTracker = NULL;
pdu_rsp_request_channel_close_ack(pPdu, wChannel);
}
else
{
pdu_rsp_request_channel_close_rej(pPdu, wChannel, AccRej);
}
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
MemFree (pPdu);
if (error != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(error));
else
H245TRACE (dwInst,4,"H245CloseChannelReqResp ->");
InstanceUnlock(pInstance);
return error;
} // H245CloseChannelReqResp()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245SendLocalMuxTable
*
* DESCRIPTION
*
* HRESULT H245SendLocalMuxTable (
* H245_INST_T dwInst,
* DWORD dwTransId,
* H245_MUX_TABLE_T *pMuxTbl
* )
* Description:
* This routine is called to send a mux table to the remote
* side. The remote side can either reject or accept each mux
* table entry in a message. The confirm is sent back to the
* calling H.245 client based on the acceptance or non
* acceptance of each Mux table entry with H245_CONF_MUXTBL_SND.
*
* This is a fairly dangerous call, since the mux table
* structure is a linked lise of mux table entries. Invalid
* data structures could cause an access error. Example code is
* supplied in the appendix.
* Input
* dwInst Instance handle returned by H245Init
* dwTransId User supplied object used to identify
* this request in the asynchronous
* confirm to this call.
* pMuxTbl Mux table entry structure
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
*
* Callbacks:
* H245_CONF_MUXTBLSND
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_INVALID_MUXTBLENTRY
* H245_ERROR_PARAM
* H245_ERROR_INVALID_INST
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_NOMEM
*
* See Also:
* APPENDIX Examples
*
* callback
*
* H245_CONF_MUXTBL_SND
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245SendLocalMuxTable (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_MUX_TABLE_T *pMuxTable
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
Tracker_T *pTracker;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245SendLocalMuxTable <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* make sure parameters ar ok.. */
if (!pMuxTable)
{
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
/* allocate tracker for event */
pTracker = alloc_link_tracker (pInstance,
API_SEND_MUX_T,
dwTransId,
API_ST_WAIT_RMTACK,
API_CH_ALLOC_UNDEF,
API_CH_TYPE_UNDEF,
0,
H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
0);
if (pTracker == NULL)
{
H245TRACE(dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
// Allocate PDU buffer
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
if (pPdu == NULL)
{
H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",H245_ERROR_NOMEM);
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
lError = pdu_req_send_mux_table(pInstance,
pPdu,
pMuxTable,
0,
&pTracker->u.MuxEntryCount);
if (lError == H245_ERROR_OK)
{
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
/* free the list just built */
free_mux_desc_list(pPdu->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend.multiplexEntryDescriptors);
}
/* free the pdu */
MemFree (pPdu);
if (lError != H245_ERROR_OK)
{
unlink_dealloc_tracker (pInstance, pTracker);
H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(lError));
}
else
H245TRACE (dwInst,4,"H245SendLocalMuxTable -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245SendLocalMuxTable()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245MuxTableIndResp
*
* DESCRIPTION
*
* HRESULT H245MuxTableIndResp (
* H45_INST_T dwInst,
* H245_ACC_REJ_MUX_T AccRejMux,
* DWORD Count
* )
* Description:
* This procedure is called to either accept or reject mux
* table entries sent up in the H245_IND_MUX_TBL indication.
*
* Input
* dwInst Instance handle returned by H245Init
* AccRejMux Accept Reject Mux structure
* Count number of entries in the structure
*
* Call Type:
* Asynchronous
*
* Return Values:
* See Errors
* Errors:
* H245_ERROR_OK
* H245_ERROR_INVALID_MUXTBLENTRY
* H245_ERROR_PARAM
* H245_ERROR_INVALID_INST
* H245_ERROR_INVALID_OP
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_NOMEM
* See Also:
* H245SendLocalMuxTable
*
* callback
*
* H245_IND_MUX_TBL
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MuxTableIndResp (
H245_INST_T dwInst,
H245_ACC_REJ_MUX_T AccRejMux,
unsigned long dwCount
)
{
register struct InstanceStruct *pInstance;
DWORD ii;
Tracker_T *pTracker;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245MuxTableIndResp <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* look for tracker.. */
pTracker = NULL;
pTracker = find_tracker_by_type (pInstance, API_RECV_MUX_T, pTracker);
/* if tracker not found.. issue invalid op */
if (!pTracker)
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_OP;
}
ASSERT (pTracker->State == API_ST_WAIT_LCLACK);
/* can't ack or reject more than you got */
if ((dwCount > pTracker->u.MuxEntryCount) ||
(dwCount > 15))
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
/* verify the mux table entry id's */
for (ii=0;ii<dwCount;ii++)
{
if ((AccRejMux[ii].MuxEntryId > 15) ||
(AccRejMux[ii].MuxEntryId <= 0))
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
}
}
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* if there are any rejects in the list.. send reject */
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
if (pdu_rsp_mux_table_rej (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
FsmOutgoing(pInstance, pPdu, 0);
/* if there are any accepts in the list.. send accept */
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
if (pdu_rsp_mux_table_ack (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
FsmOutgoing(pInstance, pPdu, 0);
/* if we've acked all the entries */
if (!(pTracker->u.MuxEntryCount -= dwCount))
unlink_dealloc_tracker (pInstance, pTracker);
MemFree (pPdu);
H245TRACE (dwInst,4,"H245MuxTableIndResp -> %s",H245_ERROR_OK);
InstanceUnlock(pInstance);
return H245_ERROR_OK;
} // H245MuxTableIndResp()
#if 0
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245MiscCommand
*
* DESCRIPTION
*
* HRESULT H245MiscCommand (
* H245_INST_T dwInst,
* DWORD wChannel,
* H245_MISC_T *pMisc
* )
* Description:
* Send a Misc. command to the remote side (see H245_MISC_T
* data Structure)
*
* Input
* dwInst Instance handle returned by H245Init
* wChannel Logical Channel Number
* pMisc pointer to a misc. command structure
*
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_INVALID_CHANNEL
* H245_ERROR_NOMEM
* H245_ERROR_PARAM
* H245_ERROR_INVALID_INST
*
* callback
*
* H245_IND_MISC
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT H245MiscCommand (
H245_INST_T dwInst,
WORD wChannel,
H245_MISC_T *pMisc
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
MltmdSystmCntrlMssg *pPdu;
H245TRACE (dwInst,4,"H245MiscCommand <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
/* if the channel can not be found */
if (!find_tracker_by_txchannel(pInstance, wChannel, API_CH_ALLOC_LCL) &&
!find_tracker_by_rxchannel(pInstance, wChannel, API_CH_ALLOC_RMT))
{
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
InstanceUnlock(pInstance);
return H245_ERROR_INVALID_CHANNEL;
}
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
{
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* budld pdu for misc command */
pdu_cmd_misc (pPdu, pMisc, wChannel);
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree (pPdu);
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MiscCommand -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MiscCommand()
#endif
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestMultiplexEntry
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestMultiplexEntry (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
const unsigned short * pwMultiplexTableEntryNumbers,
unsigned long dwCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
DWORD dwIndex;
H245TRACE (dwInst,4,"H245RequestMultiplexEntry <-");
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
{
if (pwMultiplexTableEntryNumbers[dwIndex] < 1 ||
pwMultiplexTableEntryNumbers[dwIndex] > 15)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMultiplexEntry_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count = (WORD)dwCount;
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
{
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex] =
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
}
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestMultiplexEntry -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestMultiplexEntry()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestMultiplexEntryAck
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestMultiplexEntryAck (
H245_INST_T dwInst,
const unsigned short * pwMultiplexTableEntryNumbers,
unsigned long dwCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
DWORD dwIndex;
H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck <-");
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = requestMultiplexEntryAck_chosen;
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count = (WORD)dwCount;
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
{
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex] =
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
}
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestMultiplexEntryAck()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestMultiplexEntryReject
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestMultiplexEntryReject (
H245_INST_T dwInst,
const unsigned short * pwMultiplexTableEntryNumbers,
unsigned long dwCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
DWORD dwIndex;
H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject <-");
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = rqstMltplxEntryRjct_chosen;
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count = (WORD)dwCount;
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
{
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber =
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].cause.choice = RMERDs_cs_unspcfdCs_chosen;
}
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestMultiplexEntryReject()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestMode
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestMode (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
// const ModeElement * pModeElements,
//tomitowoju@intel.com
ModeDescription ModeDescriptions[],
//tomitowoju@intel.com
unsigned long dwCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
RequestedModesLink pLink;
RequestedModesLink pLink_First;
DWORD dwIndex;
// tomitowoju@intel.com
ULONG ulPDUsize;
// tomitowoju@intel.com
H245TRACE (dwInst,4,"H245RequestMode <-");
//tomitowoju@intel.com
// if (pModeElements == NULL || dwCount == 0 || dwCount > 256)
if (ModeDescriptions == NULL || dwCount == 0 || dwCount > 256)
//tomitowoju@intel.com
{
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
//tomitowoju@intel.com
// pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + sizeof(*pLink));
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
//tomitowoju@intel.com
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
USHORT usModeDescIndex =0;
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMode_chosen;
//tomitowoju@intel.com
// pLink = (RequestedModesLink)(pPdu + 1);
pLink = (RequestedModesLink)(pPdu + usModeDescIndex+1);
//tomitowoju@intel.com
//tomitowoju@intel.com
// pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink;
//tomitowoju@intel.com
//tomitowoju@intel.com
pLink_First = pLink;
//tomitowoju@intel.com
// --> linked list of mode descriptions ... up to 1..256
//tomitowoju@intel.com
while(usModeDescIndex<=(dwCount-1))
{
//tomitowoju@intel.com
//tomitowoju@intel.com
// pLink->next = NULL;
//tomitowoju@intel.com
// --> number of actual mode-elements associated with this mode description
//tomitowoju@intel.com
// pLink->value.count = (WORD)dwCount;
pLink->value.count = (WORD)ModeDescriptions[usModeDescIndex].count;
//tomitowoju@intel.com
// for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
for (dwIndex = 0; dwIndex < ModeDescriptions[usModeDescIndex].count; ++dwIndex)
{
//tomitowoju@intel.com
// pLink->value.value[dwIndex] = pModeElements[dwIndex];
pLink->value.value[dwIndex] = ModeDescriptions[usModeDescIndex].value[dwIndex];
//tomitowoju@intel.com
}
//tomitowoju@intel.com
usModeDescIndex++;
if(usModeDescIndex<=(dwCount-1))
{
pLink->next = (RequestedModesLink)(pPdu + usModeDescIndex+1);
pLink = pLink->next;
pLink->next = NULL;
}
//tomitowoju@intel.com
//tomitowoju@intel.com
}
//tomitowoju@intel.com
//tomitowoju@intel.com
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink_First;
//tomitowoju@intel.com
//--
ulPDUsize = (sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
//--
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestMode -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestMode()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestModeAck
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestModeAck (
H245_INST_T dwInst,
unsigned short wResponse
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245RequestModeAck <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = requestModeAck_chosen;
pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice = wResponse;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestModeAck -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestModeAck()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RequestModeReject
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RequestModeReject (
H245_INST_T dwInst,
unsigned short wCause
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245RequestModeReject <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = requestModeReject_chosen;
pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice = wCause;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RequestModeReject -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RequestModeReject()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245RoundTripDelayRequest
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245RoundTripDelayRequest (
H245_INST_T dwInst,
DWORD_PTR dwTransId
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245RoundTripDelayRequest <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = roundTripDelayRequest_chosen;
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245RoundTripDelayRequest -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245RoundTripDelayRequest()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245MaintenanceLoop
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MaintenanceLoop (
H245_INST_T dwInst,
DWORD_PTR dwTransId,
H245_LOOP_TYPE_T dwLoopType,
H245_CHANNEL_T wChannel
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245MaintenanceLoop <-");
if (dwLoopType < systemLoop_chosen ||
dwLoopType > logicalChannelLoop_chosen ||
(dwLoopType != systemLoop_chosen && wChannel == 0))
{
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = maintenanceLoopRequest_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice = (WORD)dwLoopType;
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop = wChannel;
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MaintenanceLoop -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MaintenanceLoop()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245MaintenanceLoopRelease
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MaintenanceLoopRelease (H245_INST_T dwInst)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245MaintenanceLoopRelease <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = mntnncLpOffCmmnd_chosen;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MaintenanceLoopRelease -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MaintenanceLoopRelease()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245MaintenanceLoopAccept
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MaintenanceLoopAccept (
H245_INST_T dwInst,
H245_CHANNEL_T wChannel
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245MaintenanceLoopAccept <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = maintenanceLoopAck_chosen;
pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop = wChannel;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MaintenanceLoopAccept -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MaintenanceLoopAccept()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245MaintenanceLoopReject
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MaintenanceLoopReject (
H245_INST_T dwInst,
H245_CHANNEL_T wChannel,
unsigned short wCause
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245MaintenanceLoopReject <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = maintenanceLoopReject_chosen;
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop = wChannel;
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.cause.choice = wCause;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MaintenanceLoopReject -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MaintenanceLoopReject()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245NonStandardObject
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245NonStandardObject (
H245_INST_T dwInst,
H245_MESSAGE_TYPE_T MessageType,
const unsigned char * pData,
unsigned long dwDataLength,
const unsigned short * pwObjectId,
unsigned long dwObjectIdLength
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
POBJECTID pObject;
H245TRACE (dwInst,4,"H245NonStandardObject <-");
if (pData == NULL || dwDataLength == 0 || pwObjectId == NULL || dwObjectIdLength == 0)
{
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + dwObjectIdLength * sizeof(*pObject));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
switch (MessageType)
{
case H245_MESSAGE_REQUEST:
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
break;
case H245_MESSAGE_RESPONSE:
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
break;
case H245_MESSAGE_COMMAND:
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
break;
case H245_MESSAGE_INDICATION:
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
break;
default:
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
} // switch
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = object_chosen;
// Copy the object identifier
pObject = (POBJECTID) (pPdu + 1);
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object = pObject;
do
{
pObject->next = pObject + 1;
pObject->value = *pwObjectId++;
++pObject;
} while (--dwObjectIdLength);
// Null terminate the linked list
--pObject;
pObject->next = NULL;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245NonStandardObject -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245NonStandardObject()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245NonStandardH221
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245NonStandardH221 (
H245_INST_T dwInst,
H245_MESSAGE_TYPE_T MessageType,
const unsigned char * pData,
unsigned long dwDataLength,
unsigned char byCountryCode,
unsigned char byExtension,
unsigned short wManufacturerCode
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245NonStandard221 <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
switch (MessageType)
{
case H245_MESSAGE_REQUEST:
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
break;
case H245_MESSAGE_RESPONSE:
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
break;
case H245_MESSAGE_COMMAND:
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
break;
case H245_MESSAGE_INDICATION:
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
break;
default:
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_PARAM));
InstanceUnlock(pInstance);
return H245_ERROR_PARAM;
} // switch
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = h221NonStandard_chosen;
// Fill in the H.221 identifier
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = byCountryCode;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension = byExtension;
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = wManufacturerCode;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245NonStandardH221 -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245NonStandardH221
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CommunicationModeRequest
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CommunicationModeRequest(H245_INST_T dwInst)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245CommunicationModeRequest <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = communicationModeRequest_chosen;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245CommunicationModeRequest -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245CommunicationModeRequest
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CommunicationModeResponse
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CommunicationModeResponse(
H245_INST_T dwInst,
const H245_COMM_MODE_ENTRY_T *pTable,
unsigned char byTableCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError = H245_ERROR_OK;
CommunicationModeTableLink pLink;
unsigned int uIndex;
H245TRACE (dwInst,4,"H245CommunicationModeResponse <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = cmmnctnMdRspns_chosen;
pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice = communicationModeTable_chosen;
pLink = (CommunicationModeTableLink)(pPdu + 1);
pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable = pLink;
for (uIndex = 0; uIndex < byTableCount; ++uIndex)
{
pLink[uIndex].next = &pLink[uIndex + 1];
lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
if (lError != H245_ERROR_OK)
break;
}
pLink[byTableCount - 1].next = NULL;
if (lError == H245_ERROR_OK)
{
lError = FsmOutgoing(pInstance, pPdu, 0);
}
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245CommunicationModeResponse -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245CommunicationModeResponse()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245CommunicationModeCommand
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245CommunicationModeCommand(
H245_INST_T dwInst,
const H245_COMM_MODE_ENTRY_T *pTable,
unsigned char byTableCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError = H245_ERROR_OK;
CommunicationModeCommandLink pLink;
unsigned int uIndex;
H245TRACE (dwInst,4,"H245CommunicationModeCommand <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = communicationModeCommand_chosen;
pLink = (CommunicationModeCommandLink)(pPdu + 1);
pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable = pLink;
for (uIndex = 0; uIndex < byTableCount; ++uIndex)
{
pLink[uIndex].next = &pLink[uIndex + 1];
lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
if (lError != H245_ERROR_OK)
break;
}
pLink[byTableCount - 1].next = NULL;
if (lError == H245_ERROR_OK)
{
lError = FsmOutgoing(pInstance, pPdu, 0);
}
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245CommunicationModeCommand -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245CommunicationModeCommand()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245ConferenceRequest
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245ConferenceRequest (
H245_INST_T dwInst,
H245_CONFER_REQ_ENUM_T RequestType,
unsigned char byMcuNumber,
unsigned char byTerminalNumber
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245ConferenceRequest <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = conferenceRequest_chosen;
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice = (WORD)RequestType;
switch (RequestType)
{
case dropTerminal_chosen:
case requestTerminalID_chosen:
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber = byMcuNumber;
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber = byTerminalNumber;
// Fall-through to next case is intentional
case terminalListRequest_chosen:
case makeMeChair_chosen:
case cancelMakeMeChair_chosen:
case enterH243Password_chosen:
case enterH243TerminalID_chosen:
case enterH243ConferenceID_chosen:
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
default:
lError = H245_ERROR_PARAM;
} // switch
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245ConferenceRequest -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245ConferenceRequest()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245ConferenceResponse
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245ConferenceResponse (
H245_INST_T dwInst,
H245_CONFER_RSP_ENUM_T ResponseType,
unsigned char byMcuNumber,
unsigned char byTerminalNumber,
const unsigned char *pOctetString,
unsigned char byOctetStringLength,
const TerminalLabel *pTerminalList,
unsigned short wTerminalListCount
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
unsigned uIndex;
H245TRACE (dwInst,4,"H245ConferenceResponse <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_rspns_chosen;
pPdu->u.MSCMg_rspns.choice = conferenceResponse_chosen;
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = (WORD)ResponseType;
switch (ResponseType)
{
case mCTerminalIDResponse_chosen:
case terminalIDResponse_chosen:
case conferenceIDResponse_chosen:
case passwordResponse_chosen:
if (pOctetString == NULL ||
byOctetStringLength == 0 ||
byOctetStringLength > 128)
{
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber = byMcuNumber;
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber = byTerminalNumber;
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length = byOctetStringLength;
memcpy(pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value,
pOctetString,
byOctetStringLength);
// Fall-through to next case is intentional
case videoCommandReject_chosen:
case terminalDropReject_chosen:
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case terminalListResponse_chosen:
if (pTerminalList == NULL ||
wTerminalListCount == 0 ||
wTerminalListCount > 256)
{
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
return H245_ERROR_PARAM;
}
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count = wTerminalListCount;
for (uIndex = 0; uIndex < wTerminalListCount; ++uIndex)
{
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value[uIndex] =
pTerminalList[uIndex];
}
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case H245_RSP_DENIED_CHAIR_TOKEN:
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = deniedChairToken_chosen;
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case H245_RSP_GRANTED_CHAIR_TOKEN:
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = grantedChairToken_chosen;
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
default:
lError = H245_ERROR_PARAM;
} // switch
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245ConferenceResponse -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245ConferenceResponse()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245ConferenceCommand
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245ConferenceCommand (
H245_INST_T dwInst,
H245_CONFER_CMD_ENUM_T CommandType,
H245_CHANNEL_T Channel,
unsigned char byMcuNumber,
unsigned char byTerminalNumber
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245ConferenceCommand <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = conferenceCommand_chosen;
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice = (WORD)CommandType;
switch (CommandType)
{
case brdcstMyLgclChnnl_chosen:
case cnclBrdcstMyLgclChnnl_chosen:
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl = Channel;
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case ConferenceCommand_makeTerminalBroadcaster_chosen:
case ConferenceCommand_sendThisSource_chosen:
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.mcuNumber = byMcuNumber;
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.terminalNumber = byTerminalNumber;
// Fall-through to next case is intentional
case cnclMkTrmnlBrdcstr_chosen:
case cancelSendThisSource_chosen:
case dropConference_chosen:
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
default:
lError = H245_ERROR_PARAM;
} // switch
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245ConferenceCommand -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245ConferenceCommand()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245ConferenceIndication
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245ConferenceIndication(
H245_INST_T dwInst,
H245_CONFER_IND_ENUM_T IndicationType,
unsigned char bySbeNumber,
unsigned char byMcuNumber,
unsigned char byTerminalNumber
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245ConferenceIndication <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = conferenceIndication_chosen;
pPdu->u.indication.u.conferenceIndication.choice = (WORD)IndicationType;
switch (IndicationType)
{
case sbeNumber_chosen:
pPdu->u.indication.u.conferenceIndication.u.sbeNumber = bySbeNumber;
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case terminalNumberAssign_chosen:
case terminalJoinedConference_chosen:
case terminalLeftConference_chosen:
case terminalYouAreSeeing_chosen:
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber = byMcuNumber;
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber = byTerminalNumber;
// Fall-through to next case is intentional
case seenByAtLeastOneOther_chosen:
case cnclSnByAtLstOnOthr_chosen:
case seenByAll_chosen:
case cancelSeenByAll_chosen:
case requestForFloor_chosen:
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
default:
lError = H245_ERROR_PARAM;
} // switch
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245ConferenceIndication -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245ConferenceIndication()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245UserInput
*
* DESCRIPTION
*
* HRESULT H245UserInput (
* H245_INST_T dwInst,
* char *pGenString,
* H245_NONSTANDARD_PARAMETER_T *pNonStd
* )
* Description:
*
* Send a User Input indiation to the remote side. One of the
* two parameters must be set (pGenString, pNonStd). The client
* can either send a string or a NonStandard parameter set to the
* remote client. Only one of the two parameters can contain a
* value. The other is required to be NULL.
*
* Input
* dwInst Instance handle returned by H245Init
* pGenString choice: String to be sent to remote
* side in accordance with T.51 specification.
* pNonStd choice: NonStandard Parameter
*
* Call Type:
* Synchronous
*
* Return Values:
* See Errors
*
* Errors:
* H245_ERROR_OK
* H245_ERROR_NOT_CONNECTED
* H245_ERROR_NOMEM
* H245_ERROR_PARAM
*
* callback
* H245_IND_USERINPUT
*
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245UserInput (
H245_INST_T dwInst,
const WCHAR * pGenString,
const H245_NONSTANDARD_PARAMETER_T * pNonStd
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
MltmdSystmCntrlMssg *pPdu;
#if 1
int nLength;
char * pszGeneral = NULL;
#endif
H245TRACE (dwInst,4,"H245UserInput <-");
/* check for valid instance handle */
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
/* system should be in connected state */
if (pInstance->API.SystemState != APIST_Connected)
{
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
InstanceUnlock(pInstance);
return H245_ERROR_NOT_CONNECTED;
}
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
if (pPdu == NULL)
{
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
/* build PDU */
#if 1
if (pGenString)
{
nLength = WideCharToMultiByte(CP_ACP, // code page
0, // dwFlags
pGenString, // Unicode string
-1, // Unicode string length (bytes)
NULL, // ASCII string
0, // max ASCII string length
NULL, // default character
NULL); // default character used
pszGeneral = MemAlloc(nLength);
if (pszGeneral == NULL)
{
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
InstanceUnlock(pInstance);
return H245_ERROR_NOMEM;
}
nLength = WideCharToMultiByte(CP_ACP, // code page
0, // dwFlags
pGenString, // Unicode string
-1, // Unicode string length (bytes)
pszGeneral, // ASCII string
nLength, // max ASCII string length
NULL, // default character
NULL); // default character used
lError = pdu_ind_usrinpt (pPdu, NULL, pszGeneral);
}
else
{
lError = pdu_ind_usrinpt (pPdu, pNonStd, NULL);
}
#else
lError = pdu_ind_usrinpt (pPdu, pNonStd, pGenString);
#endif
if (lError == H245_ERROR_OK)
lError = FsmOutgoing(pInstance, pPdu, 0);
#if 1
if (pszGeneral)
MemFree(pszGeneral);
#endif
MemFree (pPdu);
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245UserInput -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245UserInput()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245FlowControl
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245FlowControl (
H245_INST_T dwInst,
H245_SCOPE_T Scope,
H245_CHANNEL_T Channel, // only used if Scope is H245_SCOPE_CHANNEL_NUMBER
unsigned short wResourceID, // only used if Scope is H245_SCOPE_RESOURCE_ID
unsigned long dwRestriction // H245_NO_RESTRICTION if no restriction
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245FlowControl <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = MSCMg_cmmnd_chosen;
pPdu->u.MSCMg_cmmnd.choice = flowControlCommand_chosen;
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice = (WORD)Scope;
if (dwRestriction == H245_NO_RESTRICTION)
{
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = noRestriction_chosen;
}
else
{
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = maximumBitRate_chosen;
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate = dwRestriction;
}
switch (Scope)
{
case FCCd_scp_lgclChnnlNmbr_chosen:
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr = Channel;
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
case FlwCntrlCmmnd_scp_rsrcID_chosen:
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID = wResourceID;
// Fall-through to next case
case FCCd_scp_whlMltplx_chosen:
lError = FsmOutgoing(pInstance, pPdu, 0);
break;
default:
lError = H245_ERROR_PARAM;
} // switch
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245FlowControl -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245FlowControl()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245H223SkewIndication
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245H223SkewIndication (
H245_INST_T dwInst,
H245_CHANNEL_T wLogicalChannelNumber1,
H245_CHANNEL_T wLogicalChannelNumber2,
unsigned short wSkew
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245H223SkewIndication <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = h223SkewIndication_chosen;
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1 = wLogicalChannelNumber1;
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2 = wLogicalChannelNumber2;
pPdu->u.indication.u.h223SkewIndication.skew = wSkew;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245H223SkewIndication -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245H223SkewIndication()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245H2250MaximumSkewIndication
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245H2250MaximumSkewIndication(
H245_INST_T dwInst,
H245_CHANNEL_T wLogicalChannelNumber1,
H245_CHANNEL_T wLogicalChannelNumber2,
unsigned short wMaximumSkew
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = h2250MxmmSkwIndctn_chosen;
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1 = wLogicalChannelNumber1;
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2 = wLogicalChannelNumber2;
pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew = wMaximumSkew;
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245H2250MaximumSkewIndication()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245MCLocationIndication
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245MCLocationIndication(
H245_INST_T dwInst,
const H245_TRANSPORT_ADDRESS_T * pSignalAddress
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245MCLocationIndication <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = mcLocationIndication_chosen;
lError = SetupTransportAddress(&pPdu->u.indication.u.mcLocationIndication.signalAddress,
pSignalAddress);
if (lError == H245_ERROR_OK)
{
lError = FsmOutgoing(pInstance, pPdu, 0);
}
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245MCLocationIndication -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245MCLocationIndication()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245VendorIdentification
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245VendorIdentification(
H245_INST_T dwInst,
const H245_NONSTANDID_T *pIdentifier,
const unsigned char *pProductNumber,
unsigned char byProductNumberLength,
const unsigned char *pVersionNumber,
unsigned char byVersionNumberLength
)
{
register struct InstanceStruct *pInstance;
register PDU_T * pPdu;
HRESULT lError;
H245TRACE (dwInst,4,"H245VendorIdentification <-");
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
if (pPdu == NULL)
{
lError = H245_ERROR_NOMEM;
}
else
{
memset(pPdu, 0, sizeof(*pPdu));
pPdu->choice = indication_chosen;
pPdu->u.indication.choice = vendorIdentification_chosen;
pPdu->u.indication.u.vendorIdentification.bit_mask = 0;
pPdu->u.indication.u.vendorIdentification.vendor = *pIdentifier;
if (pProductNumber != NULL && byProductNumberLength != 0)
{
pPdu->u.indication.u.vendorIdentification.bit_mask |= productNumber_present;
pPdu->u.indication.u.vendorIdentification.productNumber.length = byProductNumberLength;
memcpy(pPdu->u.indication.u.vendorIdentification.productNumber.value,
pProductNumber,
byProductNumberLength);
}
if (pVersionNumber != NULL && byVersionNumberLength != 0)
{
pPdu->u.indication.u.vendorIdentification.bit_mask |= versionNumber_present;
pPdu->u.indication.u.vendorIdentification.versionNumber.length = byVersionNumberLength;
memcpy(pPdu->u.indication.u.vendorIdentification.versionNumber.value,
pVersionNumber,
byVersionNumberLength);
}
lError = FsmOutgoing(pInstance, pPdu, 0);
MemFree(pPdu);
}
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245VendorIdentification -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245VendorIdentification()
/*****************************************************************************
*
* TYPE: H245 API
*
* PROCEDURE: H245SendPDU
*
* DESCRIPTION
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245SendPDU (
H245_INST_T dwInst,
PDU_T * pPdu
)
{
register struct InstanceStruct *pInstance;
HRESULT lError;
H245TRACE (dwInst,4,"H245SendPDU <-");
// Check for valid instance handle
pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(H245_ERROR_INVALID_INST));
return H245_ERROR_INVALID_INST;
}
lError = FsmOutgoing(pInstance, pPdu, 0);
if (lError != H245_ERROR_OK)
H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(lError));
else
H245TRACE (dwInst,4,"H245SendPDU -> OK");
InstanceUnlock(pInstance);
return lError;
} // H245SendPDU()
/*****************************************************************************
*
* TYPE: H245 API
*
*****************************************************************************
*
* PROCEDURE: H245SystemControl
*
* DESCRIPTION
*
* HRESULT H245SystemControl
* ( H245_INST_T dwInst,
* DWORD Request ,
* VOID *pData
* )
*
* Description:
* This function should not be used by clients who
* normally interface to the H.245 subsystem. It is
* defined here to help during development and debug
* of the H.245 subsystem.
*
* This is a roll your own.. and can do what
* ever the user needs.. It's a hook to allow
* IOCTL (unix) calls that can either be
* passed to lower stack elements (AT&T Streams IOCTL
* would be an example - :) or simply to get or put
* information to the H245 SubSytem.
*
* Input
* dwInst Instance handle returned by H245Init
* Request Requested system control
* pData In the case of sending information
* down to H.245 this is an input
* parameter, and it's data format
* is determined by the Request.
* output
* pData In the case of retrieving information
* from H.245 this can be an output
* parameter, and it's data format is
* determined by the Request. It may not
* have valid data if the request is a
* synchronous request. (See Request Options).
* Call Type:
*
* Synchronous
*
* Request Options:
*
* H245_SYSCON_GET_STATS Retrieves Statistics
* from H.245 subsystem
* parameter pData = &H245_SYSCON_STAT_T
* H245_ SYSCON_RESET_STATS Resets the statistics
* pData = NULL
* H245_SYS_TRACE Set Trace Level
* pData = &DWORD (Trace Level)
*
* Return Values:
* See Request Options
*
* Errors:
* H245_ERROR_OK
*
* RETURN:
*
*****************************************************************************/
H245DLL HRESULT
H245SystemControl (
H245_INST_T dwInst,
unsigned long dwRequest,
void * pData
)
{
HRESULT lError;
DWORD dwTemp;
H245TRACE(dwInst,4,"H245SystemControl <-");
if (dwRequest == H245_SYSCON_DUMP_TRACKER)
{
register struct InstanceStruct *pInstance = InstanceLock(dwInst);
if (pInstance == NULL)
{
lError = H245_ERROR_INVALID_INST;
}
else
{
dump_tracker(pInstance);
InstanceUnlock(pInstance);
lError = H245_ERROR_OK;
}
}
else if (pData == NULL)
{
lError = H245_ERROR_PARAM;
}
else
{
lError = H245_ERROR_OK;
switch (dwRequest)
{
case H245_SYSCON_GET_FSM_N100:
*((DWORD *)pData) = (DWORD) uN100;
H245TRACE(dwInst,20,"H245SystemControl: Get N100 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T101:
*((DWORD *)pData) = (DWORD) uT101;
H245TRACE(dwInst,20,"H245SystemControl: Get T101 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T102:
*((DWORD *)pData) = (DWORD) uT102;
H245TRACE(dwInst,20,"H245SystemControl: Get T102 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T103:
*((DWORD *)pData) = (DWORD) uT103;
H245TRACE(dwInst,20,"H245SystemControl: Get T103 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T104:
*((DWORD *)pData) = (DWORD) uT104;
H245TRACE(dwInst,20,"H245SystemControl: Get T104 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T105:
*((DWORD *)pData) = (DWORD) uT105;
H245TRACE(dwInst,20,"H245SystemControl: Get T105 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T106:
*((DWORD *)pData) = (DWORD) uT106;
H245TRACE(dwInst,20,"H245SystemControl: Get T106 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T107:
*((DWORD *)pData) = (DWORD) uT107;
H245TRACE(dwInst,20,"H245SystemControl: Get T107 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T108:
*((DWORD *)pData) = (DWORD) uT108;
H245TRACE(dwInst,20,"H245SystemControl: Get T108 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_GET_FSM_T109:
*((DWORD *)pData) = (DWORD) uT109;
H245TRACE(dwInst,20,"H245SystemControl: Get T109 = %d",*((DWORD *)pData));
break;
case H245_SYSCON_SET_FSM_N100:
dwTemp = (DWORD) uN100;
uN100 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set N100 = %d",uN100);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T101:
dwTemp = (DWORD) uT101;
uT101 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T101 = %d",uT101);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T102:
dwTemp = (DWORD) uT102;
uT102 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T102 = %d",uT102);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T103:
dwTemp = (DWORD) uT103;
uT103 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T103 = %d",uT103);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T104:
dwTemp = (DWORD) uT104;
uT104 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T104 = %d",uT104);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T105:
dwTemp = (DWORD) uT105;
uT105 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T105 = %d",uT105);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T106:
dwTemp = (DWORD) uT106;
uT106 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T106 = %d",uT106);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T107:
dwTemp = (DWORD) uT107;
uT107 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T107 = %d",uT107);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T108:
dwTemp = (DWORD) uT108;
uT108 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T108 = %d",uT108);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_SET_FSM_T109:
dwTemp = (DWORD) uT109;
uT109 = (unsigned int) *((DWORD *)pData);
H245TRACE(dwInst,20,"H245SystemControl: Set T109 = %d",uT109);
*((DWORD *)pData) = dwTemp;
break;
case H245_SYSCON_TRACE_LVL:
dwTemp = TraceLevel;
TraceLevel = *(DWORD *)pData;
H245TRACE(dwInst,20,"H245SystemControl: Set TraceLevel = %d",TraceLevel);
*((DWORD *)pData) = dwTemp;
break;
default:
lError = H245_ERROR_NOTIMP;
} // switch
} // else
if (lError != H245_ERROR_OK)
H245TRACE(dwInst,1,"H245SystemControl -> %s",map_api_error(lError));
else
H245TRACE(dwInst,4,"H245SystemControl -> OK");
return lError;
} // H245SystemControl()