? libpri-matt.diff
? libpri-matt2.diff
? libpri-matt3-pc.diff
? libpri-matt3.diff
? libpri-matt5.diff
Index: libpri.h
===================================================================
RCS file: /usr/cvsroot/libpri/libpri.h,v
retrieving revision 1.40
diff -u -r1.40 libpri.h
--- libpri.h	17 Jan 2005 12:58:05 -0000	1.40
+++ libpri.h	18 Feb 2005 21:09:25 -0000
@@ -46,11 +46,11 @@
 #define PRI_SWITCH_DMS100		2	/* DMS 100 */
 #define PRI_SWITCH_LUCENT5E		3	/* Lucent 5E */
 #define PRI_SWITCH_ATT4ESS		4	/* AT&T 4ESS */
-#define PRI_SWITCH_EUROISDN_E1	5	/* Standard EuroISDN (CTR4, ETSI 300-102) */
-#define PRI_SWITCH_EUROISDN_T1	6	/* T1 EuroISDN variant (ETSI 300-102) */
+#define PRI_SWITCH_EUROISDN_E1		5	/* Standard EuroISDN (CTR4, ETSI 300-102) */
+#define PRI_SWITCH_EUROISDN_T1		6	/* T1 EuroISDN variant (ETSI 300-102) */
 #define PRI_SWITCH_NI1			7	/* National ISDN 1 */
-#define PRI_SWITCH_GR303_EOC	8	/* GR-303 Embedded Operations Channel */
-#define PRI_SWITCH_GR303_TMC	9	/* GR-303 Timeslot Management Channel */
+#define PRI_SWITCH_GR303_EOC		8	/* GR-303 Embedded Operations Channel */
+#define PRI_SWITCH_GR303_TMC		9	/* GR-303 Timeslot Management Channel */
 #define PRI_SWITCH_QSIG			10	/* QSIG Switch */
 /* Switchtypes 10 - 20 are reserved for internal use */
 
@@ -476,7 +476,21 @@
 extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
 
 extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
-	 
+
+/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
+extern int pri_sr_set_connection_call_independent(struct pri_sr *req);
+
+/* Send an MWI indication to a remote location.  If activate is non zero, activates, if zero, decativates */
+extern int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
+
+/* Send an MWI deactivate request to a remote location */
+extern int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
+
+#define PRI_2BCT
+/* Attempt to pass the channels back to the NET side if compatable and
+ * suscribed.  Sometimes called 2 bchannel transfer (2BCT) */
+int pri_channel_bridge(q931_call *call1, q931_call *call2);
+
 /* Override message and error stuff */
 extern void pri_set_message(void (*__pri_error)(char *));
 extern void pri_set_error(void (*__pri_error)(char *));
Index: pri.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri.c,v
retrieving revision 1.31
diff -u -r1.31 pri.c
--- pri.c	15 Dec 2004 20:15:28 -0000	1.31
+++ pri.c	18 Feb 2005 21:09:25 -0000
@@ -22,6 +22,7 @@
 #include "compat.h"
 #include "libpri.h"
 #include "pri_internal.h"
+#include "pri_facility.h"
 #include "pri_q921.h"
 #include "pri_q931.h"
 #include "pri_timers.h"
@@ -231,6 +232,30 @@
 		return "Restart channel";
 	case PRI_EVENT_RING:
 		return "Ring";
+	case PRI_EVENT_HANGUP:
+		return "Hangup";
+	case PRI_EVENT_RINGING:
+		return "Ringing";
+	case PRI_EVENT_ANSWER:
+		return "Answer";
+	case PRI_EVENT_HANGUP_ACK:
+		return "Hangup ACK";
+	case PRI_EVENT_RESTART_ACK:
+		return "Restart ACK";
+	case PRI_EVENT_FACNAME:
+		return "FacName";
+	case PRI_EVENT_INFO_RECEIVED:
+		return "Info Received";
+	case PRI_EVENT_PROCEEDING:
+		return "Proceeding";
+	case PRI_EVENT_SETUP_ACK:
+		return "Setup ACK";
+	case PRI_EVENT_HANGUP_REQ:
+		return "Hangup Req";
+	case PRI_EVENT_NOTIFY:
+		return "Notify";
+	case PRI_EVENT_PROGRESS:
+		return "Progress";
 	case PRI_EVENT_CONFIG_ERR:
 		return "Configuration Error";
 	default:
@@ -399,6 +424,28 @@
 }
 #endif
 
