[libpri-commits] mattf: branch 1.4 r524 - in /branches/1.4: libpri.h q931.c

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


Author: mattf
Date: Mon Feb 18 14:31:38 2008
New Revision: 524

URL: http://svn.digium.com/view/libpri?view=rev&rev=524
Log:
Improve transmission, receiving, and dumping of bearer capability IE (#11593)

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

Modified: branches/1.4/libpri.h
URL: http://svn.digium.com/view/libpri/branches/1.4/libpri.h?view=diff&rev=524&r1=523&r2=524
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Mon Feb 18 14:31:38 2008
@@ -207,6 +207,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 */
@@ -516,6 +562,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.4/q931.c
URL: http://svn.digium.com/view/libpri/branches/1.4/q931.c?view=diff&rev=524&r1=523&r2=524
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Mon Feb 18 14:31:38 2008
@@ -543,12 +543,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_H223_H245, "H.223 and H.245" },	/* Recommendation Q.931(05/98) page 60) */
+ 		{ PRI_LAYER_1_H223_H245, "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" },
@@ -559,7 +559,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]));
 }
@@ -580,32 +580,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;
+		}
 	}
 }
 
@@ -618,22 +729,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;
 }
@@ -641,6 +774,7 @@
 static FUNC_SEND(transmit_bearer_capability)
 {
 	int tc;
+	int pos;
 
 	/* We are ready to transmit single IE only */	
 	if(order > 1)
@@ -660,34 +794,46 @@
 		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)
-			tc = PRI_TRANS_CAP_AUDIO_4ESS;
-	}
 	ie->data[0] = 0x80 | tc;
 	ie->data[1] = call->transmoderate | 0x80;
-	if ( (tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
-		(call->transmoderate == TRANS_MODE_PACKET) ) {
+
+ 	pos = 2;
+ 	/* octet 4.1 exists iff mode/rate is multirate */
+ 	if (call->transmoderate == TRANS_MODE_MULTIRATE ) {
+ 		ie->data[pos++] = call->transmultiple | 0x80;
+	}
+
+	if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
+		(call->transmoderate == TRANS_MODE_PACKET)) {
 		/* Apparently EuroISDN switches don't seem to like user layer 2/3 */
 		return 4;
 	}
 	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)
@@ -2800,6 +2946,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