[libpri-commits] mattf: branch 1.2 r521 - in /branches/1.2: libpri.h q931.c

SVN commits to the libpri project libpri-commits at lists.digium.com
Mon Feb 18 14:25:09 CST 2008


Author: mattf
Date: Mon Feb 18 14:25:09 2008
New Revision: 521

URL: http://svn.digium.com/view/libpri?view=rev&rev=521
Log:
Fix for bug #960.  Better support for more exotic bearer capabilities

Modified:
    branches/1.2/libpri.h
    branches/1.2/q931.c

Modified: branches/1.2/libpri.h
URL: http://svn.digium.com/view/libpri/branches/1.2/libpri.h?view=diff&rev=521&r1=520&r2=521
==============================================================================
--- branches/1.2/libpri.h (original)
+++ branches/1.2/libpri.h Mon Feb 18 14:25:09 2008
@@ -205,6 +205,52 @@
 #define PRI_LAYER_1_V120_RATE_ADAPT	0x28
 #define PRI_LAYER_1_X31_RATE_ADAPT	0x29
 
+
+/* Intermediate rates for V.110 */
+#define PRI_INT_RATE_8K			1
+#define PRI_INT_RATE_16K		2
+#define PRI_INT_RATE_32K		3
+
+
+/* Rate adaption for bottom 5 bits of rateadaption */
+#define PRI_RATE_USER_RATE_MASK		0x1F
+#define PRI_RATE_ADAPT_UNSPEC		0x00
+#define PRI_RATE_ADAPT_0K6		0x01
+#define PRI_RATE_ADAPT_1K2		0x02
+#define PRI_RATE_ADAPT_2K4		0x03
+#define PRI_RATE_ADAPT_3K6		0x04
+#define PRI_RATE_ADAPT_4K8		0x05
+#define PRI_RATE_ADAPT_7K2		0x06
+#define PRI_RATE_ADAPT_8K		0x07
+#define PRI_RATE_ADAPT_9K6		0x08
+#define PRI_RATE_ADAPT_14K4		0x09
+#define PRI_RATE_ADAPT_16K		0x0A
+#define PRI_RATE_ADAPT_19K2		0x0B
+#define PRI_RATE_ADAPT_32K		0x0C
+#define PRI_RATE_ADAPT_38K4		0x0D
+#define PRI_RATE_ADAPT_48K		0x0E
+#define PRI_RATE_ADAPT_56K		0x0F
+#define PRI_RATE_ADAPT_57K6		0x12
+#define PRI_RATE_ADAPT_28K8		0x13
+#define PRI_RATE_ADAPT_24K		0x14
+#define PRI_RATE_ADAPT_0K1345		0x15
+#define PRI_RATE_ADAPT_0K1		0x16
+#define PRI_RATE_ADAPT_0K075_1K2	0x17
+#define PRI_RATE_ADAPT_1K2_0K075	0x18
+#define PRI_RATE_ADAPT_0K05		0x19
+#define PRI_RATE_ADAPT_0K075		0x1A
+#define PRI_RATE_ADAPT_0K110		0x1B
+#define PRI_RATE_ADAPT_0K150		0x1C
+#define PRI_RATE_ADAPT_0K200		0x1D
+#define PRI_RATE_ADAPT_0K300		0x1E
+#define PRI_RATE_ADAPT_12K		0x1F
+
+/* in-band negotiation flag for rateadaption bit 5 */
+#define PRI_RATE_ADAPT_NEGOTIATION_POSS	0x20
+
+/* async flag for rateadaption bit 6 */
+#define PRI_RATE_ADAPT_ASYNC		0x40
+
 /* Notifications */
 #define PRI_NOTIFY_USER_SUSPENDED		0x00	/* User suspended */
 #define PRI_NOTIFY_USER_RESUMED			0x01	/* User resumed */
@@ -510,6 +556,7 @@
 
 /* Run any pending schedule events */
 extern pri_event *pri_schedule_run(struct pri *pri);
+extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
 
 extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
    int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,