+int pri_channel_bridge(q931_call *call1, q931_call *call2)
+{
+	if (!call1 || !call2)
+		return -1;
+
+	/* Check switchtype compatibility */
+	if (call1->pri->switchtype != PRI_SWITCH_LUCENT5E ||
+			call2->pri->switchtype != PRI_SWITCH_LUCENT5E)
+		return -1;
+
+	/* Check to see if calls are on the same PRI dchannel
+	 * Currently only support calls on the same dchannel
+	 */
+	if (call1->pri != call2->pri)
+		return -1;
+	
+	if (eect_initiate_transfer(call1->pri, call1, call2))
+		return -1;
+
+	return 0;
+}
+
 int pri_hangup(struct pri *pri, q931_call *call, int cause)
 {
 	if (!pri || !call)
@@ -456,10 +503,71 @@
 	
 }
 
+int pri_sr_set_connection_call_independent(struct pri_sr *req)
+{
+	if (!req)
+		return -1;
+
+	req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
+	return 0;
+}
+
+/* Don't call any other pri functions on this */
+int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
+					int calledplan)
+{
+	struct pri_sr req;
+	if (!pri || !c)
+		return -1;
+
+	pri_sr_init(&req);
+	pri_sr_set_connection_call_independent(&req);
+
+	req.caller = caller;
+	req.callerplan = callerplan;
+	req.callername = callername;
+	req.callerpres = callerpres;
+	req.called = called;
+	req.calledplan = calledplan;
+
+	if (mwi_message_send(pri, c, &req, 1) < 0) {
+		pri_message("Unable to send MWI activate message\n");
+		return -1;
+	}
+	/* Do more stuff when we figure out that the CISC stuff works */
+	return q931_setup(pri, c, &req);
+}
+
+int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
+					int calledplan)
+{
+	struct pri_sr req;
+	if (!pri || !c)
+		return -1;
+
+	pri_sr_init(&req);
+	pri_sr_set_connection_call_independent(&req);
+
+	req.caller = caller;
+	req.callerplan = callerplan;
+	req.callername = callername;
+	req.callerpres = callerpres;
+	req.called = called;
+	req.calledplan = calledplan;
+
+	if(mwi_message_send(pri, c, &req, 0) < 0) {
+		pri_message("Unable to send MWI deactivate message\n");
+		return -1;
+	}
+
+	return q931_setup(pri, c, &req);
+}
+	
 int pri_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
 {
 	if (!pri || !c)
 		return -1;
+
 	return q931_setup(pri, c, req);
 }
 
Index: pri_facility.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.c,v
retrieving revision 1.3
diff -u -r1.3 pri_facility.c
--- pri_facility.c	3 Feb 2005 22:14:44 -0000	1.3
+++ pri_facility.c	18 Feb 2005 21:09:25 -0000
@@ -1,9 +1,12 @@
 /* 
+   This file and it's contents are licensed under the terms and conditions
+   of the GNU Public License.  See http://www.gnu.org for details.
+   
    Routines for dealing with facility messages and their respective
    components (ROSE)
 
    by Matthew Fredrickson <creslin@digium.com>
-   Copyright (C) 2004 Digium, Inc
+   Copyright (C) 2004-2005 Digium, Inc
 */
 
 #include "compat.h"
@@ -18,9 +21,14 @@
 
 #undef DEBUG
 
+static unsigned char get_invokeid(struct pri *pri)
+{
+	return ++pri->last_invoke;
+}
+
 struct addressingdataelements_presentednumberunscreened {
-	char partyAddress[21];
-	char partySubaddress[21];
+	char partyaddress[21];
+	char partysubaddress[21];
 	int  npi;
 	int  ton;
 	int  pres;
@@ -182,8 +190,8 @@
 			pri_message("!! Oversized NumberDigits component (%d)\n", comp->len);
 			return -1;
 		}
-		memcpy(value->partyAddress, comp->data, comp->len);
-		value->partyAddress[comp->len] = '\0';
+		memcpy(value->partyaddress, comp->data, comp->len);
+		value->partyaddress[comp->len] = '\0';
 
 		return 0;
 	}
@@ -331,8 +339,8 @@
 	int i = 0;
 	int diversion_counter;
 	int diversion_reason;
-	struct addressingdataelements_presentednumberunscreened divertingNr;
-	struct addressingdataelements_presentednumberunscreened originalCalledNr;
+	struct addressingdataelements_presentednumberunscreened divertingnr;
+ 	struct addressingdataelements_presentednumberunscreened originalcallednr;
 	struct rose_component *comp = NULL;
 	unsigned char *vdata = data;
 
