/*++
*******************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved				*
* 																										*
* This software contains proprietary and confidential information of Digi		*
* International Inc.  By accepting transfer of this copy, Recipient agrees		*
* to retain this software in confidence, to prevent disclosure to others,		*
* and to make no use of this software other than that for which it was			*
* delivered.  This is an unpublished copyrighted work of Digi International	*
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly	*
* prohibited.																						*
* 																										*
* Restricted Rights Legend																		*
*																										*
* Use, duplication, or disclosure by the Government is subject to					*
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in			*
* Technical Data and Computer Software clause at DFARS 252.227-7031 or			*
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -				*
* Restricted Rights at 48 CFR 52.227-19, as applicable.								*
*																										*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343				*
*																										*
*******************************************************************************

Module Name:

   isdnv1.c

Abstract:

   Version 1 of Spider Isdn Api.  Used by Prime adapter.

Author:

   Michael Zarns

--*/

#include "digiisdn.h"
#pragma hdrstop

// #defines for meer's isdn_proto.h
#define ATNT       1
#define DIGI_API   1
#include "..\..\firmware\clyde\inc\isdn_proto.h"
#include "..\..\firmware\clyde\inc\il3_sm.h"


STATIC VOID
V1PutComplete(
		IN PVOID    pOwner,
		IN HANDLE   Context,
		IN PVOID    pControl,
		IN ULONG    cbControl,
		IN PVOID    pData,
		IN ULONG    cbData,
		IN NTSTATUS IoStatus )
/*++

Description:

	Generic completion routine for PutMsgs with no data portion.  Does nothing.

--*/
{
	ASSERT( pOwner != NULL );
	ASSERT( Context == NULL );
	ASSERT( pControl != NULL );
	ASSERT( cbControl != 0 );
	ASSERT( pData == NULL );
	ASSERT( cbData == 0 );

	if ( NT_ERROR( IoStatus ) )
	{
		DigiDump( DIGIWARN, ( "DXB:V1PutComplete pOwner 0x%x, pIoStatus 0x%x!\n", 
		          pOwner, IoStatus ) );
	}
}


STATIC NTSTATUS
V1Connect(
	PVOID   pOwner,
	HANDLE  hStream,
	ULONG   Snid,
	ULONG   MaxFrameSize,
	ULONG   ConnType,
	PSTRING pCalledID )
/*++

Description:

	Sends an XN_CONNECT request out.  Used when dialing.

--*/
{
	NTSTATUS Status;
	xn_call_t Connect = { 0 };

	if ( pCalledID->Length > sizeof (Connect.address.number) )
		return STATUS_INVALID_PARAMETER_6;

	Connect.command = XN_CONNECT;
	Connect.address.sn_id = Snid;

	switch ( ConnType )
	{
		case ISDN_CONN_TOLLSAVER:
			Connect.bearcap.ue_tcap    = I_INFO_TC_SPEECH | 0x80;
			// Connect.bearcap.ue_rt_adpt = I_RATE_MU_LAW | 0x80;
			break;

		case ISDN_CONN_D56:
			Connect.bearcap.ue_tcap    = I_INFO_TC_UNRES_DIG | 0x80;
			Connect.bearcap.ue_rt_adpt = I_RATE_ADAPT_V110 | 0x80;
			Connect.bearcap.ue_rt      = I_RVAL_56K | 0x80;
			break;

		case ISDN_CONN_D64:
			Connect.bearcap.ue_tcap = I_INFO_TC_UNRES_DIG | 0x80;
			break;
			
		default:
			DigiDump( DIGIWARN, ( "Isdn!V1Connect: Warning - overriding invalid ConnType 0x%x!\n", ConnType ) );
			Connect.bearcap.ue_tcap = I_INFO_TC_UNRES_DIG | 0x80;
			break;
	}

	// Destination Address
	{
		STRING Dest = { 0 };
		Dest.Buffer = Connect.address.number;
		Dest.MaximumLength = sizeof Connect.address.number;

		ASSERT( Dest.MaximumLength >= pCalledID->Length );
		RtlCopyString( &Dest, pCalledID );
		Connect.address.number_len = (UCHAR)Dest.Length;
	}

	DigiDump( DIGIV1, ( "Isdn!V1Connect: pOwner 0x%x, Snid 0x%x, CalledID %s\n", pOwner, Snid, pCalledID->Buffer ) );
	Status = DsPutMsgEx( hStream, &Connect, sizeof Connect, NULL, 0, NULL, DS_PRIORITY_LOW, V1PutComplete );

	return Status;
}


