patch-2.2.12 linux/drivers/isdn/isdn_tty.c
Next file: linux/drivers/isdn/isdn_tty.h
Previous file: linux/drivers/isdn/isdn_ppp.c
Back to the patch index
Back to the overall index
- Lines: 607
- Date:
Wed Aug 25 17:29:48 1999
- Orig file:
v2.2.11/linux/drivers/isdn/isdn_tty.c
- Orig date:
Mon Aug 9 16:05:56 1999
diff -u --recursive --new-file v2.2.11/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.68 1999/07/11 17:51:51 armin Exp $
+/* $Id: isdn_tty.c,v 1.72 1999/07/31 12:59:45 armin Exp $
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
@@ -20,6 +20,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.c,v $
+ * Revision 1.72 1999/07/31 12:59:45 armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.71 1999/07/27 10:34:34 armin
+ * Fixed last change. Did not compile with AUDIO support off.
+ *
+ * Revision 1.70 1999/07/25 16:17:58 keil
+ * Fix Suspend/Resume
+ *
+ * Revision 1.69 1999/07/25 12:56:15 armin
+ * isdn_tty_at_cout() now queues the message if online and
+ * data is in queue or flip buffer is full.
+ * needed for fax connections.
+ *
* Revision 1.68 1999/07/11 17:51:51 armin
* Bugfix, "-" was missing for AT&L settings.
*
@@ -331,7 +345,7 @@
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.68 $";
+char *isdn_tty_revision = "$Revision: 1.72 $";
/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -534,6 +548,15 @@
ISDN_AUDIO_SKB_DLECOUNT(skb) =
isdn_tty_countDLE(skb->data, skb->len);
}
+#ifdef CONFIG_ISDN_TTY_FAX
+ else {
+ if (info->faxonline & 2) {
+ isdn_tty_fax_bitorder(info, skb);
+ ISDN_AUDIO_SKB_DLECOUNT(skb) =
+ isdn_tty_countDLE(skb->data, skb->len);
+ }
+ }
+#endif
#endif
/* Try to deliver directly via tty-flip-buf if queue is empty */
save_flags(flags);
@@ -863,6 +886,35 @@
}
}
+/*
+ * return the usage calculated by si and layer 2 protocol
+ */
+int
+isdn_calc_usage(int si, int l2)
+{
+ int usg = ISDN_USAGE_MODEM;
+
+#ifdef CONFIG_ISDN_AUDIO
+ if (si == 1) {
+ switch(l2) {
+ case ISDN_PROTO_L2_MODEM:
+ usg = ISDN_USAGE_MODEM;
+ break;
+#ifdef CONFIG_ISDN_TTY_FAX
+ case ISDN_PROTO_L2_FAX:
+ usg = ISDN_USAGE_FAX;
+ break;
+#endif
+ case ISDN_PROTO_L2_TRANS:
+ default:
+ usg = ISDN_USAGE_VOICE;
+ break;
+ }
+ }
+#endif
+ return(usg);
+}
+
/* isdn_tty_dial() performs dialing of a tty an the necessary
* setup of the lower levels before that.
*/
@@ -882,8 +934,14 @@
si = bit2si[j];
break;
}
+ usg = isdn_calc_usage(si, l2);
#ifdef CONFIG_ISDN_AUDIO
- if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+ if ((si == 1) &&
+ (l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+ && (l2 != ISDN_PROTO_L2_FAX)
+#endif
+ ) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@@ -921,6 +979,12 @@
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+#ifdef CONFIG_ISDN_TTY_FAX
+ if (l2 == ISDN_PROTO_L2_FAX) {
+ cmd.parm.fax = info->fax;
+ info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
+ }
+#endif
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
@@ -943,7 +1007,7 @@
* ISDN-line (hangup). The usage-status is cleared
* and some cleanup is done also.
*/
-static void
+void
isdn_tty_modem_hup(modem_info * info, int local)
{
isdn_ctrl cmd;
@@ -964,6 +1028,10 @@
}
#ifdef CONFIG_ISDN_AUDIO
info->vonline = 0;
+#ifdef CONFIG_ISDN_TTY_FAX
+ info->faxonline = 0;
+ info->fax->phase = ISDN_FAX_PHASE_IDLE;
+#endif
info->emu.vpar[4] = 0;
info->emu.vpar[5] = 8;
if (info->dtmf_state) {
@@ -997,9 +1065,8 @@
}
isdn_all_eaz(info->isdn_driver, info->isdn_channel);
info->emu.mdmreg[REG_RINGCNT] = 0;
- usage = ((info->emu.mdmreg[REG_SI1I] != 1) ||
- (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
- ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+ usage = isdn_calc_usage(info->emu.mdmreg[REG_SI1I],
+ info->emu.mdmreg[REG_L2PROT]);
isdn_free_channel(info->isdn_driver, info->isdn_channel,
usage);
}
@@ -1086,8 +1153,14 @@
si = bit2si[j];
break;
}
+ usg = isdn_calc_usage(si, l2);
#ifdef CONFIG_ISDN_AUDIO
- if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+ if ((si == 1) &&
+ (l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+ && (l2 != ISDN_PROTO_L2_FAX)
+#endif
+ ) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@@ -1140,11 +1213,11 @@
cmd.parm.cmsg.para[5] = l;
strncpy(&cmd.parm.cmsg.para[6], id, l);
cmd.command =CAPI_PUT_MESSAGE;
-/* info->dialing = 1;
- strcpy(dev->num[i], n);
+ info->dialing = 1;
+// strcpy(dev->num[i], n);
isdn_info_update();
-*/
isdn_command(&cmd);
+ isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
}
}
@@ -1174,8 +1247,14 @@
si = bit2si[j];
break;
}
+ usg = isdn_calc_usage(si, l2);
#ifdef CONFIG_ISDN_AUDIO
- if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+ if ((si == 1) &&
+ (l2 != ISDN_PROTO_L2_MODEM)
+#ifdef CONFIG_ISDN_TTY_FAX
+ && (l2 != ISDN_PROTO_L2_FAX)
+#endif
+ ) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@@ -2160,8 +2239,42 @@
m->vpar[1] = 0; /* Silence detection level (0 = none ) */
m->vpar[2] = 70; /* Silence interval (7 sec. ) */
m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */
- m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */
- m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */
+ m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */
+ m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */
+}
+#endif
+
+#ifdef CONFIG_ISDN_TTY_FAX
+static void
+isdn_tty_modem_reset_faxpar(modem_info * info)
+{
+ T30_s *f = info->fax;
+
+ f->code = 0;
+ f->phase = ISDN_FAX_PHASE_IDLE;
+ f->direction = 0;
+ f->resolution = 1; /* fine */
+ f->rate = 5; /* 14400 bit/s */
+ f->width = 0;
+ f->length = 0;
+ f->compression = 0;
+ f->ecm = 0;
+ f->binary = 0;
+ f->scantime = 0;
+ memset(&f->id[0], 32, FAXIDLEN - 1);
+ f->id[FAXIDLEN - 1] = 0;
+ f->badlin = 0;
+ f->badmul = 0;
+ f->bor = 0;
+ f->nbc = 0;
+ f->cq = 0;
+ f->cr = 0;
+ f->ctcrty = 0;
+ f->minsp = 0;
+ f->phcto = 30;
+ f->rel = 0;
+ memset(&f->pollid[0], 32, FAXIDLEN - 1);
+ f->pollid[FAXIDLEN - 1] = 0;
}
#endif
@@ -2178,6 +2291,9 @@
#ifdef CONFIG_ISDN_AUDIO
isdn_tty_modem_reset_vpar(m);
#endif
+#ifdef CONFIG_ISDN_TTY_FAX
+ isdn_tty_modem_reset_faxpar(info);
+#endif
m->mdmcmdl = 0;
}
@@ -2250,6 +2366,12 @@
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
+#ifdef CONFIG_ISDN_TTY_FAX
+ if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
+ printk(KERN_ERR "Could not allocate fax t30-buffer\n");
+ return -3;
+ }
+#endif
#ifdef COMPAT_HAS_NEW_WAITQ
init_MUTEX(&info->write_sem);
#else
@@ -2330,8 +2452,15 @@
break;
}
return ret;
- } else
- return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+ } else {
+ int tmp;
+ tmp = isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+#ifdef ISDN_DEBUG_MODEM_ICALL
+ printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
+ isdn_map_eaz2msn(emu->msn, di), tmp);
+#endif
+ return tmp;
+ }
}
/*
@@ -2383,7 +2512,7 @@
(info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
idx = isdn_dc2minor(di, ch);
#ifdef ISDN_DEBUG_MODEM_ICALL
- printk(KERN_DEBUG "m_fi: match1\n");
+ printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
info->flags, info->isdn_driver, info->isdn_channel,
dev->usage[idx]);
@@ -2405,8 +2534,7 @@
info->drv_index = idx;
dev->m_idx[idx] = info->line;
dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
- dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
- ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+ dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
strcpy(dev->num[idx], nr);
strcpy(info->emu.cpn, eaz);
info->emu.mdmreg[REG_SI1I] = si2bit[si1];
@@ -2584,6 +2712,13 @@
}
}
return 1;
+#ifdef CONFIG_ISDN_TTY_FAX
+ case ISDN_STAT_FAXIND:
+ if (TTY_IS_ACTIVE(info)) {
+ isdn_tty_fax_command(info);
+ }
+ break;
+#endif
#ifdef CONFIG_ISDN_AUDIO
case ISDN_STAT_AUDIO:
if (TTY_IS_ACTIVE(info)) {
@@ -2621,6 +2756,8 @@
char *p;
char c;
ulong flags;
+ struct sk_buff *skb = 0;
+ char *sp = 0;
if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2629,6 +2766,34 @@
save_flags(flags);
cli();
tty = info->tty;
+ if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
+ restore_flags(flags);
+ return;
+ }
+
+ /* use queue instead of direct flip, if online and */
+ /* data is in queue or flip buffer is full */
+ if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
+ (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
+ skb = alloc_skb(strlen(msg)
+#ifdef CONFIG_ISDN_AUDIO
+ + sizeof(isdn_audio_skb)
+#endif
+ , GFP_ATOMIC);
+ if (!skb) {
+ restore_flags(flags);
+ return;
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ skb_reserve(skb, sizeof(isdn_audio_skb));
+#endif
+ sp = skb_put(skb, strlen(msg));
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ }
+
for (p = msg; *p; p++) {
switch (*p) {
case '\r':
@@ -2643,16 +2808,26 @@
default:
c = *p;
}
- if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
- restore_flags(flags);
- return;
+ if (skb) {
+ *sp++ = c;
+ } else {
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
+ tty_insert_flip_char(tty, c, 0);
}
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
- tty_insert_flip_char(tty, c, 0);
}
- restore_flags(flags);
- queue_task(&tty->flip.tqueue, &tq_timer);
+ if (skb) {
+ __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
+ dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
+ restore_flags(flags);
+ /* Schedule dequeuing */
+ if ((dev->modempoll) && (info->rcvsched))
+ isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+
+ } else {
+ restore_flags(flags);
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ }
}
/*
@@ -3328,7 +3503,7 @@
/* If more than one bit set in reg18, autoselect Layer2 */
if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
if (m->mdmreg[REG_SI1I] == 1) {
- if (l2 != ISDN_PROTO_L2_MODEM)
+ if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
l2 = ISDN_PROTO_L2_TRANS;
} else
l2 = ISDN_PROTO_L2_X75I;
@@ -3342,6 +3517,12 @@
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+#ifdef CONFIG_ISDN_TTY_FAX
+ if (l2 == ISDN_PROTO_L2_FAX) {
+ cmd.parm.fax = info->fax;
+ info->fax->direction = ISDN_TTY_FAX_CONN_IN;
+ }
+#endif
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
@@ -3362,7 +3543,6 @@
isdn_tty_cmd_PLUSF(char **p, modem_info * info)
{
atemu *m = &info->emu;
- int par;
char rs[20];
if (!strncmp(p[0], "CLASS", 5)) {
@@ -3372,6 +3552,10 @@
p[0]++;
sprintf(rs, "\r\n%d",
(m->mdmreg[REG_SI1] & 1) ? 8 : 0);
+#ifdef CONFIG_ISDN_TTY_FAX
+ if (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX)
+ sprintf(rs, "\r\n2");
+#endif
isdn_tty_at_cout(rs, info);
break;
case '=':
@@ -3379,23 +3563,37 @@
switch (*p[0]) {
case '0':
p[0]++;
+ m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+ m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
m->mdmreg[REG_SI1] = 4;
info->xmit_size =
m->mdmreg[REG_PSIZE] * 16;
break;
+#ifdef CONFIG_ISDN_TTY_FAX
case '2':
- printk(KERN_DEBUG "isdn_tty: FCLASS=2\n");
p[0]++;
+ m->mdmreg[REG_SI1] = 1;
+ m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
+ m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FAX;
+ info->xmit_size =
+ m->mdmreg[REG_PSIZE] * 16;
break;
+#endif
case '8':
p[0]++;
+ /* L2 will change on dialout with si=1 */
+ m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
+ m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
m->mdmreg[REG_SI1] = 5;
info->xmit_size = VBUF;
break;
case '?':
p[0]++;
- isdn_tty_at_cout("\r\n0,2,8",
- info);
+#ifdef CONFIG_ISDN_TTY_FAX
+ isdn_tty_at_cout("\r\n0,2,8", info);
+#else
+ isdn_tty_at_cout("\r\n0,8", info);
+#endif
break;
default:
PARSE_ERROR1;
@@ -3406,115 +3604,11 @@
}
return 0;
}
- if (!strncmp(p[0], "AA", 2)) {
- p[0] += 2;
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs, "\r\n%d",
- m->mdmreg[REG_RINGATA]);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- m->mdmreg[REG_RINGATA] = par;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
- if (!strncmp(p[0], "TBC=", 4)) { /* UNKLAR !! */
- p[0] += 4;
- printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
- switch (*p[0]) {
- case '0':
- p[0]++;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
- if (!strncmp(p[0], "BOR=", 4)) { /* UNKLAR !! */
- p[0] += 4;
- printk(KERN_DEBUG "isdn_tty: Fax FBOR=%c\n", *p[0]);
- switch (*p[0]) {
- case '0':
- p[0]++;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
- if (!strncmp(p[0], "DCC=", 4)) { /* SETUP irgendwie !! */
- int i, val[]={0,0,0,0,0,0,0,0};
-
- p[0] += 4;
- if (*p[0] == '?') {
- isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0,1),(0),(0),(0-7)",info);
- p[0]++;
- } else {
- for (i=0; (*p[0]>='0') && (*p[0]<='9'); i++) {
- val[i] = *p[0] - 48;
- p[0]++;
- if (*p[0] == ',')
- p[0]++;
- }
- printk(KERN_DEBUG "isdn_tty: Fax Setup values=%d,%d,%d,%d,%d,%d,%d,%d\n",
- val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
- }
- return 0;
- }
- if (!strncmp(p[0], "LID=", 4)) { /* set sender ID !! */
- char senderID[80];
- int i;
-
- p[0] += 4;
- if (*p[0] =='"')
- p[0]++;
- for(i=0; (*p[0]) && (*p[0] != '"'); i++)
- senderID[i] = *p[0]++;
- senderID[i] = 0;
- if (*p[0] =='"')
- p[0]++;
- printk(KERN_DEBUG "isdn_tty: Fax sender=>%s<\n", senderID);
- return 0;
- }
- if (!strncmp(p[0], "MFR?", 4)) {
- p[0] += 4;
- printk(KERN_DEBUG "isdn_tty: FMFR?\n");
- isdn_tty_at_cout("\r\nISDNfax", info);
- return 0;
- }
- if (!strncmp(p[0], "MDL?", 4)) {
- p[0] += 4;
- printk(KERN_DEBUG "isdn_tty: FMDL?\n");
- isdn_tty_at_cout("\r\nAVM-B1", info);
- return 0;
- }
- if (!strncmp(p[0], "AP=?", 4)) {
- p[0] += 4;
- printk(KERN_DEBUG "isdn_tty: FAP=?\n");
- return 0;
- }
- if (!strncmp(p[0], "PHCTO=", 6)) {
- /* beim trace mit dem zyxel folgt der wert 30 ;*/
- p[0] += 6;
- printk(KERN_DEBUG "isdn_tty: FPHCTO=%s\n", p[0]);
- return 0;
- }
- if (!strncmp(p[0], "CR=", 3)) {
- p[0] += 3;
- printk(KERN_DEBUG "isdn_tty: FCR=%s\n", p[0]);
- return 0;
- }
- printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
+#ifdef CONFIG_ISDN_TTY_FAX
+ return (isdn_tty_cmd_PLUSF_FAX(p, info));
+#else
PARSE_ERROR1;
+#endif
}
/*
@@ -3959,8 +4053,10 @@
isdn_tty_suspend(ds, info, m);
break;
case 'R': /* RESUME */
+ p++;
isdn_tty_get_msnstr(ds, &p);
isdn_tty_resume(ds, info, m);
+ break;
case 'M': /* MESSAGE */
p++;
isdn_tty_send_msg(info, m, p);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)