patch-2.2.13 linux/drivers/isdn/eicon/eicon_idi.c

Next file: linux/drivers/isdn/eicon/eicon_idi.h
Previous file: linux/drivers/isdn/eicon/eicon.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.12/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.11 1999/07/25 15:12:03 armin Exp $
+/* $Id: eicon_idi.c,v 1.18 1999/09/07 12:48:05 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -21,6 +21,33 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.18  1999/09/07 12:48:05  armin
+ * Prepared for sub-address usage.
+ *
+ * Revision 1.17  1999/09/07 12:35:39  armin
+ * Better checking and channel Id handling.
+ *
+ * Revision 1.16  1999/09/04 13:44:19  armin
+ * Fix of V.42 analog Modem negotiation handling.
+ *
+ * Revision 1.15  1999/08/28 21:32:50  armin
+ * Prepared for fax related functions.
+ * Now compilable without errors/warnings.
+ *
+ * Revision 1.14  1999/08/28 20:24:40  armin
+ * Corrected octet 3/3a in CPN/OAD information element.
+ * Thanks to John Simpson <xfl23@dial.pipex.com>
+ *
+ * Revision 1.13  1999/08/22 20:26:44  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.12  1999/08/18 20:16:59  armin
+ * Added XLOG function for all cards.
+ * Bugfix of alloc_skb NULL pointer.
+ *
  * Revision 1.11  1999/07/25 15:12:03  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -70,6 +97,7 @@
  *
  */
 
+#include <linux/config.h>
 #define __NO_VERSION__
 #include "eicon.h"
 #include "eicon_idi.h"
@@ -77,7 +105,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.11 $";
+char *eicon_idi_revision = "$Revision: 1.18 $";
 
 eicon_manifbuf *manbuf;
 
@@ -143,9 +171,14 @@
 			reqbuf->XBuffer.P[l++] = 5; 
 			break;
 		case ISDN_PROTO_L2_TRANS:
-		case ISDN_PROTO_L2_MODEM:
 			reqbuf->XBuffer.P[l++] = 2;
 			break;
+		case ISDN_PROTO_L2_MODEM:
+  			if (chan->fsm_state == EICON_STATE_IWAIT)
+				reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */
+			else
+				reqbuf->XBuffer.P[l++] = 10; /* V.42 */
+			break;
 		case ISDN_PROTO_L2_FAX:
   			if (chan->fsm_state == EICON_STATE_IWAIT)
 				reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */
@@ -264,8 +297,8 @@
 int
 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 {
-        struct sk_buff *skb = 0;
-        struct sk_buff *skb2 = 0;
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
 	eicon_REQ *reqbuf;
 	eicon_chan_ptr *chan2;
 
@@ -415,10 +448,19 @@
 int
 idi_connect_res(eicon_card *card, eicon_chan *chan)
 {
-  chan->fsm_state = EICON_STATE_IWAIT;
-  idi_do_req(card, chan, CALL_RES, 0);
-  idi_do_req(card, chan, ASSIGN, 1);
-  return(0);
+	chan->fsm_state = EICON_STATE_IWAIT;
+	idi_do_req(card, chan, CALL_RES, 0);
+	
+	/* check if old NetID has been removed */
+	if (chan->e.B2Id) {
+		if (DebugVar & 1)
+			printk(KERN_WARNING "idi_err: Ch%d: Old NetID %x was not removed.\n",
+				chan->No, chan->e.B2Id);
+		idi_do_req(card, chan, REMOVE, 1);
+	}
+
+	idi_do_req(card, chan, ASSIGN, 1);
+	return(0);
 }
 
 int
@@ -428,6 +470,7 @@
 	int l = 0;
 	int i;
 	unsigned char tmp;
+	unsigned char *sub, *sp;
 	unsigned char bc[5];
 	unsigned char hlc[5];
         struct sk_buff *skb;
@@ -456,18 +499,52 @@
 	reqbuf->ReqCh = 0;
 	reqbuf->ReqId = 1;
 
+	sub = NULL;
+	sp = phone;
+	while (*sp) {
+		if (*sp == '.') {
+			sub = sp + 1;
+			*sp = 0;
+		} else
+			sp++;
+	}
 	reqbuf->XBuffer.P[l++] = CPN;
 	reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
-	reqbuf->XBuffer.P[l++] = 0xc1;
+	reqbuf->XBuffer.P[l++] = 0x81;
 	for(i=0; i<strlen(phone);i++) 
-		reqbuf->XBuffer.P[l++] = phone[i];
-
+		reqbuf->XBuffer.P[l++] = phone[i] & 0x7f;
+	if (sub) {
+		reqbuf->XBuffer.P[l++] = DSA;
+		reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
+		reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
+		reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
+		while (*sub)
+			reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
+	}
+
+	sub = NULL;
+	sp = eazmsn;
+	while (*sp) {
+		if (*sp == '.') {
+			sub = sp + 1;
+			*sp = 0;
+		} else
+			sp++;
+	}
 	reqbuf->XBuffer.P[l++] = OAD;
 	reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
 	reqbuf->XBuffer.P[l++] = 0x01;
-	reqbuf->XBuffer.P[l++] = 0x81;
+	reqbuf->XBuffer.P[l++] = 0x80;
 	for(i=0; i<strlen(eazmsn);i++) 
-		reqbuf->XBuffer.P[l++] = eazmsn[i];
+		reqbuf->XBuffer.P[l++] = eazmsn[i] & 0x7f;
+	if (sub) {
+		reqbuf->XBuffer.P[l++] = OSA;
+		reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
+		reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
+		reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
+		while (*sub)
+			reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
+	}
 
 	if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
 		reqbuf->XBuffer.P[l++] = BC;
@@ -481,6 +558,7 @@
 				reqbuf->XBuffer.P[l++] = hlc[i];
 		}
 	}