STATIC NTSTATUS
V1Connack(
	PVOID  pOwner,
	HANDLE hStream,
	ULONG  ChanIndex,
	ULONG  Channel )
/*++

Description:

	Sends an XN_CONNACK request to the board.  Used to accept an incoming call.

--*/
{
	xn_cccc_t Connack = { 0 };

	Connack.command    = XN_CONNACK;
	Connack.controller = (UCHAR)ChanIndex;
	Connack.channel    = (UCHAR)Channel;

//	if ( ConnType == ISDN_CONN_TOLLSAVER )
//		Connack.pref_tx_cap = I_INFO_TC_RES_DIG;

	DigiDump( DIGIV1, ( "Isdn!V1Connack: pOwner 0x%x, ChanIndex 0x%x, Channel 0x%x\n", pOwner, ChanIndex, Channel ) );
	return DsPutMsgEx( hStream, &Connack, sizeof Connack, NULL, 0, NULL, DS_PRIORITY_LOW, V1PutComplete );
}


STATIC NTSTATUS
V1Disconn(
	PVOID  pOwner,
	HANDLE hStream,
	ULONG  ChanIndex,
	ULONG  Channel )
/*++

Description:

	Sends an XN_DISCONN request to the board.  Used to drop or reject a call currently 
	in progress.

--*/
{
	xn_cccc_t Disconn = { 0 };
	Disconn.command    = XN_DISCONN;

	DigiDump( DIGIV1, ( "Isdn!V1Disconn: pOwner 0x%x, ChanIndex 0x%x, Channel 0x%x\n", pOwner, ChanIndex, Channel ) );
	return DsPutMsgEx( hStream, &Disconn, sizeof Disconn, NULL, 0, NULL, DS_PRIORITY_LOW, V1PutComplete );
}


STATIC NTSTATUS
V1Connend(
	PVOID  pOwner,
	HANDLE hStream,
	ULONG  ChanIndex,
	ULONG  Channel )
/*++

Description:

	Sends an XN_CONNEND request to the board.  Used to reject an incoming call 
	that has not yet been accepted.

--*/
{
	xn_cccc_t Connend = { 0 };

	Connend.command    = XN_CONNEND;
	Connend.controller = (UCHAR)ChanIndex;
	Connend.channel    = (UCHAR)Channel;

	DigiDump( DIGIV1, ( "Isdn!V1Connend: pOwner 0x%x, ChanIndex 0x%x, Channel 0x%x\n", pOwner, ChanIndex, Channel ) );
	return DsPutMsgEx( hStream, &Connend, sizeof Connend, NULL, 0, NULL, DS_PRIORITY_LOW, V1PutComplete );
}


STATIC NTSTATUS
V1Listen(
	PVOID  pOwner,
	HANDLE hStream,
	ULONG  Snid )
/*++

Description:

	Sends an XN_LISTEN request to the board.  Required to accept incoming calls.

--*/
{
	xn_lstn_t Listen = { 0 };

	Listen.command = XN_LISTEN;
	Listen.address.sn_id = Snid;

	DigiDump( DIGIV1, ( "Isdn!V1Listen: pOwner 0x%x, Snid 0x%x\n", pOwner, Snid ) );
	return DsPutMsgEx( hStream, &Listen, sizeof Listen, NULL, 0, NULL, DS_PRIORITY_LOW, V1PutComplete );
}


