[libpri-commits] dhubbard: branch dhubbard/issue3450_to_commit r622 - /team/dhubbard/issue3450...

SVN commits to the libpri project libpri-commits at lists.digium.com
Wed Aug 20 15:59:05 CDT 2008


Author: dhubbard
Date: Wed Aug 20 15:59:04 2008
New Revision: 622

URL: http://svn.digium.com/view/libpri?view=rev&rev=622
Log:
changes that are ready to be committed to the 1.4 libpri branch

Modified:
    team/dhubbard/issue3450_to_commit/libpri.h
    team/dhubbard/issue3450_to_commit/pri.c
    team/dhubbard/issue3450_to_commit/pri_internal.h
    team/dhubbard/issue3450_to_commit/pri_q921.h
    team/dhubbard/issue3450_to_commit/pri_q931.h
    team/dhubbard/issue3450_to_commit/q921.c
    team/dhubbard/issue3450_to_commit/q931.c

Modified: team/dhubbard/issue3450_to_commit/libpri.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/libpri.h?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/libpri.h (original)
+++ team/dhubbard/issue3450_to_commit/libpri.h Wed Aug 20 15:59:04 2008
@@ -81,6 +81,8 @@
 #define PRI_EVENT_NOTIFY		16	/* Notification received */
 #define PRI_EVENT_PROGRESS		17	/* When we get CALL_PROCEEDING or PROGRESS */
 #define PRI_EVENT_KEYPAD_DIGIT		18	/* When we receive during ACTIVE state */
+#define PRI_EVENT_SERVICE		19	/* SERVICE maintenance message */
+#define PRI_EVENT_SERVICE_ACK		20	/* SERVICE maintenance acknowledgement message */
 
 /* Simple states */
 #define PRI_STATE_DOWN		0
@@ -430,6 +432,18 @@
 	char digits[64];
 } pri_event_keypad_digit;
 
+typedef struct pri_event_service {
+	int e;
+	int channel;
+	int changestatus;
+} pri_event_service;
+
+typedef struct pri_event_service_ack {
+	int e;
+	int channel;
+	int changestatus;
+} pri_event_service_ack;
+
 typedef union {
 	int e;
 	pri_event_generic gen;		/* Generic view */
@@ -445,6 +459,8 @@
 	pri_event_setup_ack   setup_ack;	/* SETUP_ACKNOWLEDGE structure */
 	pri_event_notify notify;		/* Notification */
 	pri_event_keypad_digit digit;			/* Digits that come during a call */
+	pri_event_service service;	/* service message */
+	pri_event_service_ack service_ack;	/* service acknowledgement message */
 } pri_event;
 
 struct pri;
@@ -555,6 +571,9 @@
 int pri_restart(struct pri *pri);
 
 int pri_reset(struct pri *pri, int channel);
+
+/* handle b-channel maintenance messages */
+extern int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
 
 /* Create a new call */
 q931_call *pri_new_call(struct pri *pri);
@@ -600,6 +619,9 @@
 
 /* Send an MWI deactivate request to a remote location */
 int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
+
+/* Set service message support flag */
+int pri_set_service_message_support(struct pri *pri, int supportflag);
 
 #define PRI_2BCT
 /* Attempt to pass the channels back to the NET side if compatable and

Modified: team/dhubbard/issue3450_to_commit/pri.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/pri.c?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/pri.c (original)
+++ team/dhubbard/issue3450_to_commit/pri.c Wed Aug 20 15:59:04 2008
@@ -108,6 +108,14 @@
 	if (timer < 0 || timer > PRI_MAX_TIMERS)
 		return -1;
 	return pri->timers[timer];
+}
+
+int pri_set_service_message_support(struct pri *pri, int supportflag)
+{
+	if (!pri)
+		return -1;
+	pri->service_message_support = supportflag;
+	return 0;	
 }
 
 int pri_timer2idx(char *timer)
@@ -612,6 +620,14 @@
 	return q931_restart(pri, channel);
 }
 
+int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
+{
+	if (!pri) {
+		return -1;
+	}
+	return maintenance_service(pri, span, channel, changestatus);
+}
+
 q931_call *pri_new_call(struct pri *pri)
 {
 	if (!pri)

Modified: team/dhubbard/issue3450_to_commit/pri_internal.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/pri_internal.h?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/pri_internal.h (original)
+++ team/dhubbard/issue3450_to_commit/pri_internal.h Wed Aug 20 15:59:04 2008
@@ -113,6 +113,9 @@
 
 	/* do we do overlap dialing */
 	int overlapdial;