Modified: branches/1.2/q931.c
URL: http://svn.digium.com/view/libpri/branches/1.2/q931.c?view=diff&rev=521&r1=520&r2=521
==============================================================================
--- branches/1.2/q931.c (original)
+++ branches/1.2/q931.c Mon Feb 18 14:25:09 2008
@@ -528,12 +528,12 @@
 static char *l12str(int proto)
 {
 	static struct msgtype protos[] = {
-		{ PRI_LAYER_1_ITU_RATE_ADAPT, "ITU Rate Adaption" },
+		{ PRI_LAYER_1_ITU_RATE_ADAPT, "V.110 Rate Adaption" },
 		{ PRI_LAYER_1_ULAW, "u-Law" },
 		{ PRI_LAYER_1_ALAW, "A-Law" },
 		{ PRI_LAYER_1_G721, "G.721 ADPCM" },
 		{ PRI_LAYER_1_G722_G725, "G.722/G.725 7kHz Audio" },
-		{ PRI_LAYER_1_G7XX_384K, "G.7xx 384k Video" },
+		{ PRI_LAYER_1_G7XX_384K, "H.223/H.245 Multimedia" },
 		{ PRI_LAYER_1_NON_ITU_ADAPT, "Non-ITU Rate Adaption" },
 		{ PRI_LAYER_1_V120_RATE_ADAPT, "V.120 Rate Adaption" },
 		{ PRI_LAYER_1_X31_RATE_ADAPT, "X.31 Rate Adaption" },
@@ -544,7 +544,7 @@
 static char *ra2str(int proto)
 {
 	static struct msgtype protos[] = {
-		{ RATE_ADAPT_56K, "from 56kbps" },
+		{ PRI_RATE_ADAPT_9K6, "9.6 kbit/s" },
 	};
 	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
 }
@@ -565,32 +565,143 @@
 	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
 }
 
+static char *int_rate2str(int proto)
+{
+    static struct msgtype protos[] = {
+		{ PRI_INT_RATE_8K, "8 kbit/s" },
+		{ PRI_INT_RATE_16K, "16 kbit/s" },
+		{ PRI_INT_RATE_32K, "32 kbit/s" },
+    };
+    return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
+}
+
 static FUNC_DUMP(dump_bearer_capability)
 {
 	int pos=2;
 	pri_message(pri, "%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));
 	pri_message(pri, "%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 */
 	if ((ie->data[1] & 0x7f) == 0x18) {
 	    pri_message(pri, "%c                              Ext: %d  Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
 		pos++;
 	}
-	/* Stop here if no more */
-	if (pos >= len - 2)
-		return;
-
-	if ((ie->data[1] & 0x7f) != TRANS_MODE_PACKET) {
-		/* Look for octets 5 and 5.a if present */
-		pri_message(pri, "%c                              Ext: %d  User information layer 1: %s (%d)\n", prefix, (ie->data[pos] >> 7), l12str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
-		if ((ie->data[pos] & 0x7f) == PRI_LAYER_1_ITU_RATE_ADAPT)
-			pri_message(pri, "%c                                Ext: %d  Rate adaptatation: %s (%d)\n", prefix, ie->data[pos] >> 7, ra2str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
+
+	/* don't count the IE num and length as part of the data */
+	len -= 2;
+	
+	/* Look for octet 5; this is identified by bits 5,6 == 01 */
+     	if (pos < len &&
+		(ie->data[pos] & 0x60) == 0x20) {
+
+		/* although the layer1 is only the bottom 5 bits of the byte,
+		   previous versions of this library passed bits 5&6 through
+		   too, so we have to do the same for binary compatability */
+		u_int8_t layer1 = ie->data[pos] & 0x7f;
+
+		pri_message(pri, "%c                                User information layer 1: %s (%d)\n",
+		            prefix, l12str(layer1), layer1);
 		pos++;
-	} else {
-		/* Look for octets 6 and 7 but not 5 and 5.a */
-		pri_message(pri, "%c                              Ext: %d  User information layer 2: %s (%d)\n", prefix, ie->data[pos] >> 7, l22str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
+		
+		/* octet 5a? */
+		if (pos < len && !(ie->data[pos-1] & 0x80)) {
+			int ra = ie->data[pos] & 0x7f;
+
+			pri_message(pri, "%c                                Async: %d, Negotiation: %d, "
+				"User rate: %s (%#x)\n", 
+				prefix,
+				ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
+				ra & PRI_RATE_ADAPT_NEGOTIATION_POSS ? 1 : 0,
+				ra2str(ra & PRI_RATE_USER_RATE_MASK),
+				ra & PRI_RATE_USER_RATE_MASK);
+			pos++;
+		}
+		
+		/* octet 5b? */
+		if (pos < len && !(ie->data[pos-1] & 0x80)) {
+			u_int8_t data = ie->data[pos];
+			if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
+				pri_message(pri, "%c                                Intermediate rate: %s (%d), "
+					"NIC on Tx: %d, NIC on Rx: %d, "
+					"Flow control on Tx: %d, "
+					"Flow control on Rx: %d\n",
+					prefix, int_rate2str((data & 0x60)>>5),
+					(data & 0x60)>>5,
+					(data & 0x10)?1:0,
+					(data & 0x08)?1:0,
+					(data & 0x04)?1:0,
+					(data & 0x02)?1:0);
+			} else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
+				pri_message(pri, "%c                                Hdr: %d, Multiframe: %d, Mode: %d, "
+					"LLI negot: %d, Assignor: %d, "
+					"In-band neg: %d\n", prefix,
+					(data & 0x40)?1:0,
+					(data & 0x20)?1:0,
+					(data & 0x10)?1:0,
+					(data & 0x08)?1:0,
+					(data & 0x04)?1:0,
+					(data & 0x02)?1:0);
+			} else {
+				pri_message(pri, "%c                                Unknown octet 5b: 0x%x\n", data );
+			}
+			pos++;
+		}
+
+		/* octet 5c? */
+		if (pos < len && !(ie->data[pos-1] & 0x80)) {
+			u_int8_t data = ie->data[pos];
+			const char *stop_bits[] = {"?","1","1.5","2"};
+			const char *data_bits[] = {"?","5","7","8"};
+			const char *parity[] = {"Odd","?","Even","None",
+				       "zero","one","?","?"};
+	
+			pri_message(pri, "%c                                Stop bits: %s, data bits: %s, "
+			    "parity: %s\n", prefix,
+			    stop_bits[(data & 0x60) >> 5],
+			    data_bits[(data & 0x18) >> 3],
+			    parity[(data & 0x7)]);
+	
+			pos++;
+		}
+	
+			/* octet 5d? */
+		if (pos < len && !(ie->data[pos-1] & 0x80)) {
+			u_int8_t data = ie->data[pos];
+			pri_message(pri, "%c                                Duplex mode: %d, modem type: %d\n",
+				prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
+ 			pos++;
+		}
+ 	}
+
+
+	/* Look for octet 6; this is identified by bits 5,6 == 10 */
+	if (pos < len && 
+		(ie->data[pos] & 0x60) == 0x40) {
+		pri_message(pri, "%c                                User information layer 2: %s (%d)\n",
+			prefix, l22str(ie->data[pos] & 0x1f),
+			ie->data[pos] & 0x1f);
 		pos++;
-		pri_message(pri, "%c                              Ext: %d  User information layer 3: %s (%d)\n", prefix, ie->data[pos] >> 7, l32str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
+	}
+
+	/* Look for octet 7; this is identified by bits 5,6 == 11 */
+	if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
+		pri_message(pri, "%c                                User information layer 3: %s (%d)\n",
+			prefix, l32str(ie->data[pos] & 0x1f),
+			ie->data[pos] & 0x1f);
 		pos++;
+
+		/* octets 7a and 7b? */
+		if (pos + 1 < len && !(ie->data[pos-1] & 0x80) &&
+			!(ie->data[pos] & 0x80)) {
+			unsigned int proto;
+			proto = ((ie->data[pos] & 0xF) << 4 ) | 
+			         (ie->data[pos+1] & 0xF);
+
+			pri_message(pri, "%c                                Network layer: 0x%x\n", prefix,
+			            proto );
+			pos += 2;
+		}
 	}
 }
 
@@ -603,22 +714,44 @@
 	}
 	call->transcapability = ie->data[0] & 0x1f;
 	call->transmoderate = ie->data[1] & 0x7f;
-	if (call->transmoderate == PRI_TRANS_CAP_AUDIO_4ESS)
-		call->transmoderate = PRI_TRANS_CAP_3_1K_AUDIO;
-
-	if (pos >= len - 2)
-		return 0;
-
-	if (call->transmoderate != TRANS_MODE_PACKET) {
+   
+	/* octet 4.1 exists iff mode/rate is multirate */
+	if (call->transmoderate == TRANS_MODE_MULTIRATE) {
+		call->transmultiple = ie->data[pos++] & 0x7f;
+	}
+
+	/* Look for octet 5; this is identified by bits 5,6 == 01 */
+	if (pos < len && 
+	     (ie->data[pos] & 0x60) == 0x20 ) {
+		/* although the layer1 is only the bottom 5 bits of the byte,
+		   previous versions of this library passed bits 5&6 through
+		   too, so we have to do the same for binary compatability */
 		call->userl1 = ie->data[pos] & 0x7f;
-		if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
-			call->rateadaption = ie->data[++pos] & 0x7f;
-		}
 		pos++;
-	} else {
-		/* Get 6 and 7 */
-		call->userl2 = ie->data[pos++] & 0x7f;
-		call->userl3 = ie->data[pos] & 0x7f;
+		
+		/* octet 5a? */
+		if (pos < len && !(ie->data[pos-1] & 0x80)) {
+			call->rateadaption = ie->data[pos] & 0x7f;
+			pos++;
+ 		}
+		
+		/* octets 5b through 5d? */
+		while (pos < len && !(ie->data[pos-1] & 0x80)) {
+			pos++;
+		}
+		
+	}
+
+	/* Look for octet 6; this is identified by bits 5,6 == 10 */
+     	if (pos < len && 
+             (ie->data[pos] & 0x60) == 0x40) {
+		call->userl2 = ie->data[pos++] & 0x1f;
+	}
+
+	/* Look for octet 7; this is identified by bits 5,6 == 11 */
+     	if (pos < len && 
+             (ie->data[pos] & 0x60) == 0x60) {
+		call->userl3 = ie->data[pos++] & 0x1f;
 	}
 	return 0;
 }
@@ -626,6 +759,7 @@
 static FUNC_SEND(transmit_bearer_capability)
 {
 	int tc;
+	int pos;
 
 	/* We are ready to transmit single IE only */	
 	if(order > 1)
@@ -656,22 +790,39 @@
 		/* Apparently EuroISDN switches don't seem to like user layer 2/3 */
 		return 4;
 	}
+
+	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[2] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
+			ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
 			if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
-				ie->data[3] = call->rateadaption | 0x80;
-				return 6;
+				ie->data[pos++] = call->rateadaption | 0x80;
 			}
-			return 5;
-		} else
-			return 4;
-	} else {
-		ie->data[2] = 0x80 | call->userl2;
-		ie->data[3] = 0x80 | call->userl3;
-		return 6;
-	}
+			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;
 }
 
 char *pri_plan2str(int plan)
@@ -2748,6 +2899,8 @@
 	if (!req->userl1)
 		req->userl1 = PRI_LAYER_1_ULAW;
 	c->userl1 = req->userl1;
+	c->userl2 = -1;
+	c->userl3 = -1;
 	c->ds1no = (req->channel & 0xff00) >> 8;
 	c->ds1explicit = (req->channel & 0x10000) >> 16;
 	req->channel &= 0xff;




More information about the libpri-commits mailing list