/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) * Copyright 1999 by Ralf Spachmann (mel@melware.de) * Copyright 1999 by Cytronics & Melware * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ttyfax.c,v $ * Revision 1.4 1999/09/21 19:00:35 armin * Extended FCON message with added CPN * can now be activated with Bit 1 of Reg 23. * * Revision 1.3 1999/08/22 20:26:12 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. * - "struct device" changed to "struct net_device" in 2.3.14, added a * define in isdn_compat.h for older kernel versions. * * Revision 1.2 1999/08/05 10:36:10 armin * Bugfix: kernel oops on getting revision. * * Revision 1.1 1999/07/31 12:59:50 armin * Added tty fax capabilities. * * */ #undef ISDN_TTY_FAX_STAT_DEBUG #undef ISDN_TTY_FAX_CMD_DEBUG #define __NO_VERSION__ #include #include #include "isdn_common.h" #include "isdn_tty.h" #include "isdn_ttyfax.h" static char *isdn_tty_fax_revision = "$Revision: 1.4 $"; #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } static char * isdn_getrev(const char *revision) { char *rev; char *p; if ((p = strchr(revision, ':'))) { rev = p + 2; p = strchr(rev, '$'); *--p = 0; } else rev = "???"; return rev; } /* * Fax Class 2 Modem results * */ static void isdn_tty_fax_modem_result(int code, modem_info * info) { atemu *m = &info->emu; T30_s *f = info->fax; char rs[50]; char rss[50]; char *rp; int i; static char *msg[] = {"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:", "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:", "+FCFR", "+FPTS:", "+FET:" }; isdn_tty_at_cout("\r\n", info); isdn_tty_at_cout(msg[code], info); #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n", msg[code], info->line); #endif switch (code) { case 0: /* OK */ break; case 1: /* ERROR */ break; case 2: /* +FCON */ /* Append CPN, if enabled */ if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) && (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { sprintf(rs, "/%s", m->cpn); isdn_tty_at_cout(rs, info); } info->online = 1; f->fet = 0; if (f->phase == ISDN_FAX_PHASE_A) f->phase = ISDN_FAX_PHASE_B; break; case 3: /* +FCSI */ case 8: /* +FTSI */ sprintf(rs, "\"%s\"", f->r_id); isdn_tty_at_cout(rs, info); break; case 4: /* +FDIS */ rs[0] = 0; rp = &f->r_resolution; for(i = 0; i < 8; i++) { sprintf(rss, "%c%s", rp[i] + 48, (i < 7) ? "," : ""); strcat(rs, rss); } isdn_tty_at_cout(rs, info); #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n", rs, info->line); #endif break; case 5: /* +FHNG */ sprintf(rs, "%d", f->code); isdn_tty_at_cout(rs, info); info->faxonline = 0; break; case 6: /* +FDCS */ rs[0] = 0; rp = &f->r_resolution; for(i = 0; i < 8; i++) { sprintf(rss, "%c%s", rp[i] + 48, (i < 7) ? "," : ""); strcat(rs, rss); } isdn_tty_at_cout(rs, info); #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n", rs, info->line); #endif break; case 7: /* CONNECT */ info->faxonline |= 2; break; case 9: /* FCFR */ break; case 10: /* FPTS */ isdn_tty_at_cout("1", info); break; case 11: /* FET */ sprintf(rs, "%d", f->fet); isdn_tty_at_cout(rs, info); break; } isdn_tty_at_cout("\r\n", info); switch (code) { case 7: /* CONNECT */ info->online = 2; if (info->faxonline & 1) { sprintf(rs, "%c", XON); isdn_tty_at_cout(rs, info); } break; } } int isdn_tty_fax_command(modem_info * info) { T30_s *f = info->fax; char rs[10]; #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n", f->r_code, info->line); #endif switch(f->r_code) { case ISDN_TTY_FAX_FCON: info->faxonline = 1; isdn_tty_fax_modem_result(2, info); /* +FCON */ return(0); case ISDN_TTY_FAX_FCON_I: info->faxonline = 16; isdn_tty_fax_modem_result(2, info); /* +FCON */ return(0); case ISDN_TTY_FAX_RID: if (info->faxonline & 1) isdn_tty_fax_modem_result(3, info); /* +FCSI */ if (info->faxonline & 16) isdn_tty_fax_modem_result(8, info); /* +FTSI */ return(0); case ISDN_TTY_FAX_DIS: isdn_tty_fax_modem_result(4, info); /* +FDIS */ return(0); case ISDN_TTY_FAX_HNG: if (f->phase == ISDN_FAX_PHASE_C) { if (f->direction == ISDN_TTY_FAX_CONN_IN) { sprintf(rs, "%c%c", DLE, ETX); isdn_tty_at_cout(rs, info); } else { sprintf(rs, "%c", 0x18); isdn_tty_at_cout(rs, info); } info->faxonline &= ~2; /* leave data mode */ info->online = 1; } f->phase = ISDN_FAX_PHASE_E; isdn_tty_fax_modem_result(5, info); /* +FHNG */ isdn_tty_fax_modem_result(0, info); /* OK */ return(0); case ISDN_TTY_FAX_DCS: isdn_tty_fax_modem_result(6, info); /* +FDCS */ isdn_tty_fax_modem_result(7, info); /* CONNECT */ f->phase = ISDN_FAX_PHASE_C; return(0); case ISDN_TTY_FAX_TRAIN_OK: isdn_tty_fax_modem_result(6, info); /* +FDCS */ isdn_tty_fax_modem_result(0, info); /* OK */ return(0); case ISDN_TTY_FAX_SENT: isdn_tty_fax_modem_result(0, info); /* OK */ return(0); case ISDN_TTY_FAX_CFR: isdn_tty_fax_modem_result(9, info); /* +FCFR */ return(0); case ISDN_TTY_FAX_ET: sprintf(rs, "%c%c", DLE, ETX); isdn_tty_at_cout(rs, info); isdn_tty_fax_modem_result(10, info); /* +FPTS */ isdn_tty_fax_modem_result(11, info); /* +FET */ isdn_tty_fax_modem_result(0, info); /* OK */ info->faxonline &= ~2; /* leave data mode */ info->online = 1; f->phase = ISDN_FAX_PHASE_D; return(0); case ISDN_TTY_FAX_PTS: isdn_tty_fax_modem_result(10, info); /* +FPTS */ if (f->direction == ISDN_TTY_FAX_CONN_OUT) { if (f->fet == 1) f->phase = ISDN_FAX_PHASE_B; if (f->fet == 0) isdn_tty_fax_modem_result(0, info); /* OK */ } return(0); case ISDN_TTY_FAX_EOP: info->faxonline &= ~2; /* leave data mode */ info->online = 1; f->phase = ISDN_FAX_PHASE_D; return(0); } return(-1); } void isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb) { __u8 LeftMask; __u8 RightMask; __u8 fBit; __u8 Data; int i; if (!info->fax->bor) { for(i = 0; i < skb->len; i++) { Data = skb->data[i]; for ( LeftMask = 0x80, RightMask = 0x01; LeftMask > RightMask; LeftMask >>= 1, RightMask <<= 1 ) { fBit = (Data & LeftMask); if (Data & RightMask) Data |= LeftMask; else Data &= ~LeftMask; if (fBit) Data |= RightMask; else Data &= ~RightMask; } skb->data[i] = Data; } } } /* * Parse AT+F.. FAX class 2 commands */ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) { atemu *m = &info->emu; T30_s *f = info->fax; isdn_ctrl cmd; int par; char rs[50]; char rss[50]; int maxdccval[]={1,5,2,2,3,2,0,7}; /* FAA still unchanged */ if (!strncmp(p[0], "AA", 2)) { /* TODO */ p[0] += 2; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", 0); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; break; default: PARSE_ERROR1; } return 0; } /* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */ if (!strncmp(p[0], "BADLIN", 6)) { p[0] += 6; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->badlin); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-255"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; f->badlin = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */ if (!strncmp(p[0], "BADMUL", 6)){ p[0] +=6; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", f->badmul); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-255"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; f->badmul = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* BOR=n - Phase C bit order, 0=direct, 1=reverse */ if (!strncmp(p[0], "BOR", 3)){ p[0] +=3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", f->bor); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,1"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 1)) PARSE_ERROR1; f->bor = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* NBC=n - No Best Capabilities */ if (!strncmp(p[0], "NBC", 3)){ p[0] +=3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", f->nbc); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,1"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 1)) PARSE_ERROR1; f->nbc = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* BUF? - Readonly buffersize readout */ if (!strncmp(p[0], "BUF?", 4)) { p[0] += 4; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE])); #endif p[0]++; sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE])); isdn_tty_at_cout(rs, info); return 0; } /* CIG=string - local fax station id string for polling rx */ if (!strncmp(p[0], "CIG", 3)) { int i, r; p[0] += 3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n\"%s\"", f->pollid); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n\"STRING\""); isdn_tty_at_cout(rs, info); } else { if (*p[0] =='"') p[0]++; for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++) { f->pollid[i] = *p[0]++; } if (*p[0] =='"') p[0]++; for(r=i; r < FAXIDLEN; r++) { f->pollid[r] = 32; } f->pollid[FAXIDLEN-1] = 0; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid); #endif } break; default: PARSE_ERROR1; } return 0; } /* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */ if (!strncmp(p[0], "CQ", 2)) { p[0] += 2; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", f->cq); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,1,2"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 2)) PARSE_ERROR1; f->cq = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */ if (!strncmp(p[0], "CR", 2)) { p[0] += 2; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */ isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,1"); /* display online help */ isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 1)) PARSE_ERROR1; f->cr = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* CTCRTY=value - ECM retry count */ if (!strncmp(p[0], "CTCRTY", 6)){ p[0] +=6; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->ctcrty); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-255"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; f->ctcrty = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */ if (!strncmp(p[0], "DCC", 3)) { char *rp = &f->resolution; int i; p[0] += 3; switch(*p[0]) { case '?': p[0]++; strcpy(rs, "\r\n"); for(i = 0; i < 8; i++) { sprintf(rss, "%c%s", rp[i] + 48, (i < 7) ? "," : ""); strcat(rs, rss); } isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info); p[0]++; } else { for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) { if (*p[0] != ',') { if ((*p[0] - 48) > maxdccval[i]) { PARSE_ERROR1; } rp[i] = *p[0] - 48; p[0]++; if (*p[0] == ',') p[0]++; } else p[0]++; } #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n", rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]); #endif } break; default: PARSE_ERROR1; } return 0; } /* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */ if (!strncmp(p[0], "DIS", 3)) { char *rp = &f->resolution; int i; p[0] += 3; switch(*p[0]) { case '?': p[0]++; strcpy(rs, "\r\n"); for(i = 0; i < 8; i++) { sprintf(rss, "%c%s", rp[i] + 48, (i < 7) ? "," : ""); strcat(rs, rss); } isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info); p[0]++; } else { for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) { if (*p[0] != ',') { if ((*p[0] - 48) > maxdccval[i]) { PARSE_ERROR1; } rp[i] = *p[0] - 48; p[0]++; if (*p[0] == ',') p[0]++; } else p[0]++; } #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n", rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]); #endif } break; default: PARSE_ERROR1; } return 0; } /* DR - Receive Phase C data command, initiates document reception */ if (!strncmp(p[0], "DR", 2)) { p[0] += 2; if ((info->faxonline & 16) && /* incoming connection */ ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) { #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); #endif f->code = ISDN_TTY_FAX_DR; cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; cmd.command = ISDN_CMD_FAXCMD; isdn_command(&cmd); if (f->phase == ISDN_FAX_PHASE_B) { f->phase = ISDN_FAX_PHASE_C; } else if (f->phase == ISDN_FAX_PHASE_D) { switch(f->fet) { case 0: /* next page will be received */ f->phase = ISDN_FAX_PHASE_C; isdn_tty_fax_modem_result(7, info); /* CONNECT */ break; case 1: /* next doc will be received */ f->phase = ISDN_FAX_PHASE_B; break; case 2: /* fax session is terminating */ f->phase = ISDN_FAX_PHASE_E; break; default: PARSE_ERROR1; } } } else { PARSE_ERROR1; } return 1; } /* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */ if (!strncmp(p[0], "DT", 2)) { int i, val[]={4,0,2,3}; char *rp = &f->resolution; p[0] += 2; if (!info->faxonline & 1) /* not outgoing connection */ PARSE_ERROR1; for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<4); i++) { if (*p[0] != ',') { if ((*p[0] - 48) > maxdccval[val[i]]) { PARSE_ERROR1; } rp[val[i]] = *p[0] - 48; p[0]++; if (*p[0] == ',') p[0]++; } else p[0]++; } #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n", rp[4], rp[0], rp[2], rp[3]); #endif if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { f->code = ISDN_TTY_FAX_DT; cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; cmd.command = ISDN_CMD_FAXCMD; isdn_command(&cmd); if (f->phase == ISDN_FAX_PHASE_D) { f->phase = ISDN_FAX_PHASE_C; isdn_tty_fax_modem_result(7, info); /* CONNECT */ } } else { PARSE_ERROR1; } return 1; } /* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */ if (!strncmp(p[0], "ECM", 3)) { p[0] += 3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->ecm); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,2"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par != 0) && (par != 2)) PARSE_ERROR1; f->ecm = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* ET=n - End of page or document */ if (!strncmp(p[0], "ET=", 3)) { p[0] += 3; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-2"); isdn_tty_at_cout(rs, info); } else { if ((f->phase != ISDN_FAX_PHASE_D) || (!info->faxonline & 1)) PARSE_ERROR1; par = isdn_getnum(p); if ((par < 0) || (par > 2)) PARSE_ERROR1; f->fet = par; f->code = ISDN_TTY_FAX_ET; cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; cmd.command = ISDN_CMD_FAXCMD; isdn_command(&cmd); #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); #endif return 1; } return 0; } /* K - terminate */ if (!strncmp(p[0], "K", 1)) { p[0] += 1; if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E)) PARSE_ERROR1; isdn_tty_modem_hup(info, 1); return 1; } /* LID=string - local fax ID */ if (!strncmp(p[0], "LID", 3)) { int i, r; p[0] += 3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n\"%s\"", f->id); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n\"STRING\""); isdn_tty_at_cout(rs, info); } else { if (*p[0] =='"') p[0]++; for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++) { f->id[i] = *p[0]++; } if (*p[0] =='"') p[0]++; for(r=i; r < FAXIDLEN; r++) { f->id[r] = 32; } f->id[FAXIDLEN-1] = 0; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id); #endif } break; default: PARSE_ERROR1; } return 0; } /* MDL? - DCE Model */ if (!strncmp(p[0], "MDL?", 4)) { p[0] += 4; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: FMDL?\n"); #endif isdn_tty_at_cout("\r\nisdn4linux", info); return 0; } /* MFR? - DCE Manufacturer */ if (!strncmp(p[0], "MFR?", 4)) { p[0] += 4; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: FMFR?\n"); #endif isdn_tty_at_cout("\r\nisdn4linux", info); return 0; } /* MINSP=n - Minimum Speed for Phase C */ if (!strncmp(p[0], "MINSP", 5)) { p[0] += 5; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->minsp); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-5"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 5)) PARSE_ERROR1; f->minsp = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* PHCTO=value - DTE phase C timeout */ if (!strncmp(p[0], "PHCTO", 5)){ p[0] +=5; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->phcto); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0-255"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; f->phcto = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* REL=n - Phase C received EOL alignment */ if (!strncmp(p[0], "REL", 3)) { p[0] += 3; switch (*p[0]) { case '?': p[0]++; sprintf(rs, "\r\n%d",f->rel); isdn_tty_at_cout(rs, info); break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; sprintf(rs, "\r\n0,1"); isdn_tty_at_cout(rs, info); } else { par = isdn_getnum(p); if ((par < 0) || (par > 1)) PARSE_ERROR1; f->rel = par; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par); #endif } break; default: PARSE_ERROR1; } return 0; } /* REV? - DCE Revision */ if (!strncmp(p[0], "REV?", 4)) { p[0] += 4; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: FREV?\n"); #endif strcpy(rss, isdn_tty_fax_revision); sprintf(rs, "\r\nRev: %s", isdn_getrev(rss)); isdn_tty_at_cout(rs, info); return 0; } /* Phase C Transmit Data Block Size */ if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */ p[0] += 4; #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]); #endif switch (*p[0]) { case '0': p[0]++; break; default: PARSE_ERROR1; } return 0; } printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]); PARSE_ERROR1; }