diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-21 04:26:39 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-21 04:26:39 -0800 |
| commit | ed407526409355987fadaeaaba75149d1bac88bc (patch) | |
| tree | 4ad351152e7d39584120d734ea4f55049b287487 | |
| parent | 756ee81990fdeb9f662c20296a797dfd44481579 (diff) | |
Remove stale legacy ISDN files.
From Armin Schindler <armin@melware.de>:
"These files were added in the first place for the compat
driver to the legacy isdn4linux module. Since the Eicon
driver now uses CAPI only, these files are obsolete."
| -rw-r--r-- | drivers/isdn/hardware/eicon/i4l_idi.c | 3135 | ||||
| -rw-r--r-- | drivers/isdn/hardware/eicon/i4l_idi.h | 381 | ||||
| -rw-r--r-- | drivers/isdn/hardware/eicon/i4lididrv.c | 1418 | ||||
| -rw-r--r-- | drivers/isdn/hardware/eicon/i4lididrv.h | 272 |
4 files changed, 0 insertions, 5206 deletions
diff --git a/drivers/isdn/hardware/eicon/i4l_idi.c b/drivers/isdn/hardware/eicon/i4l_idi.c deleted file mode 100644 index 02457b2f9d4d..000000000000 --- a/drivers/isdn/hardware/eicon/i4l_idi.c +++ /dev/null @@ -1,3135 +0,0 @@ -/* $Id: i4l_idi.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ - * - * ISDN interface module for Eicon active cards. - * I4L - IDI Interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999-2002 Cytronics & Melware (info@melware.de) - * - * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH - * for sponsoring and testing fax - * capabilities with Diva Server cards. - * (dor@deutschemailbox.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include <linux/config.h> -#include "i4lididrv.h" - -#undef EICON_FULL_SERVICE_OKTETT - -char *eicon_idi_revision = "$Revision: 1.1.2.2 $"; - -eicon_manifbuf *manbuf; - -static int eicon_idi_manage_assign(eicon_card *card); -static int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer); - -static int -idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan) -{ - int l = 0; - int tmp; - - tmp = 0; - if (!signet) { - /* Signal Layer */ - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 1; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = KEY; - reqbuf->XBuffer.P[l++] = 3; - reqbuf->XBuffer.P[l++] = 'I'; - reqbuf->XBuffer.P[l++] = '4'; - reqbuf->XBuffer.P[l++] = 'L'; - reqbuf->XBuffer.P[l++] = SHIFT|6; - reqbuf->XBuffer.P[l++] = SIN; - reqbuf->XBuffer.P[l++] = 2; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = DSIG_ID; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - } - else { - /* Network Layer */ - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 1; - reqbuf->XBuffer.P[l++] = chan->e.D3Id; - reqbuf->XBuffer.P[l++] = LLC; - reqbuf->XBuffer.P[l++] = 2; - switch(chan->l2prot) { - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - case ISDN_PROTO_L2_TRANS: - reqbuf->XBuffer.P[l++] = 2; /* transparent */ - break; - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - reqbuf->XBuffer.P[l++] = 5; /* X.75 */ - 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_HDLC: - case ISDN_PROTO_L2_FAX: - if (chan->fsm_state == EICON_STATE_IWAIT) - reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */ - else - reqbuf->XBuffer.P[l++] = 2; /* transparent */ - break; - default: - reqbuf->XBuffer.P[l++] = 1; - } - switch(chan->l3prot) { - case ISDN_PROTO_L3_FCLASS2: -#ifdef CONFIG_ISDN_TTY_FAX - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = NLC; - tmp = idi_fill_in_T30(chan, &reqbuf->XBuffer.P[l+1]); - reqbuf->XBuffer.P[l++] = tmp; - l += tmp; - break; -#endif - case ISDN_PROTO_L3_TRANS: - default: - reqbuf->XBuffer.P[l++] = 4; - } - /* Additional DLC element */ - switch(chan->l2prot) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_FAX: - reqbuf->XBuffer.P[l++] = DLC; - reqbuf->XBuffer.P[l++] = 2; - reqbuf->XBuffer.P[l++] = (2138 % 256); /* max. info (lo byte) */ - reqbuf->XBuffer.P[l++] = (2138 / 256); /* max. info (hi byte) */ - break; - } - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = NL_ID; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 1; /* Net Entity */ - } - return(0); -} - -static int -idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch) -{ - reqbuf->Req = rq; - reqbuf->ReqCh = Ch; - reqbuf->ReqId = 1; - reqbuf->XBuffer.length = 1; - reqbuf->XBuffer.P[0] = 0; - reqbuf->Reference = signet; - return(0); -} - -static int -idi_put_suspend_req(eicon_REQ *reqbuf, eicon_chan *chan) -{ - reqbuf->Req = SUSPEND; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.P[0] = CAI; - reqbuf->XBuffer.P[1] = 1; - reqbuf->XBuffer.P[2] = chan->No; - reqbuf->XBuffer.P[3] = 0; - reqbuf->XBuffer.length = 4; - reqbuf->Reference = 0; /* Sig Entity */ - return(0); -} - -static int -idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan) -{ - int l = 9; - reqbuf->Req = CALL_RES; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.P[0] = CAI; - reqbuf->XBuffer.P[1] = 6; - reqbuf->XBuffer.P[2] = 9; - reqbuf->XBuffer.P[3] = 0; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 32; - reqbuf->XBuffer.P[7] = 0; - switch(chan->l2prot) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - reqbuf->XBuffer.P[1] = 1; - reqbuf->XBuffer.P[2] = 0x05; - l = 4; - break; - case ISDN_PROTO_L2_V11096: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 5; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_V11019: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 6; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_V11038: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 7; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_MODEM: - /* reqbuf->XBuffer.P[1] = 12; */ - reqbuf->XBuffer.P[2] = 0x11; - reqbuf->XBuffer.P[3] = 9; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 32; - reqbuf->XBuffer.P[7] = 0; - break; - case ISDN_PROTO_L2_FAX: - reqbuf->XBuffer.P[2] = 0x10; - reqbuf->XBuffer.P[3] = 0; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 32; - reqbuf->XBuffer.P[7] = 0; - break; - case ISDN_PROTO_L2_TRANS: - switch(chan->l3prot) { - case ISDN_PROTO_L3_TRANSDSP: - reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */ - } - break; - } - reqbuf->XBuffer.P[l-1] = 0; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No); - return(0); -} - -int -idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); - if (layer) cmd |= 0x700; - switch(cmd) { - case ASSIGN: - case ASSIGN|0x700: - idi_assign_req(reqbuf, layer, chan); - break; - case REMOVE: - case REMOVE|0x700: - idi_put_req(reqbuf, REMOVE, layer, 0); - break; - case INDICATE_REQ: - idi_put_req(reqbuf, INDICATE_REQ, 0, 0); - break; - case HANGUP: - idi_put_req(reqbuf, HANGUP, 0, 0); - break; - case SUSPEND: - idi_put_suspend_req(reqbuf, chan); - break; - case RESUME: - idi_put_req(reqbuf, RESUME, 0 ,0); - break; - case REJECT: - idi_put_req(reqbuf, REJECT, 0 ,0); - break; - case CALL_ALERT: - idi_put_req(reqbuf, CALL_ALERT, 0, 0); - break; - case CALL_RES: - idi_call_res_req(reqbuf, chan); - break; - case CALL_HOLD: - idi_put_req(reqbuf, CALL_HOLD, 0, 0); - break; - case N_CONNECT|0x700: - idi_put_req(reqbuf, N_CONNECT, 1, 0); - break; - case N_CONNECT_ACK|0x700: - idi_put_req(reqbuf, N_CONNECT_ACK, 1, 0); - break; - case N_DISC|0x700: - idi_put_req(reqbuf, N_DISC, 1, chan->e.IndCh); - break; - case N_DISC_ACK|0x700: - idi_put_req(reqbuf, N_DISC_ACK, 1, chan->e.IndCh); - break; - default: - eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - return(-1); - } - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_tx_request(card); - return(0); -} - -int -eicon_idi_listen_req(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); - if (!chan->e.D3Id) { - idi_do_req(card, chan, ASSIGN, 0); - } - if (chan->fsm_state == EICON_STATE_NULL) { - if (!(chan->statectrl & HAVE_CONN_REQ)) { - idi_do_req(card, chan, INDICATE_REQ, 0); - chan->fsm_state = EICON_STATE_LISTEN; - } - } - return(0); -} - -static unsigned char -idi_si2bc(int si1, int si2, char *bc, char *hlc) -{ - hlc[0] = 0; - switch(si1) { - case 1: - bc[0] = 0x90; /* 3,1 kHz audio */ - bc[1] = 0x90; /* 64 kbit/s */ - bc[2] = 0xa3; /* G.711 A-law */ -#ifdef EICON_FULL_SERVICE_OKTETT - if (si2 == 1) { - bc[0] = 0x80; /* Speech */ - hlc[0] = 0x02; /* hlc len */ - hlc[1] = 0x91; /* first hic */ - hlc[2] = 0x81; /* Telephony */ - } -#endif - return(3); - case 2: - bc[0] = 0x90; /* 3,1 kHz audio */ - bc[1] = 0x90; /* 64 kbit/s */ - bc[2] = 0xa3; /* G.711 A-law */ -#ifdef EICON_FULL_SERVICE_OKTETT - if (si2 == 2) { - hlc[0] = 0x02; /* hlc len */ - hlc[1] = 0x91; /* first hic */ - hlc[2] = 0x84; /* Fax Gr.2/3 */ - } -#endif - return(3); - case 5: - case 7: - default: - bc[0] = 0x88; - bc[1] = 0x90; - return(2); - } - return (0); -} - -int -idi_hangup(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - if ((chan->fsm_state == EICON_STATE_ACTIVE) || - (chan->fsm_state == EICON_STATE_WMCONN)) { - if (chan->e.B2Id) idi_do_req(card, chan, N_DISC, 1); - } - if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1); - if (chan->fsm_state != EICON_STATE_NULL) { - chan->statectrl |= WAITING_FOR_HANGUP; - idi_do_req(card, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - } - eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No); -#ifdef CONFIG_ISDN_TTY_FAX - chan->fax = 0; -#endif - return(0); -} - -int -capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm) -{ - if ((cm->para[0] != 3) || (cm->para[1] != 0)) - return -1; - if (cm->para[2] < 3) - return -1; - if (cm->para[4] != 0) - return -1; - switch(cm->para[3]) { - case 4: /* Suspend */ - eicon_log(card, 8, "idi_req: Ch%d: Call Suspend\n", chan->No); - if (cm->para[5]) { - idi_do_req(card, chan, SUSPEND, 0); - } else { - idi_do_req(card, chan, CALL_HOLD, 0); - } - break; - case 5: /* Resume */ - eicon_log(card, 8, "idi_req: Ch%d: Call Resume\n", chan->No); - idi_do_req(card, chan, RESUME, 0); - break; - } - return 0; -} - -int -idi_connect_res(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - chan->fsm_state = EICON_STATE_IWAIT; - - /* check if old NetID has been removed */ - if (chan->e.B2Id) { - eicon_log(card, 1, "idi_conn_res: Ch%d: old net_id %x still exist, removing.\n", - chan->No, chan->e.B2Id); - idi_do_req(card, chan, REMOVE, 1); - } - - idi_do_req(card, chan, ASSIGN, 1); - idi_do_req(card, chan, CALL_RES, 0); - return(0); -} - -int -idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, - char *eazmsn, int si1, int si2) -{ - int l = 0; - int i; - unsigned char tmp; - unsigned char *sub, *sp; - unsigned char bc[5]; - unsigned char hlc[5]; - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((!card) || (!chan)) - return 1; - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - reqbuf->Req = CALL_REQ; - 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++] = 0x81; - for(i=0; i<strlen(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++] = 0x80; - for(i=0; i<strlen(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 (si2 > 2) { - reqbuf->XBuffer.P[l++] = SHIFT|6; - reqbuf->XBuffer.P[l++] = SIN; - reqbuf->XBuffer.P[l++] = 2; - reqbuf->XBuffer.P[l++] = si1; - reqbuf->XBuffer.P[l++] = si2; - } - else if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) { - reqbuf->XBuffer.P[l++] = BC; - reqbuf->XBuffer.P[l++] = tmp; - for(i=0; i<tmp;i++) - reqbuf->XBuffer.P[l++] = bc[i]; - if ((tmp=hlc[0])) { - reqbuf->XBuffer.P[l++] = HLC; - reqbuf->XBuffer.P[l++] = tmp; - for(i=1; i<=tmp;i++) - reqbuf->XBuffer.P[l++] = hlc[i]; - } - } - - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = 0x09; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 32; - reqbuf->XBuffer.P[l++] = 0; - switch(chan->l2prot) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - reqbuf->XBuffer.P[l-6] = 5; - reqbuf->XBuffer.P[l-7] = 1; - l -= 5; - break; - case ISDN_PROTO_L2_V11096: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 5; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_V11019: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 6; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_V11038: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 7; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_MODEM: - /* reqbuf->XBuffer.P[l-7] = 12; */ - reqbuf->XBuffer.P[l-6] = 0x11; - reqbuf->XBuffer.P[l-5] = 7; - reqbuf->XBuffer.P[l-4] = 0; - reqbuf->XBuffer.P[l-3] = 0; - reqbuf->XBuffer.P[l-2] = 32; - reqbuf->XBuffer.P[l-1] = 0; - break; - case ISDN_PROTO_L2_FAX: - reqbuf->XBuffer.P[l-6] = 0x10; - reqbuf->XBuffer.P[l-5] = 0; - reqbuf->XBuffer.P[l-4] = 0; - reqbuf->XBuffer.P[l-3] = 0; - reqbuf->XBuffer.P[l-2] = 32; - reqbuf->XBuffer.P[l-1] = 0; - break; - case ISDN_PROTO_L2_TRANS: - switch(chan->l3prot) { - case ISDN_PROTO_L3_TRANSDSP: - reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */ - } - break; - } - - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - - if (chan->statectrl & WAITING_FOR_HANGUP) { - /* If the line did not disconnect yet, - we have to delay this command */ - eicon_log(card, 32, "idi_req: Ch%d: delaying conn_req\n", chan->No); - chan->statectrl |= HAVE_CONN_REQ; - chan->tskb1 = skb; - chan->tskb2 = skb2; - } else { - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_tx_request(card); - } - - eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); - return(0); -} - - -static void -idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len) -{ - int i,j; - int pos = 0; - int codeset = 0; - int wlen = 0; - int lock = 0; - __u8 w; - __u16 code; - isdn_ctrl cmd; - - memset(message, 0, sizeof(idi_ind_message)); - - if ((!len) || (!buffer[pos])) return; - - while(pos <= len) { - w = buffer[pos++]; - if (!w) return; - if (w & 0x80) { - wlen = 0; - } - else { - wlen = buffer[pos++]; - } - - if (pos > len) return; - - if (lock & 0x80) lock &= 0x7f; - else codeset = lock; - - if((w&0xf0) == SHIFT) { - codeset = w; - if(!(codeset & 0x08)) lock = codeset & 7; - codeset &= 7; - lock |= 0x80; - } - else { - if (w==ESC && wlen >=2) { - code = buffer[pos++]|0x800; - wlen--; - } - else code = w; - code |= (codeset<<8); - - if (pos + wlen > len) { - eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No, - wlen, code, (pos + wlen) - len); - return; - } - - switch(code) { - case OAD: - if (wlen > sizeof(message->oad)) { - pos += wlen; - break; - } - j = 1; - if (wlen) { - message->plan = buffer[pos++]; - if (message->plan &0x80) - message->screen = 0; - else { - message->screen = buffer[pos++]; - j = 2; - } - } - for(i=0; i < wlen-j; i++) - message->oad[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, - message->plan, message->screen, message->oad); - break; - case RDN: - if (wlen > sizeof(message->rdn)) { - pos += wlen; - break; - } - j = 1; - if (wlen) { - if (!(buffer[pos++] & 0x80)) { - pos++; - j = 2; - } - } - for(i=0; i < wlen-j; i++) - message->rdn[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No, - message->rdn); - break; - case CPN: - if (wlen > sizeof(message->cpn)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->cpn[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, - (__u8)message->cpn[0], message->cpn + 1); - break; - case DSA: - if (wlen > sizeof(message->dsa)) { - pos += wlen; - break; - } - pos += 2; - for(i=0; i < wlen-2; i++) - message->dsa[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); - break; - case OSA: - if (wlen > sizeof(message->osa)) { - pos += wlen; - break; - } - pos += 2; - for(i=0; i < wlen-2; i++) - 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; - break; - } - for(i=0; i < wlen; i++) - message->bc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, - message->bc[0],message->bc[1],message->bc[2]); - break; - case 0x800|BC: - if (wlen > sizeof(message->e_bc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_bc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); - break; - case LLC: - if (wlen > sizeof(message->llc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->llc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d ...\n", chan->No, message->llc[0], - message->llc[1],message->llc[2],message->llc[3]); - break; - case HLC: - if (wlen > sizeof(message->hlc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->hlc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x ...\n", chan->No, - message->hlc[0], message->hlc[1], - message->hlc[2], message->hlc[3], message->hlc[4]); - break; - case DSP: - case 0x600|DSP: - if (wlen > sizeof(message->display)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->display[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No, - message->display); - break; - case 0x600|KEY: - if (wlen > sizeof(message->keypad)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->keypad[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No, - message->keypad); - break; - case NI: - case 0x600|NI: - if (wlen) { - switch(buffer[pos] & 127) { - case 0: - eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No); - break; - case 1: - eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No); - break; - case 2: - eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No); - break; - default: - eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n", - chan->No, buffer[pos] & 127); - } - pos += wlen; - } - break; - case PI: - case 0x600|PI: - if (wlen > 1) { - switch(buffer[pos+1] & 127) { - case 1: - eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); - break; - case 2: - eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); - break; - case 3: - eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); - break; - case 4: - eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); - break; - case 5: - eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No); - break; - case 8: - eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No); - break; - default: - eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n", - chan->No, buffer[pos+1] & 127); - } - } - pos += wlen; - break; - case CAU: - if (wlen > sizeof(message->cau)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->cau[i] = buffer[pos++]; - memcpy(&chan->cause, &message->cau, 2); - eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No, - message->cau[0],message->cau[1]); - break; - case 0x800|CAU: - if (wlen > sizeof(message->e_cau)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_cau[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No, - message->e_cau[0],message->e_cau[1]); - break; - case 0x800|CHI: - if (wlen > sizeof(message->e_chi)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_chi[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, - message->e_cau[0]); - break; - case 0x800|0x7a: - pos ++; - message->e_mt=buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); - break; - case DT: - if (wlen > sizeof(message->dt)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->dt[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, - message->dt[2], message->dt[1], message->dt[0], - message->dt[3], message->dt[4], message->dt[5]); - break; - case 0x600|SIN: - if (wlen > sizeof(message->sin)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->sin[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No, - message->sin[0],message->sin[1]); - break; - case 0x600|CPS: - eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No); - pos += wlen; - break; - case 0x600|CIF: - for (i = 0; i < wlen; i++) - if (buffer[pos + i] != '0') break; - memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i); - cmd.parm.num[wlen - i] = 0; - eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); - pos += wlen; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_CINF; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - break; - case 0x600|DATE: - eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No); - pos += wlen; - break; - case 0xa1: - eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No); - pos += wlen; - break; - case 0xe08: - case 0xe7a: - case 0xe04: - case 0xe00: - /* *** TODO *** */ - case CHA: - /* Charge advice */ - case FTY: - case 0x600|FTY: - case CHI: - case 0x800: - /* Not yet interested in this */ - pos += wlen; - break; - case 0x880: - /* Managment Information Element */ - if (!manbuf) { - eicon_log(ccard, 1, "idi_err: manbuf not allocated\n"); - } - else { - memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen); - manbuf->length[manbuf->count] = wlen; - manbuf->count++; - manbuf->pos += wlen; - } - pos += wlen; - break; - default: - pos += wlen; - eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", - chan->No, code, wlen); - } - } - } -} - -static void -idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *sin, unsigned char *si1, unsigned char *si2) -{ - si1[0] = 0; - si2[0] = 0; - - switch (bc[0] & 0x7f) { - case 0x00: /* Speech */ - si1[0] = 1; -#ifdef EICON_FULL_SERVICE_OKTETT - si1[0] = sin[0]; - si2[0] = sin[1]; -#endif - break; - case 0x10: /* 3.1 Khz audio */ - si1[0] = 1; -#ifdef EICON_FULL_SERVICE_OKTETT - si1[0] = sin[0]; - si2[0] = sin[1]; -#endif - break; - case 0x08: /* Unrestricted digital information */ - si1[0] = 7; - si2[0] = sin[1]; - break; - case 0x09: /* Restricted digital information */ - si1[0] = 2; - break; - case 0x11: - /* Unrestr. digital information with - * tones/announcements ( or 7 kHz audio - */ - si1[0] = 3; - break; - case 0x18: /* Video */ - si1[0] = 4; - break; - } - switch (bc[1] & 0x7f) { - case 0x40: /* packed mode */ - si1[0] = 8; - break; - case 0x10: /* 64 kbit */ - case 0x11: /* 2*64 kbit */ - case 0x13: /* 384 kbit */ - case 0x15: /* 1536 kbit */ - case 0x17: /* 1920 kbit */ - /* moderate = bc[1] & 0x7f; */ - break; - } -} - -/********************* FAX stuff ***************************/ - -#ifdef CONFIG_ISDN_TTY_FAX - -static int -idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer) -{ - eicon_t30_s *t30 = (eicon_t30_s *) buffer; - - if (!chan->fax) { - eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n"); - return 0; - } - memset(t30, 0, sizeof(eicon_t30_s)); - t30->station_id_len = EICON_FAXID_LEN; - memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN); - t30->resolution = chan->fax->resolution; - t30->rate = chan->fax->rate + 1; /* eicon rate starts with 1 */ - t30->format = T30_FORMAT_SFF; - t30->pages_low = 0; - t30->pages_high = 0; - t30->atf = 1; /* optimised for AT+F command set */ - t30->code = 0; - t30->feature_bits_low = 0; - t30->feature_bits_high = 0; - t30->control_bits_low = 0; - t30->control_bits_high = 0; - - if (chan->fax->nbc) { - /* set compression by DCC value */ - switch(chan->fax->compression) { - case (0): /* 1-D modified */ - break; - case (1): /* 2-D modified Read */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - break; - case (2): /* 2-D uncompressed */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - break; - case (3): /* 2-D modified Read */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - break; - } - } else { - /* set compression to best */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - } - switch(chan->fax->ecm) { - case (0): /* disable ECM */ - break; - case (1): - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES; - break; - case (2): - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - break; - } - - if (DebugVar & 128) { - char st[40]; - eicon_log(NULL, 128, "sT30:code = %x\n", t30->code); - eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate); - eicon_log(NULL, 128, "sT30:res = %x\n", t30->resolution); - eicon_log(NULL, 128, "sT30:format = %x\n", t30->format); - eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low); - eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high); - eicon_log(NULL, 128, "sT30:atf = %x\n", t30->atf); - eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low); - eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high); - eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low); - eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high); - //eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5); - //eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6); - //eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7); - eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len); - eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len); - strlcpy(st, t30->station_id, t30->station_id_len + 1); - eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st); - } - return(sizeof(eicon_t30_s)); -} - -/* send fax struct */ -static int -idi_send_edata(eicon_card *card, eicon_chan *chan) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No); - - skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ)); - - reqbuf->Req = N_EDATA; - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - - reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P); - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_tx_request(card); - return (0); -} - -static void -idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) -{ - eicon_t30_s *p = (eicon_t30_s *)buffer; - int i; - - if (DebugVar & 128) { - char st[40]; - eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s)); - eicon_log(ccard, 128, "rT30:code = %x\n", p->code); - eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate); - eicon_log(ccard, 128, "rT30:res = %x\n", p->resolution); - eicon_log(ccard, 128, "rT30:format = %x\n", p->format); - eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low); - eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high); - eicon_log(ccard, 128, "rT30:atf = %x\n", p->atf); - eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low); - eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high); - eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low); - eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high); - //eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5); - //eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6); - //eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7); - eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len); - eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len); - strlcpy(st, p->station_id, p->station_id_len + 1); - eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st); - } - if (!chan->fax) { - eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n"); - return; - } - chan->fax->code = p->code; - i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1); - memcpy(chan->fax->r_id, p->station_id, i); - chan->fax->r_id[i] = 0; - chan->fax->r_resolution = p->resolution; - chan->fax->r_rate = p->rate - 1; - chan->fax->r_binary = 0; /* no binary support */ - chan->fax->r_width = 0; - chan->fax->r_length = 2; - chan->fax->r_scantime = 0; - chan->fax->r_compression = 0; - chan->fax->r_ecm = 0; - if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) { - chan->fax->r_compression = 1; - if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) { - chan->fax->r_compression = 2; - } - } - if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) { - chan->fax->r_compression = 3; - } - - if (p->feature_bits_low & T30_FEATURE_BIT_ECM) { - chan->fax->r_ecm = 2; - if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES) - chan->fax->r_ecm = 1; - } -} - -static void -idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header) -{ - static __u16 wd2sff[] = { - 1728, 2048, 2432, 1216, 864 - }; - static __u16 ln2sff[2][3] = { - { 1143, 1401, 0 } , { 2287, 2802, 0 } - }; - struct sk_buff *skb; - eicon_sff_dochead *doc; - eicon_sff_pagehead *page; - u_char *docp; - - if (!chan->fax) { - eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n"); - return; - } - if (header == 2) { /* DocHeader + PageHeader */ - skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC); - } else { - skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC); - } - if (!skb) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No); - return; - } - - if (header == 2) { /* DocHeader + PageHeader */ - docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); - doc = (eicon_sff_dochead *) docp; - page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead)); - memset(docp, 0,sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); - doc->id = 0x66666653; - doc->version = 0x01; - doc->off1pagehead = sizeof(eicon_sff_dochead); - } else { - page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead)); - memset(page, 0, sizeof(eicon_sff_pagehead)); - } - - switch(header) { - case 1: /* PageHeaderEnd */ - page->pageheadid = 254; - page->pageheadlen = 0; - break; - case 0: /* PageHeader */ - case 2: /* DocHeader + PageHeader */ - page->pageheadid = 254; - page->pageheadlen = sizeof(eicon_sff_pagehead) - 2; - page->resvert = chan->fax->resolution; - page->reshoriz = 0; /* always 203 dpi */ - page->coding = 0; /* always 1D */ - page->linelength = wd2sff[chan->fax->width]; - page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length]; - eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength); - eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength); - break; - } - idi_send_data(card, chan, 0, skb, 0, 0); -} - -void -idi_fax_cmd(eicon_card *card, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if ((!card) || (!chan)) - return; - - if (!chan->fax) { - eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n"); - return; - } - switch (chan->fax->code) { - case ISDN_TTY_FAX_DT: - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_send_edata(card, chan); - break; - } - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - idi_send_edata(card, chan); - break; - } - break; - - case ISDN_TTY_FAX_DR: - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_send_edata(card, chan); - - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_CFR; - card->interface.statcallb(&cmd); - - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - card->interface.statcallb(&cmd); - - /* telling 1-D compression */ - chan->fax->r_compression = 0; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DCS; - card->interface.statcallb(&cmd); - - chan->fax2.NextObject = FAX_OBJECT_DOCU; - chan->fax2.PrevObject = FAX_OBJECT_DOCU; - - break; - } - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - idi_send_edata(card, chan); - break; - } - break; - - case ISDN_TTY_FAX_ET: - switch(chan->fax->fet) { - case 0: - case 1: - idi_fax_send_header(card, chan, 0); - break; - case 2: - idi_fax_send_header(card, chan, 1); - break; - } - break; - } -} - -static void -idi_edata_rcveop(eicon_card *card, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n"); - return; - } - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_ET; - card->interface.statcallb(&cmd); -} - -static void -idi_reset_fax_stat(eicon_chan *chan) -{ - chan->fax2.LineLen = 0; - chan->fax2.LineData = 0; - chan->fax2.LineDataLen = 0; - chan->fax2.NullByteExist = 0; - chan->fax2.Dle = 0; - chan->fax2.PageCount = 0; - chan->fax2.Eop = 0; -} - -static void -idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n"); - return; - } - if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) { - idi_parse_edata(ccard, chan, buffer, len); - - if (chan->fax->phase == ISDN_FAX_PHASE_A) { - idi_reset_fax_stat(chan); - - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, ""); - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_FCON; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DIS; - ccard->interface.statcallb(&cmd); - - if (chan->fax->r_compression != 0) { - /* telling fake compression in second DIS message */ - chan->fax->r_compression = 0; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DIS; - ccard->interface.statcallb(&cmd); - } - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */ - ccard->interface.statcallb(&cmd); - } else - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - - if ((chan->fax->code == EDATA_T30_MCF) && - (chan->fax->fet != 2)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_PTS; - ccard->interface.statcallb(&cmd); - } - - switch(chan->fax->fet) { - case 0: /* new page */ - /* stay in phase D , wait on cmd +FDT */ - break; - case 1: /* new document */ - /* link-level switch to phase B */ - break; - case 2: /* session end */ - default: - /* send_edata produces error on some */ - /* fax-machines here, so we don't */ - /* idi_send_edata(ccard, chan); */ - break; - } - } - } - - if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { - idi_parse_edata(ccard, chan, buffer, len); - - if ((chan->fax->code == EDATA_T30_DCS) && - (chan->fax->phase == ISDN_FAX_PHASE_A)) { - idi_reset_fax_stat(chan); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, ""); - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_FCON_I; - ccard->interface.statcallb(&cmd); - } else - if ((chan->fax->code == EDATA_T30_TRAIN_OK) && - (chan->fax->phase == ISDN_FAX_PHASE_A)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; - ccard->interface.statcallb(&cmd); - } else - if ((chan->fax->code == EDATA_T30_TRAIN_OK) && - (chan->fax->phase == ISDN_FAX_PHASE_B)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; - ccard->interface.statcallb(&cmd); - } else - if (chan->fax->phase == ISDN_FAX_PHASE_C) { - switch(chan->fax->code) { - case EDATA_T30_TRAIN_OK: - idi_send_edata(ccard, chan); - break; - case EDATA_T30_MPS: - chan->fax->fet = 0; - idi_edata_rcveop(ccard, chan); - break; - case EDATA_T30_EOM: - chan->fax->fet = 1; - idi_edata_rcveop(ccard, chan); - break; - case EDATA_T30_EOP: - chan->fax->fet = 2; - idi_edata_rcveop(ccard, chan); - break; - } - } - } -} - -static void -fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No); - return; - } - skb_reserve(skb, MAX_HEADER_LEN); - memcpy(skb_put(skb, len), Data, len); - ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); -} - -static void -idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) -{ - eicon_OBJBUFFER InBuf; - eicon_OBJBUFFER LineBuf; - unsigned int Length = 0; - unsigned int aLength = 0; - unsigned int ObjectSize = 0; - unsigned int ObjHeadLen = 0; - unsigned int ObjDataLen = 0; - __u8 Recordtype; - __u8 PageHeaderLen; - __u8 Event; - eicon_sff_pagehead *ob_page; - - __u16 Cl2Eol = 0x8000; - -# define EVENT_NONE 0 -# define EVENT_NEEDDATA 1 - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n"); - return; - } - - - - if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { - InBuf.Data = skb->data; - InBuf.Size = skb->len; - InBuf.Len = 0; - InBuf.Next = InBuf.Data; - LineBuf.Data = chan->fax2.abLine; - LineBuf.Size = sizeof(chan->fax2.abLine); - LineBuf.Len = chan->fax2.LineLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - - Event = EVENT_NONE; - while (Event == EVENT_NONE) { - switch(chan->fax2.NextObject) { - case FAX_OBJECT_DOCU: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < sizeof(eicon_sff_dochead)) { - Event = EVENT_NEEDDATA; - break; - } - ObjectSize = sizeof(eicon_sff_dochead); - Length = ObjectSize; - if (LineBuf.Len < Length) { - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - InBuf.Len += Length; - InBuf.Next += Length; - } else { - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - } - chan->fax2.PrevObject = FAX_OBJECT_DOCU; - chan->fax2.NextObject = FAX_OBJECT_PAGE; - break; - - case FAX_OBJECT_PAGE: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < 2) { - Event = EVENT_NEEDDATA; - break; - } - if (LineBuf.Len == 0) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - if (LineBuf.Len == 1) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - PageHeaderLen = *(LineBuf.Data + 1); - ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead); - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - Length = ObjectSize; - /* extract page dimensions */ - if (LineBuf.Len < Length) { - aLength = Length - LineBuf.Len; - memcpy(LineBuf.Next, InBuf.Next, aLength); - LineBuf.Next += aLength; - InBuf.Next += aLength; - LineBuf.Len += aLength; - InBuf.Len += aLength; - } - if (Length > 2) { - ob_page = (eicon_sff_pagehead *)LineBuf.Data; - switch(ob_page->linelength) { - case 2048: - chan->fax->r_width = 1; - break; - case 2432: - chan->fax->r_width = 2; - break; - case 1216: - chan->fax->r_width = 3; - break; - case 864: - chan->fax->r_width = 4; - break; - case 1728: - default: - chan->fax->r_width = 0; - } - switch(ob_page->pagelength) { - case 1143: - case 2287: - chan->fax->r_length = 0; - break; - case 1401: - case 2802: - chan->fax->r_length = 1; - break; - default: - chan->fax->r_length = 2; - } - eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength); - eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength); - } - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - - chan->fax2.PrevObject = FAX_OBJECT_PAGE; - chan->fax2.NextObject = FAX_OBJECT_LINE; - break; - - case FAX_OBJECT_LINE: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < 1) { - Event = EVENT_NEEDDATA; - break; - } - if (LineBuf.Len == 0) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - Recordtype = *LineBuf.Data; - if (Recordtype == 0) { - /* recordtype pixel row (2 byte length) */ - ObjHeadLen = 3; - if (Length < ObjHeadLen) { - Event = EVENT_NEEDDATA; - break; - } - while (LineBuf.Len < ObjHeadLen) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - ObjDataLen = *((__u16*) (LineBuf.Data + 1)); - ObjectSize = ObjHeadLen + ObjDataLen; - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - } else - if ((Recordtype >= 1) && (Recordtype <= 216)) { - /* recordtype pixel row (1 byte length) */ - ObjHeadLen = 1; - ObjDataLen = Recordtype; - ObjectSize = ObjHeadLen + ObjDataLen; - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - } else - if ((Recordtype >= 217) && (Recordtype <= 253)) { - /* recordtype empty lines */ - ObjHeadLen = 1; - ObjDataLen = 0; - ObjectSize = ObjHeadLen + ObjDataLen; - LineBuf.Len--; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len); - break; - } else - if (Recordtype == 254) { - /* recordtype page header */ - chan->fax2.PrevObject = FAX_OBJECT_LINE; - chan->fax2.NextObject = FAX_OBJECT_PAGE; - break; - } else { - /* recordtype user information */ - ObjHeadLen = 2; - if (Length < ObjHeadLen) { - Event = EVENT_NEEDDATA; - break; - } - while (LineBuf.Len < ObjHeadLen) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - ObjDataLen = *(LineBuf.Data + 1); - ObjectSize = ObjHeadLen + ObjDataLen; - if (ObjDataLen == 0) { - /* illegal line coding */ - LineBuf.Len -= ObjHeadLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len); - break; - } else { - /* user information */ - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - Length = ObjectSize; - if (LineBuf.Len < Length) { - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - InBuf.Len += Length; - InBuf.Next += Length; - } else { - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - } - } - break; - } - Length = ObjectSize; - if (LineBuf.Len > ObjHeadLen) { - fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen, - (LineBuf.Len - ObjHeadLen)); - } - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - if (Length > 0) { - fax_put_rcv(ccard, chan, InBuf.Next, Length); - InBuf.Len += Length; - InBuf.Next += Length; - } - fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol)); - break; - } /* end of switch (chan->fax2.NextObject) */ - } /* end of while (Event==EVENT_NONE) */ - if (InBuf.Len < InBuf.Size) { - Length = InBuf.Size - InBuf.Len; - if ((LineBuf.Len + Length) > LineBuf.Size) { - eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No, - Length); - } else { - memcpy(LineBuf.Next, InBuf.Next, Length); - LineBuf.Len += Length; - } - } - chan->fax2.LineLen = LineBuf.Len; - } else { /* CONN_OUT */ - /* On CONN_OUT we do not need incoming data, drop it */ - /* maybe later for polling */ - } - -# undef EVENT_NONE -# undef EVENT_NEEDDATA - - return; -} - -static int -idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf) -{ - struct sk_buff *skb; - - skb = alloc_skb(OutBuf->Len, GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No); - return(-1); - } - memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len); - - OutBuf->Len = 0; - OutBuf->Next = OutBuf->Data; - - return(idi_send_data(ccard, chan, 0, skb, 1, 0)); -} - -int -idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) -{ - isdn_ctrl cmd; - eicon_OBJBUFFER InBuf; - __u8 InData; - __u8 InMask; - eicon_OBJBUFFER OutBuf; - eicon_OBJBUFFER LineBuf; - __u32 LineData; - unsigned int LineDataLen; - __u8 Byte; - __u8 Event; - int ret = 1; - -# define EVENT_NONE 0 -# define EVENT_EOD 1 -# define EVENT_EOL 2 -# define EVENT_EOP 3 - - if ((!ccard) || (!chan)) - return -1; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n"); - return -1; - } - - if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { - /* Simply ignore any data written in data mode when receiving a fax. */ - /* This is not completely correct because only XON's should come here. */ - dev_kfree_skb(skb); - return 1; - } - - if (chan->fax->phase != ISDN_FAX_PHASE_C) { - dev_kfree_skb(skb); - return 1; - } - - if (chan->queued + skb->len > 1200) - return 0; - if (chan->pqueued > 1) - return 0; - - InBuf.Data = skb->data; - InBuf.Size = skb->len; - InBuf.Len = 0; - InBuf.Next = InBuf.Data; - InData = 0; - InMask = 0; - - LineBuf.Data = chan->fax2.abLine; - LineBuf.Size = sizeof(chan->fax2.abLine); - LineBuf.Len = chan->fax2.LineLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - LineData = chan->fax2.LineData; - LineDataLen = chan->fax2.LineDataLen; - - OutBuf.Data = chan->fax2.abFrame; - OutBuf.Size = sizeof(chan->fax2.abFrame); - OutBuf.Len = 0; - OutBuf.Next = OutBuf.Data; - - Event = EVENT_NONE; - - chan->fax2.Eop = 0; - - for (;;) { - for (;;) { - if (InMask == 0) { - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) { - chan->fax2.Dle = _DLE_; - InBuf.Next++; - InBuf.Len++; - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - } - if (chan->fax2.Dle == _DLE_) { - chan->fax2.Dle = 0; - if (*InBuf.Next == _ETX_) { - Event = EVENT_EOP; - break; - } else - if (*InBuf.Next == _DLE_) { - /* do nothing */ - } else { - eicon_log(ccard, 1, - "idi_err: Ch%d: unknown DLE escape %02x found\n", - chan->No, *InBuf.Next); - InBuf.Next++; - InBuf.Len++; - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - } - } - InBuf.Len++; - InData = *InBuf.Next++; - InMask = (chan->fax->bor) ? 0x80 : 0x01; - } - while (InMask) { - LineData >>= 1; - LineDataLen++; - if (InData & InMask) - LineData |= 0x80000000; - if (chan->fax->bor) - InMask >>= 1; - else - InMask <<= 1; - - if ((LineDataLen >= T4_EOL_BITSIZE) && - ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) { - Event = EVENT_EOL; - if (LineDataLen > T4_EOL_BITSIZE) { - Byte = (__u8) - ((LineData & ~T4_EOL_MASK_DWORD) >> - (32 - LineDataLen)); - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - } - LineDataLen = 0; - break; - } - if (LineDataLen >= T4_EOL_BITSIZE + 8) { - Byte = (__u8) - ((LineData & ~T4_EOL_MASK_DWORD) >> - (32 - T4_EOL_BITSIZE - 8)); - LineData &= T4_EOL_MASK_DWORD; - LineDataLen = T4_EOL_BITSIZE; - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - } - } - if (Event != EVENT_NONE) - break; - } - - if ((Event != EVENT_EOL) && (Event != EVENT_EOP)) - break; - - if ((Event == EVENT_EOP) && (LineDataLen > 0)) { - LineData >>= 32 - LineDataLen; - LineDataLen = 0; - while (LineData != 0) { - Byte = (__u8) LineData; - LineData >>= 8; - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - - } - } - if (chan->fax2.NullByteExist) { - if (chan->fax2.NullBytesPos == 0) { - LineBuf.Len = 0; - } else { - LineBuf.Len = chan->fax2.NullBytesPos + 1; - } - } - if (LineBuf.Len > 0) { - if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) { - ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); - } - if (LineBuf.Len <= 216) { - *OutBuf.Next++ = (__u8) LineBuf.Len; - OutBuf.Len++; - } else { - *OutBuf.Next++ = 0; - *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len; - OutBuf.Len += 3; - } - memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len); - OutBuf.Next += LineBuf.Len; - OutBuf.Len += LineBuf.Len; - } - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - chan->fax2.NullByteExist = 0; - if (Event == EVENT_EOP) - break; - - Event = EVENT_NONE; - } - - if (Event == EVENT_EOP) { - chan->fax2.Eop = 1; - chan->fax2.PageCount++; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_EOP; - ccard->interface.statcallb(&cmd); - } - if (OutBuf.Len > 0) { - ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); - } - - chan->fax2.LineLen = LineBuf.Len; - chan->fax2.LineData = LineData; - chan->fax2.LineDataLen = LineDataLen; - -# undef EVENT_NONE -# undef EVENT_EOD -# undef EVENT_EOL -# undef EVENT_EOP - - if (ret >= 0) - dev_kfree_skb(skb); - if (ret == 0) - ret = 1; - return(ret); -} - -static void -idi_fax_hangup(eicon_card *ccard, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n"); - return; - } - if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) && - (chan->fax->code == 0)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_PTS; - ccard->interface.statcallb(&cmd); - } - if ((chan->fax->code > 1) && (chan->fax->code < 120)) - chan->fax->code += 120; - eicon_log(ccard, 8, "idi_fax: Ch%d: Hangup (code=%d)\n", chan->No, chan->fax->code); - chan->fax->r_code = ISDN_TTY_FAX_HNG; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); -} - -#endif /******** FAX ********/ - -static int -idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, - UReq, buffer[0], buffer[1], buffer[2], buffer[3]); - - skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ)); - - reqbuf->Req = N_UDATA; - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - - reqbuf->XBuffer.length = len + 1; - reqbuf->XBuffer.P[0] = UReq; - memcpy(&reqbuf->XBuffer.P[1], buffer, len); - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_tx_request(card); - return (0); -} - -void -idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value) -{ - u_char buf[6]; - struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; - - if ((!ccard) || (!chan)) - return; - - memset(buf, 0, 6); - switch(cmd) { - case ISDN_AUDIO_SETDD: - if (value[0]) { - dtmf_buf->tone = (__u16) (value[1] * 5); - dtmf_buf->gap = (__u16) (value[1] * 5); - idi_send_udata(ccard, chan, - DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER, - buf, 4); - } else { - idi_send_udata(ccard, chan, - DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER, - buf, 0); - } - break; - } -} - -static void -idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) -{ - isdn_ctrl cmd; - eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]); - static char *connmsg[] = - {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34", - "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90", - "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17", "V.32", "K56Flex", - "X2", "V.18", "V.18LH", "V.18HL", "V.21LH", "V.21HL", - "Bell 103LH", "Bell 103HL", "V.23", "V.23", "EDT 110", - "Baudot45", "Baudot47", "Baudot50", "DTMF" }; - static u_char dtmf_code[] = { - '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' - }; - - if ((!ccard) || (!chan)) - return; - - switch (buffer[0]) { - case DSP_UDATA_INDICATION_SYNC: - eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_DCD_OFF: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_DCD_ON: - if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && - ((chan->fsm_state == EICON_STATE_IBWAIT) || - (chan->fsm_state == EICON_STATE_WMCONN))) { - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - if (p->norm > 34) { - sprintf(cmd.parm.num, "%d/(%d)", p->speed, p->norm); - } else { - sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); - } - ccard->interface.statcallb(&cmd); - } - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); - eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - break; - case DSP_UDATA_INDICATION_CTS_OFF: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_CTS_ON: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); - eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - break; - case DSP_UDATA_INDICATION_DISCONNECT: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); - break; - case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, - dtmf_code[buffer[1]]); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_AUDIO; - cmd.parm.num[0] = ISDN_AUDIO_DTMF; - cmd.parm.num[1] = dtmf_code[buffer[1]]; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - break; - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); - } -} - -static 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; - char tnum[64]; - int dlev; - int free_buff; - eicon_IND *ind = (eicon_IND *)skb->data; - eicon_chan *chan; - idi_ind_message message; - isdn_ctrl cmd; - - if (!ccard) { - eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n"); - dev_kfree_skb(skb); - return; - } - - if ((chan = ccard->IdTable[ind->IndId]) == NULL) { - eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n"); - dev_kfree_skb(skb); - return; - } - - if ((ind->Ind != 8) && (ind->Ind != 0xc)) - dlev = 144; - else - dlev = 128; - - 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; - /* Signal Layer */ - if (chan->e.D3Id == ind->IndId) { - idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); - switch(ind->Ind) { - case HANGUP: - eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No); - skb_queue_purge(&chan->e.X); - chan->queued = 0; - chan->pqueued = 0; - chan->waitq = 0; - chan->waitpq = 0; - if (message.e_cau[0] & 0x7f) { - cmd.driver = ccard->myid; - cmd.arg = chan->No; - sprintf(cmd.parm.num,"E%02x%02x", - chan->cause[0]&0x7f, message.e_cau[0]&0x7f); - cmd.command = ISDN_STAT_CAUSE; - ccard->interface.statcallb(&cmd); - } - chan->cause[0] = 0; - if ((chan->fsm_state == EICON_STATE_ACTIVE) || - ((chan->l2prot == ISDN_PROTO_L2_FAX) && - (chan->fsm_state == EICON_STATE_OBWAIT))) { - chan->fsm_state = EICON_STATE_NULL; - } else { - if (chan->e.B2Id) - idi_do_req(ccard, chan, REMOVE, 1); - chan->statectrl &= ~WAITING_FOR_HANGUP; - chan->statectrl &= ~IN_HOLD; - if (chan->statectrl & HAVE_CONN_REQ) { - eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No); - chan->statectrl &= ~HAVE_CONN_REQ; - if ((chan->tskb1) && (chan->tskb2)) { - skb_queue_tail(&chan->e.X, chan->tskb1); - skb_queue_tail(&ccard->sndq, chan->tskb2); - } - chan->tskb1 = NULL; - chan->tskb2 = NULL; - } else { - 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); -#ifdef CONFIG_ISDN_TTY_FAX - chan->fax = 0; -#endif - } - } - break; - case INDICATE_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No); - if (chan->fsm_state != EICON_STATE_LISTEN) { - eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n", - chan->No, chan->fsm_state); - idi_do_req(ccard, chan, HANGUP, 0); - break; - } - chan->fsm_state = EICON_STATE_ICALL; - idi_bc2si(message.bc, message.hlc, message.sin, &chan->si1, &chan->si2); - strcpy(chan->cpn, message.cpn + 1); - strcpy(chan->oad, message.oad); - strcpy(chan->dsa, message.dsa); - strcpy(chan->osa, message.osa); - chan->plan = message.plan; - chan->screen = message.screen; - try_stat_icall_again: - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_ICALL; - cmd.arg = chan->No; - cmd.parm.setup.si1 = chan->si1; - cmd.parm.setup.si2 = chan->si2; - strcpy(tnum, chan->cpn); - if (strlen(chan->dsa)) { - strcat(tnum, "."); - strcat(tnum, chan->dsa); - } - tnum[ISDN_MSNLEN - 1] = 0; - strcpy(cmd.parm.setup.eazmsn, tnum); - strcpy(tnum, chan->oad); - if (strlen(chan->osa)) { - strcat(tnum, "."); - strcat(tnum, chan->osa); - } - tnum[ISDN_MSNLEN - 1] = 0; - strcpy(cmd.parm.setup.phone, tnum); - cmd.parm.setup.plan = chan->plan; - cmd.parm.setup.screen = chan->screen; - tmp = ccard->interface.statcallb(&cmd); - switch(tmp) { - case 0: /* no user responding */ - idi_do_req(ccard, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - break; - case 1: /* alert */ - eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) { - chan->fsm_state = EICON_STATE_ICALL; - idi_do_req(ccard, chan, CALL_ALERT, 0); - } - break; - case 2: /* reject */ - eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No); - idi_do_req(ccard, chan, REJECT, 0); - break; - case 3: /* incomplete number */ - eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No); - chan->fsm_state = EICON_STATE_ICALLW; - break; - } - break; - case INFO_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALLW) && - (message.cpn[0])) { - strcat(chan->cpn, message.cpn + 1); - goto try_stat_icall_again; - } - break; - case CALL_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALL) || - (chan->fsm_state == EICON_STATE_WMCONN) || - (chan->fsm_state == EICON_STATE_IWAIT)) { - chan->fsm_state = EICON_STATE_IBWAIT; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - switch(chan->l2prot) { - case ISDN_PROTO_L2_FAX: -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->fax) - chan->fax->phase = ISDN_FAX_PHASE_A; -#endif - break; - case ISDN_PROTO_L2_MODEM: - /* do nothing, wait for connect */ - break; - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - case ISDN_PROTO_L2_TRANS: - idi_do_req(ccard, chan, N_CONNECT, 1); - break; - default: - /* On most incoming calls we use automatic connect */ - /* idi_do_req(ccard, chan, N_CONNECT, 1); */ - break; - } - } 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); - if (chan->fsm_state == EICON_STATE_OCALL) { - /* check if old NetID has been removed */ - if (chan->e.B2Id) { - eicon_log(ccard, 1, "idi_ind: Ch%d: old net_id %x still exist, removing.\n", - chan->No, chan->e.B2Id); - idi_do_req(ccard, chan, REMOVE, 1); - } -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if (chan->fax) { - chan->fax->phase = ISDN_FAX_PHASE_A; - } else { - eicon_log(ccard, 1, "idi_ind: Call_Con with NULL fax struct, ERROR\n"); - idi_hangup(ccard, chan); - break; - } - } -#endif - chan->fsm_state = EICON_STATE_OBWAIT; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - - idi_do_req(ccard, chan, ASSIGN, 1); - idi_do_req(ccard, chan, N_CONNECT, 1); - } else - idi_hangup(ccard, chan); - break; - case AOC_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No); - break; - case CALL_HOLD_ACK: - chan->statectrl |= IN_HOLD; - eicon_log(ccard, 8, "idi_ind: Ch%d: Call Hold Ack\n", chan->No); - break; - case SUSPEND_REJ: - eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Rejected\n", chan->No); - break; - case SUSPEND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Ack\n", chan->No); - break; - case RESUME: - eicon_log(ccard, 8, "idi_ind: Ch%d: Resume Ack\n", chan->No); - break; - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); - } - } - /* Network Layer */ - else if (chan->e.B2Id == ind->IndId) { - - if (chan->No == ccard->nchannels) { - /* Management Indication */ - 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) { - case N_CONNECT_ACK: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No); - if (chan->l2prot == ISDN_PROTO_L2_MODEM) { - chan->fsm_state = EICON_STATE_WMCONN; - break; - } - if (chan->l2prot == ISDN_PROTO_L2_FAX) { -#ifdef CONFIG_ISDN_TTY_FAX - chan->fsm_state = EICON_STATE_ACTIVE; - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - if (chan->fax) { - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_fax_send_header(ccard, chan, 2); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DCS; - ccard->interface.statcallb(&cmd); - } - } - else { - eicon_log(ccard, 1, "idi_ind: N_Connect_Ack with NULL fax struct, ERROR\n"); - } -#endif - break; - } - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, "64000"); - ccard->interface.statcallb(&cmd); - break; - case 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, N_CONNECT_ACK, 1); - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - break; - } - if (chan->l2prot == ISDN_PROTO_L2_MODEM) { - chan->fsm_state = EICON_STATE_WMCONN; - break; - } - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, "64000"); - ccard->interface.statcallb(&cmd); - break; - case N_DISC: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc\n", chan->No); - if (chan->e.B2Id) { - skb_queue_purge(&chan->e.X); - idi_do_req(ccard, chan, N_DISC_ACK, 1); - idi_do_req(ccard, chan, REMOVE, 1); - } -#ifdef CONFIG_ISDN_TTY_FAX - if ((chan->l2prot == ISDN_PROTO_L2_FAX) && (chan->fax)){ - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - idi_fax_hangup(ccard, chan); - } -#endif - chan->e.IndCh = 0; - chan->queued = 0; - chan->pqueued = 0; - chan->waitq = 0; - chan->waitpq = 0; - if (!(chan->statectrl & IN_HOLD)) { - 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; - if (!(chan->statectrl & IN_HOLD)) { - chan->statectrl |= WAITING_FOR_HANGUP; - } - } -#ifdef CONFIG_ISDN_TTY_FAX - chan->fax = 0; -#endif - break; - case N_DISC_ACK: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc_Ack\n", chan->No); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - idi_fax_hangup(ccard, chan); - } -#endif - break; - case N_DATA_ACK: - eicon_log(ccard, 128, "idi_ind: Ch%d: N_Data_Ack\n", chan->No); - break; - case N_DATA: - skb_pull(skb, sizeof(eicon_IND) - 1); - eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); - if (chan->l2prot == ISDN_PROTO_L2_FAX) { -#ifdef CONFIG_ISDN_TTY_FAX - idi_faxdata_rcv(ccard, chan, skb); -#endif - } else { - ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); - free_buff = 0; - } - break; - case N_UDATA: - idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - break; -#ifdef CONFIG_ISDN_TTY_FAX - case N_EDATA: - idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - break; -#endif - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); - } - } - else { - eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); - } - if (free_buff) - dev_kfree_skb(skb); -} - -static int -idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) -{ - isdn_ctrl cmd; - int tqueued = 0; - int twaitpq = 0; - - if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) { - /* I don't know why this happens, should not ! */ - /* just ignoring this RC */ - eicon_log(ccard, 16, "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 1; - } - - /* Management Interface */ - if (chan->No == ccard->nchannels) { - /* Managementinterface: changing state */ - if (chan->e.Req != 0x02) - chan->fsm_state = 1; - } - - /* Remove an Id */ - if (chan->e.Req == REMOVE) { - if (ack->Reference != chan->e.ref) { - /* This should not happen anymore */ - eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, - ack->Reference, chan->e.ref); - } - ccard->IdTable[ack->RcId] = NULL; - if (!chan->e.ReqCh) - chan->e.D3Id = 0; - else - chan->e.B2Id = 0; - eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, - ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); - return 1; - } - - /* Signal layer */ - if (!chan->e.ReqCh) { - 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); - } else { - /* Network layer */ - switch(chan->e.Req & 0x0f) { - case 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 N_MDATA: - case N_DATA: - tqueued = chan->queued; - twaitpq = chan->waitpq; - if ((chan->e.Req & 0x0f) == N_DATA) { - chan->waitpq = 0; - if(chan->pqueued) - chan->pqueued--; -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if (((chan->queued - chan->waitq) < 1) && - (chan->fax2.Eop)) { - chan->fax2.Eop = 0; - if (chan->fax) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_SENT; - ccard->interface.statcallb(&cmd); - } - else { - eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n"); - } - } - } -#endif - } - chan->queued -= chan->waitq; - if (chan->queued < 0) chan->queued = 0; - if (((chan->e.Req & 0x0f) == N_DATA) && (tqueued)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BSENT; - cmd.arg = chan->No; - cmd.parm.length = twaitpq; - ccard->interface.statcallb(&cmd); - } - break; - default: - 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); - } - } - return 1; -} - -void -idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) -{ - int j; - eicon_RC *ack = (eicon_RC *)skb->data; - eicon_chan *chan; - isdn_ctrl cmd; - int dCh = -1; - - if (!ccard) { - eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n"); - dev_kfree_skb(skb); - return; - } - - if ((chan = ccard->IdTable[ack->RcId]) != NULL) - dCh = chan->No; - - switch (ack->Rc) { - case OK_FC: - case N_FLOW_CONTROL: - case ASSIGN_RC: - eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n", - dCh, ack->Rc); - break; - case READY_INT: - case TIMER_INT: - /* we do nothing here */ - break; - - case OK: - if (!chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh); - break; - } - if (!idi_handle_ack_ok(ccard, chan, ack)) - chan = NULL; - break; - - case ASSIGN_OK: - if (chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", - chan->No, chan->e.D3Id, chan->e.B2Id); - } - for(j = 0; j < ccard->nchannels + 1; j++) { - if ((ccard->bch[j].e.ref == ack->Reference) && - (ccard->bch[j].e.Req == ASSIGN)) { - if (!ccard->bch[j].e.ReqCh) - ccard->bch[j].e.D3Id = ack->RcId; - else - ccard->bch[j].e.B2Id = ack->RcId; - ccard->IdTable[ack->RcId] = &ccard->bch[j]; - chan = &ccard->bch[j]; - break; - } - } - eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, - ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); - if (j > ccard->nchannels) { - eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", - ack->Reference, ack->RcId); - } - break; - - case OUT_OF_RESOURCES: - case UNKNOWN_COMMAND: - case WRONG_COMMAND: - case WRONG_ID: - case 0x08: /* ADAPTER_DEAD */ - case WRONG_CH: - case UNKNOWN_IE: - case WRONG_IE: - default: - if (!chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh); - break; - } else - switch (chan->e.Req) { - case 12: /* Alert */ - eicon_log(ccard, 2, "idi_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n", - dCh, ack->Rc, ack->RcId, ack->RcCh); - break; - default: - if (dCh != ccard->nchannels) - eicon_log(ccard, 1, "idi_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, "idi_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 */ - idi_hangup(ccard, chan); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - } - } - if (chan) { - chan->e.ref = 0; - chan->e.busy = 0; - } - dev_kfree_skb(skb); -} - -int -idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk) -{ - struct sk_buff *xmit_skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - int len, plen = 0, offset = 0; - - if ((!card) || (!chan)) { - eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n"); - return -1; - } - - if (chan->fsm_state != EICON_STATE_ACTIVE) { - eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - - len = skb->len; - if (len > EICON_MAX_QUEUE) /* too much for the shared memory */ - return -1; - if (!len) - return 0; - - if ((chk) && (chan->pqueued > 1)) - return 0; - - eicon_log(card, 128, "idi_snd: Ch%d: %d bytes (Pqueue=%d)\n", - chan->No, len, chan->pqueued); - while(offset < len) { - - plen = ((len - offset) > 270) ? 270 : len - offset; - - xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!xmit_skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); - if (xmit_skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ)); - if ((len - offset) > 270) { - reqbuf->Req = N_MDATA; - } else { - reqbuf->Req = N_DATA; - /* if (ack) reqbuf->Req |= N_D_BIT; */ - } - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen); - reqbuf->XBuffer.length = plen; - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, xmit_skb); - skb_queue_tail(&card->sndq, skb2); - - offset += plen; - } - if (que) { - chan->queued += len; - chan->pqueued++; - } - eicon_tx_request(card); - dev_kfree_skb(skb); - return len; -} - - -static int -eicon_idi_manage_assign(eicon_card *card) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan *chan; - eicon_chan_ptr *chan2; - - chan = &(card->bch[card->nchannels]); - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n"); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - - reqbuf->XBuffer.P[0] = 0; - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = MAN_ID; - reqbuf->XBuffer.length = 1; - reqbuf->Reference = 2; /* Man Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_tx_request(card); - return(0); -} - -int -eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) -{ - int l = 0; - int ret = 0; - int timeout; - int i; - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan *chan; - eicon_chan_ptr *chan2; - - chan = &(card->bch[card->nchannels]); - - if (!(chan->e.D3Id)) { - chan->e.D3Id = 1; - skb_queue_purge(&chan->e.X); - chan->e.busy = 0; - - if ((ret = eicon_idi_manage_assign(card))) { - chan->e.D3Id = 0; - return(ret); - } - - timeout = jiffies + 50; - while (time_before(jiffies, timeout)) { - 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"); - return -ENOMEM; - } - if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) { - kfree(manbuf); - return -EFAULT; - } - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n"); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - kfree(manbuf); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - - reqbuf->XBuffer.P[l++] = ESC; - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = 0x80; - for (i = 0; i < manbuf->length[0]; i++) - reqbuf->XBuffer.P[l++] = manbuf->data[i]; - reqbuf->XBuffer.P[1] = manbuf->length[0] + 1; - - reqbuf->XBuffer.P[l++] = 0; - reqbuf->Req = (manbuf->count) ? manbuf->count : MAN_READ; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 2; /* Man Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - - manbuf->count = 0; - manbuf->pos = 0; - - eicon_tx_request(card); - - timeout = jiffies + 50; - while (time_before(jiffies, timeout)) { - if (chan->fsm_state) break; - SLEEP(10); - } - if ((!chan->fsm_state) || (chan->fsm_state == 2)) { - kfree(manbuf); - return -EIO; - } - if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) { - kfree(manbuf); - return -EFAULT; - } - - kfree(manbuf); - return(0); -} diff --git a/drivers/isdn/hardware/eicon/i4l_idi.h b/drivers/isdn/hardware/eicon/i4l_idi.h deleted file mode 100644 index 196888e87dbb..000000000000 --- a/drivers/isdn/hardware/eicon/i4l_idi.h +++ /dev/null @@ -1,381 +0,0 @@ -/* $Id: i4l_idi.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ - * - * ISDN interface module for Eicon active cards. - * I4L - IDI Interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999-2002 Cytronics & Melware (info@melware.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef E_IDI_H -#define E_IDI_H - -#include <linux/config.h> - -#undef N_DATA -#undef ID_MASK - -#include "pc.h" - -#define AOC_IND 26 /* Advice of Charge */ -#define PI 0x1e /* Progress Indicator */ -#define NI 0x27 /* Notification Indicator */ - -/* defines for statectrl */ -#define WAITING_FOR_HANGUP 0x01 -#define HAVE_CONN_REQ 0x02 -#define IN_HOLD 0x04 - -typedef struct { - char cpn[32]; - char oad[32]; - char dsa[32]; - char osa[32]; - __u8 plan; - __u8 screen; - __u8 sin[4]; - __u8 chi[4]; - __u8 e_chi[4]; - __u8 bc[12]; - __u8 e_bc[12]; - __u8 llc[18]; - __u8 hlc[5]; - __u8 cau[4]; - __u8 e_cau[2]; - __u8 e_mt; - __u8 dt[6]; - char display[83]; - char keypad[35]; - char rdn[32]; -} idi_ind_message; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Req __attribute__ ((packed)); - __u8 ReqId __attribute__ ((packed)); - __u8 ReqCh __attribute__ ((packed)); - __u8 Reserved1 __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 Reserved[8] __attribute__ ((packed)); - eicon_PBUFFER XBuffer; -} eicon_REQ; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Rc __attribute__ ((packed)); - __u8 RcId __attribute__ ((packed)); - __u8 RcCh __attribute__ ((packed)); - __u8 Reserved1 __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 Reserved2[8] __attribute__ ((packed)); -} eicon_RC; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Ind __attribute__ ((packed)); - __u8 IndId __attribute__ ((packed)); - __u8 IndCh __attribute__ ((packed)); - __u8 MInd __attribute__ ((packed)); - __u16 MLength __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 RNR __attribute__ ((packed)); - __u8 Reserved __attribute__ ((packed)); - __u32 Ack __attribute__ ((packed)); - eicon_PBUFFER RBuffer; -} eicon_IND; - -typedef struct { - __u8 *Data; - unsigned int Size; - unsigned int Len; - __u8 *Next; -} eicon_OBJBUFFER; - -extern int idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer); -extern int idi_hangup(eicon_card *card, eicon_chan *chan); -extern int idi_connect_res(eicon_card *card, eicon_chan *chan); -extern int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan); -extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, - char *eazmsn, int si1, int si2); - -extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb); -extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb); -extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb); -extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk); -extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value); -extern int capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm); -#ifdef CONFIG_ISDN_TTY_FAX -extern void idi_fax_cmd(eicon_card *card, eicon_chan *chan); -extern int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb); -#endif - -#include "dsp_defs.h" - -#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1 -/* -parameters: - <byte> transmit framer type - <byte> receive framer type -*/ - -#define DSP_REQUEST_SWITCH_FRAMER_HDLC 0 -#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT 1 -#define DSP_REQUEST_SWITCH_FRAMER_ASYNC 2 - - -#define DSP_UDATA_REQUEST_CLEARDOWN 2 -/* -parameters: - - none - -*/ - - -#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON 3 -/* -parameters: - - none - -*/ - - -#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF 4 -/* -parameters: - - none - -*/ - -typedef struct eicon_dsp_ind { - __u16 time __attribute__ ((packed)); - __u8 norm __attribute__ ((packed)); - __u16 options __attribute__ ((packed)); - __u32 speed __attribute__ ((packed)); - __u16 delay __attribute__ ((packed)); - __u32 txspeed __attribute__ ((packed)); - __u32 rxspeed __attribute__ ((packed)); -} eicon_dsp_ind; - -#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002 -#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004 -#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008 -#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010 - -#define DSP_UDATA_INDICATION_DISCONNECT 5 -/* -returns: - <byte> cause -*/ - -#define DSP_DISCONNECT_CAUSE_NONE 0x00 -#define DSP_DISCONNECT_CAUSE_BUSY_TONE 0x01 -#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE 0x02 -#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY 0x03 -#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04 -#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05 - -#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6 -/* -returns: - <word> confirmation number -*/ - - -#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS 16 -/* -parameters: - <word> tone duration (ms) - <word> gap duration (ms) - <byte> digit 0 tone code - ... - <byte> digit n tone code -*/ - -#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH 5 - -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ 0x00 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ 0x01 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ 0x02 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ 0x03 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK 0x03 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ 0x00 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ 0x04 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ 0x08 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ 0x0c -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK 0x0c - -#define DSP_DTMF_DIGIT_TONE_CODE_0 0x07 -#define DSP_DTMF_DIGIT_TONE_CODE_1 0x00 -#define DSP_DTMF_DIGIT_TONE_CODE_2 0x04 -#define DSP_DTMF_DIGIT_TONE_CODE_3 0x08 -#define DSP_DTMF_DIGIT_TONE_CODE_4 0x01 -#define DSP_DTMF_DIGIT_TONE_CODE_5 0x05 -#define DSP_DTMF_DIGIT_TONE_CODE_6 0x09 -#define DSP_DTMF_DIGIT_TONE_CODE_7 0x02 -#define DSP_DTMF_DIGIT_TONE_CODE_8 0x06 -#define DSP_DTMF_DIGIT_TONE_CODE_9 0x0a -#define DSP_DTMF_DIGIT_TONE_CODE_STAR 0x03 -#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK 0x0b -#define DSP_DTMF_DIGIT_TONE_CODE_A 0x0c -#define DSP_DTMF_DIGIT_TONE_CODE_B 0x0d -#define DSP_DTMF_DIGIT_TONE_CODE_C 0x0e -#define DSP_DTMF_DIGIT_TONE_CODE_D 0x0f - - -#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT 16 -/* -returns: - - none - - One indication will be sent for every request. -*/ - - -#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER 17 -/* -parameters: - <word> tone duration (ms) - <word> gap duration (ms) -*/ -typedef struct enable_dtmf_s { - __u16 tone; - __u16 gap; -} enable_dtmf_s; - -#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18 -/* -parameters: - - none - -*/ - -#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17 -/* -returns: - <byte> digit 0 tone code - ... - <byte> digit n tone code -*/ - -#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH 1 - - -#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18 -/* -returns: - - none - -*/ - -#define DSP_UDATA_INDICATION_FAX_CALLING_TONE 19 -/* -returns: - - none - -*/ - -#define DSP_UDATA_INDICATION_ANSWER_TONE 20 -/* -returns: - - none - -*/ - -/* ============= FAX ================ */ - -#define EICON_FAXID_LEN 20 - -typedef struct eicon_t30_s { - __u8 code; - __u8 rate; - __u8 resolution; - __u8 format; - __u8 pages_low; - __u8 pages_high; - __u8 atf; - __u8 control_bits_low; - __u8 control_bits_high; - __u8 feature_bits_low; - __u8 feature_bits_high; - __u8 universal_5; - __u8 universal_6; - __u8 universal_7; - __u8 station_id_len; - __u8 head_line_len; - __u8 station_id[EICON_FAXID_LEN]; -/* __u8 head_line[]; */ -} eicon_t30_s; - - /* EDATA transmit messages */ -#define EDATA_T30_DIS 0x01 -#define EDATA_T30_FTT 0x02 -#define EDATA_T30_MCF 0x03 - - /* EDATA receive messages */ -#define EDATA_T30_DCS 0x81 -#define EDATA_T30_TRAIN_OK 0x82 -#define EDATA_T30_EOP 0x83 -#define EDATA_T30_MPS 0x84 -#define EDATA_T30_EOM 0x85 -#define EDATA_T30_DTC 0x86 - -#define T30_FORMAT_SFF 0 -#define T30_FORMAT_ASCII 1 -#define T30_FORMAT_COUNT 2 - -#define T30_CONTROL_BIT_DISABLE_FINE 0x0001 -#define T30_CONTROL_BIT_ENABLE_ECM 0x0002 -#define T30_CONTROL_BIT_ECM_64_BYTES 0x0004 -#define T30_CONTROL_BIT_ENABLE_2D_CODING 0x0008 -#define T30_CONTROL_BIT_ENABLE_T6_CODING 0x0010 -#define T30_CONTROL_BIT_ENABLE_UNCOMPR 0x0020 -#define T30_CONTROL_BIT_ACCEPT_POLLING 0x0040 -#define T30_CONTROL_BIT_REQUEST_POLLING 0x0080 -#define T30_CONTROL_BIT_MORE_DOCUMENTS 0x0100 - -#define T30_CONTROL_BIT_ALL_FEATURES\ - (T30_CONTROL_BIT_ENABLE_ECM | T30_CONTROL_BIT_ENABLE_2D_CODING |\ - T30_CONTROL_BIT_ENABLE_T6_CODING | T30_CONTROL_BIT_ENABLE_UNCOMPR) - -#define T30_FEATURE_BIT_FINE 0x0001 -#define T30_FEATURE_BIT_ECM 0x0002 -#define T30_FEATURE_BIT_ECM_64_BYTES 0x0004 -#define T30_FEATURE_BIT_2D_CODING 0x0008 -#define T30_FEATURE_BIT_T6_CODING 0x0010 -#define T30_FEATURE_BIT_UNCOMPR_ENABLED 0x0020 -#define T30_FEATURE_BIT_POLLING 0x0040 - -#define FAX_OBJECT_DOCU 1 -#define FAX_OBJECT_PAGE 2 -#define FAX_OBJECT_LINE 3 - -#define T4_EOL 0x800 -#define T4_EOL_BITSIZE 12 -#define T4_EOL_DWORD (T4_EOL << (32 - T4_EOL_BITSIZE)) -#define T4_EOL_MASK_DWORD ((__u32) -1 << (32 - T4_EOL_BITSIZE)) - -#define SFF_LEN_FLD_SIZE 3 - -#define _DLE_ 0x10 -#define _ETX_ 0x03 - -typedef struct eicon_sff_dochead { - __u32 id __attribute__ ((packed)); - __u8 version __attribute__ ((packed)); - __u8 reserved1 __attribute__ ((packed)); - __u16 userinfo __attribute__ ((packed)); - __u16 pagecount __attribute__ ((packed)); - __u16 off1pagehead __attribute__ ((packed)); - __u32 offnpagehead __attribute__ ((packed)); - __u32 offdocend __attribute__ ((packed)); -} eicon_sff_dochead; - -typedef struct eicon_sff_pagehead { - __u8 pageheadid __attribute__ ((packed)); - __u8 pageheadlen __attribute__ ((packed)); - __u8 resvert __attribute__ ((packed)); - __u8 reshoriz __attribute__ ((packed)); - __u8 coding __attribute__ ((packed)); - __u8 reserved2 __attribute__ ((packed)); - __u16 linelength __attribute__ ((packed)); - __u16 pagelength __attribute__ ((packed)); - __u32 offprevpage __attribute__ ((packed)); - __u32 offnextpage __attribute__ ((packed)); -} eicon_sff_pagehead; - -#endif /* E_IDI_H */ diff --git a/drivers/isdn/hardware/eicon/i4lididrv.c b/drivers/isdn/hardware/eicon/i4lididrv.c deleted file mode 100644 index 5eda595b7f2f..000000000000 --- a/drivers/isdn/hardware/eicon/i4lididrv.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* $Id: i4lididrv.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ - * - * ISDN interface module for Eicon active cards. - * I4L - IDI Interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999-2002 Cytronics & Melware (info@melware.de) - * - * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH - * for sponsoring and testing fax - * capabilities with Diva Server cards. - * (dor@deutschemailbox.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/proc_fs.h> -#include <linux/vmalloc.h> - -#include "i4lididrv.h" -#include <linux/smp_lock.h> -#include "divasync.h" - -#include "../avmb1/capicmd.h" /* this should be moved in a common place */ - -#define INCLUDE_INLINE_FUNCS - -static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains - start of card-list */ - -static char *DRIVERNAME = "Eicon Diva - native I4L Interface driver (http://www.melware.net)"; -static char *DRIVERLNAME = "diva2i4l"; -static char *DRIVERRELEASE = "2.0"; -static char *eicon_revision = "$Revision: 1.1.2.2 $"; -extern char *eicon_idi_revision; - -#define EICON_CTRL_VERSION 2 - -ulong DebugVar; - -static spinlock_t status_lock; -static spinlock_t ll_lock; - -#define MAX_DESCRIPTORS 32 -extern void DIVA_DIDD_Read(DESCRIPTOR *, int); - -static dword notify_handle; -static DESCRIPTOR DAdapter; -static DESCRIPTOR MAdapter; - -/* Parameter to be set by insmod */ -static char *id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -static int debug = 1; - -MODULE_DESCRIPTION( "ISDN4Linux Interface for Eicon active card driver"); -MODULE_AUTHOR( "Armin Schindler"); -MODULE_SUPPORTED_DEVICE( "ISDN subsystem and Eicon active card driver"); -MODULE_PARM_DESC(id, "ID-String for ISDN4Linux"); -MODULE_PARM(id, "s"); -MODULE_PARM_DESC(debug, "Initial debug value"); -MODULE_PARM(debug, "i"); -MODULE_LICENSE("GPL"); - -void no_printf (unsigned char * x ,...) -{ - /* dummy debug function */ -} -DIVA_DI_PRINTF dprintf = no_printf; - -#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) -#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) -#include "debuglib.c" - -static char * -eicon_getrev(const char *revision) -{ - char *rev; - char *p; - if ((p = strchr(revision, ':'))) { - rev = p + 2; - p = strchr(rev, '$'); - *--p = 0; - } else rev = "1.0"; - return rev; - -} - -static void -stop_dbg(void) -{ - DbgDeregister(); - memset(&MAdapter, 0, sizeof(MAdapter)); - dprintf = no_printf; -} - -static eicon_chan * -find_channel(eicon_card *card, int channel) -{ - if ((channel >= 0) && (channel < card->nchannels)) - return &(card->bch[channel]); - eicon_log(card, 1, "%s: Invalid channel %d\n", DRIVERLNAME, channel); - return NULL; -} - -static void -eicon_rx_request(struct eicon_card *card) -{ - struct sk_buff *skb, *skb2, *skb_new; - eicon_IND *ind, *ind2, *ind_new; - eicon_chan *chan; - - if (!card) { - eicon_log(card, 1, "%s: NULL card in rcv_dispatch !\n", DRIVERLNAME); - return; - } - - while((skb = skb_dequeue(&card->rcvq))) { - ind = (eicon_IND *)skb->data; - - if ((chan = card->IdTable[ind->IndId]) == NULL) { - if (DebugVar & 1) { - switch(ind->Ind) { - case N_DISC_ACK: - /* doesn't matter if this happens */ - break; - default: - eicon_log(card, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); - eicon_log(card, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", - ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); - } - } - dev_kfree_skb(skb); - continue; - } - - if (chan->e.complete) { /* check for rec-buffer chaining */ - if (ind->MLength == ind->RBuffer.length) { - chan->e.complete = 1; - idi_handle_ind(card, skb); - continue; - } - else { - chan->e.complete = 0; - ind->Ind = ind->MInd; - skb_queue_tail(&chan->e.R, skb); - continue; - } - } - else { - if (!(skb2 = skb_dequeue(&chan->e.R))) { - chan->e.complete = 1; - eicon_log(card, 1, "%s: buffer incomplete, but 0 in queue\n", DRIVERLNAME); - dev_kfree_skb(skb); - continue; - } - ind2 = (eicon_IND *)skb2->data; - skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length), - GFP_ATOMIC); - if (!skb_new) { - eicon_log(card, 1, "%s: skb_alloc failed in rcv_dispatch()\n", DRIVERLNAME); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - continue; - } - ind_new = (eicon_IND *)skb_put(skb_new, - ((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length)); - ind_new->Ind = ind2->Ind; - ind_new->IndId = ind2->IndId; - ind_new->IndCh = ind2->IndCh; - ind_new->MInd = ind2->MInd; - ind_new->MLength = ind2->MLength; - ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length; - memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length); - memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - if (ind->MLength == ind->RBuffer.length) { - chan->e.complete = 2; - idi_handle_ind(card, skb_new); - continue; - } - else { - chan->e.complete = 0; - skb_queue_tail(&chan->e.R, skb_new); - continue; - } - } - } -} - -static void -eicon_ack_request(struct eicon_card *card) -{ - struct sk_buff *skb; - - if (!card) { - eicon_log(card, 1, "%s: NULL card in ack_dispatch!\n", DRIVERLNAME); - return; - } - while((skb = skb_dequeue(&card->rackq))) { - idi_handle_ack(card, skb); - } -} - -/* - * IDI-Callback function - */ -static void -eicon_idi_callback(ENTITY *de) -{ - eicon_card *ccard = (eicon_card *)de->R; - struct sk_buff *skb; - eicon_RC *ack; - eicon_IND *ind; - int len = 0; - - if (de->complete == 255) { - /* Return Code */ - skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "%s: skb_alloc failed in _idi_callback()\n", DRIVERLNAME); - } else { - ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); - ack->Rc = de->Rc; - if (de->Rc == ASSIGN_OK) { - ack->RcId = de->Id; - de->user[1] = de->Id; - } else { - ack->RcId = de->user[1]; - } - ack->RcCh = de->RcCh; - ack->Reference = de->user[0]; - skb_queue_tail(&ccard->rackq, skb); - eicon_ack_request(ccard); - eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n", - de->user[0], de->Rc, ack->RcId, de->RLength, de->complete); - DBG_TRC(("idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x", - de->user[0], de->Rc, ack->RcId, de->RLength, de->complete)) - de->Rc = 0; - } - } else { - /* Indication */ - if (de->complete) { - len = de->RLength; - } else { - len = 270; - if (de->RLength <= 270) - eicon_log(ccard, 1, "idi_cbk: ind not complete but <= 270\n"); - } - skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "%s: skb_alloc failed in _idi_callback()\n", DRIVERLNAME); - } else { - ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); - ind->Ind = de->Ind; - ind->IndId = de->user[1]; - ind->IndCh = de->IndCh; - ind->MInd = de->Ind; - ind->RBuffer.length = len; - ind->MLength = de->RLength; - memcpy(&ind->RBuffer.P, &de->RBuffer->P, len); - skb_queue_tail(&ccard->rcvq, skb); - eicon_rx_request(ccard); - eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n", - de->user[0], de->Ind, ind->IndId, de->RLength, de->complete); - DBG_TRC(("idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x", - de->user[0], de->Ind, ind->IndId, de->RLength, de->complete)) - de->Ind = 0; - } - } - de->RNum = 0; - de->RNR = 0; - eicon_tx_request(ccard); -} - -/* -** Kernel thread to prevent in_interrupt -*/ -static DECLARE_TASK_QUEUE(tq_divad); -static struct semaphore diva_thread_sem; -static struct semaphore diva_thread_end; -static int divad_pid = -1; -static int divad_thread(void * data); -static void diva_tx(void *data); -static atomic_t thread_running; - -static void __init -diva_init_thread(void) -{ - int pid = 0; - - pid = kernel_thread(divad_thread, NULL, CLONE_KERNEL); - if (pid >= 0) { - divad_pid = pid; - } -} - -static int -divad_thread(void * data) -{ - atomic_inc(&thread_running); - if (atomic_read(&thread_running) > 1) { - printk(KERN_WARNING"%s: thread already running\n", DRIVERLNAME); - return(0); - } - - printk(KERN_INFO "%s: thread started with pid %d\n", DRIVERLNAME, current->pid); - exit_mm(current); - exit_files(current); - exit_fs(current); - - /* Set to RealTime */ - current->policy = SCHED_FIFO; - current->rt_priority = 33; - - strcpy(current->comm, "kdiva2i4ld"); - - for(;;) { - down_interruptible(&diva_thread_sem); - if(!(atomic_read(&thread_running))) - break; - if(signal_pending(current)) { - flush_signals(current); - } else { - run_task_queue(&tq_divad); - } - } - up(&diva_thread_end); - divad_pid = -1; - return 0; -} - -static void -stop_diva_thread(void) -{ - if (divad_pid >= 0) { - atomic_set(&thread_running, 0); - up(&diva_thread_sem); - down_interruptible(&diva_thread_end); - } -} - -void -eicon_tx_request(struct eicon_card *card) -{ - card->tq.routine = diva_tx; - card->tq.data = (void *)card; - queue_task(&card->tq, &tq_divad); - up(&diva_thread_sem); -} - -static void -diva_tx(void *data) -{ - struct eicon_card *card = (eicon_card *) data; - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_chan *chan; - eicon_chan_ptr *chan2; - eicon_REQ *reqbuf = 0; - int ReqCount = 0; - int tmpid = 0; - int quloop = 1; - int dlev = 0; - ENTITY *ep = 0; - - if (!card) { - eicon_log(card, 1, "%s: NULL card in transmit !\n", DRIVERLNAME); - return; - } - - ReqCount = 0; - if (!(skb2 = skb_dequeue(&card->sndq))) - quloop = 0; - while(quloop) { - chan2 = (eicon_chan_ptr *)skb2->data; - chan = chan2->ptr; - if (!chan->e.busy) { - if((skb = skb_dequeue(&chan->e.X))) { - - reqbuf = (eicon_REQ *)skb->data; - if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) { - eicon_log(card, 16, "%s: transmit: error Id=0 on %d (Net)\n", DRIVERLNAME, chan->No); - } else { - dlev = 160; - if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */ - - if (!reqbuf->Reference) { /* Signal Layer */ - ep = &chan->de; - tmpid = chan->e.D3Id; - chan->e.ReqCh = 0; - } - else { /* Net Layer */ - ep = &chan->be; - tmpid = chan->e.B2Id; - chan->e.ReqCh = 1; - if (((reqbuf->Req & 0x0f) == 0x08) || - ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */ - chan->waitq = reqbuf->XBuffer.length; - chan->waitpq += reqbuf->XBuffer.length; - dlev = 128; - } - } - - } else { /* It is an ASSIGN */ - if (!reqbuf->Reference) - ep = &chan->de; - else - ep = &chan->be; - ep->Id = reqbuf->ReqId; - tmpid = reqbuf->ReqId; - - if (!reqbuf->Reference) - chan->e.ReqCh = 0; - else - chan->e.ReqCh = 1; - } - - chan->e.ref = chan->No; - chan->e.Req = reqbuf->Req; - ReqCount++; - if (ep) { - ep->callback = eicon_idi_callback; - ep->R = (BUFFERS *)card; - ep->user[0] = (word)chan->No; - ep->user[1] = (word)tmpid; - ep->XNum = 1; - ep->RNum = 0; - ep->RNR = 0; - ep->Rc = 0; - ep->Ind = 0; - ep->X->PLength = reqbuf->XBuffer.length; - memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length); - ep->ReqCh = reqbuf->ReqCh; - ep->Req = reqbuf->Req; - } - chan->e.busy = 1; - eicon_log(card, dlev, "idi: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", - reqbuf->Req, tmpid, - reqbuf->ReqCh, reqbuf->XBuffer.length, - chan->e.ref); - if (ep) { - card->d.request(ep); - if (ep->Rc) - eicon_idi_callback(ep); - } - } - dev_kfree_skb(skb); - } - dev_kfree_skb(skb2); - } - else { - skb_queue_tail(&card->sackq, skb2); - eicon_log(card, 128, "%s: transmit: busy chan %d\n", DRIVERLNAME, chan->No); - } - if (!(skb2 = skb_dequeue(&card->sndq))) - quloop = 0; - } - while((skb = skb_dequeue(&card->sackq))) { - skb_queue_tail(&card->sndq, skb); - } -} - -static int -eicon_command(eicon_card * card, isdn_ctrl * c) -{ - ulong a; - eicon_chan *chan; - isdn_ctrl cmd; - int ret = 0; - - eicon_log(card, 16, "%s_cmd 0x%x with arg 0x%lx (0x%lx)\n", DRIVERLNAME, - c->command, c->arg, (ulong) *c->parm.num); - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - switch (c->arg) { - case EICON_IOCTL_GETVER: - return(EICON_CTRL_VERSION); - case EICON_IOCTL_MANIF: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!card->d.features & DI_MANAGE) - return -ENODEV; - ret = eicon_idi_manage( - card, - (eicon_manifbuf *)a); - return ret; - - case EICON_IOCTL_GETXLOG: - return -ENODEV; - case EICON_IOCTL_DEBUGVAR: - DebugVar = a; - eicon_log(card, 1, "%s: Debug Value set to %ld\n", DRIVERLNAME, DebugVar); - return 0; - case EICON_IOCTL_LOADPCI: - eicon_log(card, 1, "%s: Wrong version of load-utility,\n", DRIVERLNAME); - eicon_log(card, 1, "%s: re-compile eiconctrl !\n", DRIVERLNAME); - eicon_log(card, 1, "%s: Maybe update of utility is necessary !\n", DRIVERLNAME); - return -EINVAL; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { - eicon_log(card, 1, "%s: Dial on channel %d with state %d\n", DRIVERLNAME, - chan->No, chan->fsm_state); - return -EBUSY; - } - chan->fsm_state = EICON_STATE_OCALL; - - ret = idi_connect_req(card, chan, c->parm.setup.phone, - c->parm.setup.eazmsn, - c->parm.setup.si1, - c->parm.setup.si2); - if (ret) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg &= 0x1f; - card->interface.statcallb(&cmd); - } - return ret; - case ISDN_CMD_ACCEPTD: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (chan->fsm_state == EICON_STATE_ICALL) { - idi_connect_res(card, chan); - } - return 0; - case ISDN_CMD_ACCEPTB: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - return 0; - case ISDN_CMD_HANGUP: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - idi_hangup(card, chan); - return 0; - case ISDN_CMD_SETEAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->eazmask = 0x3ff; - eicon_idi_listen_req(card, chan); - return 0; - case ISDN_CMD_CLREAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->eazmask = 0; - eicon_idi_listen_req(card, chan); - return 0; - case ISDN_CMD_SETL2: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->l2prot = (c->arg >> 8); - memcpy(chan->a_para, c->parm.aux.para, sizeof(chan->a_para)); - return 0; - case ISDN_CMD_SETL3: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->l3prot = (c->arg >> 8); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) { - chan->fax = c->parm.fax; - eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax); - } -#endif - return 0; -#ifdef CONFIG_ISDN_TTY_FAX - case ISDN_CMD_FAXCMD: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (!chan->fax) - break; - idi_fax_cmd(card, chan); - return 0; -#endif - case ISDN_CMD_AUDIO: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num); - return 0; - case CAPI_PUT_MESSAGE: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (c->parm.cmsg.Length < 8) - break; - switch(c->parm.cmsg.Command) { - case CAPI_FACILITY: - if (c->parm.cmsg.Subcommand == CAPI_REQ) - return(capipmsg(card, chan, &c->parm.cmsg)); - break; - case CAPI_MANUFACTURER: - default: - break; - } - return 0; - } - - return -EINVAL; -} - -static int -find_free_number(void) -{ - int num = 0; - char cid[40]; - eicon_card *p; - ulong flags; - - spin_lock_irqsave(&ll_lock, flags); - while(num < 100) { - sprintf(cid, "%s%d", id, num); - num++; - p = cards; - while (p) { - if (!strcmp(p->regname, cid)) - break; - p = p->next; - } - if (p) - { - spin_unlock_irqrestore(&ll_lock, flags); - return(num - 1); - } - } - spin_unlock_irqrestore(&ll_lock, flags); - return(999); -} - -/* - * Find card with given driverId - */ -static inline eicon_card * -eicon_findcard(int driverid) -{ - eicon_card *p; - ulong flags; - - spin_lock_irqsave(&ll_lock, flags); - p = cards; - while (p) { - if (p->myid == driverid) { - spin_unlock_irqrestore(&ll_lock, flags); - return p; - } - p = p->next; - } - spin_unlock_irqrestore(&ll_lock, flags); - return (eicon_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl * c) -{ - eicon_card *card = eicon_findcard(c->driver); - - if (card) - return (eicon_command(card, c)); - printk(KERN_ERR - "%s: if_command %d called with invalid driverId %d!\n", DRIVERLNAME, - c->command, c->driver); - return -ENODEV; -} - -static int -if_writecmd(const u_char * buf, int len, int user, int id, int channel) -{ - /* Not used */ - return (len); -} - -static int -if_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - int count = 0; - int cnt = 0; - u_char *p = buf; - struct sk_buff *skb; - ulong flags; - - eicon_card *card = eicon_findcard(id); - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - - spin_lock_irqsave(&status_lock, flags); - while((skb = skb_dequeue(&card->statq))) { - - if ((skb->len + count) > len) - cnt = len - count; - else - cnt = skb->len; - - if (user) - copy_to_user(p, skb->data, cnt); - else - memcpy(p, skb->data, cnt); - - count += cnt; - p += cnt; - - if (cnt == skb->len) { - dev_kfree_skb(skb); - if (card->statq_entries > 0) - card->statq_entries--; - } else { - skb_pull(skb, cnt); - skb_queue_head(&card->statq, skb); - spin_unlock_irqrestore(&status_lock, flags); - return count; - } - } - card->statq_entries = 0; - spin_unlock_irqrestore(&status_lock, flags); - return count; - } - printk(KERN_ERR - "%s: if_readstatus called with invalid driverId!\n", DRIVERLNAME); - return 0; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - eicon_card *card = eicon_findcard(id); - eicon_chan *chan; - int ret = 0; - int len; - - len = skb->len; - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, channel))) - return -ENODEV; - - if (chan->fsm_state == EICON_STATE_ACTIVE) { -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if ((ret = idi_faxdata_send(card, chan, skb)) > 0) - ret = len; - } - else -#endif - ret = idi_send_data(card, chan, ack, skb, 1, 1); - return (ret); - } else { - return -ENODEV; - } - } - printk(KERN_ERR - "%s: if_sendbuf called with invalid driverId!\n", DRIVERLNAME); - return -ENODEV; -} - -/* jiftime() copied from HiSax */ -static inline int jiftime(char *s, long mark) -{ - s += 8; - - *s-- = '\0'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = '.'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 6 + '0'; - mark /= 6; - *s-- = ':'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; - return(8); -} - -void -eicon_putstatus(eicon_card * card, char * buf) -{ - int count; - isdn_ctrl cmd; - u_char *p; - struct sk_buff *skb; - ulong flags; - - if (!card) { - if (!(card = cards)) - return; - } - - spin_lock_irqsave(&status_lock, flags); - count = strlen(buf); - skb = alloc_skb(count, GFP_ATOMIC); - if (!skb) { - spin_unlock_irqrestore(&status_lock, flags); - printk(KERN_ERR "%s: could not alloc skb in putstatus\n", DRIVERLNAME); - return; - } - p = skb_put(skb, count); - memcpy(p, buf, count); - - skb_queue_tail(&card->statq, skb); - - if (card->statq_entries >= MAX_STATUS_BUFFER) { - if ((skb = skb_dequeue(&card->statq))) { - count -= skb->len; - dev_kfree_skb(skb); - } else - count = 0; - } else - card->statq_entries++; - - spin_unlock_irqrestore(&status_lock, flags); - if (count) { - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = count; - card->interface.statcallb(&cmd); - } -} - -/* - * Debug and Log - */ -void -eicon_log(eicon_card * card, int level, const char *fmt, ...) -{ - va_list args; - char Line[160]; - u_char *p; - - - if ((DebugVar & level) || (DebugVar & 256)) { - va_start(args, fmt); - - if (DebugVar & level) { - if (DebugVar & 256) { - /* log-buffer */ - p = Line; - p += jiftime(p, jiffies); - *p++ = 32; - p += vsprintf(p, fmt, args); - *p = 0; - eicon_putstatus(card, Line); - } else { - /* printk, syslogd */ - vsprintf(Line, fmt, args); - printk(KERN_DEBUG "%s", Line); - } - } - - va_end(args); - } -} - - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list. - */ -static void -eicon_alloccard(DESCRIPTOR *d) -{ - int j; - char cid[40]; - eicon_card *card; - ulong flags; - - sprintf(cid, "%s%d", id, find_free_number()); - if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { - eicon_log(card, 1, - "%s: (%s) Could not allocate card-struct.\n", DRIVERLNAME, cid); - return; - } - memset((char *) card, 0, sizeof(eicon_card)); - skb_queue_head_init(&card->sndq); - skb_queue_head_init(&card->rcvq); - skb_queue_head_init(&card->rackq); - skb_queue_head_init(&card->sackq); - skb_queue_head_init(&card->statq); - card->statq_entries = 0; - card->interface.owner = THIS_MODULE; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = - ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L2_TRANS | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_L3_TRANSDSP | - ISDN_FEATURE_P_UNKNOWN; - card->interface.hl_hdrlen = 20; - card->ptype = ISDN_PTYPE_UNKNOWN; - strcpy(card->interface.id, cid); - card->myid = -1; - card->type = d->type; - - if (d->features & (DI_FAX3 | DI_EXTD_FAX)) - card->interface.features |= (ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_FCLASS2); - if (d->features & DI_MODEM) - card->interface.features |= ISDN_FEATURE_L2_MODEM; - if (d->features & DI_V110) - card->interface.features |= (ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038); - - card->flags = 0; - card->nchannels = d->channels; - card->interface.channels = d->channels; - if (!(card->bch = (eicon_chan *) vmalloc(sizeof(eicon_chan) * (card->nchannels + 1)))) { - eicon_log(card, 1, - "%s: (%s) Could not allocate bch-struct.\n", DRIVERLNAME, cid); - kfree(card); - return; - } - for (j=0; j< (card->nchannels + 1); j++) { - memset((char *)&card->bch[j], 0, sizeof(eicon_chan)); - card->bch[j].statectrl = 0; - card->bch[j].l2prot = ISDN_PROTO_L2_X75I; - card->bch[j].l3prot = ISDN_PROTO_L3_TRANS; - card->bch[j].e.D3Id = 0; - card->bch[j].e.B2Id = 0; - card->bch[j].e.Req = 0; - card->bch[j].No = j; - card->bch[j].tskb1 = NULL; - card->bch[j].tskb2 = NULL; - skb_queue_head_init(&card->bch[j].e.X); - skb_queue_head_init(&card->bch[j].e.R); - } - - if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2 - , GFP_KERNEL))) { - eicon_log(card, 1, - "%s: (%s) Could not allocate DBUFFER-struct.\n", DRIVERLNAME, cid); - kfree(card); - vfree(card->bch); - return; - } - if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) { - eicon_log(card, 1, - "%s: (%s) Could not allocate BUFFERS-struct.\n", DRIVERLNAME, cid); - kfree(card); - vfree(card->bch); - kfree(card->dbuf); - return; - } - if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) { - eicon_log(card, 1, - "%s: (%s) Could not allocate BUFFERSP-struct.\n", DRIVERLNAME, cid); - kfree(card); - vfree(card->bch); - kfree(card->dbuf); - kfree(card->sbuf); - return; - } - for (j=0; j< (card->nchannels + 1); j++) { - memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER)); - card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j]; - memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS)); - card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)]; - - memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS)); - card->bch[j].de.X = (BUFFERS *)&card->sbuf[j]; - memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS)); - card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)]; - - memset((char *)&card->sbufp[j], 0, 270); - card->bch[j].de.X->P = (char *)&card->sbufp[j * 270]; - memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270); - card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270]; - } - memcpy(&card->d, d, sizeof(*d)); /* DESCRIPTOR entries */ - - /* initializing some variables */ - card->lock = SPIN_LOCK_UNLOCKED; - card->ReadyInt = 0; - - for(j = 0; j < 256; j++) - card->IdTable[j] = NULL; - - for(j = 0; j < (card->d.channels + 1); j++) { - card->bch[j].e.busy = 0; - card->bch[j].e.D3Id = 0; - card->bch[j].e.B2Id = 0; - card->bch[j].e.ref = 0; - card->bch[j].e.Req = 0; - card->bch[j].e.complete = 1; - card->bch[j].fsm_state = EICON_STATE_NULL; - } - printk(KERN_INFO "%s: registered card '%s' with %d channels\n", - DRIVERLNAME, cid, d->channels); - - spin_lock_irqsave(&ll_lock, flags); - card->next = cards; - cards = card; - spin_unlock_irqrestore(&ll_lock, flags); -} - -/* - * register card at linklevel - */ -static int -eicon_registercard(eicon_card * card) -{ - isdn_ctrl cmd; - - if (!register_isdn(&card->interface)) { - printk(KERN_WARNING - "%s: Unable to register %s\n", DRIVERLNAME, - card->interface.id); - return -1; - } - card->myid = card->interface.channels; - sprintf(card->regname, "%s", card->interface.id); - - /* after register we start it */ - card->flags |= EICON_FLAGS_LOADED; - card->flags |= EICON_FLAGS_RUNNING; - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - - return 0; -} - -static void -unregister_card(eicon_card * card, int rme) -{ - int count; - int channel; - isdn_ctrl cmd; - eicon_chan *chan; - - if(rme) { - /* before unload we need to remove the signal entity */ - for(channel = 0; channel < card->nchannels; channel++) - { - chan = &(card->bch[channel]); - if (chan->e.D3Id) { - idi_do_req(card, chan, REMOVE, 0); - count = 100; - while(count--) { - if (!chan->e.D3Id) - break; - SLEEP(2); - } - if (!count) - printk(KERN_WARNING"%s: ch:%d unlink to diva module not successful !\n", - DRIVERLNAME, chan->No); - } - } - } - - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - DBG_TRC(("channel entities freed")); -} - -static void -eicon_freecard(eicon_card *card) { - int i; - - for(i = 0; i < (card->nchannels + 1); i++) { - skb_queue_purge(&card->bch[i].e.X); - skb_queue_purge(&card->bch[i].e.R); - } - skb_queue_purge(&card->sndq); - skb_queue_purge(&card->rcvq); - skb_queue_purge(&card->rackq); - skb_queue_purge(&card->sackq); - skb_queue_purge(&card->statq); - - kfree(card->sbufp); - kfree(card->sbuf); - kfree(card->dbuf); - vfree(card->bch); - kfree(card); - DBG_TRC(("card structures freed")); -} - -static int -eicon_addcard(DESCRIPTOR *d) -{ - eicon_card *p; - eicon_card *q = NULL; - int registered; - int added = 0; - int failed = 0; - ulong flags; - - eicon_alloccard(d); - p = cards; - while (p) { - registered = 0; - if (!p->interface.statcallb) { - /* Not yet registered. - * Try to register and activate it. - */ - added++; - if (!eicon_registercard(p)) - registered = 1; - } else { - /* Card already registered */ - registered = 1; - } - - if (registered) { - /* Init OK, next card ... */ - spin_lock_irqsave(&ll_lock, flags); - q = p; - p = p->next; - spin_unlock_irqrestore(&ll_lock, flags); - } else { - /* registering failed, remove card from list, free memory */ - printk(KERN_ERR - "%s: Initialization of %s failed\n", DRIVERLNAME, - p->interface.id); - spin_lock_irqsave(&ll_lock, flags); - if (q) { - q->next = p->next; - eicon_freecard(p); - p = q->next; - } else { - cards = p->next; - eicon_freecard(p); - p = cards; - } - spin_unlock_irqrestore(&ll_lock, flags); - failed++; - } - } - return (added - failed); -} - -static void * -didd_callback(void *context, DESCRIPTOR* adapter, int removal) -{ - eicon_card *cp = NULL, *lastcp = NULL; - ulong flags; - - if (adapter->type == IDI_DADAPTER) - { - printk(KERN_ERR "%s: Change in DAdapter ? Oops ?.\n", DRIVERLNAME); - DBG_ERR(("Notification about IDI_DADAPTER change ! Oops.")); - return(NULL); - } - else if (adapter->type == IDI_DIMAINT) - { - if (removal) - { - stop_dbg(); - } - else - { - memcpy(&MAdapter, adapter, sizeof(MAdapter)); - dprintf = (DIVA_DI_PRINTF)MAdapter.request; - DbgRegister("I4L", DRIVERRELEASE, DBG_DEFAULT); - } - } - else if ((adapter->type > 0) && - (adapter->type < 16)) - { /* IDI Adapter */ - if (removal) - { - spin_lock_irqsave(&ll_lock, flags); - lastcp = cp = cards; - while (cp) { - if (cp->d.request == adapter->request) - { - spin_unlock_irqrestore(&ll_lock, flags); - DBG_LOG(("remove adapter from list")); - unregister_card(cp, 0); - spin_lock_irqsave(&ll_lock, flags); - if (cp == lastcp) - cards = cp->next; - else - lastcp->next = cp->next; - eicon_freecard(cp); - break; - } - lastcp = cp; - cp = cp->next; - } - spin_unlock_irqrestore(&ll_lock, flags); - } - else - { - if (adapter->channels) { - DBG_LOG(("add adapter to list")); - eicon_addcard(adapter); - } - } - } - return(NULL); -} - -static int __init -connect_didd(void) -{ - int x = 0; - int dadapter = 0; - IDI_SYNC_REQ req; - DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS]; - - DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table)); - - for (x = 0; x < MAX_DESCRIPTORS; x++) - { - if (DIDD_Table[x].type == IDI_DADAPTER) - { /* DADAPTER found */ - dadapter = 1; - memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter)); - req.didd_notify.e.Req = 0; - req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; - req.didd_notify.info.context = 0; - DAdapter.request((ENTITY *)&req); - if (req.didd_notify.e.Rc != 0xff) - { - stop_dbg(); - return(0); - } - notify_handle = req.didd_notify.info.handle; - } - else if (DIDD_Table[x].type == IDI_DIMAINT) - { /* MAINT found */ - memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter)); - dprintf = (DIVA_DI_PRINTF)MAdapter.request; - DbgRegister("I4L", DRIVERRELEASE, DBG_DEFAULT); - } - else if ((DIDD_Table[x].type > 0) && - (DIDD_Table[x].type < 16)) - { /* IDI Adapter found */ - if (DIDD_Table[x].channels) { - eicon_addcard(&DIDD_Table[x]); - } - } - } - - if (!dadapter) { - stop_dbg(); - } - - return(dadapter); -} - -static void __exit -disconnect_didd(void) -{ - IDI_SYNC_REQ req; - - stop_dbg(); - - req.didd_notify.e.Req = 0; - req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY; - req.didd_notify.info.handle = notify_handle; - DAdapter.request((ENTITY *)&req); -} - -/* -** proc entry -*/ -extern struct proc_dir_entry *proc_net_isdn_eicon; -static struct proc_dir_entry *i4lidi_proc_entry = NULL; - -static int -i4lidi_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - char tmprev[32]; - - len += sprintf(page+len, "%s\n", DRIVERNAME); - len += sprintf(page+len, "name : %s\n", DRIVERLNAME); - len += sprintf(page+len, "release : %s\n", DRIVERRELEASE); - strcpy(tmprev, eicon_revision); - len += sprintf(page+len, "revision : %s/", eicon_getrev(tmprev)); - strcpy(tmprev, eicon_idi_revision); - len += sprintf(page+len, "%s\n", eicon_getrev(tmprev)); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return((count < len-off) ? count : len-off); -} - -static void __init -create_proc(void) -{ - if(!(i4lidi_proc_entry = create_proc_entry(DRIVERLNAME, - S_IFREG | S_IRUGO | S_IWUSR, proc_net_isdn_eicon))) - { - printk(KERN_WARNING "%s: failed to create proc entry.\n", DRIVERLNAME); - return; - } - i4lidi_proc_entry->read_proc = i4lidi_proc_read; - i4lidi_proc_entry->owner = THIS_MODULE; -} - -static void __exit -remove_proc(void) -{ - if(i4lidi_proc_entry) - remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon); -} - -/* -** load / unload -*/ -static int __init -i4l_idi_init(void) -{ - int ret = 0; - char tmprev[50]; - - status_lock = SPIN_LOCK_UNLOCKED; - ll_lock = SPIN_LOCK_UNLOCKED; - - if (strlen(id) < 1) - strcpy(id, "diva"); - - DebugVar = debug; - - init_MUTEX_LOCKED(&diva_thread_sem); - init_MUTEX_LOCKED(&diva_thread_end); - - printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:",DRIVERLNAME , DRIVERRELEASE); - strcpy(tmprev, eicon_revision); - printk("%s/", eicon_getrev(tmprev)); - strcpy(tmprev, eicon_idi_revision); - printk("%s\n", eicon_getrev(tmprev)); - - diva_init_thread(); - - if(!connect_didd()) { - printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME); - stop_diva_thread(); - ret = -EIO; - goto out; - } - create_proc(); - -out: - return(ret); -} - -static void __exit -i4l_idi_exit(void) -{ - eicon_card *card, *last, *cc; - ulong flags; - - spin_lock_irqsave(&ll_lock, flags); - cc = cards; - card = cc; - cards = NULL; - spin_unlock_irqrestore(&ll_lock, flags); - - remove_proc(); - - while (card) { - unregister_card(card, 1); - card = card->next; - } - - stop_diva_thread(); - disconnect_didd(); - - card = cc; - while (card) { - last = card; - card = card->next; - eicon_freecard(last); - } - printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME); -} - -module_init(i4l_idi_init); -module_exit(i4l_idi_exit); diff --git a/drivers/isdn/hardware/eicon/i4lididrv.h b/drivers/isdn/hardware/eicon/i4lididrv.h deleted file mode 100644 index bb4692082ab6..000000000000 --- a/drivers/isdn/hardware/eicon/i4lididrv.h +++ /dev/null @@ -1,272 +0,0 @@ -/* $Id: i4lididrv.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ - * - * ISDN interface module for Eicon active cards. - * I4L - IDI Interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999-2002 Cytronics & Melware (info@melware.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - - -#ifndef i4lididrv_h -#define i4lididrv_h - -#include <linux/isdn.h> -#include <linux/isdnif.h> - -#include "platform.h" -#include "di_defs.h" - -#define EICON_IOCTL_GETTYPE 6 -#define EICON_IOCTL_LOADPCI 7 -#define EICON_IOCTL_GETVER 9 -#define EICON_IOCTL_GETXLOG 10 - -#define EICON_IOCTL_MANIF 90 - -#define EICON_IOCTL_FREEIT 97 -#define EICON_IOCTL_TEST 98 -#define EICON_IOCTL_DEBUGVAR 99 - -/* Constants for describing Card-Type */ -#define EICON_CTYPE_S 0 -#define EICON_CTYPE_SX 1 -#define EICON_CTYPE_SCOM 2 -#define EICON_CTYPE_QUADRO 3 -#define EICON_CTYPE_S2M 4 -#define EICON_CTYPE_MAESTRA 5 -#define EICON_CTYPE_MAESTRAQ 6 -#define EICON_CTYPE_MAESTRAQ_U 7 -#define EICON_CTYPE_MAESTRAP 8 -#define EICON_CTYPE_ISABRI 0x10 -#define EICON_CTYPE_ISAPRI 0x20 -#define EICON_CTYPE_MASK 0x0f -#define EICON_CTYPE_QUADRO_NR(n) (n<<4) - -#define MAX_HEADER_LEN 10 - -#define MAX_STATUS_BUFFER 150 - -/* Data for Management interface */ -typedef struct { - int count; - int pos; - int length[50]; - unsigned char data[700]; -} eicon_manifbuf; - -#define TRACE_OK (1) - -#ifdef __KERNEL__ - -/* Macro for delay via schedule() */ -#define SLEEP(j) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - schedule_timeout(j); \ -} - -/* Kernel includes */ -#include <linux/config.h> -#include <linux/sched.h> -#include <linux/skbuff.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/ctype.h> - -typedef struct { - __u16 length __attribute__ ((packed)); /* length of data/parameter field */ - __u8 P[1]; /* data/parameter field */ -} eicon_PBUFFER; - -typedef struct { - __u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */ - __u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */ - __u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */ - __u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */ - __u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */ - __u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */ - __u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */ - __u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */ - __u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */ - __u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */ - __u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */ - __u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */ - __u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */ - __u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */ - __u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */ - __u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */ - __u8 B[1]; /* buffer space for Req,Ind and Rc */ -} eicon_pr_ram; - -typedef struct { - __u8 Req; /* pending request */ - __u8 Rc; /* return code received */ - __u8 Ind; /* indication received */ - __u8 ReqCh; /* channel of current Req */ - __u8 RcCh; /* channel of current Rc */ - __u8 IndCh; /* channel of current Ind */ - __u8 D3Id; /* ID used by this entity */ - __u8 B2Id; /* ID used by this entity */ - __u8 GlobalId; /* reserved field */ - __u8 XNum; /* number of X-buffers */ - __u8 RNum; /* number of R-buffers */ - struct sk_buff_head X; /* X-buffer queue */ - struct sk_buff_head R; /* R-buffer queue */ - __u8 RNR; /* receive not ready flag */ - __u8 complete; /* receive complete status */ - __u8 busy; /* busy flag */ - __u16 ref; /* saved reference */ -} entity; - -#define FAX_MAX_SCANLINE 2500 - -typedef struct { - __u8 PrevObject; - __u8 NextObject; - __u8 abLine[FAX_MAX_SCANLINE]; - __u8 abFrame[FAX_MAX_SCANLINE]; - unsigned int LineLen; - unsigned int LineDataLen; - __u32 LineData; - unsigned int NullBytesPos; - __u8 NullByteExist; - int PageCount; - __u8 Dle; - __u8 Eop; -} eicon_ch_fax_buf; - -typedef struct { - int No; /* Channel Number */ - unsigned short fsm_state; /* Current D-Channel state */ - unsigned short statectrl; /* State controling bits */ - unsigned short eazmask; /* EAZ-Mask for this Channel */ - int queued; /* User-Data Bytes in TX queue */ - int pqueued; /* User-Data Packets in TX queue */ - int waitq; /* User-Data Bytes in wait queue */ - int waitpq; /* User-Data Bytes in packet queue */ - struct sk_buff *tskb1; /* temp skb 1 */ - struct sk_buff *tskb2; /* temp skb 2 */ - unsigned char l2prot; /* Layer 2 protocol */ - unsigned char l3prot; /* Layer 3 protocol */ -#ifdef CONFIG_ISDN_TTY_FAX - T30_s *fax; /* pointer to fax data in LL */ - eicon_ch_fax_buf fax2; /* fax related struct */ -#endif - entity e; /* Native Entity */ - ENTITY de; /* Divas D Entity */ - ENTITY be; /* Divas B Entity */ - char cpn[32]; /* remember cpn */ - char oad[32]; /* remember oad */ - char dsa[32]; /* remember dsa */ - char osa[32]; /* remember osa */ - unsigned char cause[2]; /* Last Cause */ - unsigned char si1; - unsigned char si2; - unsigned char plan; - unsigned char screen; - unsigned char a_para[8]; /* Additional parameter */ -} eicon_chan; - -typedef struct { - eicon_chan *ptr; -} eicon_chan_ptr; - - -#define EICON_FLAGS_RUNNING 1 /* Cards driver activated */ -#define EICON_FLAGS_LOADED 8 /* Firmware loaded */ - -/* D-Channel states */ -#define EICON_STATE_NULL 0 -#define EICON_STATE_ICALL 1 -#define EICON_STATE_OCALL 2 -#define EICON_STATE_IWAIT 3 -#define EICON_STATE_OWAIT 4 -#define EICON_STATE_IBWAIT 5 -#define EICON_STATE_OBWAIT 6 -#define EICON_STATE_BWAIT 7 -#define EICON_STATE_BHWAIT 8 -#define EICON_STATE_BHWAIT2 9 -#define EICON_STATE_DHWAIT 10 -#define EICON_STATE_DHWAIT2 11 -#define EICON_STATE_BSETUP 12 -#define EICON_STATE_ACTIVE 13 -#define EICON_STATE_ICALLW 14 -#define EICON_STATE_LISTEN 15 -#define EICON_STATE_WMCONN 16 - -#define EICON_MAX_QUEUE 2138 - -typedef struct { - __u8 ret; - __u8 id; - __u8 ch; -} eicon_ack; - -typedef struct { - __u8 code; - __u8 id; - __u8 ch; -} eicon_req; - -typedef struct { - __u8 ret; - __u8 id; - __u8 ch; - __u8 more; -} eicon_indhdr; - -/* - * Per card driver data - */ -typedef struct eicon_card { - DESCRIPTOR d; /* IDI Descriptor */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char type; /* Cardtype (EICON_CTYPE_...) */ - struct eicon_card *qnext; /* Pointer to next quadro adapter */ - int Feature; /* Protocol Feature Value */ - struct eicon_card *next; /* Pointer to next device struct */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head rackq; /* Req-Ack-Message queue */ - struct sk_buff_head sackq; /* Data-Ack-Message queue */ - struct sk_buff_head statq; /* Status-Message queue */ - int statq_entries; - eicon_chan* IdTable[256]; /* Table to find entity */ - __u16 ref_in; - __u16 ref_out; - int nchannels; /* Number of B-Channels */ - int ReadyInt; /* Ready Interrupt */ - eicon_chan *bch; /* B-Channel status/control */ - DBUFFER *dbuf; /* Dbuffer for Diva Server */ - BUFFERS *sbuf; /* Buffer for Diva Server */ - char *sbufp; /* Data Buffer for Diva Server */ - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Drivers card name */ - spinlock_t lock; /* spin lock per card */ - struct tq_struct tq; /* task queue for thread */ -} eicon_card; - -#include "i4l_idi.h" - -extern eicon_card *cards; -extern char *eicon_ctype_name[]; - -extern ulong DebugVar; -extern void eicon_log(eicon_card * card, int level, const char *fmt, ...); -extern void eicon_putstatus(eicon_card * card, char * buf); - -extern void eicon_tx_request(struct eicon_card *); - -extern spinlock_t eicon_lock; - -#endif /* __KERNEL__ */ - -#endif /* i4lididrv_h */ |