@@ -359,23 +367,23 @@
 		for(; i < len; NEXT_COMPONENT(comp, i)) {
 			GET_COMPONENT(comp, i, vdata, len);
 			switch(comp->type) {
-			case 0xA1:		/* divertingNr: PresentedNumberUnscreened */
-				if(rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingNr) != 0)
+			case 0xA1:		/* divertingnr: presentednumberunscreened */
+				if(rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr) != 0)
 					return -1;
 #ifdef DEBUG
 				if (pri->debug) {
-					pri_message("    Received divertingNr '%s'\n", divertingNr.partyAddress);
-					pri_message("      ton = %d, pres = %d, npi = %d\n", divertingNr.ton, divertingNr.pres, divertingNr.npi);
+					pri_message("    Received divertingNr '%s'\n", divertingnr.partyaddress);
+					pri_message("      ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
 				}
 #endif
 				break;
 			case 0xA2:		/* originalCalledNr: PresentedNumberUnscreened */
-				if(rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalCalledNr) != 0)
+				if(rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr) != 0)
 					return -1;
 #ifdef DEBUG
 				if (pri->debug) {
-					pri_message("    Received originalCalledNr '%s'\n", originalCalledNr.partyAddress);
-					pri_message("      ton = %d, pres = %d, npi = %d\n", originalCalledNr.ton, originalCalledNr.pres, originalCalledNr.npi);
+					pri_message("    Received originalcallednr '%s'\n", originalcallednr.partyaddress);
+					pri_message("      ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
 				}
 #endif
 				break;
@@ -387,18 +395,18 @@
 		if (i < len)
 			return -1;	/* Aborted before */
 
-		if (divertingNr.pres >= 0) {
-			call->redirectingplan = divertingNr.npi;
-			call->redirectingpres = divertingNr.pres;
+		if (divertingnr.pres >= 0) {
+			call->redirectingplan = divertingnr.npi;
+			call->redirectingpres = divertingnr.pres;
 			call->redirectingreason = diversion_reason;
-			strncpy(call->redirectingnum, divertingNr.partyAddress, sizeof(call->redirectingnum)-1);
+			strncpy(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum)-1);
 			call->redirectingnum[sizeof(call->redirectingnum)-1] = '\0';
 		}
-		else if (originalCalledNr.pres >= 0) {
-			call->redirectingplan = originalCalledNr.npi;
-			call->redirectingpres = originalCalledNr.pres;
+		else if (originalcallednr.pres >= 0) {
+			call->redirectingplan = originalcallednr.npi;
+			call->redirectingpres = originalcallednr.pres;
 			call->redirectingreason = diversion_reason;
-			strncpy(call->redirectingnum, originalCalledNr.partyAddress, sizeof(call->redirectingnum)-1);
+			strncpy(call->redirectingnum, originalcallednr.partyaddress, sizeof(call->redirectingnum)-1);
 			call->redirectingnum[sizeof(call->redirectingnum)-1] = '\0';
 		}
 		return 0;
@@ -408,7 +416,364 @@
 	return -1;
 }
 
-int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
+{
+	int i = 0, j, compsp = 0;
+	struct rose_component *comp, *compstk[10];
+	unsigned char buffer[256];
+	int len = 253;
+	
+	if (!strlen(call->callername)) {
+		return -1;
+	}
+
+	buffer[i] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+	i++;
+	/* Interpretation component */
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
+	
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	
+	ASN1_PUSH(compstk, compsp, comp);
+	/* Invoke component contents */
+	/*	Invoke ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+	/*	Operation Tag */
+	
+	/* ROSE operationId component */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
+
+	/* ROSE ARGUMENT component */
+	ASN1_ADD_SIMPLE(comp, 0x30, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	/* ROSE DivertingLegInformation2.diversionCounter component */
+	/* Always is 1 because other isn't available in the current design */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
+	
+	/* ROSE DivertingLegInformation2.diversionReason component */
+	ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
+		
+	/* ROSE DivertingLegInformation2.divertingNr component */
+	ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+	
+	ASN1_PUSH(compstk, compsp, comp);
+		/* Redirecting information always not screened */
+	
+	switch(call->redirectingpres) {
+		case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+		case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+			if (call->redirectingnum && strlen(call->redirectingnum)) {
+				ASN1_ADD_SIMPLE(comp, 0xA0, buffer, i);
+				ASN1_PUSH(compstk, compsp, comp);
+					/* NPI of redirected number is not supported in the current design */
+				ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+				ASN1_PUSH(compstk, compsp, comp);
+					ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
+					j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
+				if (j < 0)
+					return -1;
+					
+				i += j;
+				ASN1_FIXUP(compstk, compsp, buffer, i);
+				ASN1_FIXUP(compstk, compsp, buffer, i);
+				break;
+			}
+			/* fall through */
+		case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+		case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+			ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+			break;
+		/* Don't know how to handle this */
+		case PRES_ALLOWED_NETWORK_NUMBER:
+		case PRES_PROHIB_NETWORK_NUMBER:
+		case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+		case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+			ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+			break;
+		default:
+			pri_message("!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
+		case PRES_NUMBER_NOT_AVAILABLE:
+			ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+			break;
+	}
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	/* ROSE DivertingLegInformation2.originalCalledNr component */
+	/* This information isn't supported by current design - duplicate divertingNr */
+	ASN1_ADD_SIMPLE(comp, 0xA2, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+		/* Redirecting information always not screened */
+	switch(call->redirectingpres) {
+		case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+		case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+			if (call->redirectingnum && strlen(call->redirectingnum)) {
+				ASN1_ADD_SIMPLE(comp, 0xA0, buffer, i);
+				ASN1_PUSH(compstk, compsp, comp);
+				ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+				ASN1_PUSH(compstk, compsp, comp);
+				ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
+	
+				j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
+				if (j < 0)
+					return -1;
+				
+				i += j;
+				ASN1_FIXUP(compstk, compsp, buffer, i);
+				ASN1_FIXUP(compstk, compsp, buffer, i);
+				break;
+			}
+				/* fall through */
+		case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+		case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+			ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+			break;
+		/* Don't know how to handle this */
+		case PRES_ALLOWED_NETWORK_NUMBER:
+		case PRES_PROHIB_NETWORK_NUMBER:
+		case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+		case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+			ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+			break;
+		default:
+			pri_message("!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
+		case PRES_NUMBER_NOT_AVAILABLE:
+			ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+			break;
+	}
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+		
+	/* Fix length of stacked components */
+	while(compsp > 0) {
+		ASN1_FIXUP(compstk, compsp, buffer, i);
+	}
+	
+	if (pri_call_adpu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
+		return -1;
+		
+	return 0;
+}
+
+/* Sending callername information functions */
+static int add_callername_facility_ies(struct pri *pri, q931_call *c)
+{
+	int res = 0;
+	int i = 0;
+	unsigned char buffer[256];
+	unsigned char namelen = 0;
+	struct rose_component *comp = NULL, *compstk[10];
+	int compsp = 0;
+	static unsigned char op_tag[] = { 
+		0x2a, /* informationFollowing 42 */
+		0x86,
+		0x48,
+		0xce,
+		0x15,
+		0x00,
+		0x04
+	};
+		
+	if (!strlen(c->redirectingnum)) {
+		return -1;
+	}
+
+	buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+	/* Interpretation component */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
+	ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	/* Invoke ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+
+	/* Operation Tag */
+	res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+	if (res < 0)
+		return -1;
+	i += res;
+
+	ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_adpu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
+		return -1;
+
+
+	/* Now the ADPu that contains the information that needs sent.
+	 * We can reuse the buffer since the queue function doesn't
+	 * need it. */
+
+	i = 0;
+	namelen = strlen(c->callername);
+	if (namelen > 50) {
+		namelen = 50; /* truncate the name */
+	}
+
+	buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+	/* Interpretation component */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
+	ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	/* Invoke ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+
+	/* Operation ID: Calling name */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
+
+	res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i,  50, c->callername, namelen);
+	if (res < 0)
+	  return -1;
+	i += res;
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_adpu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL))
+		return -1;
+	
+	return 0;
+}
+
+/* End Callername */
+
+/* MWI related encode and decode functions */
+static void mwi_activate_encode_cb(void *data)
+{
+	return;
+}
+
+extern int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
+{
+	int i = 0;
+	unsigned char buffer[255] = "";
+	int destlen = strlen(req->called);
+	struct rose_component *comp = NULL, *compstk[10];
+	int compsp = 0;
+	int res;
+
+	if (destlen <= 0) {
+		return -1;
+	} else if (destlen > 20)
+		destlen = 20;  /* Destination number cannot be greater then 20 digits */
+
+	buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+	/* Interpretation component */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
+	ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
+	ASN1_ADD_SIMPLE(comp, 0x30 /* Sequence */, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	/* PartyNumber */
+	res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
+	
+	if (res < 0)
+		return -1;
+	i += res;
+
+	/* Enumeration: basicService */
+	ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1 /* contents: Voice */);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	return pri_call_adpu_queue(call, Q931_SETUP, buffer, i, mwi_activate_encode_cb, NULL);
+}
+/* End MWI */
+
+/* EECT functions */
+extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
+{
+	/* Did all the tests to see if we're on the same PRI and
+	 * are on a compatible switchtype */
+	/* TODO */
+	int i = 0;
+	int res = 0;
+	unsigned char buffer[255] = "";
+	unsigned short call_reference = c2->cr;
+	struct rose_component *comp = NULL, *compstk[10];
+	int compsp = 0;
+	static unsigned char op_tag[] = {
+		0x2A,
+		0x86,
+		0x48,
+		0xCE,
+		0x15,
+		0x00,
+		0x08,
+	};
+
+	buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+	/* Interpretation component */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
+	ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+
+	res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+	if (res < 0)
+		return -1;
+	i += res;
+
+	ASN1_ADD_SIMPLE(comp, ASN1_SEQUENCE | 0x20, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+	ASN1_ADD_WORDCOMP(comp, 0x02, buffer, i, call_reference);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	res = pri_call_adpu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
+	if (res) {
+		pri_message("Could not queue ADPU in facility message\n");
+		return -1;
+	}
+
+	/* Remember that if we queue a facility IE for a facility message we
+	 * have to explicitly send the facility message ourselves */
+
+	res = q931_facility(c1->pri, c1);
+	if (res) {
+		pri_message("Could not schedule facility message for call %d\n", c1->cr);
+		return -1;
+	}
+
+	return 0;
+}
+/* End EECT */
+
+
+extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
 {
 	int i = 0;
 	int operation_tag;
@@ -480,3 +845,73 @@
 	return -1;
 }
 
+extern int pri_call_adpu_queue(q931_call *call, int messagetype, void *adpu, int adpu_len, void (*function)(void *data), void *data)
+{
+	struct adpu_event *cur = NULL;
+	struct adpu_event *new_event = NULL;
+
+	if (!call || !messagetype || !adpu || (adpu_len < 1) || (adpu_len > 255))
+		return -1;
+
+	new_event = malloc(sizeof(struct adpu_event));
+	memset(new_event, 0, sizeof(struct adpu_event));
+
+	if (new_event) {
+		new_event->message = messagetype;
+		new_event->callback = function;
+		new_event->data = data;
+		memcpy(new_event->adpu, adpu, adpu_len);
+		new_event->adpu_len = adpu_len;
+	} else {
+		pri_error("malloc failed\n");
+		return -1;
+	}
+	
+	if (call->adpus) {
+		cur = call->adpus;
+		while (cur->next) {
+			cur = cur->next;
+		}
+		cur->next = new_event;
+	} else
+		call->adpus = new_event;
+
+	return 0;
+}
+
+extern int pri_call_adpu_queue_cleanup(q931_call *call)
+{
+	struct adpu_event *cur_event = NULL, *free_event = NULL;
+
+	if (call && call->adpus) {
+		cur_event = call->adpus;
+		while (cur_event) {
+			/* TODO: callbacks, some way of giving return res on status of adpu */
+			free_event = cur_event;
+			free(free_event);
+			cur_event = cur_event->next;
+		}
+		call->adpus = NULL;
+	}
+
+	return 0;
+}
+
+extern int pri_call_add_standard_adpus(struct pri *pri, q931_call *call)
+{
+	if (pri->switchtype == PRI_SWITCH_QSIG) { /* For Q.SIG it does network and cpe operations */
+		rose_diverting_leg_information2_encode(pri, call);
+	}
+
+	if (pri->localtype == PRI_NETWORK) {
+		switch (pri->switchtype) {
+			case PRI_SWITCH_NI2:
+				add_callername_facility_ies(pri, call);
+				break;
+			default:
+				break;
+		}
+	}
+	return 0;
+}
+
Index: pri_facility.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.h,v
retrieving revision 1.2
diff -u -r1.2 pri_facility.h
--- pri_facility.h	3 Feb 2005 22:14:44 -0000	1.2
+++ pri_facility.h	18 Feb 2005 21:09:25 -0000
@@ -4,7 +4,7 @@
    within those messages.
 
    by Matthew Fredrickson <creslin@digium.com>
-   Copyright (C) Digium, Inc. 2004
+   Copyright (C) Digium, Inc. 2004-2005
 */
 
 #ifndef _PRI_FACILITY_H
@@ -134,38 +134,80 @@
 	}
 	
 #define ASN1_GET_INTEGER(component, variable) \
-	{ \
+	do { \
 		int comp_idx; \
 		(variable) = 0; \
 		for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
 			(variable) = ((variable) << 8) | (component)->data[comp_idx]; \
-	}
+	} while (0)
 
 #define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
-	(component) = (struct rose_component *)&((ptr)[(idx)]); \
-	(component)->type = (comptype); \
-	(component)->len = 0; \
-	(idx) += 2;
+	do { \
+		(component) = (struct rose_component *)&((ptr)[(idx)]); \
+		(component)->type = (comptype); \
+		(component)->len = 0; \
+		(idx) += 2; \
+	} while (0)
 
 #define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
-	(component) = (struct rose_component *)&((ptr)[(idx)]); \
-	(component)->type = (comptype); \
-	(component)->len = 1; \
-	(component)->data[0] = (value); \
-	(idx) += 3;
+	do { \
+		(component) = (struct rose_component *)&((ptr)[(idx)]); \
+		(component)->type = (comptype); \
+		(component)->len = 1; \
+		(component)->data[0] = (value); \
+		(idx) += 3; \
+	} while (0)
+
+#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
+	do { \
+		int __val = (value); \
+		int __i = 0; \
+		(component) = (struct rose_component *)&((ptr)[(idx)]); \
+		(component)->type = (comptype); \
+		if ((__val >> 24)) \
+			(component)->data[__i++] = (__val >> 24) & 0xff; \
+		if ((__val >> 16)) \
+			(component)->data[__i++] = (__val >> 16) & 0xff; \
+		if ((__val >> 8)) \
+			(component)->data[__i++] = (__val >> 8) & 0xff; \
+		(component)->data[__i++] = __val & 0xff; \
+		(component)->len = __i; \
+		(idx) += 2 + __i; \
+	} while (0)
 
 #define ASN1_PUSH(stack, stackpointer, component) \
-	(stack)[(stackpointer)++] = (component);
+	(stack)[(stackpointer)++] = (component)
 
 #define ASN1_FIXUP(stack, stackpointer, data, idx) \
-	--(stackpointer); \
-	(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2;
+	do { \
+		--(stackpointer); \
+		(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
+	} while (0)
 
-/* Decoder fo the invoke part of a ROSE request
-   It currently only support calling name decode */
+/* Decoder for the invoke part of a ROSE request */
 extern int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
+
 extern int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
-int typeofnumber_from_q931(struct pri *pri, int ton);
-int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
+
+extern int typeofnumber_from_q931(struct pri *pri, int ton);
+
+extern int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
+
+/* Queues an MWI adpu on a the given call */
+extern int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
+
+/* starts a 2BCT */
+extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
+
+/* Use this function to queue a facility-IE born ADPU onto a call
+ * call is the call to use, messagetype is any one of the Q931 messages,
+ * adpu is the adpu data, adpu_len is the length of the adpu data  */
+extern int pri_call_adpu_queue(q931_call *call, int messagetype, void *adpu, int adpu_len, void (*function)(void *data), void *data);
+
+/* Used by q931.c to cleanup the adpu queue upon destruction of a call */
+extern int pri_call_adpu_queue_cleanup(q931_call *call);
+
+/* Adds the "standard" ADPUs to a call */
+extern int pri_call_add_standard_adpus(struct pri *pri, q931_call *call);
 
 #endif /* _PRI_FACILITY_H */
Index: pri_internal.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_internal.h,v
retrieving revision 1.16
diff -u -r1.16 pri_internal.h
--- pri_internal.h	3 Feb 2005 22:14:44 -0000	1.16
+++ pri_internal.h	18 Feb 2005 21:09:25 -0000
@@ -124,11 +124,22 @@
 	int redirectingplan;
 	int redirectingpres;
 	int redirectingreason;
+	int justsignalling;
 };
 
 /* Internal switch types */
-#define PRI_SWITCH_GR303_EOC_PATH	10
-#define PRI_SWITCH_GR303_TMC_SWITCHING	11
+#define PRI_SWITCH_GR303_EOC_PATH	19
+#define PRI_SWITCH_GR303_TMC_SWITCHING	20
+
+struct adpu_event {
+	int message;			/* What message to send the ADPU in */
+	void (*callback)(void *data);	/* Callback function for when response is received */
+	void *data;			/* Data to callback */
+	unsigned char adpu[255];			/* ADPU to send */
+	int adpu_len; 			/* Length of ADPU */
+	int sent;  			/* Have we been sent already? */
+	struct adpu_event *next;	/* Linked list pointer */
+};
 
 /* q931_call datastructure */
 
@@ -163,6 +174,7 @@
 	int rateadaption;
 	
 	int sentchannel;
+	int justsignalling;		/* for a signalling-only connection */
 
 	int progcode;			/* Progress coding */
 	int progloc;			/* Progress Location */	
@@ -202,6 +214,8 @@
         int useruserprotocoldisc;
 	char useruserinfo[256];
 	char callingsubaddr[256];	/* Calling parties sub address */
+
+	struct adpu_event *adpus;	/* ADPU queue for call */
 };
 
 extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
Index: pri_q931.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_q931.h,v
retrieving revision 1.19
diff -u -r1.19 pri_q931.h
--- pri_q931.h	5 Nov 2004 02:12:02 -0000	1.19
+++ pri_q931.h	18 Feb 2005 21:09:25 -0000
@@ -267,6 +267,8 @@
 
 extern int q931_restart(struct pri *pri, int channel);
 
+extern int q931_facility(struct pri *pri, q931_call *call);
+
 extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
 
 extern int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode);
Index: q931.c
===================================================================
RCS file: /usr/cvsroot/libpri/q931.c,v
retrieving revision 1.114
diff -u -r1.114 q931.c
--- q931.c	5 Feb 2005 16:54:52 -0000	1.114
+++ q931.c	18 Feb 2005 21:09:25 -0000
@@ -277,9 +277,15 @@
  	}
 #endif
 #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
-	if ((ie->data[0] & 3) != 1) {
-		pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
-		return -1;
+	switch (ie->data[0] & 3) {
+		case 0:
+			call->justsignalling = 1;
+			break;
+		case 1:
+			break;
+		default:
+			pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
+			return -1;
 	}
 #endif
 	if (ie->data[0] & 0x08)
@@ -326,10 +332,17 @@
 {
 	int pos=0;
 
+	
 	/* We are ready to transmit single IE only */
 	if (order > 1)
 		return 0;
-
+	
+	if (call->justsignalling) {
+		ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
+					   ECMA-165 section 7.3 */
+		return pos + 2;
+	}
+		
 	/* Start with standard stuff */
 	if (pri->switchtype == PRI_SWITCH_GR303_TMC)
 		ie->data[pos] = 0x69;
@@ -615,6 +628,13 @@
 		ie->data[1] = 0x90;
 		return 4;
 	}
+	
+	if (call->justsignalling) {
+		ie->data[0] = 0xa8;
+		ie->data[1] = 0x80;
+		return 4;
+	}
+	
 	if (pri->switchtype == PRI_SWITCH_ATT4ESS) {
 		/* 4ESS uses a different trans capability for 3.1khz audio */
 		if (tc == PRI_TRANS_CAP_3_1K_AUDIO)
@@ -1049,6 +1069,33 @@
 
 static FUNC_SEND(transmit_facility)
 {
+	struct adpu_event *tmp;
+	int i = 0;
+
+	for (tmp = call->adpus; tmp; tmp = tmp->next) {
+		if (tmp->message == msgtype)
+			break;
+	}
+
+	if (!tmp)	/* No APDU found */
+		return 0;
+
+	if (tmp->adpu_len > 235) { /* TODO: find out how much sapce we can use */
+		pri_message("Requested ADPU (%d bytes) is too long\n", tmp->adpu_len);
+
+
+		return 0;
+	}
+	
+	memcpy(ie->data, tmp->adpu, tmp->adpu_len);
+	i += tmp->adpu_len;
+
+	return i + 2;
+}
+
+#if 0
+static FUNC_SEND(transmit_facility)
+{
 	int i = 0, j, first_i, compsp = 0;
 	struct rose_component *comp, *compstk[10];
 	unsigned char namelen = strlen(call->callername);
@@ -1220,6 +1267,7 @@
 finish2:
 	return (i ? i+2 : 0);
 }
+#endif
 
 static FUNC_RECV(receive_facility)
 {
@@ -2212,6 +2260,7 @@
 				pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
 			if (cur->retranstimer)
 				pri_schedule_del(pri, cur->retranstimer);
+			pri_call_adpu_queue_cleanup(cur);
 			free(cur);
 			return;
 		}
@@ -2410,6 +2459,8 @@
 	int offset=0;
 	int x;
 	int codeset;
+	struct adpu_event *facevent = c->adpus;
+	
 	memset(buf, 0, sizeof(buf));
 	len = sizeof(buf);
 	init_header(pri, c, buf, &h, &mh, &len);
@@ -2417,11 +2468,30 @@
 	x=0;
 	codeset = 0;
 	while(ies[x] > -1) {
-		res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
+		if (ies[x] == Q931_IE_FACILITY) {
+			res = 0;
+			while (facevent) {
+				if (!facevent->sent && (facevent->message == msgtype)) { 
+					int tmpres;
+					tmpres = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
+					if (tmpres < 0) {
+						pri_error("!! Unable to add IE '%s'\n", ie2str(ies[x]));
+						return -1;
+					}
+					res += tmpres;
+					facevent->sent = 1;
+				}
+				facevent = facevent->next;
+			}
+		} else {
+			res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
+		}
+
 		if (res < 0) {
 			pri_error("!! Unable to add IE '%s'\n", ie2str(ies[x]));
 			return -1;
 		}
+
 		offset += res;
 		len -= res;
 		x++;
@@ -2479,6 +2549,13 @@
 	return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
 }
 
+static int facility_ies[] = { Q931_IE_FACILITY, -1 };
+
+int q931_facility(struct pri*pri, q931_call *c)
+{
+	return send_message(pri, c, Q931_FACILITY, facility_ies);
+}
+
 static int notify_ies[] = { Q931_IE_NOTIFY_IND, -1 };
 
 int q931_notify(struct pri *pri, q931_call *c, int channel, int info)
@@ -2737,6 +2814,8 @@
 
 static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
 
+static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
+
 int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
 {
 	int res;
@@ -2757,7 +2836,8 @@
 	c->channelno = req->channel;		
 	c->slotmap = -1;
 	c->nonisdn = req->nonisdn;
-	c->newcall = 0;		
+	c->newcall = 0;
+	c->justsignalling = req->justsignalling;		
 	c->complete = req->numcomplete; 
 	if (req->exclusive) 
 		c->chanflags = FLAG_EXCLUSIVE;
@@ -2810,8 +2890,13 @@
 		c->progressmask = PRI_PROG_CALLER_NOT_ISDN;
 	else
 		c->progressmask = 0;
+
+	pri_call_add_standard_adpus(pri, c);
+
 	if (pri->subchannel)
 		res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
+	else if (c->justsignalling)
+		res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
 	else
 		res = send_message(pri, c, Q931_SETUP, setup_ies);
 	if (!res) {
@@ -2961,6 +3046,8 @@
 	int missingmand;
 	int codeset, cur_codeset;
 	int last_ie[8];
+	struct adpu_event *cur = NULL;
+
 	memset(last_ie, 0, sizeof(last_ie));
 	if (pri->debug & PRI_DEBUG_Q931_DUMP)
 		q931_dump(h, len, 0);
@@ -3480,6 +3567,16 @@
 		c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
 		pri->ev.e = PRI_EVENT_SETUP_ACK;
 		pri->ev.setup_ack.channel = c->channelno;
+
+		cur = c->adpus;
+		while (cur) {
+			if (!cur->sent && cur->message == Q931_FACILITY) {
+				q931_facility(pri, c);
+				break;
+			}
+			cur = cur->next;
+		}
+
 		return Q931_RES_HAVEEVENT;
 	case Q931_NOTIFY:
 		pri->ev.e = PRI_EVENT_NOTIFY;
Index: testprilib.c
===================================================================
RCS file: /usr/cvsroot/libpri/testprilib.c,v
retrieving revision 1.4
diff -u -r1.4 testprilib.c
--- testprilib.c	3 Feb 2005 22:14:44 -0000	1.4
+++ testprilib.c	18 Feb 2005 21:09:25 -0000
@@ -53,6 +53,7 @@
 #include <pthread.h>
 #include <sys/select.h>
 #include "libpri.h"
+#include "pri_q931.h"
 
 #ifndef AF_LOCAL
 #define AF_LOCAL AF_UNIX
@@ -89,7 +90,7 @@
 			}
 #if 0
 			sr = pri_sr_new();
-			pri_sr_set_channel(sr, x, 0, 0);
+			pri_sr_set_channel(sr, x+1, 0, 0);
 			pri_sr_set_bearer(sr, 0, PRI_LAYER_1_ULAW);
 			pri_sr_set_called(sr, dest, PRI_NATIONAL_ISDN, 1);
 			pri_sr_set_caller(sr, num, name, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
@@ -107,6 +108,11 @@
 		}
 		printf("Setup %d calls!\n", TEST_CALLS);
 		break;
+	case PRI_EVENT_RINGING:
+		printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
+		q931_facility(pri, e->ringing.call);
+		pri_answer(pri, e->ringing.call, e->ringing.channel, 0);
+		break;
 	default:
 		printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
 	}
@@ -116,6 +122,11 @@
 {
 	/* CPE */
 	switch(e->gen.e) {
+	case PRI_EVENT_RING:
+		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
+		pri_proceeding(pri, e->ring.call, e->ring.channel, 0);
+		pri_acknowledge(pri, e->ring.call, e->ring.channel, 0);
+		break;
 	case PRI_EVENT_DCHAN_UP:
 	default:
 		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
