[libpri-commits] tilghman: branch group/issue10217 r835 - /team/group/issue10217/

SVN commits to the libpri project libpri-commits at lists.digium.com
Tue Jun 2 18:42:47 CDT 2009


Author: tilghman
Date: Tue Jun  2 18:42:44 2009
New Revision: 835

URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=835
Log:
Commit klaus3000's patch, plus my modifications

Modified:
    team/group/issue10217/libpri.h
    team/group/issue10217/pri.c
    team/group/issue10217/pri_internal.h
    team/group/issue10217/q931.c

Modified: team/group/issue10217/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue10217/libpri.h?view=diff&rev=835&r1=834&r2=835
==============================================================================
--- team/group/issue10217/libpri.h (original)
+++ team/group/issue10217/libpri.h Tue Jun  2 18:42:44 2009
@@ -636,6 +636,7 @@
 
 int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
 int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
+int pri_sr_set_lowlayer(struct pri_sr *sr, int transmode, int userl1);
 int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
 int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
 int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);

Modified: team/group/issue10217/pri.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue10217/pri.c?view=diff&rev=835&r1=834&r2=835
==============================================================================
--- team/group/issue10217/pri.c (original)
+++ team/group/issue10217/pri.c Tue Jun  2 18:42:44 2009
@@ -928,6 +928,14 @@
 	return 0;
 }
 
+int pri_sr_set_lowlayer(struct pri_sr *sr, int transmode, int userl1)
+{
+	sr->usellc = 1;
+	sr->llctransmode = transmode;
+	sr->llcuserl1 = userl1;
+	return 0;
+}
+
 int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
 {
 	sr->called = called;

Modified: team/group/issue10217/pri_internal.h
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue10217/pri_internal.h?view=diff&rev=835&r1=834&r2=835
==============================================================================
--- team/group/issue10217/pri_internal.h (original)
+++ team/group/issue10217/pri_internal.h Tue Jun  2 18:42:44 2009
@@ -156,6 +156,9 @@
 	int justsignalling;
 	const char *useruserinfo;
 	int transferable;
+	int usellc;
+	int llctransmode;
+	int llcuserl1;
 };
 
 /* Internal switch types */
@@ -205,7 +208,59 @@
 	int userl2;
 	int userl3;
 	int rateadaption;
-	
+
+	/* Low Layer Capability */
+	int usellc;
+	int llctranscapability;
+	int llctransmode;
+	int llctransrate;
+	int llctransmultiplier;
+	int llcuser1proto;
+	/* Note: this struct within a union within a struct within a union within a struct
+	 * is purely designed to make the code logic easier to follow without having to
+	 * ensure that the bitmaps are correct.  As this is an internal header, it does not
+	 * translate to assisting any part of the API (though that might be helpful in
+	 * libpri.h, as well). */
+	union {
+		char octet5[4];
+		struct {
+			unsigned int e5a:1;
+			unsigned int async:1;
+			unsigned int negot:1;
+			unsigned int userrate:5;
+			unsigned int e5b:1;
+			union {
+				/* For V.110, I.460, and X.30 rate adaption */
+				struct {
+					unsigned int interrate:2;
+					unsigned int nicontx:1;
+					unsigned int niconrx:1;
+					unsigned int flowontx:1;
+					unsigned int flowonrx:1;
+				};
+				/* For V.120 rate adaption */
+				struct {
+					unsigned int header:1;
+					unsigned int multiframe:1;
+					unsigned int mode:1;
+					unsigned int negotlli:1;
+					unsigned int assignor:1;
+					unsigned int inbandnegot:1;
+				};
+			};
+			unsigned int s5b:1;
+			unsigned int e5c:1;
+			unsigned int stopbits:2;
+			unsigned int databits:2;
+			unsigned int parity:3;
+			unsigned int e5d:1;
+			unsigned int duplex:1;
+			unsigned int modemtype:6;
+		} __attribute__((packed));
+	} llcuser1;
+
+	/* TODO user layer 2, 3 */
+
 	int sentchannel;
 	int justsignalling;		/* for a signalling-only connection */
 

Modified: team/group/issue10217/q931.c
URL: http://svn.asterisk.org/svn-view/libpri/team/group/issue10217/q931.c?view=diff&rev=835&r1=834&r2=835
==============================================================================
--- team/group/issue10217/q931.c (original)
+++ team/group/issue10217/q931.c Tue Jun  2 18:42:44 2009
@@ -614,11 +614,209 @@
     return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
 }
 
