Linux-2.4.0-test2
[davej-history.git] / drivers / isdn / eicon / eicon_idi.c
blob9cef520bc5271eb07130ec245cc5b16bd6587cb2
1 /* $Id: eicon_idi.c,v 1.33 2000/03/06 15:45:17 armin Exp $
3 * ISDN lowlevel-module for Eicon active cards.
4 * IDI interface
6 * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
7 * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
9 * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH
10 * for sponsoring and testing fax
11 * capabilities with Diva Server cards.
12 * (dor@deutschemailbox.de)
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * $Log: eicon_idi.c,v $
29 * Revision 1.33 2000/03/06 15:45:17 armin
30 * Fixed incomplete number handling with BRI PtP connection.
32 * Revision 1.32 2000/03/04 17:04:21 armin
33 * Fix of statemachine, B-connect before D-connect,
34 * thanks to Helmut Adams <adams@ipcon.de>
35 * Minor change in send-data packet handling.
37 * Revision 1.31 2000/02/22 16:26:40 armin
38 * Fixed membase error message.
39 * Fixed missing log buffer struct.
41 * Revision 1.30 2000/02/16 16:08:46 armin
42 * Fixed virtual channel handling of IDI.
44 * Revision 1.29 2000/01/23 21:21:23 armin
45 * Added new trace capability and some updates.
46 * DIVA Server BRI now supports data for ISDNLOG.
48 * Revision 1.28 2000/01/20 19:55:34 keil
49 * Add FAX Class 1 support
51 * Revision 1.27 1999/11/29 13:12:03 armin
52 * Autoconnect on L2_TRANS doesn't work with link_level correctly,
53 * changed back to former mode.
55 * Revision 1.26 1999/11/25 11:43:27 armin
56 * Fixed statectrl and connect message.
57 * X.75 fix and HDLC/transparent with autoconnect.
58 * Minor cleanup.
60 * Revision 1.25 1999/11/18 20:30:55 armin
61 * removed old workaround for ISA cards.
63 * Revision 1.24 1999/10/26 21:15:33 armin
64 * using define for checking phone number len to avoid buffer overflow.
66 * Revision 1.23 1999/10/11 18:13:25 armin
67 * Added fax capabilities for Eicon Diva Server cards.
69 * Revision 1.22 1999/10/08 22:09:33 armin
70 * Some fixes of cards interface handling.
71 * Bugfix of NULL pointer occurence.
72 * Changed a few log outputs.
74 * Revision 1.21 1999/09/26 14:17:53 armin
75 * Improved debug and log via readstat()
77 * Revision 1.20 1999/09/21 20:35:43 armin
78 * added more error checking.
80 * Revision 1.19 1999/09/21 20:06:40 armin
81 * Added pointer checks.
83 * Revision 1.18 1999/09/07 12:48:05 armin
84 * Prepared for sub-address usage.
86 * Revision 1.17 1999/09/07 12:35:39 armin
87 * Better checking and channel Id handling.
89 * Revision 1.16 1999/09/04 13:44:19 armin
90 * Fix of V.42 analog Modem negotiation handling.
92 * Revision 1.15 1999/08/28 21:32:50 armin
93 * Prepared for fax related functions.
94 * Now compilable without errors/warnings.
96 * Revision 1.14 1999/08/28 20:24:40 armin
97 * Corrected octet 3/3a in CPN/OAD information element.
98 * Thanks to John Simpson <xfl23@dial.pipex.com>
100 * Revision 1.13 1999/08/22 20:26:44 calle
101 * backported changes from kernel 2.3.14:
102 * - several #include "config.h" gone, others come.
103 * - "struct device" changed to "struct net_device" in 2.3.14, added a
104 * define in isdn_compat.h for older kernel versions.
106 * Revision 1.12 1999/08/18 20:16:59 armin
107 * Added XLOG function for all cards.
108 * Bugfix of alloc_skb NULL pointer.
110 * Revision 1.11 1999/07/25 15:12:03 armin
111 * fix of some debug logs.
112 * enabled ISA-cards option.
114 * Revision 1.10 1999/07/11 17:16:24 armin
115 * Bugfixes in queue handling.
116 * Added DSP-DTMF decoder functions.
117 * Reorganized ack_handler.
119 * Revision 1.9 1999/03/29 11:19:42 armin
120 * I/O stuff now in seperate file (eicon_io.c)
121 * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
123 * Revision 1.8 1999/03/02 12:37:43 armin
124 * Added some important checks.
125 * Analog Modem with DSP.
126 * Channels will be added to Link-Level after loading firmware.
128 * Revision 1.7 1999/02/03 18:34:35 armin
129 * Channel selection for outgoing calls w/o CHI.
130 * Added channel # in debug messages.
131 * L2 Transparent should work with 800 byte/packet now.
133 * Revision 1.6 1999/01/26 07:18:59 armin
134 * Bug with wrong added CPN fixed.
136 * Revision 1.5 1999/01/24 20:14:11 armin
137 * Changed and added debug stuff.
138 * Better data sending. (still problems with tty's flip buffer)
140 * Revision 1.4 1999/01/10 18:46:05 armin
141 * Bug with wrong values in HLC fixed.
142 * Bytes to send are counted and limited now.
144 * Revision 1.3 1999/01/05 14:49:34 armin
145 * Added experimental usage of full BC and HLC for
146 * speech, 3.1kHz audio, fax gr.2/3
148 * Revision 1.2 1999/01/04 13:19:29 armin
149 * Channel status with listen-request wrong - fixed.
151 * Revision 1.1 1999/01/01 18:09:41 armin
152 * First checkin of new eicon driver.
153 * DIVA-Server BRI/PCI and PRI/PCI are supported.
154 * Old diehl code is obsolete.
159 #include <linux/config.h>
160 #define __NO_VERSION__
161 #include "eicon.h"
162 #include "eicon_idi.h"
163 #include "eicon_dsp.h"
165 #undef EICON_FULL_SERVICE_OKTETT
167 char *eicon_idi_revision = "$Revision: 1.33 $";
169 eicon_manifbuf *manbuf;
171 static char BC_Speech[3] = { 0x80, 0x90, 0xa3 };
172 static char BC_31khz[3] = { 0x90, 0x90, 0xa3 };
173 static char BC_64k[2] = { 0x88, 0x90 };
174 static char BC_video[3] = { 0x91, 0x90, 0xa5 };
176 #ifdef EICON_FULL_SERVICE_OKTETT
178 static char HLC_telephony[2] = { 0x91, 0x81 };
180 static char HLC_faxg3[2] = { 0x91, 0x84 };
181 #endif
183 int eicon_idi_manage_assign(eicon_card *card);
184 int eicon_idi_manage_remove(eicon_card *card);
185 int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer);
188 idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
190 int l = 0;
191 int tmp;
193 tmp = 0;
194 if (!signet) {
195 /* Signal Layer */
196 reqbuf->XBuffer.P[l++] = CAI;
197 reqbuf->XBuffer.P[l++] = 1;
198 reqbuf->XBuffer.P[l++] = 0;
199 reqbuf->XBuffer.P[l++] = KEY;
200 reqbuf->XBuffer.P[l++] = 3;
201 reqbuf->XBuffer.P[l++] = 'I';
202 reqbuf->XBuffer.P[l++] = '4';
203 reqbuf->XBuffer.P[l++] = 'L';
204 reqbuf->XBuffer.P[l++] = SHIFT|6;
205 reqbuf->XBuffer.P[l++] = SIN;
206 reqbuf->XBuffer.P[l++] = 2;
207 reqbuf->XBuffer.P[l++] = 0;
208 reqbuf->XBuffer.P[l++] = 0;
209 reqbuf->XBuffer.P[l++] = 0; /* end */
210 reqbuf->Req = ASSIGN;
211 reqbuf->ReqCh = 0;
212 reqbuf->ReqId = 0;
213 reqbuf->XBuffer.length = l;
214 reqbuf->Reference = 0; /* Sig Entity */
216 else {
217 /* Network Layer */
218 reqbuf->XBuffer.P[l++] = CAI;
219 reqbuf->XBuffer.P[l++] = 1;
220 reqbuf->XBuffer.P[l++] = chan->e.D3Id;
221 reqbuf->XBuffer.P[l++] = LLC;
222 reqbuf->XBuffer.P[l++] = 2;
223 switch(chan->l2prot) {
224 case ISDN_PROTO_L2_TRANS:
225 reqbuf->XBuffer.P[l++] = 2; /* transparent */
226 break;
227 case ISDN_PROTO_L2_X75I:
228 case ISDN_PROTO_L2_X75UI:
229 case ISDN_PROTO_L2_X75BUI:
230 reqbuf->XBuffer.P[l++] = 5; /* X.75 */
231 break;
232 case ISDN_PROTO_L2_MODEM:
233 if (chan->fsm_state == EICON_STATE_IWAIT)
234 reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */
235 else
236 reqbuf->XBuffer.P[l++] = 10; /* V.42 */
237 break;
238 case ISDN_PROTO_L2_HDLC:
239 case ISDN_PROTO_L2_FAX:
240 if (chan->fsm_state == EICON_STATE_IWAIT)
241 reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */
242 else
243 reqbuf->XBuffer.P[l++] = 2; /* transparent */
244 break;
245 default:
246 reqbuf->XBuffer.P[l++] = 1;
248 switch(chan->l3prot) {
249 case ISDN_PROTO_L3_FCLASS2:
250 #ifdef CONFIG_ISDN_TTY_FAX
251 reqbuf->XBuffer.P[l++] = 6;
252 reqbuf->XBuffer.P[l++] = NLC;
253 tmp = idi_fill_in_T30(chan, &reqbuf->XBuffer.P[l+1]);
254 reqbuf->XBuffer.P[l++] = tmp;
255 l += tmp;
256 break;
257 #endif
258 case ISDN_PROTO_L3_TRANS:
259 default:
260 reqbuf->XBuffer.P[l++] = 4;
262 reqbuf->XBuffer.P[l++] = 0; /* end */
263 reqbuf->Req = ASSIGN;
264 reqbuf->ReqCh = 0;
265 reqbuf->ReqId = 0x20;
266 reqbuf->XBuffer.length = l;
267 reqbuf->Reference = 1; /* Net Entity */
269 return(0);
273 idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
275 reqbuf->Req = rq;
276 reqbuf->ReqCh = Ch;
277 reqbuf->ReqId = 1;
278 reqbuf->XBuffer.length = 1;
279 reqbuf->XBuffer.P[0] = 0;
280 reqbuf->Reference = signet;
281 return(0);
285 idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
287 int l = 9;
288 reqbuf->Req = CALL_RES;
289 reqbuf->ReqCh = 0;
290 reqbuf->ReqId = 1;
291 reqbuf->XBuffer.P[0] = CAI;
292 reqbuf->XBuffer.P[1] = 6;
293 reqbuf->XBuffer.P[2] = 9;
294 reqbuf->XBuffer.P[3] = 0;
295 reqbuf->XBuffer.P[4] = 0;
296 reqbuf->XBuffer.P[5] = 0;
297 reqbuf->XBuffer.P[6] = 32;
298 reqbuf->XBuffer.P[7] = 3;
299 switch(chan->l2prot) {
300 case ISDN_PROTO_L2_X75I:
301 case ISDN_PROTO_L2_X75UI:
302 case ISDN_PROTO_L2_X75BUI:
303 case ISDN_PROTO_L2_HDLC:
304 reqbuf->XBuffer.P[1] = 1;
305 reqbuf->XBuffer.P[2] = 0x05;
306 l = 4;
307 break;
308 case ISDN_PROTO_L2_V11096:
309 reqbuf->XBuffer.P[2] = 0x0d;
310 reqbuf->XBuffer.P[3] = 5;
311 reqbuf->XBuffer.P[4] = 0;
312 break;
313 case ISDN_PROTO_L2_V11019:
314 reqbuf->XBuffer.P[2] = 0x0d;
315 reqbuf->XBuffer.P[3] = 6;
316 reqbuf->XBuffer.P[4] = 0;
317 break;
318 case ISDN_PROTO_L2_V11038:
319 reqbuf->XBuffer.P[2] = 0x0d;
320 reqbuf->XBuffer.P[3] = 7;
321 reqbuf->XBuffer.P[4] = 0;
322 break;
323 case ISDN_PROTO_L2_MODEM:
324 reqbuf->XBuffer.P[2] = 0x11;
325 reqbuf->XBuffer.P[3] = 7;
326 reqbuf->XBuffer.P[4] = 0;
327 reqbuf->XBuffer.P[5] = 0;
328 reqbuf->XBuffer.P[6] = 128;
329 reqbuf->XBuffer.P[7] = 0;
330 break;
331 case ISDN_PROTO_L2_FAX:
332 reqbuf->XBuffer.P[2] = 0x10;
333 reqbuf->XBuffer.P[3] = 0;
334 reqbuf->XBuffer.P[4] = 0;
335 reqbuf->XBuffer.P[5] = 0;
336 reqbuf->XBuffer.P[6] = 128;
337 reqbuf->XBuffer.P[7] = 0;
338 break;
339 case ISDN_PROTO_L2_TRANS:
340 switch(chan->l3prot) {
341 case ISDN_PROTO_L3_TRANSDSP:
342 reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */
344 break;
346 reqbuf->XBuffer.P[8] = 0;
347 reqbuf->XBuffer.length = l;
348 reqbuf->Reference = 0; /* Sig Entity */
349 eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No);
350 return(0);
354 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
356 struct sk_buff *skb;
357 struct sk_buff *skb2;
358 eicon_REQ *reqbuf;
359 eicon_chan_ptr *chan2;
361 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
362 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
364 if ((!skb) || (!skb2)) {
365 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No);
366 if (skb)
367 dev_kfree_skb(skb);
368 if (skb2)
369 dev_kfree_skb(skb2);
370 return -ENOMEM;
373 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
374 chan2->ptr = chan;
376 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
377 eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
378 if (layer) cmd |= 0x700;
379 switch(cmd) {
380 case ASSIGN:
381 case ASSIGN|0x700:
382 idi_assign_req(reqbuf, layer, chan);
383 break;
384 case REMOVE:
385 case REMOVE|0x700:
386 idi_put_req(reqbuf, REMOVE, layer, 0);
387 break;
388 case INDICATE_REQ:
389 idi_put_req(reqbuf, INDICATE_REQ, 0, 0);
390 break;
391 case HANGUP:
392 idi_put_req(reqbuf, HANGUP, 0, 0);
393 break;
394 case REJECT:
395 idi_put_req(reqbuf, REJECT, 0 ,0);
396 break;
397 case CALL_ALERT:
398 idi_put_req(reqbuf, CALL_ALERT, 0, 0);
399 break;
400 case CALL_RES:
401 idi_call_res_req(reqbuf, chan);
402 break;
403 case IDI_N_CONNECT|0x700:
404 idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
405 break;
406 case IDI_N_CONNECT_ACK|0x700:
407 idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
408 break;
409 case IDI_N_DISC|0x700:
410 idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
411 break;
412 case IDI_N_DISC_ACK|0x700:
413 idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
414 break;
415 default:
416 eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
417 dev_kfree_skb(skb);
418 dev_kfree_skb(skb2);
419 return(-1);
422 skb_queue_tail(&chan->e.X, skb);
423 skb_queue_tail(&card->sndq, skb2);
424 eicon_schedule_tx(card);
425 return(0);
429 eicon_idi_listen_req(eicon_card *card, eicon_chan *chan)
431 if ((!card) || (!chan))
432 return 1;
434 eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
435 if (!chan->e.D3Id) {
436 idi_do_req(card, chan, ASSIGN, 0);
438 if (chan->fsm_state == EICON_STATE_NULL) {
439 if (!(chan->statectrl & HAVE_CONN_REQ)) {
440 idi_do_req(card, chan, INDICATE_REQ, 0);
441 chan->fsm_state = EICON_STATE_LISTEN;
444 return(0);
447 unsigned char
448 idi_si2bc(int si1, int si2, char *bc, char *hlc)
450 hlc[0] = 0;
451 switch(si1) {
452 case 1:
453 bc[0] = 0x90; /* 3,1 kHz audio */
454 bc[1] = 0x90; /* 64 kbit/s */
455 bc[2] = 0xa3; /* G.711 A-law */
456 #ifdef EICON_FULL_SERVICE_OKTETT
457 if (si2 == 1) {
458 bc[0] = 0x80; /* Speech */
459 hlc[0] = 0x02; /* hlc len */
460 hlc[1] = 0x91; /* first hic */
461 hlc[2] = 0x81; /* Telephony */
463 #endif
464 return(3);
465 case 2:
466 bc[0] = 0x90; /* 3,1 kHz audio */
467 bc[1] = 0x90; /* 64 kbit/s */
468 bc[2] = 0xa3; /* G.711 A-law */
469 #ifdef EICON_FULL_SERVICE_OKTETT
470 if (si2 == 2) {
471 hlc[0] = 0x02; /* hlc len */
472 hlc[1] = 0x91; /* first hic */
473 hlc[2] = 0x84; /* Fax Gr.2/3 */
475 #endif
476 return(3);
477 case 5:
478 case 7:
479 default:
480 bc[0] = 0x88;
481 bc[1] = 0x90;
482 return(2);
484 return (0);
488 idi_hangup(eicon_card *card, eicon_chan *chan)
490 if ((!card) || (!chan))
491 return 1;
493 if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
494 (chan->fsm_state == EICON_STATE_WMCONN)) {
495 if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
497 if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
498 if (chan->fsm_state != EICON_STATE_NULL) {
499 chan->statectrl |= WAITING_FOR_HANGUP;
500 idi_do_req(card, chan, HANGUP, 0);
501 chan->fsm_state = EICON_STATE_NULL;
503 eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No);
504 #ifdef CONFIG_ISDN_TTY_FAX
505 chan->fax = 0;
506 #endif
507 return(0);
511 idi_connect_res(eicon_card *card, eicon_chan *chan)
513 if ((!card) || (!chan))
514 return 1;
516 chan->fsm_state = EICON_STATE_IWAIT;
518 /* check if old NetID has been removed */
519 if (chan->e.B2Id) {
520 eicon_log(card, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
521 chan->No, chan->e.B2Id);
522 idi_do_req(card, chan, REMOVE, 1);
525 idi_do_req(card, chan, ASSIGN, 1);
526 idi_do_req(card, chan, CALL_RES, 0);
527 return(0);
531 idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
532 char *eazmsn, int si1, int si2)
534 int l = 0;
535 int i;
536 unsigned char tmp;
537 unsigned char *sub, *sp;
538 unsigned char bc[5];
539 unsigned char hlc[5];
540 struct sk_buff *skb;
541 struct sk_buff *skb2;
542 eicon_REQ *reqbuf;
543 eicon_chan_ptr *chan2;
545 if ((!card) || (!chan))
546 return 1;
548 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
549 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
551 if ((!skb) || (!skb2)) {
552 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No);
553 if (skb)
554 dev_kfree_skb(skb);
555 if (skb2)
556 dev_kfree_skb(skb2);
557 return -ENOMEM;
560 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
561 chan2->ptr = chan;
563 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
564 reqbuf->Req = CALL_REQ;
565 reqbuf->ReqCh = 0;
566 reqbuf->ReqId = 1;
568 sub = NULL;
569 sp = phone;
570 while (*sp) {
571 if (*sp == '.') {
572 sub = sp + 1;
573 *sp = 0;
574 } else
575 sp++;
577 reqbuf->XBuffer.P[l++] = CPN;
578 reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
579 reqbuf->XBuffer.P[l++] = 0x81;
580 for(i=0; i<strlen(phone);i++)
581 reqbuf->XBuffer.P[l++] = phone[i] & 0x7f;
582 if (sub) {
583 reqbuf->XBuffer.P[l++] = DSA;
584 reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
585 reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
586 reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
587 while (*sub)
588 reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
591 sub = NULL;
592 sp = eazmsn;
593 while (*sp) {
594 if (*sp == '.') {
595 sub = sp + 1;
596 *sp = 0;
597 } else
598 sp++;
600 reqbuf->XBuffer.P[l++] = OAD;
601 reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
602 reqbuf->XBuffer.P[l++] = 0x01;
603 reqbuf->XBuffer.P[l++] = 0x80;
604 for(i=0; i<strlen(eazmsn);i++)
605 reqbuf->XBuffer.P[l++] = eazmsn[i] & 0x7f;
606 if (sub) {
607 reqbuf->XBuffer.P[l++] = OSA;
608 reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
609 reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
610 reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
611 while (*sub)
612 reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
615 if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
616 reqbuf->XBuffer.P[l++] = BC;
617 reqbuf->XBuffer.P[l++] = tmp;
618 for(i=0; i<tmp;i++)
619 reqbuf->XBuffer.P[l++] = bc[i];
620 if ((tmp=hlc[0])) {
621 reqbuf->XBuffer.P[l++] = HLC;
622 reqbuf->XBuffer.P[l++] = tmp;
623 for(i=1; i<=tmp;i++)
624 reqbuf->XBuffer.P[l++] = hlc[i];
628 reqbuf->XBuffer.P[l++] = CAI;
629 reqbuf->XBuffer.P[l++] = 6;
630 reqbuf->XBuffer.P[l++] = 0x09;
631 reqbuf->XBuffer.P[l++] = 0;
632 reqbuf->XBuffer.P[l++] = 0;
633 reqbuf->XBuffer.P[l++] = 0;
634 reqbuf->XBuffer.P[l++] = 32;
635 reqbuf->XBuffer.P[l++] = 3;
636 switch(chan->l2prot) {
637 case ISDN_PROTO_L2_X75I:
638 case ISDN_PROTO_L2_X75UI:
639 case ISDN_PROTO_L2_X75BUI:
640 case ISDN_PROTO_L2_HDLC:
641 reqbuf->XBuffer.P[l-6] = 5;
642 reqbuf->XBuffer.P[l-7] = 1;
643 l -= 5;
644 break;
645 case ISDN_PROTO_L2_V11096:
646 reqbuf->XBuffer.P[l-7] = 3;
647 reqbuf->XBuffer.P[l-6] = 0x0d;
648 reqbuf->XBuffer.P[l-5] = 5;
649 reqbuf->XBuffer.P[l-4] = 0;
650 l -= 3;
651 break;
652 case ISDN_PROTO_L2_V11019:
653 reqbuf->XBuffer.P[l-7] = 3;
654 reqbuf->XBuffer.P[l-6] = 0x0d;
655 reqbuf->XBuffer.P[l-5] = 6;
656 reqbuf->XBuffer.P[l-4] = 0;
657 l -= 3;
658 break;
659 case ISDN_PROTO_L2_V11038:
660 reqbuf->XBuffer.P[l-7] = 3;
661 reqbuf->XBuffer.P[l-6] = 0x0d;
662 reqbuf->XBuffer.P[l-5] = 7;
663 reqbuf->XBuffer.P[l-4] = 0;
664 l -= 3;
665 break;
666 case ISDN_PROTO_L2_MODEM:
667 reqbuf->XBuffer.P[l-6] = 0x11;
668 reqbuf->XBuffer.P[l-5] = 7;
669 reqbuf->XBuffer.P[l-4] = 0;
670 reqbuf->XBuffer.P[l-3] = 0;
671 reqbuf->XBuffer.P[l-2] = 128;
672 reqbuf->XBuffer.P[l-1] = 0;
673 break;
674 case ISDN_PROTO_L2_FAX:
675 reqbuf->XBuffer.P[l-6] = 0x10;
676 reqbuf->XBuffer.P[l-5] = 0;
677 reqbuf->XBuffer.P[l-4] = 0;
678 reqbuf->XBuffer.P[l-3] = 0;
679 reqbuf->XBuffer.P[l-2] = 128;
680 reqbuf->XBuffer.P[l-1] = 0;
681 break;
682 case ISDN_PROTO_L2_TRANS:
683 switch(chan->l3prot) {
684 case ISDN_PROTO_L3_TRANSDSP:
685 reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */
687 break;
690 reqbuf->XBuffer.P[l++] = 0; /* end */
691 reqbuf->XBuffer.length = l;
692 reqbuf->Reference = 0; /* Sig Entity */
694 if (chan->statectrl & WAITING_FOR_HANGUP) {
695 /* If the line did not disconnect yet,
696 we have to delay this command */
697 eicon_log(card, 32, "idi_req: Ch%d: delaying conn_req\n", chan->No);
698 chan->statectrl |= HAVE_CONN_REQ;
699 chan->tskb1 = skb;
700 chan->tskb2 = skb2;
701 } else {
702 skb_queue_tail(&chan->e.X, skb);
703 skb_queue_tail(&card->sndq, skb2);
704 eicon_schedule_tx(card);
707 eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
708 return(0);
712 void
713 idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len)
715 int i,j;
716 int pos = 0;
717 int codeset = 0;
718 int wlen = 0;
719 int lock = 0;
720 __u8 w;
721 __u16 code;
722 isdn_ctrl cmd;
724 memset(message, 0, sizeof(idi_ind_message));
726 if ((!len) || (!buffer[pos])) return;
728 while(pos <= len) {
729 w = buffer[pos++];
730 if (!w) return;
731 if (w & 0x80) {
732 wlen = 0;
734 else {
735 wlen = buffer[pos++];
738 if (pos > len) return;
740 if (lock & 0x80) lock &= 0x7f;
741 else codeset = lock;
743 if((w&0xf0) == SHIFT) {
744 codeset = w;
745 if(!(codeset & 0x08)) lock = codeset & 7;
746 codeset &= 7;
747 lock |= 0x80;
749 else {
750 if (w==ESC && wlen >=2) {
751 code = buffer[pos++]|0x800;
752 wlen--;
754 else code = w;
755 code |= (codeset<<8);
757 if (pos + wlen > len) {
758 eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No,
759 wlen, code, (pos + wlen) - len);
760 return;
763 switch(code) {
764 case OAD:
765 if (wlen > sizeof(message->oad)) {
766 pos += wlen;
767 break;
769 j = 1;
770 if (wlen) {
771 message->plan = buffer[pos++];
772 if (message->plan &0x80)
773 message->screen = 0;
774 else {
775 message->screen = buffer[pos++];
776 j = 2;
779 for(i=0; i < wlen-j; i++)
780 message->oad[i] = buffer[pos++];
781 eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No,
782 message->plan, message->screen, message->oad);
783 break;
784 case RDN:
785 if (wlen > sizeof(message->rdn)) {
786 pos += wlen;
787 break;
789 j = 1;
790 if (wlen) {
791 if (!(buffer[pos++] & 0x80)) {
792 pos++;
793 j = 2;
796 for(i=0; i < wlen-j; i++)
797 message->rdn[i] = buffer[pos++];
798 eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No,
799 message->rdn);
800 break;
801 case CPN:
802 if (wlen > sizeof(message->cpn)) {
803 pos += wlen;
804 break;
806 for(i=0; i < wlen; i++)
807 message->cpn[i] = buffer[pos++];
808 eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
809 (__u8)message->cpn[0], message->cpn + 1);
810 break;
811 case DSA:
812 if (wlen > sizeof(message->dsa)) {
813 pos += wlen;
814 break;
816 pos += 2;
817 for(i=0; i < wlen-2; i++)
818 message->dsa[i] = buffer[pos++];
819 eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
820 break;
821 case OSA:
822 if (wlen > sizeof(message->osa)) {
823 pos += wlen;
824 break;
826 pos += 2;
827 for(i=0; i < wlen-2; i++)
828 message->osa[i] = buffer[pos++];
829 eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
830 break;
831 case CAD:
832 pos += wlen;
833 eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n",
834 chan->No, wlen);
835 break;
836 case BC:
837 if (wlen > sizeof(message->bc)) {
838 pos += wlen;
839 break;
841 for(i=0; i < wlen; i++)
842 message->bc[i] = buffer[pos++];
843 eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No,
844 message->bc[0],message->bc[1],message->bc[2]);
845 break;
846 case 0x800|BC:
847 if (wlen > sizeof(message->e_bc)) {
848 pos += wlen;
849 break;
851 for(i=0; i < wlen; i++)
852 message->e_bc[i] = buffer[pos++];
853 eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
854 break;
855 case LLC:
856 if (wlen > sizeof(message->llc)) {
857 pos += wlen;
858 break;
860 for(i=0; i < wlen; i++)
861 message->llc[i] = buffer[pos++];
862 eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
863 message->llc[1],message->llc[2],message->llc[3]);
864 break;
865 case HLC:
866 if (wlen > sizeof(message->hlc)) {
867 pos += wlen;
868 break;
870 for(i=0; i < wlen; i++)
871 message->hlc[i] = buffer[pos++];
872 eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
873 message->hlc[0], message->hlc[1],
874 message->hlc[2], message->hlc[3], message->hlc[4]);
875 break;
876 case DSP:
877 case 0x600|DSP:
878 if (wlen > sizeof(message->display)) {
879 pos += wlen;
880 break;
882 for(i=0; i < wlen; i++)
883 message->display[i] = buffer[pos++];
884 eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No,
885 message->display);
886 break;
887 case 0x600|KEY:
888 if (wlen > sizeof(message->keypad)) {
889 pos += wlen;
890 break;
892 for(i=0; i < wlen; i++)
893 message->keypad[i] = buffer[pos++];
894 eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No,
895 message->keypad);
896 break;
897 case NI:
898 case 0x600|NI:
899 if (wlen) {
900 switch(buffer[pos] & 127) {
901 case 0:
902 eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No);
903 break;
904 case 1:
905 eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No);
906 break;
907 case 2:
908 eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No);
909 break;
910 default:
911 eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n",
912 chan->No, buffer[pos] & 127);
914 pos += wlen;
916 break;
917 case PI:
918 case 0x600|PI:
919 if (wlen > 1) {
920 switch(buffer[pos+1] & 127) {
921 case 1:
922 eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
923 break;
924 case 2:
925 eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
926 break;
927 case 3:
928 eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
929 break;
930 case 4:
931 eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
932 break;
933 case 5:
934 eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
935 break;
936 case 8:
937 eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No);
938 break;
939 default:
940 eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n",
941 chan->No, buffer[pos+1] & 127);
944 pos += wlen;
945 break;
946 case CAU:
947 if (wlen > sizeof(message->cau)) {
948 pos += wlen;
949 break;
951 for(i=0; i < wlen; i++)
952 message->cau[i] = buffer[pos++];
953 memcpy(&chan->cause, &message->cau, 2);
954 eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No,
955 message->cau[0],message->cau[1]);
956 break;
957 case 0x800|CAU:
958 if (wlen > sizeof(message->e_cau)) {
959 pos += wlen;
960 break;
962 for(i=0; i < wlen; i++)
963 message->e_cau[i] = buffer[pos++];
964 eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
965 message->e_cau[0],message->e_cau[1]);
966 break;
967 case 0x800|CHI:
968 if (wlen > sizeof(message->e_chi)) {
969 pos += wlen;
970 break;
972 for(i=0; i < wlen; i++)
973 message->e_chi[i] = buffer[pos++];
974 eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
975 message->e_cau[0]);
976 break;
977 case 0x800|0x7a:
978 pos ++;
979 message->e_mt=buffer[pos++];
980 eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
981 break;
982 case DT:
983 if (wlen > sizeof(message->dt)) {
984 pos += wlen;
985 break;
987 for(i=0; i < wlen; i++)
988 message->dt[i] = buffer[pos++];
989 eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No,
990 message->dt[2], message->dt[1], message->dt[0],
991 message->dt[3], message->dt[4], message->dt[5]);
992 break;
993 case 0x600|SIN:
994 if (wlen > sizeof(message->sin)) {
995 pos += wlen;
996 break;
998 for(i=0; i < wlen; i++)
999 message->sin[i] = buffer[pos++];
1000 eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No,
1001 message->sin[0],message->sin[1]);
1002 break;
1003 case 0x600|CPS:
1004 eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
1005 pos += wlen;
1006 break;
1007 case 0x600|CIF:
1008 for (i = 0; i < wlen; i++)
1009 if (buffer[pos + i] != '0') break;
1010 memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i);
1011 cmd.parm.num[wlen - i] = 0;
1012 eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
1013 pos += wlen;
1014 cmd.driver = ccard->myid;
1015 cmd.command = ISDN_STAT_CINF;
1016 cmd.arg = chan->No;
1017 ccard->interface.statcallb(&cmd);
1018 break;
1019 case 0x600|DATE:
1020 eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No);
1021 pos += wlen;
1022 break;
1023 case 0xa1:
1024 eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No);
1025 pos += wlen;
1026 break;
1027 case 0xe08:
1028 case 0xe7a:
1029 case 0xe04:
1030 case 0xe00:
1031 /* *** TODO *** */
1032 case CHA:
1033 /* Charge advice */
1034 case FTY:
1035 case 0x600|FTY:
1036 case CHI:
1037 case 0x800:
1038 /* Not yet interested in this */
1039 pos += wlen;
1040 break;
1041 case 0x880:
1042 /* Managment Information Element */
1043 if (!manbuf) {
1044 eicon_log(ccard, 1, "idi_err: manbuf not allocated\n");
1046 else {
1047 memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen);
1048 manbuf->length[manbuf->count] = wlen;
1049 manbuf->count++;
1050 manbuf->pos += wlen;
1052 pos += wlen;
1053 break;
1054 default:
1055 pos += wlen;
1056 eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n",
1057 chan->No, code, wlen);
1063 void
1064 idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
1066 si1[0] = 0;
1067 si2[0] = 0;
1068 if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */
1069 si1[0] = 1;
1070 #ifdef EICON_FULL_SERVICE_OKTETT
1071 si2[0] = 1;
1072 #endif
1074 if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */
1075 si1[0] = 1;
1076 #ifdef EICON_FULL_SERVICE_OKTETT
1077 si2[0] = 2;
1078 if (memcmp(hlc, HLC_faxg3, 2) == 0) { /* Fax Gr.2/3 */
1079 si1[0] = 2;
1081 #endif
1083 if (memcmp(bc, BC_64k, 2) == 0) { /* unrestricted 64 kbits */
1084 si1[0] = 7;
1086 if (memcmp(bc, BC_video, 3) == 0) { /* video */
1087 si1[0] = 4;
1091 /********************* FAX stuff ***************************/
1093 #ifdef CONFIG_ISDN_TTY_FAX
1096 idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer)
1098 eicon_t30_s *t30 = (eicon_t30_s *) buffer;
1100 if (!chan->fax) {
1101 eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n");
1102 return 0;
1104 memset(t30, 0, sizeof(eicon_t30_s));
1105 t30->station_id_len = EICON_FAXID_LEN;
1106 memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN);
1107 t30->resolution = chan->fax->resolution;
1108 t30->rate = chan->fax->rate + 1; /* eicon rate starts with 1 */
1109 t30->format = T30_FORMAT_SFF;
1110 t30->pages_low = 0;
1111 t30->pages_high = 0;
1112 t30->atf = 1; /* optimised for AT+F command set */
1113 t30->code = 0;
1114 t30->feature_bits_low = 0;
1115 t30->feature_bits_high = 0;
1116 t30->control_bits_low = 0;
1117 t30->control_bits_high = 0;
1119 if (chan->fax->nbc) {
1120 /* set compression by DCC value */
1121 switch(chan->fax->compression) {
1122 case (0): /* 1-D modified */
1123 break;
1124 case (1): /* 2-D modified Read */
1125 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
1126 t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
1127 break;
1128 case (2): /* 2-D uncompressed */
1129 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
1130 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
1131 t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
1132 t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
1133 break;
1134 case (3): /* 2-D modified Read */
1135 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING;
1136 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
1137 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
1138 t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
1139 t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING;
1140 t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
1141 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
1142 t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
1143 break;
1145 } else {
1146 /* set compression to best */
1147 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING;
1148 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
1149 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
1150 t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
1151 t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING;
1152 t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
1153 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
1154 t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
1156 switch(chan->fax->ecm) {
1157 case (0): /* disable ECM */
1158 break;
1159 case (1):
1160 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
1161 t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES;
1162 t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
1163 t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES;
1164 break;
1165 case (2):
1166 t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
1167 t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
1168 break;
1171 if (DebugVar & 128) {
1172 char st[40];
1173 eicon_log(NULL, 128, "sT30:code = %x\n", t30->code);
1174 eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate);
1175 eicon_log(NULL, 128, "sT30:res = %x\n", t30->resolution);
1176 eicon_log(NULL, 128, "sT30:format = %x\n", t30->format);
1177 eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low);
1178 eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high);
1179 eicon_log(NULL, 128, "sT30:atf = %x\n", t30->atf);
1180 eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low);
1181 eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high);
1182 eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low);
1183 eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high);
1184 //eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5);
1185 //eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6);
1186 //eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7);
1187 eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len);
1188 eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len);
1189 strncpy(st, t30->station_id, t30->station_id_len);
1190 st[t30->station_id_len] = 0;
1191 eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st);
1193 return(sizeof(eicon_t30_s));
1196 /* send fax struct */
1198 idi_send_edata(eicon_card *card, eicon_chan *chan)
1200 struct sk_buff *skb;
1201 struct sk_buff *skb2;
1202 eicon_REQ *reqbuf;
1203 eicon_chan_ptr *chan2;
1205 if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) {
1206 eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state);
1207 return -ENODEV;
1209 eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No);
1211 skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC);
1212 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
1214 if ((!skb) || (!skb2)) {
1215 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No);
1216 if (skb)
1217 dev_kfree_skb(skb);
1218 if (skb2)
1219 dev_kfree_skb(skb2);
1220 return -ENOMEM;
1223 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
1224 chan2->ptr = chan;
1226 reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
1228 reqbuf->Req = IDI_N_EDATA;
1229 reqbuf->ReqCh = chan->e.IndCh;
1230 reqbuf->ReqId = 1;
1232 reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P);
1233 reqbuf->Reference = 1; /* Net Entity */
1235 skb_queue_tail(&chan->e.X, skb);
1236 skb_queue_tail(&card->sndq, skb2);
1237 eicon_schedule_tx(card);
1238 return (0);
1241 void
1242 idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
1244 eicon_t30_s *p = (eicon_t30_s *)buffer;
1245 int i;
1247 if (DebugVar & 128) {
1248 char st[40];
1249 eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s));
1250 eicon_log(ccard, 128, "rT30:code = %x\n", p->code);
1251 eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate);
1252 eicon_log(ccard, 128, "rT30:res = %x\n", p->resolution);
1253 eicon_log(ccard, 128, "rT30:format = %x\n", p->format);
1254 eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low);
1255 eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high);
1256 eicon_log(ccard, 128, "rT30:atf = %x\n", p->atf);
1257 eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low);
1258 eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high);
1259 eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low);
1260 eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high);
1261 //eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5);
1262 //eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6);
1263 //eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7);
1264 eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len);
1265 eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len);
1266 strncpy(st, p->station_id, p->station_id_len);
1267 st[p->station_id_len] = 0;
1268 eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st);
1270 if (!chan->fax) {
1271 eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n");
1272 return;
1274 chan->fax->code = p->code;
1275 i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1);
1276 memcpy(chan->fax->r_id, p->station_id, i);
1277 chan->fax->r_id[i] = 0;
1278 chan->fax->r_resolution = p->resolution;
1279 chan->fax->r_rate = p->rate - 1;
1280 chan->fax->r_binary = 0; /* no binary support */
1281 chan->fax->r_width = 0;
1282 chan->fax->r_length = 2;
1283 chan->fax->r_scantime = 0;
1284 chan->fax->r_compression = 0;
1285 chan->fax->r_ecm = 0;
1286 if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) {
1287 chan->fax->r_compression = 1;
1288 if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) {
1289 chan->fax->r_compression = 2;
1292 if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) {
1293 chan->fax->r_compression = 3;
1296 if (p->feature_bits_low & T30_FEATURE_BIT_ECM) {
1297 chan->fax->r_ecm = 2;
1298 if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES)
1299 chan->fax->r_ecm = 1;
1303 void
1304 idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
1306 static __u16 wd2sff[] = {
1307 1728, 2048, 2432, 1216, 864
1309 static __u16 ln2sff[2][3] = {
1310 { 1143, 1401, 0 } , { 2287, 2802, 0 }
1312 struct sk_buff *skb;
1313 eicon_sff_dochead *doc;
1314 eicon_sff_pagehead *page;
1315 u_char *docp;
1317 if (!chan->fax) {
1318 eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n");
1319 return;
1321 if (header == 2) { /* DocHeader + PageHeader */
1322 skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC);
1323 } else {
1324 skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC);
1326 if (!skb) {
1327 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No);
1328 return;
1331 if (header == 2) { /* DocHeader + PageHeader */
1332 docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead));
1333 doc = (eicon_sff_dochead *) docp;
1334 page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead));
1335 memset(docp, 0,sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead));
1336 doc->id = 0x66666653;
1337 doc->version = 0x01;
1338 doc->off1pagehead = sizeof(eicon_sff_dochead);
1339 } else {
1340 page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead));
1341 memset(page, 0, sizeof(eicon_sff_pagehead));
1344 switch(header) {
1345 case 1: /* PageHeaderEnd */
1346 page->pageheadid = 254;
1347 page->pageheadlen = 0;
1348 break;
1349 case 0: /* PageHeader */
1350 case 2: /* DocHeader + PageHeader */
1351 page->pageheadid = 254;
1352 page->pageheadlen = sizeof(eicon_sff_pagehead) - 2;
1353 page->resvert = chan->fax->resolution;
1354 page->reshoriz = 0; /* always 203 dpi */
1355 page->coding = 0; /* always 1D */
1356 page->linelength = wd2sff[chan->fax->width];
1357 page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length];
1358 eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength);
1359 eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength);
1360 break;
1362 idi_send_data(card, chan, 0, skb, 0);
1365 void
1366 idi_fax_cmd(eicon_card *card, eicon_chan *chan)
1368 isdn_ctrl cmd;
1370 if ((!card) || (!chan))
1371 return;
1373 if (!chan->fax) {
1374 eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n");
1375 return;
1377 switch (chan->fax->code) {
1378 case ISDN_TTY_FAX_DT:
1379 if (chan->fax->phase == ISDN_FAX_PHASE_B) {
1380 idi_send_edata(card, chan);
1381 break;
1383 if (chan->fax->phase == ISDN_FAX_PHASE_D) {
1384 idi_send_edata(card, chan);
1385 break;
1387 break;
1389 case ISDN_TTY_FAX_DR:
1390 if (chan->fax->phase == ISDN_FAX_PHASE_B) {
1391 idi_send_edata(card, chan);
1393 cmd.driver = card->myid;
1394 cmd.command = ISDN_STAT_FAXIND;
1395 cmd.arg = chan->No;
1396 chan->fax->r_code = ISDN_TTY_FAX_CFR;
1397 card->interface.statcallb(&cmd);
1399 cmd.driver = card->myid;
1400 cmd.command = ISDN_STAT_FAXIND;
1401 cmd.arg = chan->No;
1402 chan->fax->r_code = ISDN_TTY_FAX_RID;
1403 card->interface.statcallb(&cmd);
1405 /* telling 1-D compression */
1406 chan->fax->r_compression = 0;
1407 cmd.driver = card->myid;
1408 cmd.command = ISDN_STAT_FAXIND;
1409 cmd.arg = chan->No;
1410 chan->fax->r_code = ISDN_TTY_FAX_DCS;
1411 card->interface.statcallb(&cmd);
1413 chan->fax2.NextObject = FAX_OBJECT_DOCU;
1414 chan->fax2.PrevObject = FAX_OBJECT_DOCU;
1416 break;
1418 if (chan->fax->phase == ISDN_FAX_PHASE_D) {
1419 idi_send_edata(card, chan);
1420 break;
1422 break;
1424 case ISDN_TTY_FAX_ET:
1425 switch(chan->fax->fet) {
1426 case 0:
1427 case 1:
1428 idi_fax_send_header(card, chan, 0);
1429 break;
1430 case 2:
1431 idi_fax_send_header(card, chan, 1);
1432 break;
1434 break;
1438 void
1439 idi_edata_rcveop(eicon_card *card, eicon_chan *chan)
1441 isdn_ctrl cmd;
1443 if (!chan->fax) {
1444 eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n");
1445 return;
1447 cmd.driver = card->myid;
1448 cmd.command = ISDN_STAT_FAXIND;
1449 cmd.arg = chan->No;
1450 chan->fax->r_code = ISDN_TTY_FAX_ET;
1451 card->interface.statcallb(&cmd);
1454 void
1455 idi_reset_fax_stat(eicon_chan *chan)
1457 chan->fax2.LineLen = 0;
1458 chan->fax2.LineData = 0;
1459 chan->fax2.LineDataLen = 0;
1460 chan->fax2.NullByteExist = 0;
1461 chan->fax2.Dle = 0;
1462 chan->fax2.PageCount = 0;
1463 chan->fax2.Eop = 0;
1466 void
1467 idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len)
1469 isdn_ctrl cmd;
1471 if (!chan->fax) {
1472 eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n");
1473 return;
1475 if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) {
1476 idi_parse_edata(ccard, chan, buffer, len);
1478 if (chan->fax->phase == ISDN_FAX_PHASE_A) {
1479 idi_reset_fax_stat(chan);
1481 chan->fsm_state = EICON_STATE_ACTIVE;
1482 cmd.driver = ccard->myid;
1483 cmd.command = ISDN_STAT_BCONN;
1484 cmd.arg = chan->No;
1485 strcpy(cmd.parm.num, "");
1486 ccard->interface.statcallb(&cmd);
1488 cmd.driver = ccard->myid;
1489 cmd.command = ISDN_STAT_FAXIND;
1490 cmd.arg = chan->No;
1491 chan->fax->r_code = ISDN_TTY_FAX_FCON;
1492 ccard->interface.statcallb(&cmd);
1494 cmd.driver = ccard->myid;
1495 cmd.command = ISDN_STAT_FAXIND;
1496 cmd.arg = chan->No;
1497 chan->fax->r_code = ISDN_TTY_FAX_RID;
1498 ccard->interface.statcallb(&cmd);
1500 cmd.driver = ccard->myid;
1501 cmd.command = ISDN_STAT_FAXIND;
1502 cmd.arg = chan->No;
1503 chan->fax->r_code = ISDN_TTY_FAX_DIS;
1504 ccard->interface.statcallb(&cmd);
1506 if (chan->fax->r_compression != 0) {
1507 /* telling fake compression in second DIS message */
1508 chan->fax->r_compression = 0;
1509 cmd.driver = ccard->myid;
1510 cmd.command = ISDN_STAT_FAXIND;
1511 cmd.arg = chan->No;
1512 chan->fax->r_code = ISDN_TTY_FAX_DIS;
1513 ccard->interface.statcallb(&cmd);
1516 cmd.driver = ccard->myid;
1517 cmd.command = ISDN_STAT_FAXIND;
1518 cmd.arg = chan->No;
1519 chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */
1520 ccard->interface.statcallb(&cmd);
1521 } else
1522 if (chan->fax->phase == ISDN_FAX_PHASE_D) {
1524 if ((chan->fax->code == EDATA_T30_MCF) &&
1525 (chan->fax->fet != 2)) {
1526 cmd.driver = ccard->myid;
1527 cmd.command = ISDN_STAT_FAXIND;
1528 cmd.arg = chan->No;
1529 chan->fax->r_code = ISDN_TTY_FAX_PTS;
1530 ccard->interface.statcallb(&cmd);
1533 switch(chan->fax->fet) {
1534 case 0: /* new page */
1535 /* stay in phase D , wait on cmd +FDT */
1536 break;
1537 case 1: /* new document */
1538 /* link-level switch to phase B */
1539 break;
1540 case 2: /* session end */
1541 default:
1542 /* send_edata produces error on some */
1543 /* fax-machines here, so we don't */
1544 /* idi_send_edata(ccard, chan); */
1545 break;
1550 if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
1551 idi_parse_edata(ccard, chan, buffer, len);
1553 if ((chan->fax->code == EDATA_T30_DCS) &&
1554 (chan->fax->phase == ISDN_FAX_PHASE_A)) {
1555 idi_reset_fax_stat(chan);
1557 cmd.driver = ccard->myid;
1558 cmd.command = ISDN_STAT_BCONN;
1559 cmd.arg = chan->No;
1560 strcpy(cmd.parm.num, "");
1561 ccard->interface.statcallb(&cmd);
1563 cmd.driver = ccard->myid;
1564 cmd.command = ISDN_STAT_FAXIND;
1565 cmd.arg = chan->No;
1566 chan->fax->r_code = ISDN_TTY_FAX_FCON_I;
1567 ccard->interface.statcallb(&cmd);
1568 } else
1569 if ((chan->fax->code == EDATA_T30_TRAIN_OK) &&
1570 (chan->fax->phase == ISDN_FAX_PHASE_A)) {
1571 cmd.driver = ccard->myid;
1572 cmd.command = ISDN_STAT_FAXIND;
1573 cmd.arg = chan->No;
1574 chan->fax->r_code = ISDN_TTY_FAX_RID;
1575 ccard->interface.statcallb(&cmd);
1577 cmd.driver = ccard->myid;
1578 cmd.command = ISDN_STAT_FAXIND;
1579 cmd.arg = chan->No;
1580 chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK;
1581 ccard->interface.statcallb(&cmd);
1582 } else
1583 if ((chan->fax->code == EDATA_T30_TRAIN_OK) &&
1584 (chan->fax->phase == ISDN_FAX_PHASE_B)) {
1585 cmd.driver = ccard->myid;
1586 cmd.command = ISDN_STAT_FAXIND;
1587 cmd.arg = chan->No;
1588 chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK;
1589 ccard->interface.statcallb(&cmd);
1590 } else
1591 if (chan->fax->phase == ISDN_FAX_PHASE_C) {
1592 switch(chan->fax->code) {
1593 case EDATA_T30_TRAIN_OK:
1594 idi_send_edata(ccard, chan);
1595 break;
1596 case EDATA_T30_MPS:
1597 chan->fax->fet = 0;
1598 idi_edata_rcveop(ccard, chan);
1599 break;
1600 case EDATA_T30_EOM:
1601 chan->fax->fet = 1;
1602 idi_edata_rcveop(ccard, chan);
1603 break;
1604 case EDATA_T30_EOP:
1605 chan->fax->fet = 2;
1606 idi_edata_rcveop(ccard, chan);
1607 break;
1613 void
1614 fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len)
1616 struct sk_buff *skb;
1618 skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC);
1619 if (!skb) {
1620 eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No);
1621 return;
1623 skb_reserve(skb, MAX_HEADER_LEN);
1624 memcpy(skb_put(skb, len), Data, len);
1625 ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
1628 void
1629 idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
1631 eicon_OBJBUFFER InBuf;
1632 eicon_OBJBUFFER LineBuf;
1633 unsigned int Length = 0;
1634 unsigned int aLength = 0;
1635 unsigned int ObjectSize = 0;
1636 unsigned int ObjHeadLen = 0;
1637 unsigned int ObjDataLen = 0;
1638 __u8 Recordtype;
1639 __u8 PageHeaderLen;
1640 __u8 Event;
1641 eicon_sff_pagehead *ob_page;
1643 __u16 Cl2Eol = 0x8000;
1645 # define EVENT_NONE 0
1646 # define EVENT_NEEDDATA 1
1648 if (!chan->fax) {
1649 eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n");
1650 return;
1655 if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
1656 InBuf.Data = skb->data;
1657 InBuf.Size = skb->len;
1658 InBuf.Len = 0;
1659 InBuf.Next = InBuf.Data;
1660 LineBuf.Data = chan->fax2.abLine;
1661 LineBuf.Size = sizeof(chan->fax2.abLine);
1662 LineBuf.Len = chan->fax2.LineLen;
1663 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1665 Event = EVENT_NONE;
1666 while (Event == EVENT_NONE) {
1667 switch(chan->fax2.NextObject) {
1668 case FAX_OBJECT_DOCU:
1669 Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
1670 if (Length < sizeof(eicon_sff_dochead)) {
1671 Event = EVENT_NEEDDATA;
1672 break;
1674 ObjectSize = sizeof(eicon_sff_dochead);
1675 Length = ObjectSize;
1676 if (LineBuf.Len < Length) {
1677 Length -= LineBuf.Len;
1678 LineBuf.Len = 0;
1679 LineBuf.Next = LineBuf.Data;
1680 InBuf.Len += Length;
1681 InBuf.Next += Length;
1682 } else {
1683 LineBuf.Len -= Length;
1684 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1685 memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
1687 chan->fax2.PrevObject = FAX_OBJECT_DOCU;
1688 chan->fax2.NextObject = FAX_OBJECT_PAGE;
1689 break;
1691 case FAX_OBJECT_PAGE:
1692 Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
1693 if (Length < 2) {
1694 Event = EVENT_NEEDDATA;
1695 break;
1697 if (LineBuf.Len == 0) {
1698 *LineBuf.Next++ = *InBuf.Next++;
1699 LineBuf.Len++;
1700 InBuf.Len++;
1702 if (LineBuf.Len == 1) {
1703 *LineBuf.Next++ = *InBuf.Next++;
1704 LineBuf.Len++;
1705 InBuf.Len++;
1707 PageHeaderLen = *(LineBuf.Data + 1);
1708 ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead);
1709 if (Length < ObjectSize) {
1710 Event = EVENT_NEEDDATA;
1711 break;
1713 Length = ObjectSize;
1714 /* extract page dimensions */
1715 if (LineBuf.Len < Length) {
1716 aLength = Length - LineBuf.Len;
1717 memcpy(LineBuf.Next, InBuf.Next, aLength);
1718 LineBuf.Next += aLength;
1719 InBuf.Next += aLength;
1720 LineBuf.Len += aLength;
1721 InBuf.Len += aLength;
1723 if (Length > 2) {
1724 ob_page = (eicon_sff_pagehead *)LineBuf.Data;
1725 switch(ob_page->linelength) {
1726 case 2048:
1727 chan->fax->r_width = 1;
1728 break;
1729 case 2432:
1730 chan->fax->r_width = 2;
1731 break;
1732 case 1216:
1733 chan->fax->r_width = 3;
1734 break;
1735 case 864:
1736 chan->fax->r_width = 4;
1737 break;
1738 case 1728:
1739 default:
1740 chan->fax->r_width = 0;
1742 switch(ob_page->pagelength) {
1743 case 1143:
1744 case 2287:
1745 chan->fax->r_length = 0;
1746 break;
1747 case 1401:
1748 case 2802:
1749 chan->fax->r_length = 1;
1750 break;
1751 default:
1752 chan->fax->r_length = 2;
1754 eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength);
1755 eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength);
1757 LineBuf.Len -= Length;
1758 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1759 memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
1761 chan->fax2.PrevObject = FAX_OBJECT_PAGE;
1762 chan->fax2.NextObject = FAX_OBJECT_LINE;
1763 break;
1765 case FAX_OBJECT_LINE:
1766 Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
1767 if (Length < 1) {
1768 Event = EVENT_NEEDDATA;
1769 break;
1771 if (LineBuf.Len == 0) {
1772 *LineBuf.Next++ = *InBuf.Next++;
1773 LineBuf.Len++;
1774 InBuf.Len++;
1776 Recordtype = *LineBuf.Data;
1777 if (Recordtype == 0) {
1778 /* recordtype pixel row (2 byte length) */
1779 ObjHeadLen = 3;
1780 if (Length < ObjHeadLen) {
1781 Event = EVENT_NEEDDATA;
1782 break;
1784 while (LineBuf.Len < ObjHeadLen) {
1785 *LineBuf.Next++ = *InBuf.Next++;
1786 LineBuf.Len++;
1787 InBuf.Len++;
1789 ObjDataLen = *((__u16*) (LineBuf.Data + 1));
1790 ObjectSize = ObjHeadLen + ObjDataLen;
1791 if (Length < ObjectSize) {
1792 Event = EVENT_NEEDDATA;
1793 break;
1795 } else
1796 if ((Recordtype >= 1) && (Recordtype <= 216)) {
1797 /* recordtype pixel row (1 byte length) */
1798 ObjHeadLen = 1;
1799 ObjDataLen = Recordtype;
1800 ObjectSize = ObjHeadLen + ObjDataLen;
1801 if (Length < ObjectSize) {
1802 Event = EVENT_NEEDDATA;
1803 break;
1805 } else
1806 if ((Recordtype >= 217) && (Recordtype <= 253)) {
1807 /* recordtype empty lines */
1808 ObjHeadLen = 1;
1809 ObjDataLen = 0;
1810 ObjectSize = ObjHeadLen + ObjDataLen;
1811 LineBuf.Len--;
1812 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1813 memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len);
1814 break;
1815 } else
1816 if (Recordtype == 254) {
1817 /* recordtype page header */
1818 chan->fax2.PrevObject = FAX_OBJECT_LINE;
1819 chan->fax2.NextObject = FAX_OBJECT_PAGE;
1820 break;
1821 } else {
1822 /* recordtype user information */
1823 ObjHeadLen = 2;
1824 if (Length < ObjHeadLen) {
1825 Event = EVENT_NEEDDATA;
1826 break;
1828 while (LineBuf.Len < ObjHeadLen) {
1829 *LineBuf.Next++ = *InBuf.Next++;
1830 LineBuf.Len++;
1831 InBuf.Len++;
1833 ObjDataLen = *(LineBuf.Data + 1);
1834 ObjectSize = ObjHeadLen + ObjDataLen;
1835 if (ObjDataLen == 0) {
1836 /* illegal line coding */
1837 LineBuf.Len -= ObjHeadLen;
1838 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1839 memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len);
1840 break;
1841 } else {
1842 /* user information */
1843 if (Length < ObjectSize) {
1844 Event = EVENT_NEEDDATA;
1845 break;
1847 Length = ObjectSize;
1848 if (LineBuf.Len < Length) {
1849 Length -= LineBuf.Len;
1850 LineBuf.Len = 0;
1851 LineBuf.Next = LineBuf.Data;
1852 InBuf.Len += Length;
1853 InBuf.Next += Length;
1854 } else {
1855 LineBuf.Len -= Length;
1856 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1857 memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
1860 break;
1862 Length = ObjectSize;
1863 if (LineBuf.Len > ObjHeadLen) {
1864 fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen,
1865 (LineBuf.Len - ObjHeadLen));
1867 Length -= LineBuf.Len;
1868 LineBuf.Len = 0;
1869 LineBuf.Next = LineBuf.Data;
1870 if (Length > 0) {
1871 fax_put_rcv(ccard, chan, InBuf.Next, Length);
1872 InBuf.Len += Length;
1873 InBuf.Next += Length;
1875 fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol));
1876 break;
1877 } /* end of switch (chan->fax2.NextObject) */
1878 } /* end of while (Event==EVENT_NONE) */
1879 if (InBuf.Len < InBuf.Size) {
1880 Length = InBuf.Size - InBuf.Len;
1881 if ((LineBuf.Len + Length) > LineBuf.Size) {
1882 eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No,
1883 Length);
1884 } else {
1885 memcpy(LineBuf.Next, InBuf.Next, Length);
1886 LineBuf.Len += Length;
1889 chan->fax2.LineLen = LineBuf.Len;
1890 } else { /* CONN_OUT */
1891 /* On CONN_OUT we do not need incoming data, drop it */
1892 /* maybe later for polling */
1895 # undef EVENT_NONE
1896 # undef EVENT_NEEDDATA
1898 return;
1902 idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf)
1904 struct sk_buff *skb;
1906 skb = alloc_skb(OutBuf->Len, GFP_ATOMIC);
1907 if (!skb) {
1908 eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No);
1909 return(-1);
1911 memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len);
1913 OutBuf->Len = 0;
1914 OutBuf->Next = OutBuf->Data;
1916 return(idi_send_data(ccard, chan, 0, skb, 1));
1920 idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
1922 isdn_ctrl cmd;
1923 eicon_OBJBUFFER InBuf;
1924 __u8 InData;
1925 __u8 InMask;
1926 eicon_OBJBUFFER OutBuf;
1927 eicon_OBJBUFFER LineBuf;
1928 __u32 LineData;
1929 unsigned int LineDataLen;
1930 __u8 Byte;
1931 __u8 Event;
1932 int ret = 1;
1934 # define EVENT_NONE 0
1935 # define EVENT_EOD 1
1936 # define EVENT_EOL 2
1937 # define EVENT_EOP 3
1939 if ((!ccard) || (!chan))
1940 return -1;
1942 if (!chan->fax) {
1943 eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n");
1944 return -1;
1947 if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
1948 /* Simply ignore any data written in data mode when receiving a fax. */
1949 /* This is not completely correct because only XON's should come here. */
1950 dev_kfree_skb(skb);
1951 return 1;
1954 if (chan->fax->phase != ISDN_FAX_PHASE_C) {
1955 dev_kfree_skb(skb);
1956 return 1;
1959 if (chan->queued + skb->len > 1200)
1960 return 0;
1962 InBuf.Data = skb->data;
1963 InBuf.Size = skb->len;
1964 InBuf.Len = 0;
1965 InBuf.Next = InBuf.Data;
1966 InData = 0;
1967 InMask = 0;
1969 LineBuf.Data = chan->fax2.abLine;
1970 LineBuf.Size = sizeof(chan->fax2.abLine);
1971 LineBuf.Len = chan->fax2.LineLen;
1972 LineBuf.Next = LineBuf.Data + LineBuf.Len;
1973 LineData = chan->fax2.LineData;
1974 LineDataLen = chan->fax2.LineDataLen;
1976 OutBuf.Data = chan->fax2.abFrame;
1977 OutBuf.Size = sizeof(chan->fax2.abFrame);
1978 OutBuf.Len = 0;
1979 OutBuf.Next = OutBuf.Data;
1981 Event = EVENT_NONE;
1983 chan->fax2.Eop = 0;
1985 for (;;) {
1986 for (;;) {
1987 if (InMask == 0) {
1988 if (InBuf.Len >= InBuf.Size) {
1989 Event = EVENT_EOD;
1990 break;
1992 if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) {
1993 chan->fax2.Dle = _DLE_;
1994 InBuf.Next++;
1995 InBuf.Len++;
1996 if (InBuf.Len >= InBuf.Size) {
1997 Event = EVENT_EOD;
1998 break;
2001 if (chan->fax2.Dle == _DLE_) {
2002 chan->fax2.Dle = 0;
2003 if (*InBuf.Next == _ETX_) {
2004 Event = EVENT_EOP;
2005 break;
2006 } else
2007 if (*InBuf.Next == _DLE_) {
2008 /* do nothing */
2009 } else {
2010 eicon_log(ccard, 1,
2011 "idi_err: Ch%d: unknown DLE escape %02x found\n",
2012 chan->No, *InBuf.Next);
2013 InBuf.Next++;
2014 InBuf.Len++;
2015 if (InBuf.Len >= InBuf.Size) {
2016 Event = EVENT_EOD;
2017 break;
2021 InBuf.Len++;
2022 InData = *InBuf.Next++;
2023 InMask = (chan->fax->bor) ? 0x80 : 0x01;
2025 while (InMask) {
2026 LineData >>= 1;
2027 LineDataLen++;
2028 if (InData & InMask)
2029 LineData |= 0x80000000;
2030 if (chan->fax->bor)
2031 InMask >>= 1;
2032 else
2033 InMask <<= 1;
2035 if ((LineDataLen >= T4_EOL_BITSIZE) &&
2036 ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) {
2037 Event = EVENT_EOL;
2038 if (LineDataLen > T4_EOL_BITSIZE) {
2039 Byte = (__u8)
2040 ((LineData & ~T4_EOL_MASK_DWORD) >>
2041 (32 - LineDataLen));
2042 if (Byte == 0) {
2043 if (! chan->fax2.NullByteExist) {
2044 chan->fax2.NullBytesPos = LineBuf.Len;
2045 chan->fax2.NullByteExist = 1;
2047 } else {
2048 chan->fax2.NullByteExist = 0;
2050 if (LineBuf.Len < LineBuf.Size) {
2051 *LineBuf.Next++ = Byte;
2052 LineBuf.Len++;
2055 LineDataLen = 0;
2056 break;
2058 if (LineDataLen >= T4_EOL_BITSIZE + 8) {
2059 Byte = (__u8)
2060 ((LineData & ~T4_EOL_MASK_DWORD) >>
2061 (32 - T4_EOL_BITSIZE - 8));
2062 LineData &= T4_EOL_MASK_DWORD;
2063 LineDataLen = T4_EOL_BITSIZE;
2064 if (Byte == 0) {
2065 if (! chan->fax2.NullByteExist) {
2066 chan->fax2.NullBytesPos = LineBuf.Len;
2067 chan->fax2.NullByteExist = 1;
2069 } else {
2070 chan->fax2.NullByteExist = 0;
2072 if (LineBuf.Len < LineBuf.Size) {
2073 *LineBuf.Next++ = Byte;
2074 LineBuf.Len++;
2078 if (Event != EVENT_NONE)
2079 break;
2082 if ((Event != EVENT_EOL) && (Event != EVENT_EOP))
2083 break;
2085 if ((Event == EVENT_EOP) && (LineDataLen > 0)) {
2086 LineData >>= 32 - LineDataLen;
2087 LineDataLen = 0;
2088 while (LineData != 0) {
2089 Byte = (__u8) LineData;
2090 LineData >>= 8;
2091 if (Byte == 0) {
2092 if (! chan->fax2.NullByteExist) {
2093 chan->fax2.NullBytesPos = LineBuf.Len;
2094 chan->fax2.NullByteExist = 1;
2096 } else {
2097 chan->fax2.NullByteExist = 0;
2099 if (LineBuf.Len < LineBuf.Size) {
2100 *LineBuf.Next++ = Byte;
2101 LineBuf.Len++;
2106 if (chan->fax2.NullByteExist) {
2107 if (chan->fax2.NullBytesPos == 0) {
2108 LineBuf.Len = 0;
2109 } else {
2110 LineBuf.Len = chan->fax2.NullBytesPos + 1;
2113 if (LineBuf.Len > 0) {
2114 if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) {
2115 ret = idi_fax_send_outbuf(ccard, chan, &OutBuf);
2117 if (LineBuf.Len <= 216) {
2118 *OutBuf.Next++ = (__u8) LineBuf.Len;
2119 OutBuf.Len++;
2120 } else {
2121 *OutBuf.Next++ = 0;
2122 *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len;
2123 OutBuf.Len += 3;
2125 memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len);
2126 OutBuf.Next += LineBuf.Len;
2127 OutBuf.Len += LineBuf.Len;
2129 LineBuf.Len = 0;
2130 LineBuf.Next = LineBuf.Data;
2131 chan->fax2.NullByteExist = 0;
2132 if (Event == EVENT_EOP)
2133 break;
2135 Event = EVENT_NONE;
2138 if (Event == EVENT_EOP) {
2139 chan->fax2.Eop = 1;
2140 chan->fax2.PageCount++;
2141 cmd.driver = ccard->myid;
2142 cmd.command = ISDN_STAT_FAXIND;
2143 cmd.arg = chan->No;
2144 chan->fax->r_code = ISDN_TTY_FAX_EOP;
2145 ccard->interface.statcallb(&cmd);
2147 if (OutBuf.Len > 0) {
2148 ret = idi_fax_send_outbuf(ccard, chan, &OutBuf);
2151 chan->fax2.LineLen = LineBuf.Len;
2152 chan->fax2.LineData = LineData;
2153 chan->fax2.LineDataLen = LineDataLen;
2155 # undef EVENT_NONE
2156 # undef EVENT_EOD
2157 # undef EVENT_EOL
2158 # undef EVENT_EOP
2160 if (ret >= 0)
2161 dev_kfree_skb(skb);
2162 if (ret == 0)
2163 ret = 1;
2164 return(ret);
2167 void
2168 idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
2170 isdn_ctrl cmd;
2172 if (!chan->fax) {
2173 eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n");
2174 return;
2176 if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) &&
2177 (chan->fax->code == 0)) {
2178 cmd.driver = ccard->myid;
2179 cmd.command = ISDN_STAT_FAXIND;
2180 cmd.arg = chan->No;
2181 chan->fax->r_code = ISDN_TTY_FAX_PTS;
2182 ccard->interface.statcallb(&cmd);
2184 if ((chan->fax->code > 1) && (chan->fax->code < 120))
2185 chan->fax->code += 120;
2186 chan->fax->r_code = ISDN_TTY_FAX_HNG;
2187 cmd.driver = ccard->myid;
2188 cmd.command = ISDN_STAT_FAXIND;
2189 cmd.arg = chan->No;
2190 ccard->interface.statcallb(&cmd);
2193 #endif /******** FAX ********/
2196 idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
2198 struct sk_buff *skb;
2199 struct sk_buff *skb2;
2200 eicon_REQ *reqbuf;
2201 eicon_chan_ptr *chan2;
2203 if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) {
2204 eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state);
2205 return -ENODEV;
2207 eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No,
2208 UReq, buffer[0], buffer[1], buffer[2], buffer[3]);
2210 skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC);
2211 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
2213 if ((!skb) || (!skb2)) {
2214 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No);
2215 if (skb)
2216 dev_kfree_skb(skb);
2217 if (skb2)
2218 dev_kfree_skb(skb2);
2219 return -ENOMEM;
2222 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
2223 chan2->ptr = chan;
2225 reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
2227 reqbuf->Req = IDI_N_UDATA;
2228 reqbuf->ReqCh = chan->e.IndCh;
2229 reqbuf->ReqId = 1;
2231 reqbuf->XBuffer.length = len + 1;
2232 reqbuf->XBuffer.P[0] = UReq;
2233 memcpy(&reqbuf->XBuffer.P[1], buffer, len);
2234 reqbuf->Reference = 1; /* Net Entity */
2236 skb_queue_tail(&chan->e.X, skb);
2237 skb_queue_tail(&card->sndq, skb2);
2238 eicon_schedule_tx(card);
2239 return (0);
2242 void
2243 idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value)
2245 u_char buf[6];
2246 struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf;
2248 if ((!ccard) || (!chan))
2249 return;
2251 memset(buf, 0, 6);
2252 switch(cmd) {
2253 case ISDN_AUDIO_SETDD:
2254 if (value[0]) {
2255 dtmf_buf->tone = (__u16) (value[1] * 5);
2256 dtmf_buf->gap = (__u16) (value[1] * 5);
2257 idi_send_udata(ccard, chan,
2258 DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER,
2259 buf, 4);
2260 } else {
2261 idi_send_udata(ccard, chan,
2262 DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER,
2263 buf, 0);
2265 break;
2269 void
2270 idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
2272 isdn_ctrl cmd;
2273 eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]);
2274 static char *connmsg[] =
2275 {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34",
2276 "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90",
2277 "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"};
2278 static u_char dtmf_code[] = {
2279 '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
2282 if ((!ccard) || (!chan))
2283 return;
2285 switch (buffer[0]) {
2286 case DSP_UDATA_INDICATION_SYNC:
2287 eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time);
2288 break;
2289 case DSP_UDATA_INDICATION_DCD_OFF:
2290 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time);
2291 break;
2292 case DSP_UDATA_INDICATION_DCD_ON:
2293 if ((chan->l2prot == ISDN_PROTO_L2_MODEM) &&
2294 (chan->fsm_state == EICON_STATE_WMCONN)) {
2295 chan->fsm_state = EICON_STATE_ACTIVE;
2296 cmd.driver = ccard->myid;
2297 cmd.command = ISDN_STAT_BCONN;
2298 cmd.arg = chan->No;
2299 sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
2300 ccard->interface.statcallb(&cmd);
2302 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time);
2303 eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No,
2304 p->norm, p->options, p->speed, p->delay);
2305 break;
2306 case DSP_UDATA_INDICATION_CTS_OFF:
2307 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time);
2308 break;
2309 case DSP_UDATA_INDICATION_CTS_ON:
2310 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time);
2311 eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No,
2312 p->norm, p->options, p->speed, p->delay);
2313 break;
2314 case DSP_UDATA_INDICATION_DISCONNECT:
2315 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]);
2316 break;
2317 case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED:
2318 eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No,
2319 dtmf_code[buffer[1]]);
2320 cmd.driver = ccard->myid;
2321 cmd.command = ISDN_STAT_AUDIO;
2322 cmd.parm.num[0] = ISDN_AUDIO_DTMF;
2323 cmd.parm.num[1] = dtmf_code[buffer[1]];
2324 cmd.arg = chan->No;
2325 ccard->interface.statcallb(&cmd);
2326 break;
2327 default:
2328 eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]);
2332 void
2333 eicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len)
2335 int i,j,n;
2336 int buflen = len * 3 + 30;
2337 char *p;
2338 struct trace_s {
2339 unsigned long time;
2340 unsigned short size;
2341 unsigned short code;
2342 unsigned char data[1];
2343 } *q;
2345 if (!(p = kmalloc(buflen, GFP_ATOMIC))) {
2346 eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n");
2347 return;
2349 memset(p, 0, buflen);
2350 q = (struct trace_s *)buffer;
2352 if (DebugVar & 512) {
2353 if ((q->code == 3) || (q->code == 4)) {
2354 n = (short) *(q->data);
2355 if (n) {
2356 j = sprintf(p, "DTRC:");
2357 for (i = 0; i < n; i++) {
2358 j += sprintf(p + j, "%02x ", q->data[i+2]);
2360 j += sprintf(p + j, "\n");
2363 } else {
2364 j = sprintf(p, "XLOG: %lx %04x %04x ",
2365 q->time, q->size, q->code);
2367 for (i = 0; i < q->size; i++) {
2368 j += sprintf(p + j, "%02x ", q->data[i]);
2370 j += sprintf(p + j, "\n");
2372 if (strlen(p))
2373 eicon_putstatus(ccard, p);
2374 kfree(p);
2377 void
2378 idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
2380 int tmp;
2381 char tnum[64];
2382 int dlev;
2383 int free_buff;
2384 ulong flags;
2385 struct sk_buff *skb2;
2386 eicon_IND *ind = (eicon_IND *)skb->data;
2387 eicon_chan *chan;
2388 idi_ind_message message;
2389 isdn_ctrl cmd;
2391 if (!ccard) {
2392 eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n");
2393 dev_kfree_skb(skb);
2394 return;
2397 if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
2398 eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n");
2399 dev_kfree_skb(skb);
2400 return;
2403 if ((ind->Ind != 8) && (ind->Ind != 0xc))
2404 dlev = 144;
2405 else
2406 dlev = 128;
2408 eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No,
2409 ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
2411 free_buff = 1;
2412 /* Signal Layer */
2413 if (chan->e.D3Id == ind->IndId) {
2414 idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
2415 switch(ind->Ind) {
2416 case HANGUP:
2417 eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No);
2418 while((skb2 = skb_dequeue(&chan->e.X))) {
2419 dev_kfree_skb(skb2);
2421 save_flags(flags);
2422 cli();
2423 chan->queued = 0;
2424 chan->waitq = 0;
2425 chan->waitpq = 0;
2426 restore_flags(flags);
2427 if (message.e_cau[0] & 0x7f) {
2428 cmd.driver = ccard->myid;
2429 cmd.arg = chan->No;
2430 sprintf(cmd.parm.num,"E%02x%02x",
2431 chan->cause[0]&0x7f, message.e_cau[0]&0x7f);
2432 cmd.command = ISDN_STAT_CAUSE;
2433 ccard->interface.statcallb(&cmd);
2435 chan->cause[0] = 0;
2436 #ifdef CONFIG_ISDN_TTY_FAX
2437 if (!chan->e.B2Id)
2438 chan->fax = 0;
2439 #endif
2440 if (((chan->fsm_state == EICON_STATE_ACTIVE) ||
2441 (chan->fsm_state == EICON_STATE_WMCONN)) ||
2442 ((chan->l2prot == ISDN_PROTO_L2_FAX) &&
2443 (chan->fsm_state == EICON_STATE_OBWAIT))) {
2444 chan->fsm_state = EICON_STATE_NULL;
2445 } else {
2446 if (chan->e.B2Id)
2447 idi_do_req(ccard, chan, REMOVE, 1);
2448 chan->statectrl &= ~WAITING_FOR_HANGUP;
2449 if (chan->statectrl & HAVE_CONN_REQ) {
2450 eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No);
2451 chan->statectrl &= ~HAVE_CONN_REQ;
2452 if ((chan->tskb1) && (chan->tskb2)) {
2453 skb_queue_tail(&chan->e.X, chan->tskb1);
2454 skb_queue_tail(&ccard->sndq, chan->tskb2);
2455 eicon_schedule_tx(ccard);
2457 chan->tskb1 = NULL;
2458 chan->tskb2 = NULL;
2459 } else {
2460 chan->fsm_state = EICON_STATE_NULL;
2461 cmd.driver = ccard->myid;
2462 cmd.arg = chan->No;
2463 cmd.command = ISDN_STAT_DHUP;
2464 ccard->interface.statcallb(&cmd);
2465 eicon_idi_listen_req(ccard, chan);
2468 break;
2469 case INDICATE_IND:
2470 eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No);
2471 if (chan->fsm_state != EICON_STATE_LISTEN) {
2472 eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n",
2473 chan->No, chan->fsm_state);
2474 idi_do_req(ccard, chan, HANGUP, 0);
2475 break;
2477 chan->fsm_state = EICON_STATE_ICALL;
2478 idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
2479 strcpy(chan->cpn, message.cpn + 1);
2480 strcpy(chan->oad, message.oad);
2481 strcpy(chan->dsa, message.dsa);
2482 strcpy(chan->osa, message.osa);
2483 chan->plan = message.plan;
2484 chan->screen = message.screen;
2485 try_stat_icall_again:
2486 cmd.driver = ccard->myid;
2487 cmd.command = ISDN_STAT_ICALL;
2488 cmd.arg = chan->No;
2489 cmd.parm.setup.si1 = chan->si1;
2490 cmd.parm.setup.si2 = chan->si2;
2491 strcpy(tnum, chan->cpn);
2492 if (strlen(chan->dsa)) {
2493 strcat(tnum, ".");
2494 strcat(tnum, chan->dsa);
2496 tnum[ISDN_MSNLEN - 1] = 0;
2497 strcpy(cmd.parm.setup.eazmsn, tnum);
2498 strcpy(tnum, chan->oad);
2499 if (strlen(chan->osa)) {
2500 strcat(tnum, ".");
2501 strcat(tnum, chan->osa);
2503 tnum[ISDN_MSNLEN - 1] = 0;
2504 strcpy(cmd.parm.setup.phone, tnum);
2505 cmd.parm.setup.plan = chan->plan;
2506 cmd.parm.setup.screen = chan->screen;
2507 tmp = ccard->interface.statcallb(&cmd);
2508 switch(tmp) {
2509 case 0: /* no user responding */
2510 idi_do_req(ccard, chan, HANGUP, 0);
2511 chan->fsm_state = EICON_STATE_NULL;
2512 break;
2513 case 1: /* alert */
2514 eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No);
2515 if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) {
2516 chan->fsm_state = EICON_STATE_ICALL;
2517 idi_do_req(ccard, chan, CALL_ALERT, 0);
2519 break;
2520 case 2: /* reject */
2521 eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No);
2522 idi_do_req(ccard, chan, REJECT, 0);
2523 break;
2524 case 3: /* incomplete number */
2525 eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
2526 chan->fsm_state = EICON_STATE_ICALLW;
2527 break;
2529 break;
2530 case INFO_IND:
2531 eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No);
2532 if ((chan->fsm_state == EICON_STATE_ICALLW) &&
2533 (message.cpn[0])) {
2534 strcat(chan->cpn, message.cpn + 1);
2535 goto try_stat_icall_again;
2537 break;
2538 case CALL_IND:
2539 eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No);
2540 if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) {
2541 chan->fsm_state = EICON_STATE_IBWAIT;
2542 cmd.driver = ccard->myid;
2543 cmd.command = ISDN_STAT_DCONN;
2544 cmd.arg = chan->No;
2545 ccard->interface.statcallb(&cmd);
2546 switch(chan->l2prot) {
2547 case ISDN_PROTO_L2_FAX:
2548 #ifdef CONFIG_ISDN_TTY_FAX
2549 if (chan->fax)
2550 chan->fax->phase = ISDN_FAX_PHASE_A;
2551 #endif
2552 break;
2553 case ISDN_PROTO_L2_MODEM:
2554 /* do nothing, wait for connect */
2555 break;
2556 case ISDN_PROTO_L2_TRANS:
2557 idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
2558 break;
2559 default:
2560 /* On most incoming calls we use automatic connect */
2561 /* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
2563 } else {
2564 if (chan->fsm_state != EICON_STATE_ACTIVE)
2565 idi_hangup(ccard, chan);
2567 break;
2568 case CALL_CON:
2569 eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
2570 if (chan->fsm_state == EICON_STATE_OCALL) {
2571 chan->fsm_state = EICON_STATE_OBWAIT;
2572 cmd.driver = ccard->myid;
2573 cmd.command = ISDN_STAT_DCONN;
2574 cmd.arg = chan->No;
2575 ccard->interface.statcallb(&cmd);
2577 /* check if old NetID has been removed */
2578 if (chan->e.B2Id) {
2579 eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
2580 chan->No, chan->e.B2Id);
2581 idi_do_req(ccard, chan, REMOVE, 1);
2584 idi_do_req(ccard, chan, ASSIGN, 1);
2585 idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
2586 #ifdef CONFIG_ISDN_TTY_FAX
2587 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2588 if (chan->fax)
2589 chan->fax->phase = ISDN_FAX_PHASE_A;
2591 #endif
2592 } else
2593 idi_hangup(ccard, chan);
2594 break;
2595 case AOC_IND:
2596 eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No);
2597 break;
2598 default:
2599 eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
2602 /* Network Layer */
2603 else if (chan->e.B2Id == ind->IndId) {
2605 if (chan->No == ccard->nchannels) {
2606 /* Management Indication */
2607 if (ind->Ind == 0x04) { /* Trace_Ind */
2608 eicon_parse_trace(ccard, ind->RBuffer.P, ind->RBuffer.length);
2609 } else {
2610 idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
2611 chan->fsm_state = 1;
2614 else
2615 switch(ind->Ind) {
2616 case IDI_N_CONNECT_ACK:
2617 eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
2618 if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
2619 chan->fsm_state = EICON_STATE_WMCONN;
2620 break;
2622 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2623 #ifdef CONFIG_ISDN_TTY_FAX
2624 chan->fsm_state = EICON_STATE_ACTIVE;
2625 idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
2626 if (chan->fax) {
2627 if (chan->fax->phase == ISDN_FAX_PHASE_B) {
2628 idi_fax_send_header(ccard, chan, 2);
2629 cmd.driver = ccard->myid;
2630 cmd.command = ISDN_STAT_FAXIND;
2631 cmd.arg = chan->No;
2632 chan->fax->r_code = ISDN_TTY_FAX_DCS;
2633 ccard->interface.statcallb(&cmd);
2636 else {
2637 eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
2639 #endif
2640 break;
2642 chan->fsm_state = EICON_STATE_ACTIVE;
2643 cmd.driver = ccard->myid;
2644 cmd.command = ISDN_STAT_BCONN;
2645 cmd.arg = chan->No;
2646 strcpy(cmd.parm.num, "64000");
2647 ccard->interface.statcallb(&cmd);
2648 break;
2649 case IDI_N_CONNECT:
2650 eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
2651 chan->e.IndCh = ind->IndCh;
2652 if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
2653 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2654 break;
2656 if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
2657 chan->fsm_state = EICON_STATE_WMCONN;
2658 break;
2660 chan->fsm_state = EICON_STATE_ACTIVE;
2661 cmd.driver = ccard->myid;
2662 cmd.command = ISDN_STAT_BCONN;
2663 cmd.arg = chan->No;
2664 strcpy(cmd.parm.num, "64000");
2665 ccard->interface.statcallb(&cmd);
2666 break;
2667 case IDI_N_DISC:
2668 eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No);
2669 if (chan->e.B2Id) {
2670 while((skb2 = skb_dequeue(&chan->e.X))) {
2671 dev_kfree_skb(skb2);
2673 idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
2674 idi_do_req(ccard, chan, REMOVE, 1);
2676 #ifdef CONFIG_ISDN_TTY_FAX
2677 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2678 idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
2679 idi_fax_hangup(ccard, chan);
2681 #endif
2682 chan->e.IndCh = 0;
2683 save_flags(flags);
2684 cli();
2685 chan->queued = 0;
2686 chan->waitq = 0;
2687 chan->waitpq = 0;
2688 restore_flags(flags);
2689 idi_do_req(ccard, chan, HANGUP, 0);
2690 if (chan->fsm_state == EICON_STATE_ACTIVE) {
2691 cmd.driver = ccard->myid;
2692 cmd.command = ISDN_STAT_BHUP;
2693 cmd.arg = chan->No;
2694 ccard->interface.statcallb(&cmd);
2695 chan->fsm_state = EICON_STATE_NULL;
2696 chan->statectrl |= WAITING_FOR_HANGUP;
2698 #ifdef CONFIG_ISDN_TTY_FAX
2699 chan->fax = 0;
2700 #endif
2701 break;
2702 case IDI_N_DISC_ACK:
2703 eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
2704 #ifdef CONFIG_ISDN_TTY_FAX
2705 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2706 idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
2707 idi_fax_hangup(ccard, chan);
2709 #endif
2710 break;
2711 case IDI_N_DATA_ACK:
2712 eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
2713 break;
2714 case IDI_N_DATA:
2715 skb_pull(skb, sizeof(eicon_IND) - 1);
2716 eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
2717 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2718 #ifdef CONFIG_ISDN_TTY_FAX
2719 idi_faxdata_rcv(ccard, chan, skb);
2720 #endif
2721 } else {
2722 ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
2723 free_buff = 0;
2725 break;
2726 case IDI_N_UDATA:
2727 idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
2728 break;
2729 #ifdef CONFIG_ISDN_TTY_FAX
2730 case IDI_N_EDATA:
2731 idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
2732 break;
2733 #endif
2734 default:
2735 eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
2738 else {
2739 eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No);
2741 if (free_buff)
2742 dev_kfree_skb(skb);
2746 idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
2748 ulong flags;
2749 isdn_ctrl cmd;
2751 if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
2752 /* I dont know why this happens, should not ! */
2753 /* just ignoring this RC */
2754 eicon_log(ccard, 16, "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No,
2755 ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
2756 return 1;
2759 /* Management Interface */
2760 if (chan->No == ccard->nchannels) {
2761 /* Managementinterface: changing state */
2762 if (chan->e.Req != 0x02)
2763 chan->fsm_state = 1;
2766 /* Remove an Id */
2767 if (chan->e.Req == REMOVE) {
2768 if (ack->Reference != chan->e.ref) {
2769 /* This should not happen anymore */
2770 eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
2771 ack->Reference, chan->e.ref);
2773 save_flags(flags);
2774 cli();
2775 ccard->IdTable[ack->RcId] = NULL;
2776 eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
2777 ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
2778 if (!chan->e.ReqCh)
2779 chan->e.D3Id = 0;
2780 else
2781 chan->e.B2Id = 0;
2782 restore_flags(flags);
2783 return 1;
2786 /* Signal layer */
2787 if (!chan->e.ReqCh) {
2788 eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
2789 ack->RcId, ack->RcCh, ack->Reference);
2790 } else {
2791 /* Network layer */
2792 switch(chan->e.Req & 0x0f) {
2793 case IDI_N_CONNECT:
2794 chan->e.IndCh = ack->RcCh;
2795 eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
2796 ack->RcId, ack->RcCh, ack->Reference);
2797 break;
2798 case IDI_N_MDATA:
2799 case IDI_N_DATA:
2800 if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
2801 if (chan->queued) {
2802 cmd.driver = ccard->myid;
2803 cmd.command = ISDN_STAT_BSENT;
2804 cmd.arg = chan->No;
2805 cmd.parm.length = chan->waitpq;
2806 ccard->interface.statcallb(&cmd);
2808 save_flags(flags);
2809 cli();
2810 chan->waitpq = 0;
2811 restore_flags(flags);
2812 #ifdef CONFIG_ISDN_TTY_FAX
2813 if (chan->l2prot == ISDN_PROTO_L2_FAX) {
2814 if (((chan->queued - chan->waitq) < 1) &&
2815 (chan->fax2.Eop)) {
2816 chan->fax2.Eop = 0;
2817 if (chan->fax) {
2818 cmd.driver = ccard->myid;
2819 cmd.command = ISDN_STAT_FAXIND;
2820 cmd.arg = chan->No;
2821 chan->fax->r_code = ISDN_TTY_FAX_SENT;
2822 ccard->interface.statcallb(&cmd);
2824 else {
2825 eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n");
2829 #endif
2831 save_flags(flags);
2832 cli();
2833 chan->queued -= chan->waitq;
2834 if (chan->queued < 0) chan->queued = 0;
2835 restore_flags(flags);
2836 break;
2837 default:
2838 eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
2839 ack->RcId, ack->RcCh, ack->Reference);
2842 return 1;
2845 void
2846 idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
2848 int j;
2849 ulong flags;
2850 eicon_RC *ack = (eicon_RC *)skb->data;
2851 eicon_chan *chan;
2852 isdn_ctrl cmd;
2853 int dCh = -1;
2855 if (!ccard) {
2856 eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n");
2857 dev_kfree_skb(skb);
2858 return;
2861 save_flags(flags);
2862 cli();
2863 if ((chan = ccard->IdTable[ack->RcId]) != NULL)
2864 dCh = chan->No;
2865 restore_flags(flags);
2867 switch (ack->Rc) {
2868 case OK_FC:
2869 case N_FLOW_CONTROL:
2870 case ASSIGN_RC:
2871 eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n",
2872 dCh, ack->Rc);
2873 break;
2874 case READY_INT:
2875 case TIMER_INT:
2876 /* we do nothing here */
2877 break;
2879 case OK:
2880 if (!chan) {
2881 eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh);
2882 break;
2884 if (!idi_handle_ack_ok(ccard, chan, ack))
2885 chan = NULL;
2886 break;
2888 case ASSIGN_OK:
2889 if (chan) {
2890 eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
2891 chan->No, chan->e.D3Id, chan->e.B2Id);
2893 save_flags(flags);
2894 cli();
2895 for(j = 0; j < ccard->nchannels + 1; j++) {
2896 if ((ccard->bch[j].e.ref == ack->Reference) &&
2897 (ccard->bch[j].e.Req == ASSIGN)) {
2898 if (!ccard->bch[j].e.ReqCh)
2899 ccard->bch[j].e.D3Id = ack->RcId;
2900 else
2901 ccard->bch[j].e.B2Id = ack->RcId;
2902 ccard->IdTable[ack->RcId] = &ccard->bch[j];
2903 chan = &ccard->bch[j];
2904 eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j,
2905 ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
2906 break;
2909 restore_flags(flags);
2910 if (j > ccard->nchannels) {
2911 eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n",
2912 ack->Reference, ack->RcId);
2914 break;
2916 case OUT_OF_RESOURCES:
2917 case UNKNOWN_COMMAND:
2918 case WRONG_COMMAND:
2919 case WRONG_ID:
2920 case WRONG_CH:
2921 case UNKNOWN_IE:
2922 case WRONG_IE:
2923 default:
2924 if (!chan) {
2925 eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh);
2926 break;
2927 } else
2928 switch (chan->e.Req) {
2929 case 12: /* Alert */
2930 eicon_log(ccard, 2, "eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n",
2931 dCh, ack->Rc, ack->RcId, ack->RcCh);
2932 break;
2933 default:
2934 if (dCh != ccard->nchannels)
2935 eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
2936 dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
2938 if (dCh == ccard->nchannels) { /* Management */
2939 chan->fsm_state = 2;
2940 eicon_log(ccard, 8, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
2941 dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
2942 } else if (dCh >= 0) {
2943 /* any other channel */
2944 /* card reports error: we hangup */
2945 idi_hangup(ccard, chan);
2946 cmd.driver = ccard->myid;
2947 cmd.command = ISDN_STAT_DHUP;
2948 cmd.arg = chan->No;
2949 ccard->interface.statcallb(&cmd);
2952 save_flags(flags);
2953 cli();
2954 if (chan) {
2955 chan->e.ref = 0;
2956 chan->e.busy = 0;
2958 restore_flags(flags);
2959 dev_kfree_skb(skb);
2960 eicon_schedule_tx(ccard);
2964 idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que)
2966 struct sk_buff *xmit_skb;
2967 struct sk_buff *skb2;
2968 eicon_REQ *reqbuf;
2969 eicon_chan_ptr *chan2;
2970 int len, plen = 0, offset = 0;
2971 unsigned long flags;
2973 if ((!card) || (!chan)) {
2974 eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n");
2975 return -1;
2978 if (chan->fsm_state != EICON_STATE_ACTIVE) {
2979 eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state);
2980 return -ENODEV;
2983 len = skb->len;
2984 if (len > EICON_MAX_QUEUE) /* too much for the shared memory */
2985 return -1;
2986 if (!len)
2987 return 0;
2988 if (chan->queued + len > EICON_MAX_QUEUE)
2989 return 0;
2991 eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
2993 save_flags(flags);
2994 cli();
2995 while(offset < len) {
2997 plen = ((len - offset) > 270) ? 270 : len - offset;
2999 xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC);
3000 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
3002 if ((!xmit_skb) || (!skb2)) {
3003 restore_flags(flags);
3004 eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
3005 if (xmit_skb)
3006 dev_kfree_skb(skb);
3007 if (skb2)
3008 dev_kfree_skb(skb2);
3009 return -ENOMEM;
3012 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
3013 chan2->ptr = chan;
3015 reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
3016 if (((len - offset) > 270) &&
3017 (chan->l2prot != ISDN_PROTO_L2_MODEM) &&
3018 (chan->l2prot != ISDN_PROTO_L2_FAX) &&
3019 (chan->l2prot != ISDN_PROTO_L2_TRANS)) {
3020 reqbuf->Req = IDI_N_MDATA;
3021 } else {
3022 reqbuf->Req = IDI_N_DATA;
3023 /* if (ack) reqbuf->Req |= N_D_BIT; */
3025 reqbuf->ReqCh = chan->e.IndCh;
3026 reqbuf->ReqId = 1;
3027 memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen);
3028 reqbuf->XBuffer.length = plen;
3029 reqbuf->Reference = 1; /* Net Entity */
3031 skb_queue_tail(&chan->e.X, xmit_skb);
3032 skb_queue_tail(&card->sndq, skb2);
3034 offset += plen;
3036 if (que)
3037 chan->queued += len;
3038 restore_flags(flags);
3039 eicon_schedule_tx(card);
3040 dev_kfree_skb(skb);
3041 return len;
3046 eicon_idi_manage_assign(eicon_card *card)
3048 struct sk_buff *skb;
3049 struct sk_buff *skb2;
3050 eicon_REQ *reqbuf;
3051 eicon_chan *chan;
3052 eicon_chan_ptr *chan2;
3054 chan = &(card->bch[card->nchannels]);
3056 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
3057 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
3059 if ((!skb) || (!skb2)) {
3060 eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n");
3061 if (skb)
3062 dev_kfree_skb(skb);
3063 if (skb2)
3064 dev_kfree_skb(skb2);
3065 return -ENOMEM;
3068 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
3069 chan2->ptr = chan;
3071 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
3073 reqbuf->XBuffer.P[0] = 0;
3074 reqbuf->Req = ASSIGN;
3075 reqbuf->ReqCh = 0;
3076 reqbuf->ReqId = 0xe0;
3077 reqbuf->XBuffer.length = 1;
3078 reqbuf->Reference = 2; /* Man Entity */
3080 skb_queue_tail(&chan->e.X, skb);
3081 skb_queue_tail(&card->sndq, skb2);
3082 eicon_schedule_tx(card);
3083 return(0);
3088 eicon_idi_manage_remove(eicon_card *card)
3090 struct sk_buff *skb;
3091 struct sk_buff *skb2;
3092 eicon_REQ *reqbuf;
3093 eicon_chan *chan;
3094 eicon_chan_ptr *chan2;
3096 chan = &(card->bch[card->nchannels]);
3098 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
3099 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
3101 if ((!skb) || (!skb2)) {
3102 eicon_log(card, 1, "idi_err: alloc_skb failed in manage_remove()\n");
3103 if (skb)
3104 dev_kfree_skb(skb);
3105 if (skb2)
3106 dev_kfree_skb(skb2);
3107 return -ENOMEM;
3110 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
3111 chan2->ptr = chan;
3113 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
3115 reqbuf->Req = REMOVE;
3116 reqbuf->ReqCh = 0;
3117 reqbuf->ReqId = 1;
3118 reqbuf->XBuffer.length = 0;
3119 reqbuf->Reference = 2; /* Man Entity */
3121 skb_queue_tail(&chan->e.X, skb);
3122 skb_queue_tail(&card->sndq, skb2);
3123 eicon_schedule_tx(card);
3124 return(0);
3129 eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
3131 int l = 0;
3132 int ret = 0;
3133 int timeout;
3134 int i;
3135 struct sk_buff *skb;
3136 struct sk_buff *skb2;
3137 eicon_REQ *reqbuf;
3138 eicon_chan *chan;
3139 eicon_chan_ptr *chan2;
3141 chan = &(card->bch[card->nchannels]);
3143 if (!(chan->e.D3Id)) {
3144 chan->e.D3Id = 1;
3145 while((skb2 = skb_dequeue(&chan->e.X)))
3146 dev_kfree_skb(skb2);
3147 chan->e.busy = 0;
3149 if ((ret = eicon_idi_manage_assign(card))) {
3150 chan->e.D3Id = 0;
3151 return(ret);
3154 timeout = jiffies + 50;
3155 while (timeout > jiffies) {
3156 if (chan->e.B2Id) break;
3157 SLEEP(10);
3159 if (!chan->e.B2Id) {
3160 chan->e.D3Id = 0;
3161 return -EIO;
3165 chan->fsm_state = 0;
3167 if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
3168 eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n");
3169 return -ENOMEM;
3171 if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
3172 kfree(manbuf);
3173 return -EFAULT;
3176 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
3177 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
3179 if ((!skb) || (!skb2)) {
3180 eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n");
3181 if (skb)
3182 dev_kfree_skb(skb);
3183 if (skb2)
3184 dev_kfree_skb(skb2);
3185 kfree(manbuf);
3186 return -ENOMEM;
3189 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
3190 chan2->ptr = chan;
3192 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
3194 reqbuf->XBuffer.P[l++] = ESC;
3195 reqbuf->XBuffer.P[l++] = 6;
3196 reqbuf->XBuffer.P[l++] = 0x80;
3197 for (i = 0; i < manbuf->length[0]; i++)
3198 reqbuf->XBuffer.P[l++] = manbuf->data[i];
3199 reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
3201 reqbuf->XBuffer.P[l++] = 0;
3202 reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
3203 reqbuf->ReqCh = 0;
3204 reqbuf->ReqId = 1;
3205 reqbuf->XBuffer.length = l;
3206 reqbuf->Reference = 2; /* Man Entity */
3208 skb_queue_tail(&chan->e.X, skb);
3209 skb_queue_tail(&card->sndq, skb2);
3211 manbuf->count = 0;
3212 manbuf->pos = 0;
3214 eicon_schedule_tx(card);
3216 timeout = jiffies + 50;
3217 while (timeout > jiffies) {
3218 if (chan->fsm_state) break;
3219 SLEEP(10);
3221 if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
3222 kfree(manbuf);
3223 return -EIO;
3225 if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
3226 kfree(manbuf);
3227 return -EFAULT;
3230 kfree(manbuf);
3231 return(0);