STATIC VOID
V1Interpreter(
	IN PVOID                pOwner, 
	IN PISDN_EVENT_HANDLERS pDispatchTable,
	IN PVOID                pControl, 
	IN ULONG                cbControl, 
	IN PVOID                pData, 
	IN ULONG                cbData )
/*++

Description:

	Called by RxEngine to interpret and process a single incoming message from the card.

--*/
{
	union ISDN_primitives const * const pMsg = pControl;
	if ( pMsg != NULL )
	{
		// Control Messages
		switch ( pMsg->command )
		{
			case XN_LISTEN:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_LISTEN on pOwner 0x%x\n", pOwner ) );
				pDispatchTable->OnListen( pOwner );
				break;

			case XN_CONNECT:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_CONNECT on pOwner 0x%x\n", pOwner ) );
				{
					ISDN_CONN_TYPE ConnType;
					if( pMsg->call.bearcap.ue_trate == 1 )
					{
						if( pMsg->call.bearcap.ue_tcap == I_INFO_TC_UNRES_DIG )
						{
							if( pMsg->call.bearcap.ue_rt_adpt ) // Rate adaption
								ConnType = ISDN_CONN_D56;
							else
								ConnType = ISDN_CONN_D64;
						}
						else
								ConnType = ISDN_CONN_TOLLSAVER;
					}
					else
						ConnType = ISDN_CONN_D64;
	
					pDispatchTable->OnConnect( pOwner, pMsg->call.controller, pMsg->call.channel, ConnType );
				}
				break;

			case XN_CONNACK:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_CONNACK on pOwner 0x%x\n", pOwner ) );
				pDispatchTable->OnConnack( pOwner, pMsg->cccc.controller, pMsg->cccc.channel );
				break;

			case XN_CACTIVE:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_CACTIVE on pOwner 0x%x\n", pOwner ) );
				pDispatchTable->OnCActive( pOwner );
				break;

			case XN_DISCONN:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_DISCONN on pOwner 0x%x, cause 0x%x\n", pOwner, pMsg->cccc.cause ) );
				pDispatchTable->OnDisconn( pOwner, pMsg->cccc.controller, pMsg->cccc.channel );
				break;

			case XN_CONNEND:
				DigiDump( DIGIV1, ( "Isdn!V1Interpreter: XN_CONNEND on pOwner 0x%x, cause 0x%x\n", pOwner, pMsg->cccc.cause ) );
				pDispatchTable->OnConnend( pOwner, pMsg->cccc.controller, pMsg->cccc.channel );
				break;

			case XN_STS:
				DigiDump( DIGIV1|DIGIWARN, ( "Isdn!V1Interpreter: XN_STS on pOwner 0x%x\n", pOwner ) );
				break;

			case XN_BAD_MSG:
				DigiDump( DIGIV1|DIGIWARN, ( "Isdn!V1Interpreter: XN_BAD_MSG on pOwner 0x%x, reason 0x%x\n", pOwner, pMsg->badm.reason ) );
				break;

			default:
				DigiDump( DIGIV1|DIGIERROR, ( "Isdn!V1Interpreter: Unknown msg 0x%x on pOwner 0x%x!\n", pMsg->command, pOwner ) );
				break;
		}
		RxEngineFreeData( pData );
	}
	else
	{
		// Data Messages
		DigiDump( DIGIV1, ( "Isdn!V1Interpreter: Rx Data, pOwner 0x%x, pData 0x%x, cbData 0x%x\n", pOwner, pData, cbData ) );
		pDispatchTable->OnData( pOwner, pData, cbData );
	}
}


ISDN_CODEC IsdnV1 = 
{
	V1Connect,
	V1Connack,
	V1Disconn,
	V1Connend,
	V1Listen,
	V1Interpreter,
	sizeof (union ISDN_primitives),
	"IL3"
};


VOID
IsdnV1Init(
	PISDN_ADAPTER pAdapter )
/*++

Description:

	Initialize the adapter dispatch table to use V1 Spider Api.

--*/
{
	pAdapter->XnDispatch = IsdnV1;
}
