* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / isdn / isdn_ttyfax.c
blob7665aa812c266cd6da310a1a40e0fbcd6446b648
1 /* $Id: isdn_ttyfax.c,v 1.3 1999/08/22 20:26:12 calle Exp $
2 * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
4 * Copyright 1999 by Armin Schindler (mac@melware.de)
5 * Copyright 1999 by Ralf Spachmann (mel@melware.de)
6 * Copyright 1999 by Cytronics & Melware
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * $Log: isdn_ttyfax.c,v $
23 * Revision 1.3 1999/08/22 20:26:12 calle
24 * backported changes from kernel 2.3.14:
25 * - several #include "config.h" gone, others come.
26 * - "struct device" changed to "struct net_device" in 2.3.14, added a
27 * define in isdn_compat.h for older kernel versions.
29 * Revision 1.2 1999/08/05 10:36:10 armin
30 * Bugfix: kernel oops on getting revision.
32 * Revision 1.1 1999/07/31 12:59:50 armin
33 * Added tty fax capabilities.
38 #undef ISDN_TTY_FAX_STAT_DEBUG
39 #undef ISDN_TTY_FAX_CMD_DEBUG
41 #define __NO_VERSION__
42 #include <linux/module.h>
43 #include <linux/isdn.h>
44 #include "isdn_common.h"
45 #include "isdn_tty.h"
46 #include "isdn_ttyfax.h"
49 static char *isdn_tty_fax_revision = "$Revision: 1.3 $";
51 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
53 static char *
54 isdn_getrev(const char *revision)
56 char *rev;
57 char *p;
59 if ((p = strchr(revision, ':'))) {
60 rev = p + 2;
61 p = strchr(rev, '$');
62 *--p = 0;
63 } else
64 rev = "???";
65 return rev;
70 * Fax Class 2 Modem results
73 static void isdn_tty_fax_modem_result(int code, modem_info * info)
75 atemu *m = &info->emu;
76 T30_s *f = info->fax;
77 char rs[50];
78 char rss[50];
79 char *rp;
80 int i;
81 static char *msg[] =
82 {"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
83 "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
84 "+FCFR", "+FPTS:", "+FET:" };
87 isdn_tty_at_cout("\r\n", info);
88 isdn_tty_at_cout(msg[code], info);
90 #ifdef ISDN_TTY_FAX_CMD_DEBUG
91 printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n",
92 msg[code], info->line);
93 #endif
94 switch (code) {
95 case 0: /* OK */
96 break;
97 case 1: /* ERROR */
98 break;
99 case 2: /* +FCON */
100 /* Append CPN, if enabled */
101 if ((m->mdmreg[REG_CPN] & BIT_CPN) &&
102 (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
103 sprintf(rs, "/%s", m->cpn);
104 isdn_tty_at_cout(rs, info);
106 info->online = 1;
107 f->fet = 0;
108 if (f->phase == ISDN_FAX_PHASE_A)
109 f->phase = ISDN_FAX_PHASE_B;
110 break;
111 case 3: /* +FCSI */
112 case 8: /* +FTSI */
113 sprintf(rs, "\"%s\"", f->r_id);
114 isdn_tty_at_cout(rs, info);
115 break;
116 case 4: /* +FDIS */
117 rs[0] = 0;
118 rp = &f->r_resolution;
119 for(i = 0; i < 8; i++) {
120 sprintf(rss, "%c%s", rp[i] + 48,
121 (i < 7) ? "," : "");
122 strcat(rs, rss);
124 isdn_tty_at_cout(rs, info);
125 #ifdef ISDN_TTY_FAX_CMD_DEBUG
126 printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
127 rs, info->line);
128 #endif
129 break;
130 case 5: /* +FHNG */
131 sprintf(rs, "%d", f->code);
132 isdn_tty_at_cout(rs, info);
133 info->faxonline = 0;
134 break;
135 case 6: /* +FDCS */
136 rs[0] = 0;
137 rp = &f->r_resolution;
138 for(i = 0; i < 8; i++) {
139 sprintf(rss, "%c%s", rp[i] + 48,
140 (i < 7) ? "," : "");
141 strcat(rs, rss);
143 isdn_tty_at_cout(rs, info);
144 #ifdef ISDN_TTY_FAX_CMD_DEBUG
145 printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
146 rs, info->line);
147 #endif
148 break;
149 case 7: /* CONNECT */
150 info->faxonline |= 2;
151 break;
152 case 9: /* FCFR */
153 break;
154 case 10: /* FPTS */
155 isdn_tty_at_cout("1", info);
156 break;
157 case 11: /* FET */
158 sprintf(rs, "%d", f->fet);
159 isdn_tty_at_cout(rs, info);
160 break;
163 isdn_tty_at_cout("\r\n", info);
165 switch (code) {
166 case 7: /* CONNECT */
167 info->online = 2;
168 if (info->faxonline & 1) {
169 sprintf(rs, "%c", XON);
170 isdn_tty_at_cout(rs, info);
172 break;
177 isdn_tty_fax_command(modem_info * info)
179 T30_s *f = info->fax;
180 char rs[10];
182 #ifdef ISDN_TTY_FAX_CMD_DEBUG
183 printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
184 f->r_code, info->line);
185 #endif
186 switch(f->r_code) {
187 case ISDN_TTY_FAX_FCON:
188 info->faxonline = 1;
189 isdn_tty_fax_modem_result(2, info); /* +FCON */
190 return(0);
191 case ISDN_TTY_FAX_FCON_I:
192 info->faxonline = 16;
193 isdn_tty_fax_modem_result(2, info); /* +FCON */
194 return(0);
195 case ISDN_TTY_FAX_RID:
196 if (info->faxonline & 1)
197 isdn_tty_fax_modem_result(3, info); /* +FCSI */
198 if (info->faxonline & 16)
199 isdn_tty_fax_modem_result(8, info); /* +FTSI */
200 return(0);
201 case ISDN_TTY_FAX_DIS:
202 isdn_tty_fax_modem_result(4, info); /* +FDIS */
203 return(0);
204 case ISDN_TTY_FAX_HNG:
205 if (f->phase == ISDN_FAX_PHASE_C) {
206 if (f->direction == ISDN_TTY_FAX_CONN_IN) {
207 sprintf(rs, "%c%c", DLE, ETX);
208 isdn_tty_at_cout(rs, info);
209 } else {
210 sprintf(rs, "%c", 0x18);
211 isdn_tty_at_cout(rs, info);
213 info->faxonline &= ~2; /* leave data mode */
214 info->online = 1;
216 f->phase = ISDN_FAX_PHASE_E;
217 isdn_tty_fax_modem_result(5, info); /* +FHNG */
218 isdn_tty_fax_modem_result(0, info); /* OK */
219 return(0);
220 case ISDN_TTY_FAX_DCS:
221 isdn_tty_fax_modem_result(6, info); /* +FDCS */
222 isdn_tty_fax_modem_result(7, info); /* CONNECT */
223 f->phase = ISDN_FAX_PHASE_C;
224 return(0);
225 case ISDN_TTY_FAX_TRAIN_OK:
226 isdn_tty_fax_modem_result(6, info); /* +FDCS */
227 isdn_tty_fax_modem_result(0, info); /* OK */
228 return(0);
229 case ISDN_TTY_FAX_SENT:
230 isdn_tty_fax_modem_result(0, info); /* OK */
231 return(0);
232 case ISDN_TTY_FAX_CFR:
233 isdn_tty_fax_modem_result(9, info); /* +FCFR */
234 return(0);
235 case ISDN_TTY_FAX_ET:
236 sprintf(rs, "%c%c", DLE, ETX);
237 isdn_tty_at_cout(rs, info);
238 isdn_tty_fax_modem_result(10, info); /* +FPTS */
239 isdn_tty_fax_modem_result(11, info); /* +FET */
240 isdn_tty_fax_modem_result(0, info); /* OK */
241 info->faxonline &= ~2; /* leave data mode */
242 info->online = 1;
243 f->phase = ISDN_FAX_PHASE_D;
244 return(0);
245 case ISDN_TTY_FAX_PTS:
246 isdn_tty_fax_modem_result(10, info); /* +FPTS */
247 if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
248 if (f->fet == 1)
249 f->phase = ISDN_FAX_PHASE_B;
250 if (f->fet == 0)
251 isdn_tty_fax_modem_result(0, info); /* OK */
253 return(0);
254 case ISDN_TTY_FAX_EOP:
255 info->faxonline &= ~2; /* leave data mode */
256 info->online = 1;
257 f->phase = ISDN_FAX_PHASE_D;
258 return(0);
261 return(-1);
265 void
266 isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb)
268 __u8 LeftMask;
269 __u8 RightMask;
270 __u8 fBit;
271 __u8 Data;
272 int i;
274 if (!info->fax->bor) {
275 for(i = 0; i < skb->len; i++) {
276 Data = skb->data[i];
277 for (
278 LeftMask = 0x80, RightMask = 0x01;
279 LeftMask > RightMask;
280 LeftMask >>= 1, RightMask <<= 1
282 fBit = (Data & LeftMask);
283 if (Data & RightMask)
284 Data |= LeftMask;
285 else
286 Data &= ~LeftMask;
287 if (fBit)
288 Data |= RightMask;
289 else
290 Data &= ~RightMask;
293 skb->data[i] = Data;
299 * Parse AT+F.. FAX class 2 commands
302 int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
304 atemu *m = &info->emu;
305 T30_s *f = info->fax;
306 isdn_ctrl cmd;
307 int par;
308 char rs[50];
309 char rss[50];
310 int maxdccval[]={1,5,2,2,3,2,0,7};
312 /* FAA still unchanged */
313 if (!strncmp(p[0], "AA", 2)) { /* TODO */
314 p[0] += 2;
315 switch (*p[0]) {
316 case '?':
317 p[0]++;
318 sprintf(rs, "\r\n%d", 0);
319 isdn_tty_at_cout(rs, info);
320 break;
321 case '=':
322 p[0]++;
323 par = isdn_getnum(p);
324 if ((par < 0) || (par > 255))
325 PARSE_ERROR1;
326 break;
327 default:
328 PARSE_ERROR1;
330 return 0;
333 /* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
334 if (!strncmp(p[0], "BADLIN", 6)) {
335 p[0] += 6;
336 switch (*p[0]) {
337 case '?':
338 p[0]++;
339 sprintf(rs, "\r\n%d",f->badlin);
340 isdn_tty_at_cout(rs, info);
341 break;
342 case '=':
343 p[0]++;
344 if (*p[0] == '?')
346 p[0]++;
347 sprintf(rs, "\r\n0-255");
348 isdn_tty_at_cout(rs, info);
350 else
352 par = isdn_getnum(p);
353 if ((par < 0) || (par > 255))
354 PARSE_ERROR1;
355 f->badlin = par;
356 #ifdef ISDN_TTY_FAX_STAT_DEBUG
357 printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
358 #endif
360 break;
361 default:
362 PARSE_ERROR1;
364 return 0;
367 /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */
368 if (!strncmp(p[0], "BADMUL", 6)){
369 p[0] +=6;
370 switch (*p[0]) {
371 case '?':
372 p[0]++;
373 sprintf(rs, "\r\n%d", f->badmul);
374 isdn_tty_at_cout(rs, info);
375 break;
376 case '=':
377 p[0]++;
378 if (*p[0] == '?')
380 p[0]++;
381 sprintf(rs, "\r\n0-255");
382 isdn_tty_at_cout(rs, info);
384 else
386 par = isdn_getnum(p);
387 if ((par < 0) || (par > 255))
388 PARSE_ERROR1;
389 f->badmul = par;
390 #ifdef ISDN_TTY_FAX_STAT_DEBUG
391 printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
392 #endif
394 break;
395 default:
396 PARSE_ERROR1;
398 return 0;
401 /* BOR=n - Phase C bit order, 0=direct, 1=reverse */
402 if (!strncmp(p[0], "BOR", 3)){
403 p[0] +=3;
404 switch (*p[0]) {
405 case '?':
406 p[0]++;
407 sprintf(rs, "\r\n%d", f->bor);
408 isdn_tty_at_cout(rs, info);
409 break;
410 case '=':
411 p[0]++;
412 if (*p[0] == '?')
414 p[0]++;
415 sprintf(rs, "\r\n0,1");
416 isdn_tty_at_cout(rs, info);
418 else
420 par = isdn_getnum(p);
421 if ((par < 0) || (par > 1))
422 PARSE_ERROR1;
423 f->bor = par;
424 #ifdef ISDN_TTY_FAX_STAT_DEBUG
425 printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
426 #endif
428 break;
429 default:
430 PARSE_ERROR1;
432 return 0;
435 /* NBC=n - No Best Capabilities */
436 if (!strncmp(p[0], "NBC", 3)){
437 p[0] +=3;
438 switch (*p[0]) {
439 case '?':
440 p[0]++;
441 sprintf(rs, "\r\n%d", f->nbc);
442 isdn_tty_at_cout(rs, info);
443 break;
444 case '=':
445 p[0]++;
446 if (*p[0] == '?')
448 p[0]++;
449 sprintf(rs, "\r\n0,1");
450 isdn_tty_at_cout(rs, info);
452 else
454 par = isdn_getnum(p);
455 if ((par < 0) || (par > 1))
456 PARSE_ERROR1;
457 f->nbc = par;
458 #ifdef ISDN_TTY_FAX_STAT_DEBUG
459 printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
460 #endif
462 break;
463 default:
464 PARSE_ERROR1;
466 return 0;
469 /* BUF? - Readonly buffersize readout */
470 if (!strncmp(p[0], "BUF?", 4)) {
471 p[0] += 4;
472 #ifdef ISDN_TTY_FAX_STAT_DEBUG
473 printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
474 #endif
475 p[0]++;
476 sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
477 isdn_tty_at_cout(rs, info);
478 return 0;
481 /* CIG=string - local fax station id string for polling rx */
482 if (!strncmp(p[0], "CIG", 3)) {
483 int i, r;
484 p[0] += 3;
485 switch (*p[0]) {
486 case '?':
487 p[0]++;
488 sprintf(rs, "\r\n\"%s\"", f->pollid);
489 isdn_tty_at_cout(rs, info);
490 break;
491 case '=':
492 p[0]++;
493 if (*p[0] == '?')
495 p[0]++;
496 sprintf(rs, "\r\n\"STRING\"");
497 isdn_tty_at_cout(rs, info);
499 else
501 if (*p[0] =='"')
502 p[0]++;
503 for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
505 f->pollid[i] = *p[0]++;
507 if (*p[0] =='"')
508 p[0]++;
509 for(r=i; r < FAXIDLEN; r++)
511 f->pollid[r] = 32;
513 f->pollid[FAXIDLEN-1] = 0;
514 #ifdef ISDN_TTY_FAX_STAT_DEBUG
515 printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
516 #endif
518 break;
519 default:
520 PARSE_ERROR1;
522 return 0;
525 /* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
526 if (!strncmp(p[0], "CQ", 2)) {
527 p[0] += 2;
528 switch (*p[0]) {
529 case '?':
530 p[0]++;
531 sprintf(rs, "\r\n%d", f->cq);
532 isdn_tty_at_cout(rs, info);
533 break;
534 case '=':
535 p[0]++;
536 if (*p[0] == '?')
538 p[0]++;
539 sprintf(rs, "\r\n0,1,2");
540 isdn_tty_at_cout(rs, info);
542 else
544 par = isdn_getnum(p);
545 if ((par < 0) || (par > 2))
546 PARSE_ERROR1;
547 f->cq = par;
548 #ifdef ISDN_TTY_FAX_STAT_DEBUG
549 printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
550 #endif
552 break;
553 default:
554 PARSE_ERROR1;
556 return 0;
559 /* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
560 if (!strncmp(p[0], "CR", 2)) {
561 p[0] += 2;
562 switch (*p[0]) {
563 case '?':
564 p[0]++;
565 sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
566 isdn_tty_at_cout(rs, info);
567 break;
568 case '=':
569 p[0]++;
570 if (*p[0] == '?')
572 p[0]++;
573 sprintf(rs, "\r\n0,1"); /* display online help */
574 isdn_tty_at_cout(rs, info);
576 else
578 par = isdn_getnum(p);
579 if ((par < 0) || (par > 1))
580 PARSE_ERROR1;
581 f->cr = par;
582 #ifdef ISDN_TTY_FAX_STAT_DEBUG
583 printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
584 #endif
586 break;
587 default:
588 PARSE_ERROR1;
590 return 0;
593 /* CTCRTY=value - ECM retry count */
594 if (!strncmp(p[0], "CTCRTY", 6)){
595 p[0] +=6;
596 switch (*p[0]) {
597 case '?':
598 p[0]++;
599 sprintf(rs, "\r\n%d",f->ctcrty);
600 isdn_tty_at_cout(rs, info);
601 break;
602 case '=':
603 p[0]++;
604 if (*p[0] == '?')
606 p[0]++;
607 sprintf(rs, "\r\n0-255");
608 isdn_tty_at_cout(rs, info);
610 else
612 par = isdn_getnum(p);
613 if ((par < 0) || (par > 255))
614 PARSE_ERROR1;
615 f->ctcrty = par;
616 #ifdef ISDN_TTY_FAX_STAT_DEBUG
617 printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
618 #endif
620 break;
621 default:
622 PARSE_ERROR1;
624 return 0;
627 /* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
628 if (!strncmp(p[0], "DCC", 3)) {
629 char *rp = &f->resolution;
630 int i;
632 p[0] += 3;
633 switch(*p[0]) {
634 case '?':
635 p[0]++;
636 strcpy(rs, "\r\n");
637 for(i = 0; i < 8; i++) {
638 sprintf(rss, "%c%s", rp[i] + 48,
639 (i < 7) ? "," : "");
640 strcat(rs, rss);
642 isdn_tty_at_cout(rs, info);
643 break;
644 case '=':
645 p[0]++;
646 if (*p[0] == '?') {
647 isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
648 p[0]++;
649 } else {
650 for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
651 if (*p[0] != ',') {
652 if ((*p[0] - 48) > maxdccval[i]) {
653 PARSE_ERROR1;
655 rp[i] = *p[0] - 48;
656 p[0]++;
657 if (*p[0] == ',')
658 p[0]++;
659 } else p[0]++;
661 #ifdef ISDN_TTY_FAX_STAT_DEBUG
662 printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
663 rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
664 #endif
666 break;
667 default:
668 PARSE_ERROR1;
670 return 0;
673 /* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
674 if (!strncmp(p[0], "DIS", 3)) {
675 char *rp = &f->resolution;
676 int i;
678 p[0] += 3;
679 switch(*p[0]) {
680 case '?':
681 p[0]++;
682 strcpy(rs, "\r\n");
683 for(i = 0; i < 8; i++) {
684 sprintf(rss, "%c%s", rp[i] + 48,
685 (i < 7) ? "," : "");
686 strcat(rs, rss);
688 isdn_tty_at_cout(rs, info);
689 break;
690 case '=':
691 p[0]++;
692 if (*p[0] == '?') {
693 isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
694 p[0]++;
695 } else {
696 for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
697 if (*p[0] != ',') {
698 if ((*p[0] - 48) > maxdccval[i]) {
699 PARSE_ERROR1;
701 rp[i] = *p[0] - 48;
702 p[0]++;
703 if (*p[0] == ',')
704 p[0]++;
705 } else p[0]++;
707 #ifdef ISDN_TTY_FAX_STAT_DEBUG
708 printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
709 rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
710 #endif
712 break;
713 default:
714 PARSE_ERROR1;
716 return 0;
719 /* DR - Receive Phase C data command, initiates document reception */
720 if (!strncmp(p[0], "DR", 2)) {
721 p[0] += 2;
722 if ((info->faxonline & 16) && /* incoming connection */
723 ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
724 #ifdef ISDN_TTY_FAX_STAT_DEBUG
725 printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
726 #endif
727 f->code = ISDN_TTY_FAX_DR;
728 cmd.driver = info->isdn_driver;
729 cmd.arg = info->isdn_channel;
730 cmd.command = ISDN_CMD_FAXCMD;
731 isdn_command(&cmd);
732 if (f->phase == ISDN_FAX_PHASE_B) {
733 f->phase = ISDN_FAX_PHASE_C;
734 } else if (f->phase == ISDN_FAX_PHASE_D) {
735 switch(f->fet) {
736 case 0: /* next page will be received */
737 f->phase = ISDN_FAX_PHASE_C;
738 isdn_tty_fax_modem_result(7, info); /* CONNECT */
739 break;
740 case 1: /* next doc will be received */
741 f->phase = ISDN_FAX_PHASE_B;
742 break;
743 case 2: /* fax session is terminating */
744 f->phase = ISDN_FAX_PHASE_E;
745 break;
746 default:
747 PARSE_ERROR1;
750 } else {
751 PARSE_ERROR1;
753 return 1;
756 /* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
757 if (!strncmp(p[0], "DT", 2)) {
758 int i, val[]={4,0,2,3};
759 char *rp = &f->resolution;
761 p[0] += 2;
762 if (!info->faxonline & 1) /* not outgoing connection */
763 PARSE_ERROR1;
765 for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<4); i++) {
766 if (*p[0] != ',') {
767 if ((*p[0] - 48) > maxdccval[val[i]]) {
768 PARSE_ERROR1;
770 rp[val[i]] = *p[0] - 48;
771 p[0]++;
772 if (*p[0] == ',')
773 p[0]++;
774 } else p[0]++;
776 #ifdef ISDN_TTY_FAX_STAT_DEBUG
777 printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
778 rp[4], rp[0], rp[2], rp[3]);
779 #endif
780 if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
781 f->code = ISDN_TTY_FAX_DT;
782 cmd.driver = info->isdn_driver;
783 cmd.arg = info->isdn_channel;
784 cmd.command = ISDN_CMD_FAXCMD;
785 isdn_command(&cmd);
786 if (f->phase == ISDN_FAX_PHASE_D) {
787 f->phase = ISDN_FAX_PHASE_C;
788 isdn_tty_fax_modem_result(7, info); /* CONNECT */
790 } else {
791 PARSE_ERROR1;
793 return 1;
796 /* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
797 if (!strncmp(p[0], "ECM", 3)) {
798 p[0] += 3;
799 switch (*p[0]) {
800 case '?':
801 p[0]++;
802 sprintf(rs, "\r\n%d",f->ecm);
803 isdn_tty_at_cout(rs, info);
804 break;
805 case '=':
806 p[0]++;
807 if (*p[0] == '?')
809 p[0]++;
810 sprintf(rs, "\r\n0,2");
811 isdn_tty_at_cout(rs, info);
813 else
815 par = isdn_getnum(p);
816 if ((par != 0) && (par != 2))
817 PARSE_ERROR1;
818 f->ecm = par;
819 #ifdef ISDN_TTY_FAX_STAT_DEBUG
820 printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
821 #endif
823 break;
824 default:
825 PARSE_ERROR1;
827 return 0;
830 /* ET=n - End of page or document */
831 if (!strncmp(p[0], "ET=", 3)) {
832 p[0] += 3;
833 if (*p[0] == '?') {
834 p[0]++;
835 sprintf(rs, "\r\n0-2");
836 isdn_tty_at_cout(rs, info);
837 } else {
838 if ((f->phase != ISDN_FAX_PHASE_D) || (!info->faxonline & 1))
839 PARSE_ERROR1;
840 par = isdn_getnum(p);
841 if ((par < 0) || (par > 2))
842 PARSE_ERROR1;
843 f->fet = par;
844 f->code = ISDN_TTY_FAX_ET;
845 cmd.driver = info->isdn_driver;
846 cmd.arg = info->isdn_channel;
847 cmd.command = ISDN_CMD_FAXCMD;
848 isdn_command(&cmd);
849 #ifdef ISDN_TTY_FAX_STAT_DEBUG
850 printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
851 #endif
852 return 1;
854 return 0;
857 /* K - terminate */
858 if (!strncmp(p[0], "K", 1)) {
859 p[0] += 1;
860 if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E))
861 PARSE_ERROR1;
862 isdn_tty_modem_hup(info, 1);
863 return 1;
866 /* LID=string - local fax ID */
867 if (!strncmp(p[0], "LID", 3)) {
868 int i, r;
869 p[0] += 3;
870 switch (*p[0]) {
871 case '?':
872 p[0]++;
873 sprintf(rs, "\r\n\"%s\"", f->id);
874 isdn_tty_at_cout(rs, info);
875 break;
876 case '=':
877 p[0]++;
878 if (*p[0] == '?')
880 p[0]++;
881 sprintf(rs, "\r\n\"STRING\"");
882 isdn_tty_at_cout(rs, info);
884 else
886 if (*p[0] =='"')
887 p[0]++;
888 for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
890 f->id[i] = *p[0]++;
892 if (*p[0] =='"')
893 p[0]++;
894 for(r=i; r < FAXIDLEN; r++)
896 f->id[r] = 32;
898 f->id[FAXIDLEN-1] = 0;
899 #ifdef ISDN_TTY_FAX_STAT_DEBUG
900 printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
901 #endif
903 break;
904 default:
905 PARSE_ERROR1;
907 return 0;
910 #if 0
911 /* LO=n - Flow control opts */
912 if (!strncmp(p[0], "LO", 2)) { /* TODO */
913 p[0] += 2;
914 switch (*p[0]) {
915 case '?':
916 p[0]++;
917 sprintf(rs, "\r\n%d",f->lo);
918 isdn_tty_at_cout(rs, info);
919 break;
920 case '=':
921 p[0]++;
922 if (*p[0] == '?')
924 p[0]++;
925 sprintf(rs, "\r\n0,1,2");
926 isdn_tty_at_cout(rs, info);
928 else
930 par = isdn_getnum(p);
931 if ((par < 0) || (par > 2))
932 PARSE_ERROR1;
933 f->lo = par;
934 #ifdef ISDN_TTY_FAX_STAT_DEBUG
935 printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par);
936 #endif
938 break;
939 default:
940 PARSE_ERROR1;
942 return 0;
944 #endif
945 #if 0
946 /* LPL=n - Doc for polling cmd */
947 if (!strncmp(p[0], "LPL", 3)) { /* TODO */
948 p[0] += 3;
949 switch (*p[0]) {
950 case '?':
951 p[0]++;
952 sprintf(rs, "\r\n%d",f->lpl);
953 isdn_tty_at_cout(rs, info);
954 break;
955 case '=':
956 p[0]++;
957 if (*p[0] == '?')
959 p[0]++;
960 sprintf(rs, "\r\n0,1");
961 isdn_tty_at_cout(rs, info);
963 else
965 par = isdn_getnum(p);
966 if ((par < 0) || (par > 1))
967 PARSE_ERROR1;
968 f->lpl = par;
969 #ifdef ISDN_TTY_FAX_STAT_DEBUG
970 printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par);
971 #endif
973 break;
974 default:
975 PARSE_ERROR1;
977 return 0;
979 #endif
981 /* MDL? - DCE Model */
982 if (!strncmp(p[0], "MDL?", 4)) {
983 p[0] += 4;
984 #ifdef ISDN_TTY_FAX_STAT_DEBUG
985 printk(KERN_DEBUG "isdn_tty: FMDL?\n");
986 #endif
987 isdn_tty_at_cout("\r\nisdn4linux", info);
988 return 0;
991 /* MFR? - DCE Manufacturer */
992 if (!strncmp(p[0], "MFR?", 4)) {
993 p[0] += 4;
994 #ifdef ISDN_TTY_FAX_STAT_DEBUG
995 printk(KERN_DEBUG "isdn_tty: FMFR?\n");
996 #endif
997 isdn_tty_at_cout("\r\nisdn4linux", info);
998 return 0;
1001 /* MINSP=n - Minimum Speed for Phase C */
1002 if (!strncmp(p[0], "MINSP", 5)) {
1003 p[0] += 5;
1004 switch (*p[0]) {
1005 case '?':
1006 p[0]++;
1007 sprintf(rs, "\r\n%d",f->minsp);
1008 isdn_tty_at_cout(rs, info);
1009 break;
1010 case '=':
1011 p[0]++;
1012 if (*p[0] == '?')
1014 p[0]++;
1015 sprintf(rs, "\r\n0-5");
1016 isdn_tty_at_cout(rs, info);
1018 else
1020 par = isdn_getnum(p);
1021 if ((par < 0) || (par > 5))
1022 PARSE_ERROR1;
1023 f->minsp = par;
1024 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1025 printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
1026 #endif
1028 break;
1029 default:
1030 PARSE_ERROR1;
1032 return 0;
1035 /* PHCTO=value - DTE phase C timeout */
1036 if (!strncmp(p[0], "PHCTO", 5)){
1037 p[0] +=5;
1038 switch (*p[0]) {
1039 case '?':
1040 p[0]++;
1041 sprintf(rs, "\r\n%d",f->phcto);
1042 isdn_tty_at_cout(rs, info);
1043 break;
1044 case '=':
1045 p[0]++;
1046 if (*p[0] == '?')
1048 p[0]++;
1049 sprintf(rs, "\r\n0-255");
1050 isdn_tty_at_cout(rs, info);
1052 else
1054 par = isdn_getnum(p);
1055 if ((par < 0) || (par > 255))
1056 PARSE_ERROR1;
1057 f->phcto = par;
1058 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1059 printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
1060 #endif
1062 break;
1063 default:
1064 PARSE_ERROR1;
1066 return 0;
1069 #if 0
1070 /* PTS=n - Page transfer status */
1071 if (!strncmp(p[0], "PTS", 3)) { /* TODO */
1072 p[0] += 3;
1073 switch (*p[0]) {
1074 case '?':
1075 p[0]++;
1076 sprintf(rs, "\r\n%d",f->pts);
1077 isdn_tty_at_cout(rs, info);
1078 break;
1079 case '=':
1080 p[0]++;
1081 if (*p[0] == '?')
1083 p[0]++;
1084 sprintf(rs, "\r\n0-5");
1085 isdn_tty_at_cout(rs, info);
1087 else
1089 par = isdn_getnum(p);
1090 if ((par < 0) || (par > 5))
1091 PARSE_ERROR1;
1092 f->pts = par;
1093 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1094 printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par);
1095 #endif
1097 break;
1098 default:
1099 PARSE_ERROR1;
1101 return 0;
1103 #endif
1105 /* REL=n - Phase C received EOL alignment */
1106 if (!strncmp(p[0], "REL", 3)) {
1107 p[0] += 3;
1108 switch (*p[0]) {
1109 case '?':
1110 p[0]++;
1111 sprintf(rs, "\r\n%d",f->rel);
1112 isdn_tty_at_cout(rs, info);
1113 break;
1114 case '=':
1115 p[0]++;
1116 if (*p[0] == '?')
1118 p[0]++;
1119 sprintf(rs, "\r\n0,1");
1120 isdn_tty_at_cout(rs, info);
1122 else
1124 par = isdn_getnum(p);
1125 if ((par < 0) || (par > 1))
1126 PARSE_ERROR1;
1127 f->rel = par;
1128 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1129 printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
1130 #endif
1132 break;
1133 default:
1134 PARSE_ERROR1;
1136 return 0;
1139 /* REV? - DCE Revision */
1140 if (!strncmp(p[0], "REV?", 4)) {
1141 p[0] += 4;
1142 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1143 printk(KERN_DEBUG "isdn_tty: FREV?\n");
1144 #endif
1145 strcpy(rss, isdn_tty_fax_revision);
1146 sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
1147 isdn_tty_at_cout(rs, info);
1148 return 0;
1151 #if 0
1152 /* SPL=n - Enable polling */
1153 if (!strncmp(p[0], "SPL", 3)) { /* TODO */
1154 p[0] += 3;
1155 switch (*p[0]) {
1156 case '?':
1157 p[0]++;
1158 sprintf(rs, "\r\n%d", f->spl);
1159 isdn_tty_at_cout(rs, info);
1160 break;
1161 case '=':
1162 p[0]++;
1163 if (*p[0] == '?')
1165 p[0]++;
1166 sprintf(rs, "\r\n0,1");
1167 isdn_tty_at_cout(rs, info);
1169 else
1171 par = isdn_getnum(p);
1172 if ((par < 0) || (par > 1))
1173 PARSE_ERROR1;
1174 f->spl = par;
1175 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1176 printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par);
1177 #endif
1179 break;
1180 default:
1181 PARSE_ERROR1;
1183 return 0;
1185 #endif
1187 /* Phase C Transmit Data Block Size */
1188 if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
1189 p[0] += 4;
1190 #ifdef ISDN_TTY_FAX_STAT_DEBUG
1191 printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
1192 #endif
1193 switch (*p[0]) {
1194 case '0':
1195 p[0]++;
1196 break;
1197 default:
1198 PARSE_ERROR1;
1200 return 0;
1203 printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
1204 PARSE_ERROR1;