+
         reqbuf->XBuffer.P[l++] = CAI;
         reqbuf->XBuffer.P[l++] = 6;
         reqbuf->XBuffer.P[l++] = 0x09;
@@ -641,15 +719,15 @@
 						(__u8)message->cpn[0], message->cpn + 1);
 				break;
 			case DSA:
-				pos++;
-				for(i=0; i < wlen-1; i++) 
+				pos += 2;
+				for(i=0; i < wlen-2; i++) 
 					message->dsa[i] = buffer[pos++];
 				if (DebugVar & 2)
 					printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
 				break;
 			case OSA:
-				pos++;
-				for(i=0; i < wlen-1; i++) 
+				pos += 2;
+				for(i=0; i < wlen-2; i++) 
 					message->osa[i] = buffer[pos++];
 				if (DebugVar & 2)
 					printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
@@ -882,6 +960,120 @@
   }
 }
 
+/********************* FAX stuff ***************************/
+
+#ifdef CONFIG_ISDN_TTY_FAX
+
+int
+idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+/* send fax struct */
+int
+idi_send_edata(eicon_card *card, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+	return (0);
+}
+
+void
+idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_fax_cmd(eicon_card *card, eicon_chan *chan) 
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_edata_rcveop(eicon_card *card, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_reset_fax_stat(eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
+{
+
+	/* TODO , code follows */
+
+}
+
+int
+idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+int
+idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+void
+idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+#endif	/******** FAX ********/
 
 int
 idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
@@ -1064,7 +1256,6 @@
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
-				chan->fsm_state = EICON_STATE_NULL;
 				if (message.e_cau[0] & 0x7f) {
 					cmd.driver = ccard->myid;
 					cmd.arg = chan->No;
@@ -1074,14 +1265,23 @@
 					ccard->interface.statcallb(&cmd);
 				}
 				chan->cause[0] = 0; 
-				cmd.driver = ccard->myid;
-				cmd.arg = chan->No;
-				cmd.command = ISDN_STAT_DHUP;
-				ccard->interface.statcallb(&cmd);
-				eicon_idi_listen_req(ccard, chan);
 #ifdef CONFIG_ISDN_TTY_FAX
-				chan->fax = 0;
+				if (!chan->e.B2Id)
+					chan->fax = 0;
 #endif
+				if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
+				    (chan->fsm_state == EICON_STATE_WMCONN)) {
+					chan->fsm_state = EICON_STATE_NULL;
+				} else {
+					if (chan->e.B2Id)
+						idi_do_req(ccard, chan, REMOVE, 1);
+					chan->fsm_state = EICON_STATE_NULL;
+					cmd.driver = ccard->myid;
+					cmd.arg = chan->No;
+					cmd.command = ISDN_STAT_DHUP;
+					ccard->interface.statcallb(&cmd);
+					eicon_idi_listen_req(ccard, chan);
+				}
 				break;
 			case INDICATE_IND:
 				if (DebugVar & 8)
@@ -1094,6 +1294,10 @@
 					strcat(chan->cpn, message.dsa);
 				}
 				strcpy(chan->oad, message.oad);