+
+	/* do we support SERVICE messages */
+	int service_message_support;
 
 #ifdef LIBPRI_COUNTERS
 	/* q921/q931 packet counters */
@@ -261,6 +264,7 @@
 
 	/* Bridged call info */
 	q931_call *bridged_call;        /* Pointer to other leg of bridged call */
+	int changestatus;		/* SERVICE message changestatus */
 };
 
 extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);

Modified: team/dhubbard/issue3450_to_commit/pri_q921.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/pri_q921.h?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/pri_q921.h (original)
+++ team/dhubbard/issue3450_to_commit/pri_q921.h Wed Aug 20 15:59:04 2008
@@ -192,4 +192,8 @@
 
 extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
 
+extern pri_event *q921_dchannel_up(struct pri *pri);
+
+extern pri_event *q921_dchannel_down(struct pri *pri);
+
 #endif

Modified: team/dhubbard/issue3450_to_commit/pri_q931.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/pri_q931.h?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/pri_q931.h (original)
+++ team/dhubbard/issue3450_to_commit/pri_q931.h Wed Aug 20 15:59:04 2008
@@ -113,6 +113,8 @@
 
 #define Q931_PROTOCOL_DISCRIMINATOR 0x08
 #define GR303_PROTOCOL_DISCRIMINATOR 0x4f
+#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 0x03
+#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_2 0x43
 
 /* Q.931 / National ISDN Message Types */
 
@@ -159,6 +161,12 @@
 /* Maintenance messages (codeset 0 only) */
 #define NATIONAL_SERVICE			0x0f
 #define NATIONAL_SERVICE_ACKNOWLEDGE	0x07
+
+#define SERVICE_CHANGE_STATUS_INSERVICE		0
+#define SERVICE_CHANGE_STATUS_LOOPBACK		1	/* not supported */
+#define SERVICE_CHANGE_STATUS_OUTOFSERVICE	2
+#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK	3	/* not supported */
+#define SERVICE_CHANGE_STATUS_SHUTDOWN		4	/* not supported */
 
 /* Special codeset 0 IE */
 #define	NATIONAL_CHANGE_STATUS		0x1
@@ -248,6 +256,8 @@
 /* EuroISDN  */
 #define Q931_SENDING_COMPLETE		0xa1
 
+extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
+extern int maintenance_service_ack(struct pri *pri, q931_call *call);
 
 /* Q.SIG specific */
 #define QSIG_IE_TRANSIT_COUNT		0x31

Modified: team/dhubbard/issue3450_to_commit/q921.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/q921.c?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/q921.c (original)
+++ team/dhubbard/issue3450_to_commit/q921.c Wed Aug 20 15:59:04 2008
@@ -263,7 +263,6 @@
 
 static void t203_expire(void *);
 static void t200_expire(void *);
-static pri_event *q921_dchannel_down(struct pri *pri);
 
 static void reschedule_t203(struct pri *pri)
 {
@@ -714,7 +713,7 @@
 	};
 }
 
-static pri_event *q921_dchannel_up(struct pri *pri)
+pri_event *q921_dchannel_up(struct pri *pri)
 {
 	/* Reset counters, etc */
 	q921_reset(pri);
@@ -744,7 +743,7 @@
 	return &pri->ev;
 }
 
