patch-2.2.15 linux/drivers/isdn/eicon/eicon_idi.c
Next file: linux/drivers/isdn/eicon/eicon_idi.h
Previous file: linux/drivers/isdn/eicon/eicon_dsp.h
Back to the patch index
Back to the overall index
- Lines: 433
- Date:
Fri Apr 21 12:46:08 2000
- Orig file:
v2.2.14/drivers/isdn/eicon/eicon_idi.c
- Orig date:
Tue Jan 4 21:18:47 2000
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
@@ -1,10 +1,10 @@
-/* $Id: eicon_idi.c,v 1.27 1999/11/29 13:12:03 armin Exp $
+/* $Id: eicon_idi.c,v 1.33 2000/03/06 15:45:17 armin Exp $
*
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
* IDI interface
*
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH
* for sponsoring and testing fax
@@ -26,6 +26,28 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_idi.c,v $
+ * Revision 1.33 2000/03/06 15:45:17 armin
+ * Fixed incomplete number handling with BRI PtP connection.
+ *
+ * Revision 1.32 2000/03/04 17:04:21 armin
+ * Fix of statemachine, B-connect before D-connect,
+ * thanks to Helmut Adams <adams@ipcon.de>
+ * Minor change in send-data packet handling.
+ *
+ * Revision 1.31 2000/02/22 16:26:40 armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.30 2000/02/16 16:08:46 armin
+ * Fixed virtual channel handling of IDI.
+ *
+ * Revision 1.29 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
+ * Revision 1.28 2000/01/20 19:55:34 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.27 1999/11/29 13:12:03 armin
* Autoconnect on L2_TRANS doesn't work with link_level correctly,
* changed back to former mode.
@@ -142,7 +164,7 @@
#undef EICON_FULL_SERVICE_OKTETT
-char *eicon_idi_revision = "$Revision: 1.27 $";
+char *eicon_idi_revision = "$Revision: 1.33 $";
eicon_manifbuf *manbuf;
@@ -224,7 +246,7 @@
reqbuf->XBuffer.P[l++] = 1;
}
switch(chan->l3prot) {
- case ISDN_PROTO_L3_FAX:
+ case ISDN_PROTO_L3_FCLASS2:
#ifdef CONFIG_ISDN_TTY_FAX
reqbuf->XBuffer.P[l++] = 6;
reqbuf->XBuffer.P[l++] = NLC;
@@ -248,10 +270,10 @@
}
int
-idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
+idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
{
reqbuf->Req = rq;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = Ch;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = 1;
reqbuf->XBuffer.P[0] = 0;
@@ -361,34 +383,34 @@
break;
case REMOVE:
case REMOVE|0x700:
- idi_put_req(reqbuf, REMOVE, layer);
+ idi_put_req(reqbuf, REMOVE, layer, 0);
break;
case INDICATE_REQ:
- idi_put_req(reqbuf, INDICATE_REQ, 0);
+ idi_put_req(reqbuf, INDICATE_REQ, 0, 0);
break;
case HANGUP:
- idi_put_req(reqbuf, HANGUP, 0);
+ idi_put_req(reqbuf, HANGUP, 0, 0);
break;
case REJECT:
- idi_put_req(reqbuf, REJECT, 0);
+ idi_put_req(reqbuf, REJECT, 0 ,0);
break;
case CALL_ALERT:
- idi_put_req(reqbuf, CALL_ALERT, 0);
+ idi_put_req(reqbuf, CALL_ALERT, 0, 0);
break;
case CALL_RES:
idi_call_res_req(reqbuf, chan);
break;
case IDI_N_CONNECT|0x700:
- idi_put_req(reqbuf, IDI_N_CONNECT, 1);
+ idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
break;
case IDI_N_CONNECT_ACK|0x700:
- idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
+ idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
break;
case IDI_N_DISC|0x700:
- idi_put_req(reqbuf, IDI_N_DISC, 1);
+ idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
break;
case IDI_N_DISC_ACK|0x700:
- idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
+ idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
break;
default:
eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
@@ -806,6 +828,11 @@
message->osa[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
break;
+ case CAD:
+ pos += wlen;
+ eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n",
+ chan->No, wlen);
+ break;
case BC:
if (wlen > sizeof(message->bc)) {
pos += wlen;
@@ -1199,7 +1226,7 @@
reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_EDATA;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P);
@@ -2198,7 +2225,7 @@
reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_UDATA;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = len + 1;
@@ -2303,6 +2330,51 @@
}
void
+eicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len)
+{
+ int i,j,n;
+ int buflen = len * 3 + 30;
+ char *p;
+ struct trace_s {
+ unsigned long time;
+ unsigned short size;
+ unsigned short code;
+ unsigned char data[1];
+ } *q;
+
+ if (!(p = kmalloc(buflen, GFP_ATOMIC))) {
+ eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n");
+ return;
+ }
+ memset(p, 0, buflen);
+ q = (struct trace_s *)buffer;
+
+ if (DebugVar & 512) {
+ if ((q->code == 3) || (q->code == 4)) {
+ n = (short) *(q->data);
+ if (n) {
+ j = sprintf(p, "DTRC:");
+ for (i = 0; i < n; i++) {
+ j += sprintf(p + j, "%02x ", q->data[i+2]);
+ }
+ j += sprintf(p + j, "\n");
+ }
+ }
+ } else {
+ j = sprintf(p, "XLOG: %lx %04x %04x ",
+ q->time, q->size, q->code);
+
+ for (i = 0; i < q->size; i++) {
+ j += sprintf(p + j, "%02x ", q->data[i]);
+ }
+ j += sprintf(p + j, "\n");
+ }
+ if (strlen(p))
+ eicon_putstatus(ccard, p);
+ kfree(p);
+}
+
+void
idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
{
int tmp;
@@ -2328,12 +2400,12 @@
return;
}
- if (ind->Ind != 8)
+ if ((ind->Ind != 8) && (ind->Ind != 0xc))
dlev = 144;
else
dlev = 128;
- eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+ eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No,
ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
free_buff = 1;
@@ -2451,15 +2523,7 @@
break;
case 3: /* incomplete number */
eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
- switch(ccard->type) {
- case EICON_CTYPE_MAESTRAP:
- case EICON_CTYPE_S2M:
- /* TODO (other protocols) */
- chan->fsm_state = EICON_STATE_ICALLW;
- break;
- default:
- idi_do_req(ccard, chan, HANGUP, 0);
- }
+ chan->fsm_state = EICON_STATE_ICALLW;
break;
}
break;
@@ -2496,8 +2560,10 @@
/* On most incoming calls we use automatic connect */
/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
}
- } else
- idi_hangup(ccard, chan);
+ } else {
+ if (chan->fsm_state != EICON_STATE_ACTIVE)
+ idi_hangup(ccard, chan);
+ }
break;
case CALL_CON:
eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
@@ -2538,8 +2604,12 @@
if (chan->No == ccard->nchannels) {
/* Management Indication */
- idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
- chan->fsm_state = 1;
+ if (ind->Ind == 0x04) { /* Trace_Ind */
+ eicon_parse_trace(ccard, ind->RBuffer.P, ind->RBuffer.length);
+ } else {
+ idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
+ chan->fsm_state = 1;
+ }
}
else
switch(ind->Ind) {
@@ -2578,6 +2648,7 @@
break;
case IDI_N_CONNECT:
eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
+ chan->e.IndCh = ind->IndCh;
if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
break;
@@ -2608,6 +2679,7 @@
idi_fax_hangup(ccard, chan);
}
#endif
+ chan->e.IndCh = 0;
save_flags(flags);
cli();
chan->queued = 0;
@@ -2637,7 +2709,7 @@
#endif
break;
case IDI_N_DATA_ACK:
- eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+ eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
break;
case IDI_N_DATA:
skb_pull(skb, sizeof(eicon_IND) - 1);
@@ -2687,7 +2759,7 @@
/* Management Interface */
if (chan->No == ccard->nchannels) {
/* Managementinterface: changing state */
- if (chan->e.Req == 0x04)
+ if (chan->e.Req != 0x02)
chan->fsm_state = 1;
}
@@ -2718,6 +2790,11 @@
} else {
/* Network layer */
switch(chan->e.Req & 0x0f) {
+ case IDI_N_CONNECT:
+ chan->e.IndCh = ack->RcCh;
+ eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
+ ack->RcId, ack->RcCh, ack->Reference);
+ break;
case IDI_N_MDATA:
case IDI_N_DATA:
if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
@@ -2854,11 +2931,14 @@
dCh, ack->Rc, ack->RcId, ack->RcCh);
break;
default:
- eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
- dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
+ if (dCh != ccard->nchannels)
+ eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+ dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
}
if (dCh == ccard->nchannels) { /* Management */
chan->fsm_state = 2;
+ eicon_log(ccard, 8, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+ dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
} else if (dCh >= 0) {
/* any other channel */
/* card reports error: we hangup */
@@ -2934,13 +3014,15 @@
reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
if (((len - offset) > 270) &&
+ (chan->l2prot != ISDN_PROTO_L2_MODEM) &&
+ (chan->l2prot != ISDN_PROTO_L2_FAX) &&
(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
reqbuf->Req = IDI_N_MDATA;
} else {
reqbuf->Req = IDI_N_DATA;
- if (ack) reqbuf->Req |= N_D_BIT;
+ /* if (ack) reqbuf->Req |= N_D_BIT; */
}
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen);
reqbuf->XBuffer.length = plen;
@@ -3058,38 +3140,36 @@
chan = &(card->bch[card->nchannels]);
- if (chan->e.D3Id)
- return -EBUSY;
- chan->e.D3Id = 1;
- while((skb2 = skb_dequeue(&chan->e.X)))
- dev_kfree_skb(skb2);
- chan->e.busy = 0;
+ if (!(chan->e.D3Id)) {
+ chan->e.D3Id = 1;
+ while((skb2 = skb_dequeue(&chan->e.X)))
+ dev_kfree_skb(skb2);
+ chan->e.busy = 0;
- if ((ret = eicon_idi_manage_assign(card))) {
- chan->e.D3Id = 0;
- return(ret);
- }
+ if ((ret = eicon_idi_manage_assign(card))) {
+ chan->e.D3Id = 0;
+ return(ret);
+ }
- timeout = jiffies + 50;
- while (timeout > jiffies) {
- if (chan->e.B2Id) break;
- SLEEP(10);
- }
- if (!chan->e.B2Id) {
- chan->e.D3Id = 0;
- return -EIO;
+ timeout = jiffies + 50;
+ while (timeout > jiffies) {
+ if (chan->e.B2Id) break;
+ SLEEP(10);
+ }
+ if (!chan->e.B2Id) {
+ chan->e.D3Id = 0;
+ return -EIO;
+ }
}
chan->fsm_state = 0;
if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n");
- chan->e.D3Id = 0;
return -ENOMEM;
}
if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
kfree(manbuf);
- chan->e.D3Id = 0;
return -EFAULT;
}
@@ -3103,7 +3183,6 @@
if (skb2)
dev_kfree_skb(skb2);
kfree(manbuf);
- chan->e.D3Id = 0;
return -ENOMEM;
}
@@ -3140,25 +3219,14 @@
SLEEP(10);
}
if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
- eicon_idi_manage_remove(card);
kfree(manbuf);
- chan->e.D3Id = 0;
return -EIO;
}
-
- if ((ret = eicon_idi_manage_remove(card))) {
- kfree(manbuf);
- chan->e.D3Id = 0;
- return(ret);
- }
-
if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
kfree(manbuf);
- chan->e.D3Id = 0;
return -EFAULT;
}
kfree(manbuf);
- chan->e.D3Id = 0;
return(0);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)