+				if (strlen(message.osa)) {
+					strcat(chan->oad, ".");
+					strcat(chan->oad, message.osa);
+				}
 				try_stat_icall_again: 
 				cmd.driver = ccard->myid;
 				cmd.command = ISDN_STAT_ICALL;
@@ -1155,15 +1359,19 @@
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
-					if (chan->l2prot != ISDN_PROTO_L2_FAX) {
-						idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
-					}
+					switch(chan->l2prot) {
+						case ISDN_PROTO_L2_FAX:
 #ifdef CONFIG_ISDN_TTY_FAX
-					else {
-						if (chan->fax)
-							chan->fax->phase = ISDN_FAX_PHASE_A;
-					}
+							if (chan->fax)
+								chan->fax->phase = ISDN_FAX_PHASE_A;
 #endif
+							break;
+						case ISDN_PROTO_L2_MODEM:
+							/* do nothing, wait for connect */
+							break;
+						default:
+							idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					}
 				} else
 					idi_hangup(ccard, chan);
 				break;
@@ -1176,6 +1384,15 @@
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
+
+					/* check if old NetID has been removed */
+					if (chan->e.B2Id) {
+						if (DebugVar & 1)
+							printk(KERN_WARNING "idi_err: Ch%d: Old NetID %x was not removed.\n",
+								chan->No, chan->e.B2Id);
+						idi_do_req(ccard, chan, REMOVE, 1);
+					}
+
 					idi_do_req(ccard, chan, ASSIGN, 1); 
 					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
 #ifdef CONFIG_ISDN_TTY_FAX
@@ -1273,12 +1490,17 @@
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
+				idi_do_req(ccard, chan, HANGUP, 0);
 				if (chan->fsm_state == EICON_STATE_ACTIVE) {
 					cmd.driver = ccard->myid;
 					cmd.command = ISDN_STAT_BHUP;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
+					chan->fsm_state = EICON_STATE_NULL;
 				}
+#ifdef CONFIG_ISDN_TTY_FAX
+				chan->fax = 0;
+#endif
 				break; 
 			case IDI_N_DISC_ACK:
 				if (DebugVar & 16)
@@ -1327,7 +1549,7 @@
    if (free_buff) dev_kfree_skb(skb);
 }
 
-void
+int
 idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 {
 	isdn_ctrl cmd;
@@ -1337,7 +1559,7 @@
 		if (DebugVar & 16)
 			printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, 
 				ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
-		return;
+		return 1;
 	}
 
 	/* Management Interface */	
@@ -1350,25 +1572,26 @@
 	/* Remove an Id */
 	if (chan->e.Req == REMOVE) {
 		if (ack->Reference != chan->e.ref) {
-			if (DebugVar & 1)
+			if (DebugVar & 16)
 				printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
 					ack->Reference, chan->e.ref);
+			return 0;
 		}
 		ccard->IdTable[ack->RcId] = NULL;
 		if (DebugVar & 16)
-			printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No,
+			printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
 				ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
 		if (!chan->e.ReqCh) 
 			chan->e.D3Id = 0;
 		else
 			chan->e.B2Id = 0;
-		return;
+		return 1;
 	}
 
 	/* Signal layer */
 	if (!chan->e.ReqCh) {
 		if (DebugVar & 16)
-			printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+			printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
 				ack->RcId, ack->RcCh, ack->Reference);
 	} else {
 	/* Network layer */
@@ -1409,10 +1632,11 @@
 				break;
 			default:
 				if (DebugVar & 16)
-					printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+					printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
 						ack->RcId, ack->RcCh, ack->Reference);
 		}
 	}
+	return 1;
 }
 
 void
@@ -1447,7 +1671,8 @@
 					printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh);
 				break;
 			}
-			idi_handle_ack_ok(ccard, chan, ack);
+			if (!idi_handle_ack_ok(ccard, chan, ack))
+				chan = NULL;
 			break;
 
 		case ASSIGN_OK:
@@ -1486,9 +1711,8 @@
 		case UNKNOWN_IE:
 		case WRONG_IE:
 		default:
-			chan->e.busy = 0;
-			if (DebugVar & 24)
-				printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", dCh, 
+			if (DebugVar & 1)
+				printk(KERN_ERR "eicon_ack: Ch%d: Not OK !!: Rc=%d Id=%x Ch=%d\n", dCh, 
 					ack->Rc, ack->RcId, ack->RcCh);
 			if (dCh == ccard->nchannels) { /* Management */
 				chan->fsm_state = 2;
@@ -1583,7 +1807,6 @@
         dev_kfree_skb(skb);
         return len;
 }
-
 
 
 int

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)