-static pri_event *q921_dchannel_down(struct pri *pri)
+pri_event *q921_dchannel_down(struct pri *pri)
 {
 	/* Reset counters, reset sabme timer etc */
 	q921_reset(pri);

Modified: team/dhubbard/issue3450_to_commit/q931.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450_to_commit/q931.c?view=diff&rev=622&r1=621&r2=622
==============================================================================
--- team/dhubbard/issue3450_to_commit/q931.c (original)
+++ team/dhubbard/issue3450_to_commit/q931.c Wed Aug 20 15:59:04 2008
@@ -89,11 +89,14 @@
 	{ Q931_SUSPEND, "SUSPEND" },
 	{ Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
 	{ Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
-
-	/* Maintenance */
-	{ NATIONAL_SERVICE, "SERVICE" },
-	{ NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
 };
+static int post_handle_q931_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c, int missingmand);
+
+struct msgtype maintenance_msgs[] = {
+	{ NATIONAL_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
+	{ NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
+};
+static int post_handle_maintenance_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c);
 
 static struct msgtype causes[] = {
 	{ PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
@@ -1169,6 +1172,29 @@
 	return 0;
 }
 
+static FUNC_DUMP(dump_change_status)
+{
+       int x;
+       
+       pri_message(pri, "%c Change Status Information (len=%2d) [", prefix, len);
+       for (x=0; x<ie->len; x++) {
+               pri_message(pri, " %02x", ie->data[x] & 0x7f);
+       }
+       pri_message(pri, " ]\n");
+}
+
+static FUNC_RECV(receive_change_status)
+{
+       call->changestatus = ie->data[0] & 0x0f;
+       return 0;
+}
+
+static FUNC_SEND(transmit_change_status)
+{
+       ie->data[0] = 0xc0 | call->changestatus;
+       return 3;
+}
+
 static char *prog2str(int prog)
 {
 	static struct msgtype progs[] = {
@@ -2132,7 +2158,7 @@
 
 static struct ie ies[] = {
 	/* Codeset 0 - Common */
-	{ 1, NATIONAL_CHANGE_STATUS, "Change Status" },
+	{ 1, NATIONAL_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
 	{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
 	{ 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
 	{ 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
@@ -2176,7 +2202,7 @@
 	{ 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
 	{ 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
 	{ 1, Q931_IE_CALL_STATUS, "Call Status" },
-	{ 1, Q931_IE_CHANGE_STATUS, "Change Status" },
+	{ 1, Q931_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
 	{ 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
 	{ 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
 	{ 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
@@ -2260,6 +2286,16 @@
 		if (msgs[x].msgnum == msg)
 			return msgs[x].name;
 	return "Unknown Message Type";
+}
+
+static char *maintenance_msg2str(int msg)
+{
+       unsigned int x;
+       for(x=0; x<sizeof(maintenance_msgs)/sizeof(maintenance_msgs[0]); x++) {
+               if (maintenance_msgs[x].msgnum == msg)
+                       return maintenance_msgs[x].name;
+       }
+       return "Unknown Message Type";
 }
 
 static inline int q931_cr(q931_h *h)
@@ -2514,7 +2550,11 @@
 	pri_message(pri, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator");
 	/* Message header begins at the end of the call reference number */
 	mh = (q931_mh *)(h->contents + h->crlen);
-	pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
+	if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
+		pri_message(pri, "%c Message type: %s (%d)\n", c, maintenance_msg2str(mh->msg), mh->msg);
+	} else {
+		pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
+	}
 	/* Drop length of header, including call reference */
 	len -= (h->crlen + 3);
 	codeset = cur_codeset = 0;
@@ -2560,12 +2600,17 @@
 	return -1;
 }
 
-static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
+static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc)
 {
 	/* Returns header and message header and modifies length in place */
 	q931_h *h = (q931_h *)buf;
 	q931_mh * mh;
 	h->pd = pri->protodisc;
+	if (protodisc) {
+		h->pd = protodisc;
+	} else {
+		h->pd = pri->protodisc;
+	}
 	h->x0 = 0;		/* Reserved 0 */
 	if (!pri->bri) {
 		h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
@@ -2628,8 +2673,8 @@
 	
 	memset(buf, 0, sizeof(buf));
 	len = sizeof(buf);
-	init_header(pri, c, buf, &h, &mh, &len);
-	mh->msg = msgtype;
+	init_header(pri, c, buf, &h, &mh, &len, (msgtype >> 8));
+	mh->msg = msgtype & 0x00ff;
 	x=0;
 	codeset = 0;
 	while(ies[x] > -1) {
@@ -2649,6 +2694,29 @@
 	q931_xmit(c->pri, h, len, 1);
 	c->acked = 1;
 	return 0;
+}
+
+static int maintenance_service_ies[] = { Q931_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 };
+
+int maintenance_service_ack(struct pri *pri, q931_call *c)
+{
+       return send_message(pri, c, (MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 << 8) | NATIONAL_SERVICE_ACKNOWLEDGE, maintenance_service_ies);
+}
+
+int maintenance_service(struct pri *pri, int span, int channel, int changestatus)
+{
+       struct q931_call *c;
+       c = q931_getcall(pri, 0 | 0x8000, 0);
+       if (!c)
+               return -1;
+       if (channel > -1) {
+               channel &= 0xff;
+       }
+       c->ds1no = span;
+       c->channelno = channel;
+       c->chanflags |= FLAG_EXCLUSIVE;
+       c->changestatus = changestatus;
+       return send_message(pri, c, (MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 << 8) | NATIONAL_SERVICE, maintenance_service_ies);
 }
 
 static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
@@ -3224,45 +3292,36 @@
 	return 0;
 }
 
-int q931_receive(struct pri *pri, q931_h *h, int len)
-{
-	q931_mh *mh;
-	q931_call *c;
-	q931_ie *ie;
-	unsigned int x;
-	int y;
-	int res;
-	int r;
-	int mandies[MAX_MAND_IES];
-	int missingmand;
-	int codeset, cur_codeset;
-	int last_ie[8];
-	struct apdu_event *cur = NULL;
-
-	memset(last_ie, 0, sizeof(last_ie));
-	if (pri->debug & PRI_DEBUG_Q931_DUMP)
-		q931_dump(pri, h, len, 0);
-#ifdef LIBPRI_COUNTERS
-	pri->q931_rxcount++;
-#endif
-	mh = (q931_mh *)(h->contents + h->crlen);
-	if ((h->pd == 0x3) || (h->pd == 0x43)) {
-		/* This is the weird maintenance stuff.  We majorly
-		   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
-		   to a 0x7 (SERVICE ACKNOWLEDGE) */
-		h->raw[h->crlen + 2] -= 0x8;
-		q931_xmit(pri, h, len, 1);
-		return 0;
-	} else if (h->pd != pri->protodisc) {
-		pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
-		return 0;
-	}
-	c = q931_getcall(pri, q931_cr(h), 0);
-	if (!c) {
-		pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
+static int prepare_to_handle_maintenance_message(struct pri *pri, q931_mh *mh, q931_call *c)
+{
+	if ((!pri) || (!mh) || (!c)) {
 		return -1;
 	}
-	/* Preliminary handling */
+        /* SERVICE messages are a superset of messages that can take b-channels
+         * or entire d-channels in and out of service */
+	switch(mh->msg) {
+        case NATIONAL_SERVICE:
+        case NATIONAL_SERVICE_ACKNOWLEDGE:
+                c->channelno = -1;
+                c->slotmap = -1;
+                c->chanflags = 0;
+                c->ds1no = 0;
+                c->ri = -1;
+                c->changestatus = -1;
+                break;  
+        default:
+                pri_error(pri, "!! Don't know how to pre-handle maintenance message type '%s' (%d)\n", maintenance_msg2str(mh->msg), mh->msg);
+                return -1;
+        }
+	return 0;
+}
+
+static int prepare_to_handle_q931_message(struct pri *pri, q931_mh *mh, q931_call *c)
+{
+	if ((!pri) || (!mh) || (!c)) {
+		return -1;
+	}
+		
 	switch(mh->msg) {
 	case Q931_RESTART:
 		if (pri->debug & PRI_DEBUG_Q931_STATE)
@@ -3391,6 +3450,54 @@
 			q931_destroycall(pri,c->cr);
 		return -1;
 	}
+	return 0;
+}
+
+int q931_receive(struct pri *pri, q931_h *h, int len)
+{
+	q931_mh *mh;
+	q931_call *c;
+	q931_ie *ie;
+	unsigned int x;
+	int y;
+	int res;
+	int r;
+	int mandies[MAX_MAND_IES];
+	int missingmand;
+	int codeset, cur_codeset;
+	int last_ie[8];
+
+	memset(last_ie, 0, sizeof(last_ie));
+	if (pri->debug & PRI_DEBUG_Q931_DUMP)
+		q931_dump(pri, h, len, 0);
+#ifdef LIBPRI_COUNTERS
+	pri->q931_rxcount++;
+#endif
+	mh = (q931_mh *)(h->contents + h->crlen);
+	if ((h->pd != pri->protodisc) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
+		pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
+		return 0;
+	}
+	if (((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) && (!pri->service_message_support)) {
+		/* Real service message support has not been enabled and is OFF in libpri by default,
+ 		 * so we have to revert to the 'traditional' KLUDGE of changing byte 4
+ 		 * from a 0xf (SERVICE) to a 0x7 (SERVICE ACKNOWLEDGE) */
+		h->raw[h->crlen + 2] -= 0x8;
+		q931_xmit(pri, h, len, 1);
+		return 0;
+	}
+	c = q931_getcall(pri, q931_cr(h), 0);
+	if (!c) {
+		pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
+		return -1;
+	}
+	/* Preliminary handling */
+	if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
+		prepare_to_handle_maintenance_message(pri, mh, c);
+	} else {
+		prepare_to_handle_q931_message(pri, mh, c);
+	}
+
 	/* Handle IEs */
 	memset(mandies, 0, sizeof(mandies));
 	missingmand = 0;
@@ -3479,6 +3586,72 @@
 	}
 	
 	/* Post handling */
+	if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
+		res = post_handle_maintenance_message(pri, mh, c);
+	} else {
+		res = post_handle_q931_message(pri, mh, c, missingmand);
+	}
+	return res;
+}
+
+static int post_handle_maintenance_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c)
+{
+        /* Do some maintenance stuff */
+        switch (mh->msg) {
+        case NATIONAL_SERVICE:
+                if (c->channelno > 0) {
+                        pri->ev.e = PRI_EVENT_SERVICE;
+                        pri->ev.service.channel = c->channelno | (c->ds1no << 8);
+                        pri->ev.service.changestatus = 0x0f & c->changestatus;
+                } else {
+                        switch (0x0f & c->changestatus) {
+                        case SERVICE_CHANGE_STATUS_INSERVICE:
+                                pri->ev.e = PRI_EVENT_DCHAN_UP;
+                                q921_dchannel_up(pri);
+                                break;
+                        case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
+                                pri->ev.e = PRI_EVENT_DCHAN_DOWN;
+                                q921_dchannel_down(pri);
+                                break;
+                        default:
+                                pri_error(pri, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
+                                return -1;
+                        }
+                }
+                maintenance_service_ack(pri, c);
+                return Q931_RES_HAVEEVENT;
+        case NATIONAL_SERVICE_ACKNOWLEDGE:
+                if (c->channelno > 0) {
+                        pri->ev.e = PRI_EVENT_SERVICE_ACK;
+                        pri->ev.service_ack.channel = c->channelno | (c->ds1no << 8);
+                        pri->ev.service_ack.changestatus = 0x0f & c->changestatus;
+                } else {
+                        switch (0x0f & c->changestatus) {
+                        case SERVICE_CHANGE_STATUS_INSERVICE:
+                                pri->ev.e = PRI_EVENT_DCHAN_UP;
+                                q921_dchannel_up(pri);
+                                break;
+                        case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
+                                pri->ev.e = PRI_EVENT_DCHAN_DOWN;
+                                q921_dchannel_down(pri);
+                                break;
+                        default:
+                                pri_error(pri, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
+                                return -1;
+                        }
+                }
+                return Q931_RES_HAVEEVENT;
+        default:
+                pri_error(pri, "!! Don't know how to post-handle maintenance message type %s (%d)\n", maintenance_msg2str(mh->msg), mh->msg);
+        }
+	return -1;
+}
+
+static int post_handle_q931_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c, int missingmand)
+{
+	int res;
+	struct apdu_event *cur = NULL;
+	
 	switch(mh->msg) {
 	case Q931_RESTART:
 		if (missingmand) {




More information about the libpri-commits mailing list