+static FUNC_RECV(receive_low_layer_compatibility)
+{
+	/* len contains the full length of the IE, including octet 1 and 2 */
+	/* data[] starts with octet 3 */
+	/* pos is the offset from data[0] */
+	int pos = 0;
+	char octet = 'a';
+	int negotiation = 0;
+
+	pri_message(pri, "    receive_low_layer_compatibility\n");
+
+	if (len < 4) {
+		pri_error(pri, "Low layer compatibility does not have minimum length of 4 octets!\n");
+		return -1;
+	}
+
+	/* octet 3: coding standard, information transfer capability */
+	if (ie->data[pos] & 0x60) {
+		pri_error(pri, "!! non-ITU-T coding standard (cannot negotiate)\n");
+		return -1;
+	}
+	call->llctranscapability = ie->data[pos] & 0x1f;
+	pos++;
+	/* check for spare octet 3a */
+	if ((ie->data[pos - 1] & 0x80) == 0) {
+		/* octet 3a: negot. indic. */
+		negotiation = (ie->data[pos] & 0x40) ? 1 : 0;
+		pos++;
+	}
+
+	if (pos >= len - 2) {
+		pri_error(pri, "Low layer compatibility does not include mandatory octet 4!\n");
+		return -1;
+	}
+
+	/* octet 4: transfer mode, information transfer rate */
+	call->llctransmode = ie->data[pos] & 0x60;
+	call->llctransrate = ie->data[pos] & 0x1f;
+	pos++;
+	/* octet 4.1 exists if mode/rate is multirate */
+	if ((call->llctransmode | call->llctransrate) == TRANS_MODE_MULTIRATE) {
+		if (pos >= len - 2) {
+			pri_error(pri, "Low layer compatibility: IE too short to include octet 4.1!\n");
+			return -1;
+		}
+		/* octet 4.1: rate multiplier */
+		call->llctransmultiplier = ie->data[pos] & 0x7f;
+		pos++;
+	}
+
+	if (pos >= len - 2) {
+		return 0;
+	}
+
+	/* Look for octet 5; this is identified by bits 7,6 == 0 1 */
+	if ((ie->data[pos] & 0x60) == 0x20) {
+		do {
+			call->llcuser1proto = ie->data[pos] & 0x1f;
+			if (pri->debug & PRI_DEBUG_Q931_STATE) {
+				pri_message(pri, "    LLC User layer 1: %s (%d)\n", 
+					    l12str(call->llcuser1proto & 0x20), call->llcuser1proto);
+			}
+			pos++;
+
+			if (!(ie->data[pos] & 0x80)) {
+				/* Protocol indicates no further information encoded */
+				return 0;
+			}
+
+			if ((call->llcuser1proto & 0x20) != PRI_LAYER_1_ITU_RATE_ADAPT &&
+				(call->llcuser1proto & 0x20) != PRI_LAYER_1_ULAW &&
+				(call->llcuser1proto & 0x20) != PRI_LAYER_1_NON_ITU_ADAPT &&
+				(call->llcuser1proto & 0x20) != PRI_LAYER_1_V120_RATE_ADAPT) {
+				/* Nothing else in octet 5 */
+				break;
+			}
+
+			/* octet 5a-5d */
+			for (octet = 'a'; octet <= 'd'; octet++) {
+				if (pos >= len - 2) {
+					pri_error(pri, "Low layer compatibility: IE too short to include octet 5%c!\n", octet);
+					return -1;
+				}
+				call->llcuser1.octet5[octet - 'a'] = ie->data[pos] & 0x7f;
+
+				if (!(ie->data[pos] & 0x80)) {
+					/* Protocol indicates no further information encoded */
+					return 0;
+				}
+
+				if (call->llcuser1.async == 0) {
+					/* Octets 5b-5d omitted */
+					break;
+				}
+
+				if (octet == 'b' && !((call->llctranscapability == PRI_TRANS_CAP_DIGITAL &&
+						((call->llcuser1proto | 0x20) == PRI_LAYER_1_ITU_RATE_ADAPT ||
+						 (call->llcuser1proto | 0x20) == PRI_LAYER_1_V120_RATE_ADAPT)) ||
+					(call->llctranscapability == PRI_TRANS_CAP_3_1K_AUDIO && (call->llcuser1proto | 0x20) == PRI_LAYER_1_ULAW))) {
+					/* Octets 5c-5d omitted */
+					break;
+				}
+				pos++;
+			}
+		} while (0);
+	}
+
+	if (pos >= len - 2) {
+		return 0;
+	}
+
+	/* ignore layer 2 and layer 3! Note: below decoder is not complete!!! */
+	return 0;
+
+	/* Look for octet 6; this is identified by bits 7,6 == 10 */
+	if ((ie->data[pos] & 0x60) == 0x40) {
+		call->userl2 = ie->data[pos++] & 0x1f;
+	}
+
+	if (pos >= len - 2) {
+		return 0;
+	}
+
+	/* Look for octet 7; this is identified by bits 7,6 == 11 */
+	if ((ie->data[pos] & 0x60) == 0x60) {
+		call->userl3 = ie->data[pos++] & 0x1f;
+	}
+	return 0;
+}
+
+static FUNC_SEND(transmit_low_layer_compatibility)
+{
+	/* len contains the full length of the IE, including octet 1 and 2 */
+	/* data[] starts with octet 3 */
+	/* pos is the offset from data[0] */
+	int pos=0;
+	int tc;
+
+	/* We are ready to transmit single IE only */	
+	if(order > 1)
+		return 0;
+
+	/* Add usellc only if needed */	
+	if (call->usellc == 0)
+		return 0;
+
+	tc = call->transcapability;
+	
+	if (pri->switchtype == PRI_SWITCH_ATT4ESS) {
+		/* 4ESS uses a different trans capability for 3.1khz audio */
+		if (tc == PRI_TRANS_CAP_3_1K_AUDIO)
+			tc = PRI_TRANS_CAP_AUDIO_4ESS;
+	}
+	ie->data[0] = 0x80 | tc;
+	ie->data[1] = call->transmoderate | 0x80;
+
+	pos=2;
+	/* octet 4.1 exists iff mode/rate is multirate */
+	if (call->transmoderate == TRANS_MODE_MULTIRATE ) {
+	    ie->data[pos++] = call->transmultiple | 0x80;
+	}
+
+	if (call->transmoderate != TRANS_MODE_PACKET) {
+		/* If you have an AT&T 4ESS, you don't send any more info */
+		if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
+			ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
+			if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
+				ie->data[pos++] = call->rateadaption | 0x80;
+			}
+			return pos+2;
+		}
+
+		ie->data[pos++] = 0xA0 | (call->userl1 & 0x1F);
+
+		if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
+		    ie->data[pos-1] &= ~0x80; /* clear EXT bit in octet 5 */
+		    ie->data[pos++] = call->rateadaption | 0x80;
+		}
+	}
+	
+	
+	if(call->userl2 != -1 )
+	    ie->data[pos++] = 0xC0 | (call->userl2 & 0x1F);
+
+	if(call->userl3 != -1 )
+	    ie->data[pos++] = 0xE0 | (call->userl3 & 0x1F);
+
+	return pos+2;
+}
+
+/* this is used for dumping both Bearer Capability and Low-layer Compatability */
 static void dump_bearer_capability(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
 {
 	int pos=2;
-	pri_message(ctrl, "%c Bearer Capability (len=%2d) [ Ext: %d  Q.931 Std: %d  Info transfer capability: %s (%d)\n",
-		prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
+	const char *iename;
+	if (full_ie == Q931_BEARER_CAPABILITY)
+		iename = "Bearer Capability";
+	else if (full_ie == Q931_LOW_LAYER_COMPAT)
+		iename = "Low-layer Compatability";
+	else
+		iename = "Unknown";
+	pri_message(ctrl, "%c %s (len=%2d) [ Ext: %d  Q.931 Std: %d  Info transfer capability: %s (%d)\n",
+		prefix, iename, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
 	pri_message(ctrl, "%c                              Ext: %d  Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
 
 	/* octet 4.1 exists iff mode/rate is multirate */
@@ -840,7 +1038,7 @@
 
 	if (call->transmoderate != TRANS_MODE_PACKET) {
 		/* If you have an AT&T 4ESS, you don't send any more info */
-		if ((ctrl->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
+		if ((ctrl->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1) && (call->usellc == 0)) {
 			ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
 			if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
 				ie->data[pos++] = call->rateadaption | 0x80;
@@ -2161,7 +2359,7 @@
 	{ 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
 	{ 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
 	{ 1, Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
-	{ 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
+	{ 4, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility", dump_bearer_capability, receive_low_layer_compatibility, transmit_low_layer_compatibility},
 	{ 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
 	{ 1, Q931_PACKET_SIZE, "Packet Size" },
 	{ 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
@@ -3095,7 +3293,7 @@
 }
 
 static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
-	Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE,
+	Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_LOW_LAYER_COMPAT, Q931_SENDING_COMPLETE,
 	Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
 
 static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
@@ -3114,6 +3312,15 @@
 	c->userl1 = req->userl1;
 	c->userl2 = -1;
 	c->userl3 = -1;
+	c->usellc = req->usellc;
+	c->llctranscapability = req->llctransmode;
+	c->llctransrate = TRANS_MODE_64_CIRCUIT;
+
+	if (!req->llcuserl1) {
+		req->llcuserl1 = PRI_LAYER_1_ULAW;
+	}
+	c->llcuser1proto = req->llcuserl1;
+
 	c->ds1no = (req->channel & 0xff00) >> 8;
 	c->ds1explicit = (req->channel & 0x10000) >> 16;
 	req->channel &= 0xff;
@@ -3391,6 +3598,12 @@
 		c->userl2 = -1;
 		c->userl3 = -1;
 		c->rateadaption = -1;
+		c->usellc = 0;
+		c->llctranscapability = -1;
+		c->llctransmode = -1;
+		c->llctransrate = -1;
+		c->llctransmultiplier = -1;
+		c->llcuser1proto = -1;
 		c->calledplan = -1;
 		c->callerplan = -1;
 		c->callerpres = -1;




More information about the libpri-commits mailing list