patch-2.0.31 linux/drivers/isdn/isdn_tty.c
Next file: linux/drivers/isdn/isdn_tty.h
Previous file: linux/drivers/isdn/isdn_syms.c
Back to the patch index
Back to the overall index
- Lines: 4106
- Date:
Thu Aug 14 11:19:48 1997
- Orig file:
v2.0.30/linux/drivers/isdn/isdn_tty.c
- Orig date:
Tue Nov 12 22:36:20 1996
diff -u --recursive --new-file v2.0.30/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
@@ -1,10 +1,10 @@
-/* $Id: isdn_tty.c,v 1.23 1996/10/22 23:14:02 fritz Exp $
- *
+/* $Id: isdn_tty.c,v 1.41 1997/05/27 15:17:31 fritz Exp $
+
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
* Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
- *
+ *
* 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)
@@ -17,9 +17,80 @@
*
* 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.
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.c,v $
+ * Revision 1.41 1997/05/27 15:17:31 fritz
+ * Added changes for recent 2.1.x kernels:
+ * changed return type of isdn_close
+ * queue_task_* -> queue_task
+ * clear/set_bit -> test_and_... where apropriate.
+ * changed type of hard_header_cache parameter.
+ *
+ * Revision 1.40 1997/03/24 22:55:27 fritz
+ * Added debug code for status callbacks.
+ *
+ * Revision 1.39 1997/03/21 18:25:56 fritz
+ * Corrected CTS handling.
+ *
+ * Revision 1.38 1997/03/07 12:13:35 fritz
+ * Bugfix: Send audio in adpcm format was broken.
+ * Bugfix: CTS handling was wrong.
+ *
+ * Revision 1.37 1997/03/07 01:37:34 fritz
+ * Bugfix: Did not compile with CONFIG_ISDN_AUDIO disabled.
+ * Bugfix: isdn_tty_tint() did not handle lowlevel errors correctly.
+ * Bugfix: conversion was wrong when sending ulaw audio.
+ * Added proper ifdef's for CONFIG_ISDN_AUDIO
+ *
+ * Revision 1.36 1997/03/04 21:41:55 fritz
+ * Fix: Excessive stack usage of isdn_tty_senddown()
+ * and isdn_tty_end_vrx() could lead to problems.
+ *
+ * Revision 1.35 1997/03/02 19:05:52 fritz
+ * Bugfix: Avoid recursion.
+ *
+ * Revision 1.34 1997/03/02 14:29:22 fritz
+ * More ttyI related cleanup.
+ *
+ * Revision 1.33 1997/02/28 02:32:45 fritz
+ * Cleanup: Moved some tty related stuff from isdn_common.c
+ * to isdn_tty.c
+ * Bugfix: Bisync protocol did not behave like documented.
+ *
+ * Revision 1.32 1997/02/23 15:43:03 fritz
+ * Small change in handling of incoming calls
+ * documented in newest version of ttyI.4
+ *
+ * Revision 1.31 1997/02/21 13:05:57 fritz
+ * Bugfix: Remote hangup did not set location-info on ttyI's
+ *
+ * Revision 1.30 1997/02/18 09:41:05 fritz
+ * Added support for bitwise access to modem registers (ATSx.y=n, ATSx.y?).
+ * Beautified output of AT&V.
+ *
+ * Revision 1.29 1997/02/16 12:11:51 fritz
+ * Added S13,Bit4 option.
+ *
+ * Revision 1.28 1997/02/10 22:07:08 fritz
+ * Added 2 modem registers for numbering plan and screening info.
+ *
+ * Revision 1.27 1997/02/10 21:31:14 fritz
+ * Changed setup-interface (incoming and outgoing).
+ *
+ * Revision 1.26 1997/02/10 20:12:48 fritz
+ * Changed interface for reporting incoming calls.
+ *
+ * Revision 1.25 1997/02/03 23:04:30 fritz
+ * Reformatted according CodingStyle.
+ * skb->free stuff replaced by macro.
+ * Finished full-duplex audio.
+ *
+ * Revision 1.24 1997/01/14 01:32:42 fritz
+ * Changed audio receive not to rely on skb->users and skb->lock.
+ * Added ATI2 and related variables.
+ * Started adding full-duplex audio capability.
+ *
* Revision 1.23 1996/10/22 23:14:02 fritz
* Changes for compatibility to 2.0.X and 2.1.X kernels.
*
@@ -114,6 +185,7 @@
* Initial revision
*
*/
+#undef ISDN_TTY_STAT_DEBUG
#define __NO_VERSION__
#include <linux/config.h>
@@ -129,29 +201,35 @@
/* Prototypes */
-static int isdn_tty_edit_at(const char *, int, modem_info *, int);
+static int isdn_tty_edit_at(const char *, int, modem_info *, int);
static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
static void isdn_tty_modem_reset_regs(modem_info *, int);
static void isdn_tty_cmd_ATA(modem_info *);
static void isdn_tty_at_cout(char *, modem_info *);
static void isdn_tty_flush_buffer(struct tty_struct *);
+static void isdn_tty_modem_result(int, modem_info *);
+#ifdef CONFIG_ISDN_AUDIO
+static int isdn_tty_countDLE(unsigned char *, int);
+#endif
/* Leave this unchanged unless you know what you do! */
#define MODEM_PARANOIA_CHECK
#define MODEM_DO_RESTART
static char *isdn_ttyname_ttyI = "ttyI";
-static char *isdn_ttyname_cui = "cui";
-static int bit2si[8] = {1,5,7,7,7,7,7,7};
-static int si2bit[8] = {4,1,4,4,4,4,4,4};
-
-char *isdn_tty_revision = "$Revision: 1.23 $";
+static char *isdn_ttyname_cui = "cui";
+static int bit2si[8] =
+{1, 5, 7, 7, 7, 7, 7, 7};
+static int si2bit[8] =
+{4, 1, 4, 4, 4, 4, 4, 4};
+
+char *isdn_tty_revision = "$Revision: 1.41 $";
#define DLE 0x10
#define ETX 0x03
#define DC4 0x14
-/* isdn_tty_try_read() is called from within isdn_receive_callback()
+/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
* to stuff incoming data directly into a tty's flip-buffer. This
* is done to speed up tty-receiving if the receive-queue is empty.
* This routine MUST be called with interrupts off.
@@ -160,37 +238,45 @@
* 0 = Failure, data has to be buffered and later processed by
* isdn_tty_readmodem().
*/
-int isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
+static int
+isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
{
- int c;
- int len;
- struct tty_struct *tty;
+ int c;
+ int len;
+ struct tty_struct *tty;
if (info->online) {
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
c = TTY_FLIPBUF_SIZE - tty->flip.count;
- len = skb->len + skb->users;
+ len = skb->len
+#ifdef CONFIG_ISDN_AUDIO
+ + ISDN_AUDIO_SKB_DLECOUNT(skb)
+#endif
+ ;
if (c >= len) {
- if (skb->users)
- while (skb->len--) {
- if (*skb->data == DLE)
- tty_insert_flip_char(tty, DLE, 0);
- tty_insert_flip_char(tty, *skb->data++, 0);
- }
- else {
- memcpy(tty->flip.char_buf_ptr,
- skb->data, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
- }
- if (info->emu.mdmreg[12] & 128)
- tty->flip.flag_buf_ptr[len - 1] = 0xff;
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
- skb->free = 1;
- kfree_skb(skb, FREE_READ);
+#ifdef CONFIG_ISDN_AUDIO
+ if (ISDN_AUDIO_SKB_DLECOUNT(skb))
+ while (skb->len--) {
+ if (*skb->data == DLE)
+ tty_insert_flip_char(tty, DLE, 0);
+ tty_insert_flip_char(tty, *skb->data++, 0);
+ } else {
+#endif
+ memcpy(tty->flip.char_buf_ptr,
+ skb->data, len);
+ tty->flip.count += len;
+ tty->flip.char_buf_ptr += len;
+ memset(tty->flip.flag_buf_ptr, 0, len);
+ tty->flip.flag_buf_ptr += len;
+#ifdef CONFIG_ISDN_AUDIO
+ }
+#endif
+ if (info->emu.mdmreg[12] & 128)
+ tty->flip.flag_buf_ptr[len - 1] = 0xff;
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ SET_SKB_FREE(skb);
+ kfree_skb(skb, FREE_READ);
return 1;
}
}
@@ -203,7 +289,8 @@
* It tries getting received data from the receive queue an stuff it into
* the tty's flip-buffer.
*/
-void isdn_tty_readmodem(void)
+void
+isdn_tty_readmodem(void)
{
int resched = 0;
int midx;
@@ -216,7 +303,7 @@
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if ((midx = dev->m_idx[i]) >= 0) {
- info = &dev->mdm.info[midx];
+ info = &dev->mdm.info[midx];
if (info->online) {
r = 0;
#ifdef CONFIG_ISDN_AUDIO
@@ -226,20 +313,20 @@
if (info->mcr & UART_MCR_RTS) {
c = TTY_FLIPBUF_SIZE - tty->flip.count;
if (c > 0) {
- save_flags(flags);
- cli();
+ save_flags(flags);
+ cli();
r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
- tty->flip.char_buf_ptr,
- tty->flip.flag_buf_ptr, c, 0);
- /* CISCO AsyncPPP Hack */
+ tty->flip.char_buf_ptr,
+ tty->flip.flag_buf_ptr, c, 0);
+ /* CISCO AsyncPPP Hack */
if (!(info->emu.mdmreg[12] & 128))
memset(tty->flip.flag_buf_ptr, 0, r);
tty->flip.count += r;
tty->flip.flag_buf_ptr += r;
tty->flip.char_buf_ptr += r;
if (r)
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
- restore_flags(flags);
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ restore_flags(flags);
}
} else
r = 1;
@@ -251,257 +338,383 @@
} else
info->rcvsched = 1;
}
- }
+ }
}
if (!resched)
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
}
-void isdn_tty_cleanup_xmit(modem_info *info)
+int
+isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
{
- struct sk_buff *skb;
- unsigned long flags;
+ ulong flags;
+ int midx;
+#ifdef CONFIG_ISDN_AUDIO
+ int ifmt;
+#endif
+ modem_info *info;
- save_flags(flags);
- cli();
- if (skb_queue_len(&info->xmit_queue))
- while ((skb = skb_dequeue(&info->xmit_queue))) {
- skb->free = 1;
- kfree_skb(skb, FREE_WRITE);
- }
- if (skb_queue_len(&info->dtmf_queue))
- while ((skb = skb_dequeue(&info->dtmf_queue))) {
- skb->free = 1;
- kfree_skb(skb, FREE_WRITE);
- }
- restore_flags(flags);
-}
-
-static void isdn_tty_tint(modem_info *info)
-{
- struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
- int len, slen;
-
- if (!skb)
- return;
- len = skb->len;
- if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
- info->isdn_channel, skb)) == len) {
- struct tty_struct *tty = info->tty;
- info->send_outstanding++;
- info->msr |= UART_MSR_CTS;
- info->lsr |= UART_LSR_TEMT;
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup) (tty);
- wake_up_interruptible(&tty->write_wait);
- return;
- }
- if (slen > 0)
- skb_pull(skb,slen);
- skb_queue_head(&info->xmit_queue, skb);
+ if ((midx = dev->m_idx[i]) < 0) {
+ /* if midx is invalid, packet is not for tty */
+ return 0;
+ }
+ info = &dev->mdm.info[midx];
+#ifdef CONFIG_ISDN_AUDIO
+ ifmt = 1;
+
+ if (info->vonline)
+ isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
+#endif
+ if ((info->online < 2)
+#ifdef CONFIG_ISDN_AUDIO
+ && (!(info->vonline & 1))
+#endif
+ ) {
+ /* If Modem not listening, drop data */
+ SET_SKB_FREE(skb);
+ kfree_skb(skb, FREE_READ);
+ return 1;
+ }
+ if (info->emu.mdmreg[13] & 2)
+ /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
+ if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
+ skb_pull(skb, 4);
+#ifdef CONFIG_ISDN_AUDIO
+ if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
+ printk(KERN_WARNING
+ "isdn_audio: insufficient skb_headroom, dropping\n");
+ SET_SKB_FREE(skb);
+ kfree_skb(skb, FREE_READ);
+ return 1;
+ }
+ ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+ if (info->vonline & 1) {
+ /* voice conversion/compression */
+ switch (info->emu.vpar[3]) {
+ case 2:
+ case 3:
+ case 4:
+ /* adpcm
+ * Since compressed data takes less
+ * space, we can overwrite the buffer.
+ */
+ skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr,
+ ifmt,
+ skb->data,
+ skb->data,
+ skb->len));
+ break;
+ case 5:
+ /* a-law */
+ if (!ifmt)
+ isdn_audio_ulaw2alaw(skb->data, skb->len);
+ break;
+ case 6:
+ /* u-law */
+ if (ifmt)
+ isdn_audio_alaw2ulaw(skb->data, skb->len);
+ break;
+ }
+ ISDN_AUDIO_SKB_DLECOUNT(skb) =
+ isdn_tty_countDLE(skb->data, skb->len);
+ }
+#endif
+ /* Try to deliver directly via tty-flip-buf if queue is empty */
+ save_flags(flags);
+ cli();
+ if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
+ if (isdn_tty_try_read(info, skb)) {
+ restore_flags(flags);
+ return 1;
+ }
+ /* Direct deliver failed or queue wasn't empty.
+ * Queue up for later dequeueing via timer-irq.
+ */
+ __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
+ dev->drv[di]->rcvcount[channel] +=
+ (skb->len
+#ifdef CONFIG_ISDN_AUDIO
+ + ISDN_AUDIO_SKB_DLECOUNT(skb)
+#endif
+ );
+ restore_flags(flags);
+ /* Schedule dequeuing */
+ if ((dev->modempoll) && (info->rcvsched))
+ isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+ return 1;
}
+void
+isdn_tty_cleanup_xmit(modem_info * info)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (skb_queue_len(&info->xmit_queue))
+ while ((skb = skb_dequeue(&info->xmit_queue))) {
+ SET_SKB_FREE(skb);
+ kfree_skb(skb, FREE_WRITE);
+ }
#ifdef CONFIG_ISDN_AUDIO
-int isdn_tty_countDLE(unsigned char *buf, int len)
-{
- int count = 0;
-
- while (len--)
- if (*buf++ == DLE)
- count++;
- return count;
+ if (skb_queue_len(&info->dtmf_queue))
+ while ((skb = skb_dequeue(&info->dtmf_queue))) {
+ SET_SKB_FREE(skb);
+ kfree_skb(skb, FREE_WRITE);
+ }
+#endif
+ restore_flags(flags);
+}
+
+static void
+isdn_tty_tint(modem_info * info)
+{
+ struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
+ int len,
+ slen;
+
+ if (!skb)
+ return;
+ len = skb->len;
+ if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
+ info->isdn_channel, skb)) == len) {
+ struct tty_struct *tty = info->tty;
+ info->send_outstanding++;
+ info->msr |= UART_MSR_CTS;
+ info->lsr |= UART_LSR_TEMT;
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
+ wake_up_interruptible(&tty->write_wait);
+ return;
+ }
+ if (slen < 0) {
+ /* Error: no channel, already shutdown, or wrong parameter */
+ SET_SKB_FREE(skb);
+ dev_kfree_skb(skb, FREE_WRITE);
+ return;
+ }
+ if (slen)
+ skb_pull(skb, slen);
+ skb_queue_head(&info->xmit_queue, skb);
+}
+
+#ifdef CONFIG_ISDN_AUDIO
+static int
+isdn_tty_countDLE(unsigned char *buf, int len)
+{
+ int count = 0;
+
+ while (len--)
+ if (*buf++ == DLE)
+ count++;
+ return count;
}
/* This routine is called from within isdn_tty_write() to perform
* DLE-decoding when sending audio-data.
*/
-static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len)
+static int
+isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len)
{
- unsigned char *p = &info->xmit_buf[info->xmit_count];
- int count = 0;
+ unsigned char *p = &info->xmit_buf[info->xmit_count];
+ int count = 0;
- while (len>0) {
- if (m->lastDLE) {
- m->lastDLE = 0;
- switch (*p) {
- case DLE:
- /* Escape code */
- if (len>1)
- memmove(p,p+1,len-1);
- p--;
- count++;
- break;
- case ETX:
- /* End of data */
- info->vonline |= 4;
- return count;
- case DC4:
- /* Abort RX */
- info->vonline &= ~1;
- isdn_tty_at_cout("\020\003", info);
- if (!info->vonline)
- isdn_tty_at_cout("\r\nVCON\r\n", info);
- /* Fall through */
- case 'q':
- case 's':
- /* Silence */
- if (len>1)
- memmove(p,p+1,len-1);
- p--;
- break;
- }
- } else {
- if (*p == DLE)
- m->lastDLE = 1;
- else
- count++;
- }
- p++;
- len--;
- }
- if (len<0) {
- printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
- return 0;
- }
- return count;
+ while (len > 0) {
+ if (m->lastDLE) {
+ m->lastDLE = 0;
+ switch (*p) {
+ case DLE:
+ /* Escape code */
+ if (len > 1)
+ memmove(p, p + 1, len - 1);
+ p--;
+ count++;
+ break;
+ case ETX:
+ /* End of data */
+ info->vonline |= 4;
+ return count;
+ case DC4:
+ /* Abort RX */
+ info->vonline &= ~1;
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG
+ "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n",
+ info->line);
+#endif
+ isdn_tty_at_cout("\020\003", info);
+ if (!info->vonline) {
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG
+ "DLEdown: send VCON on ttyI%d\n",
+ info->line);
+#endif
+ isdn_tty_at_cout("\r\nVCON\r\n", info);
+ }
+ /* Fall through */
+ case 'q':
+ case 's':
+ /* Silence */
+ if (len > 1)
+ memmove(p, p + 1, len - 1);
+ p--;
+ break;
+ }
+ } else {
+ if (*p == DLE)
+ m->lastDLE = 1;
+ else
+ count++;
+ }
+ p++;
+ len--;
+ }
+ if (len < 0) {
+ printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
+ return 0;
+ }
+ return count;
}
/* This routine is called from within isdn_tty_write() when receiving
* audio-data. It interrupts receiving, if an character other than
* ^S or ^Q is sent.
*/
-static int isdn_tty_end_vrx(const char *buf, int c, int from_user)
+static int
+isdn_tty_end_vrx(const char *buf, int c, int from_user)
{
- char tmpbuf[VBUF];
- char *p;
+ char ch;
- if (c > VBUF) {
- printk(KERN_ERR "isdn_tty: (end_vrx) BUFFER OVERFLOW!!!\n");
- return 1;
- }
- if (from_user) {
- copy_from_user(tmpbuf, buf, c);
- p = tmpbuf;
- } else
- p = (char *)buf;
- while (c--) {
- if ((*p != 0x11) && (*p != 0x13))
- return 1;
- p++;
- }
- return 0;
+ while (c--) {
+ if (from_user)
+ GET_USER(ch, buf);
+ else
+ ch = *buf;
+ if ((ch != 0x11) && (ch != 0x13))
+ return 1;
+ buf++;
+ }
+ return 0;
}
-static int voice_cf[7] = { 1, 1, 4, 3, 2, 1, 1 };
+static int voice_cf[7] =
+{0, 0, 4, 3, 2, 0, 0};
-#endif /* CONFIG_ISDN_AUDIO */
+#endif /* CONFIG_ISDN_AUDIO */
/* isdn_tty_senddown() is called either directly from within isdn_tty_write()
* or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
* outgoing data from the tty's xmit-buffer, handles voice-decompression or
* T.70 if necessary, and finally queues it up for sending via isdn_tty_tint.
*/
-static void isdn_tty_senddown(modem_info * info)
+static void
+isdn_tty_senddown(modem_info * info)
{
- unsigned char *buf = info->xmit_buf;
- int buflen;
- int skb_res;
- struct sk_buff *skb;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (!(buflen = info->xmit_count)) {
- restore_flags(flags);
- return;
- }
- if (info->isdn_driver < 0) {
- info->xmit_count = 0;
- restore_flags(flags);
- return;
- }
- skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
-#ifdef CONFIG_ISDN_AUDIO
- if (info->vonline & 2) {
- /* For now, ifmt is fixed to 1 (alaw), since this
- * is used with ISDN everywhere in the world, except
- * US, Canada and Japan.
- * Later, when US-ISDN protocols are implemented,
- * this setting will depend on the D-channel protocol.
- */
- int ifmt = 1;
- int skb_len;
- unsigned char hbuf[VBUF];
-
- memcpy(hbuf,info->xmit_buf,buflen);
- info->xmit_count = 0;
- restore_flags(flags);
- /* voice conversion/decompression */
- skb_len = buflen * voice_cf[info->emu.vpar[3]];
- skb = dev_alloc_skb(skb_len + skb_res);
- if (!skb) {
- printk(KERN_WARNING
- "isdn_tty: Out of memory in ttyI%d senddown\n", info->line);
- return;
- }
- skb_reserve(skb, skb_res);
- switch (info->emu.vpar[3]) {
- case 2:
- case 3:
- case 4:
- /* adpcm, compatible to ZyXel 1496 modem
- * with ROM revision 6.01
- */
- buflen = isdn_audio_adpcm2xlaw(info->adpcms,
- ifmt,
- hbuf,
- skb_put(skb,skb_len),
- buflen);
- skb_trim(skb, buflen);
- break;
- case 5:
- /* a-law */
- if (!ifmt)
- isdn_audio_alaw2ulaw(hbuf,buflen);
- memcpy(skb_put(skb,buflen),hbuf,buflen);
- break;
- case 6:
- /* u-law */
- if (ifmt)
- isdn_audio_ulaw2alaw(hbuf,buflen);
- memcpy(skb_put(skb,buflen),hbuf,buflen);
- break;
- }
- if (info->vonline & 4) {
- info->vonline &= ~6;
- if (!info->vonline)
- isdn_tty_at_cout("\r\nVCON\r\n",info);
- }
- } else {
-#endif /* CONFIG_ISDN_AUDIO */
- skb = dev_alloc_skb(buflen + skb_res);
- if (!skb) {
- printk(KERN_WARNING
- "isdn_tty: Out of memory in ttyI%d senddown\n", info->line);
- restore_flags(flags);
- return;
- }
- skb_reserve(skb, skb_res);
- memcpy(skb_put(skb,buflen),buf,buflen);
- info->xmit_count = 0;
- restore_flags(flags);
-#ifdef CONFIG_ISDN_AUDIO
- }
-#endif
- skb->free = 1;
- if (info->emu.mdmreg[13] & 2)
- /* Add T.70 simplified header */
- memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
- skb_queue_tail(&info->xmit_queue, skb);
- if ((info->emu.mdmreg[12] & 0x10) != 0)
- info->msr &= UART_MSR_CTS;
- info->lsr &= UART_LSR_TEMT;
+ int buflen;
+ int skb_res;
+#ifdef CONFIG_ISDN_AUDIO
+ int audio_len;
+#endif
+ struct sk_buff *skb;
+ unsigned long flags;
+
+#ifdef CONFIG_ISDN_AUDIO
+ if (info->vonline & 4) {
+ info->vonline &= ~6;
+ if (!info->vonline) {
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG
+ "senddown: send VCON on ttyI%d\n",
+ info->line);
+#endif
+ isdn_tty_at_cout("\r\nVCON\r\n", info);
+ }
+ }
+#endif
+ save_flags(flags);
+ cli();
+ if (!(buflen = info->xmit_count)) {
+ restore_flags(flags);
+ return;
+ }
+ if ((info->emu.mdmreg[12] & 0x10) != 0)
+ info->msr &= ~UART_MSR_CTS;
+ info->lsr &= ~UART_LSR_TEMT;
+ if (info->isdn_driver < 0) {
+ info->xmit_count = 0;
+ restore_flags(flags);
+ return;
+ }
+ skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
+#ifdef CONFIG_ISDN_AUDIO
+ if (info->vonline & 2)
+ audio_len = buflen * voice_cf[info->emu.vpar[3]];
+ else
+ audio_len = 0;
+ skb = dev_alloc_skb(skb_res + buflen + audio_len);
+#else
+ skb = dev_alloc_skb(skb_res + buflen);
+#endif
+ if (!skb) {
+ restore_flags(flags);
+ printk(KERN_WARNING
+ "isdn_tty: Out of memory in ttyI%d senddown\n",
+ info->line);
+ return;
+ }
+ skb_reserve(skb, skb_res);
+ memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
+ info->xmit_count = 0;
+ restore_flags(flags);
+#ifdef CONFIG_ISDN_AUDIO
+ if (info->vonline & 2) {
+ /* For now, ifmt is fixed to 1 (alaw), since this
+ * is used with ISDN everywhere in the world, except
+ * US, Canada and Japan.
+ * Later, when US-ISDN protocols are implemented,
+ * this setting will depend on the D-channel protocol.
+ */
+ int ifmt = 1;
+
+ /* voice conversion/decompression */
+ switch (info->emu.vpar[3]) {
+ case 2:
+ case 3:
+ case 4:
+ /* adpcm, compatible to ZyXel 1496 modem
+ * with ROM revision 6.01
+ */
+ audio_len = isdn_audio_adpcm2xlaw(info->adpcms,
+ ifmt,
+ skb->data,
+ skb_put(skb, audio_len),
+ buflen);
+ skb_pull(skb, buflen);
+ skb_trim(skb, audio_len);
+ break;
+ case 5:
+ /* a-law */
+ if (!ifmt)
+ isdn_audio_alaw2ulaw(skb->data,
+ buflen);
+ break;
+ case 6:
+ /* u-law */
+ if (ifmt)
+ isdn_audio_ulaw2alaw(skb->data,
+ buflen);
+ break;
+ }
+ }
+#endif /* CONFIG_ISDN_AUDIO */
+ SET_SKB_FREE(skb);
+ if (info->emu.mdmreg[13] & 2)
+ /* Add T.70 simplified header */
+ memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
+ skb_queue_tail(&info->xmit_queue, skb);
}
/************************************************************
@@ -517,53 +730,55 @@
* isdn_tty_modem_result() to stuff a "NO CARRIER" Message
* into the tty's flip-buffer.
*/
-static void isdn_tty_modem_do_ncarrier(unsigned long data)
+static void
+isdn_tty_modem_do_ncarrier(unsigned long data)
{
- modem_info * info = (modem_info *)data;
- isdn_tty_modem_result(3, info);
+ modem_info *info = (modem_info *) data;
+ isdn_tty_modem_result(3, info);
}
/* Next routine is called, whenever the DTR-signal is raised.
* It checks the ncarrier-flag, and triggers the above routine
* when necessary. The ncarrier-flag is set, whenever DTR goes
* low.
- */
-static void isdn_tty_modem_ncarrier(modem_info * info)
+ */
+static void
+isdn_tty_modem_ncarrier(modem_info * info)
{
- if (info->ncarrier) {
- info->ncarrier = 0;
- info->nc_timer.expires = jiffies + HZ;
- info->nc_timer.function = isdn_tty_modem_do_ncarrier;
- info->nc_timer.data = (unsigned long)info;
- add_timer(&info->nc_timer);
- }
+ if (info->ncarrier) {
+ info->nc_timer.expires = jiffies + HZ;
+ info->nc_timer.function = isdn_tty_modem_do_ncarrier;
+ info->nc_timer.data = (unsigned long) info;
+ add_timer(&info->nc_timer);
+ }
}
/* isdn_tty_dial() performs dialing of a tty an the necessary
* setup of the lower levels before that.
*/
-static void isdn_tty_dial(char *n, modem_info * info, atemu * m)
+static void
+isdn_tty_dial(char *n, modem_info * info, atemu * m)
{
- int usg = ISDN_USAGE_MODEM;
- int si = 7;
- int l2 = m->mdmreg[14];
+ int usg = ISDN_USAGE_MODEM;
+ int si = 7;
+ int l2 = m->mdmreg[14];
isdn_ctrl cmd;
ulong flags;
int i;
- int j;
+ int j;
- for (j=7;j>=0;j--)
- if (m->mdmreg[18] & (1<<j)) {
- si = bit2si[j];
- break;
- }
-#ifdef CONFIG_ISDN_AUDIO
- if (si == 1) {
- l2 = 4;
- usg = ISDN_USAGE_VOICE;
- }
+ for (j = 7; j >= 0; j--)
+ if (m->mdmreg[18] & (1 << j)) {
+ si = bit2si[j];
+ break;
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ if (si == 1) {
+ l2 = 4;
+ usg = ISDN_USAGE_VOICE;
+ }
#endif
- m->mdmreg[20] = si2bit[si];
+ m->mdmreg[20] = si2bit[si];
save_flags(flags);
cli();
i = isdn_get_free_channel(usg, l2, m->mdmreg[15], -1, -1);
@@ -571,38 +786,44 @@
restore_flags(flags);
isdn_tty_modem_result(6, info);
} else {
- info->isdn_driver = dev->drvmap[i];
- info->isdn_channel = dev->chanmap[i];
- info->drv_index = i;
- dev->m_idx[i] = info->line;
- dev->usage[i] |= ISDN_USAGE_OUTGOING;
- isdn_info_update();
- restore_flags(flags);
- cmd.driver = info->isdn_driver;
- cmd.arg = info->isdn_channel;
- cmd.command = ISDN_CMD_CLREAZ;
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- strcpy(cmd.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_SETEAZ;
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_SETL2;
- cmd.arg = info->isdn_channel + (l2 << 8);
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_SETL3;
- cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- cmd.driver = info->isdn_driver;
- cmd.arg = info->isdn_channel;
- sprintf(cmd.num, "%s,%s,%d,%d", n, isdn_map_eaz2msn(m->msn, info->isdn_driver),
- si, m->mdmreg[19]);
- cmd.command = ISDN_CMD_DIAL;
- info->dialing = 1;
- strcpy(dev->num[i], n);
- isdn_info_update();
- dev->drv[info->isdn_driver]->interface->command(&cmd);
+ info->isdn_driver = dev->drvmap[i];
+ info->isdn_channel = dev->chanmap[i];
+ info->drv_index = i;
+ dev->m_idx[i] = info->line;
+ dev->usage[i] |= ISDN_USAGE_OUTGOING;
+ info->last_dir = 1;
+ strcpy(info->last_num, n);
+ isdn_info_update();
+ restore_flags(flags);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.command = ISDN_CMD_CLREAZ;
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETEAZ;
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL2;
+ info->last_l2 = l2;
+ cmd.arg = info->isdn_channel + (l2 << 8);
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL3;
+ cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ sprintf(cmd.parm.setup.phone, "%s", n);
+ sprintf(cmd.parm.setup.eazmsn, "%s",
+ isdn_map_eaz2msn(m->msn, info->isdn_driver));
+ cmd.parm.setup.si1 = si;
+ cmd.parm.setup.si2 = m->mdmreg[19];
+ cmd.command = ISDN_CMD_DIAL;
+ info->dialing = 1;
+ strcpy(dev->num[i], n);
+ isdn_info_update();
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
}
}
@@ -610,64 +831,66 @@
* ISDN-line (hangup). The usage-status is cleared
* and some cleanup is done also.
*/
-void isdn_tty_modem_hup(modem_info * info)
+static void
+isdn_tty_modem_hup(modem_info * info, int local)
{
isdn_ctrl cmd;
- int usage;
+ int usage;
- if (!info)
- return;
+ if (!info)
+ return;
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
+ printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
#endif
- info->rcvsched = 0;
- info->online = 0;
- isdn_tty_flush_buffer(info->tty);
- if (info->vonline & 1) {
- /* voice-recording, add DLE-ETX */
- isdn_tty_at_cout("\020\003", info);
- }
- if (info->vonline & 2) {
- /* voice-playing, add DLE-DC4 */
- isdn_tty_at_cout("\020\024", info);
- }
- info->vonline = 0;
-#ifdef CONFIG_ISDN_AUDIO
- if (info->dtmf_state) {
- kfree(info->dtmf_state);
- info->dtmf_state = NULL;
- }
- if (info->adpcms) {
- kfree(info->adpcms);
- info->adpcms = NULL;
- }
- if (info->adpcmr) {
- kfree(info->adpcmr);
- info->adpcmr = NULL;
- }
+ info->rcvsched = 0;
+ isdn_tty_flush_buffer(info->tty);
+ if (info->online) {
+ info->last_lhup = local;
+ info->online = 0;
+ /* NO CARRIER message */
+ isdn_tty_modem_result(3, info);
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ info->vonline = 0;
+ if (info->dtmf_state) {
+ kfree(info->dtmf_state);
+ info->dtmf_state = NULL;
+ }
+ if (info->adpcms) {
+ kfree(info->adpcms);
+ info->adpcms = NULL;
+ }
+ if (info->adpcmr) {
+ kfree(info->adpcmr);
+ info->adpcmr = NULL;
+ }
#endif
- info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
- info->lsr |= UART_LSR_TEMT;
+ info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
+ info->lsr |= UART_LSR_TEMT;
if (info->isdn_driver >= 0) {
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_HANGUP;
- cmd.arg = info->isdn_channel;
- dev->drv[info->isdn_driver]->interface->command(&cmd);
+ if (local) {
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_HANGUP;
+ cmd.arg = info->isdn_channel;
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ }
isdn_all_eaz(info->isdn_driver, info->isdn_channel);
- usage = (info->emu.mdmreg[20] == 1)?
- ISDN_USAGE_VOICE:ISDN_USAGE_MODEM;
+ info->emu.mdmreg[1] = 0;
+ usage = (info->emu.mdmreg[20] == 1) ?
+ ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
isdn_free_channel(info->isdn_driver, info->isdn_channel,
- usage);
+ usage);
}
info->isdn_driver = -1;
info->isdn_channel = -1;
- if (info->drv_index >= 0) {
- dev->m_idx[info->drv_index] = -1;
- info->drv_index = -1;
- }
+ if (info->drv_index >= 0) {
+ dev->m_idx[info->drv_index] = -1;
+ info->drv_index = -1;
+ }
}
-static inline int isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
+static inline int
+isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
{
#ifdef MODEM_PARANOIA_CHECK
if (!info) {
@@ -688,9 +911,13 @@
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static void isdn_tty_change_speed(modem_info * info)
+static void
+isdn_tty_change_speed(modem_info * info)
{
- uint cflag, cval, fcr, quot;
+ uint cflag,
+ cval,
+ fcr,
+ quot;
int i;
if (!info->tty || !info->tty->termios)
@@ -707,19 +934,19 @@
}
if (quot) {
info->mcr |= UART_MCR_DTR;
- isdn_tty_modem_ncarrier(info);
+ isdn_tty_modem_ncarrier(info);
} else {
info->mcr &= ~UART_MCR_DTR;
- if (info->emu.mdmreg[13] & 4) {
+ if (info->emu.mdmreg[13] & 4) {
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in changespeed\n");
+ printk(KERN_DEBUG "Mhup in changespeed\n");
#endif
- if (info->online)
- info->ncarrier = 1;
- isdn_tty_modem_reset_regs(info, 0);
- isdn_tty_modem_hup(info);
- }
- return;
+ if (info->online)
+ info->ncarrier = 1;
+ isdn_tty_modem_reset_regs(info, 0);
+ isdn_tty_modem_hup(info, 1);
+ }
+ return;
}
/* byte size and parity */
cval = cflag & (CSIZE | CSTOPB);
@@ -742,7 +969,8 @@
}
}
-static int isdn_tty_startup(modem_info * info)
+static int
+isdn_tty_startup(modem_info * info)
{
ulong flags;
@@ -750,12 +978,12 @@
return 0;
save_flags(flags);
cli();
- isdn_MOD_INC_USE_COUNT();
+ isdn_MOD_INC_USE_COUNT();
#ifdef ISDN_DEBUG_MODEM_OPEN
printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
#endif
/*
- * Now, initialize the UART
+ * Now, initialize the UART
*/
info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
if (info->tty)
@@ -776,7 +1004,8 @@
* This routine will shutdown a serial port; interrupts are disabled, and
* DTR is dropped if the hangup on close termio flag is on.
*/
-static void isdn_tty_shutdown(modem_info * info)
+static void
+isdn_tty_shutdown(modem_info * info)
{
ulong flags;
@@ -786,17 +1015,18 @@
printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
#endif
save_flags(flags);
- cli(); /* Disable interrupts */
- isdn_MOD_DEC_USE_COUNT();
+ cli(); /* Disable interrupts */
+ isdn_MOD_DEC_USE_COUNT();
+ info->msr &= ~UART_MSR_RI;
if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
- if (info->emu.mdmreg[13] & 4) {
- isdn_tty_modem_reset_regs(info, 0);
+ if (info->emu.mdmreg[13] & 4) {
+ isdn_tty_modem_reset_regs(info, 0);
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
+ printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
#endif
- isdn_tty_modem_hup(info);
- }
+ isdn_tty_modem_hup(info, 1);
+ }
}
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -814,9 +1044,11 @@
* - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
* - If dialing, abort dial.
*/
-static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
+static int
+isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
{
- int c, total = 0;
+ int c,
+ total = 0;
ulong flags;
modem_info *info = (modem_info *) tty->driver_data;
@@ -824,70 +1056,82 @@
return 0;
if (!tty)
return 0;
- save_flags(flags);
- cli();
+ save_flags(flags);
+ cli();
while (1) {
c = MIN(count, info->xmit_size - info->xmit_count);
if (info->isdn_driver >= 0)
c = MIN(c, dev->drv[info->isdn_driver]->maxbufsize);
if (c <= 0)
break;
- if ((info->online > 1) ||
- (info->vonline & 2)) {
- atemu *m = &info->emu;
-
- if (!(info->vonline & 2))
- isdn_tty_check_esc(buf, m->mdmreg[2], c,
- &(m->pluscount),
- &(m->lastplus),
- from_user);
- if (from_user)
- copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
- else
- memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
-#ifdef CONFIG_ISDN_AUDIO
- if (info->vonline & 2) {
- int cc;
-
- if (!(cc = isdn_tty_handleDLEdown(info,m,c))) {
- /* If DLE decoding results in zero-transmit, but
- * c originally was non-zero, do a wakeup.
- */
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup) (tty);
- wake_up_interruptible(&tty->write_wait);
- info->msr |= UART_MSR_CTS;
- info->lsr |= UART_LSR_TEMT;
- }
- info->xmit_count += cc;
- } else
+ if ((info->online > 1)
+#ifdef CONFIG_ISDN_AUDIO
+ || (info->vonline & 3)
#endif
- info->xmit_count += c;
- if (m->mdmreg[13] & 1) {
- isdn_tty_senddown(info);
- isdn_tty_tint(info);
- }
- } else {
- info->msr |= UART_MSR_CTS;
- info->lsr |= UART_LSR_TEMT;
+ ) {
+ atemu *m = &info->emu;
+
#ifdef CONFIG_ISDN_AUDIO
- if (info->vonline & 1) {
- if (isdn_tty_end_vrx(buf, c, from_user)) {
- info->vonline &= ~1;
- isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
- }
- } else
+ if (!info->vonline)
+#endif
+ isdn_tty_check_esc(buf, m->mdmreg[2], c,
+ &(m->pluscount),
+ &(m->lastplus),
+ from_user);
+ if (from_user)
+ copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
+ else
+ memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
+#ifdef CONFIG_ISDN_AUDIO
+ if (info->vonline) {
+ int cc = isdn_tty_handleDLEdown(info, m, c);
+ if (info->vonline & 2) {
+ if (!cc) {
+ /* If DLE decoding results in zero-transmit, but
+ * c originally was non-zero, do a wakeup.
+ */
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
+ wake_up_interruptible(&tty->write_wait);
+ info->msr |= UART_MSR_CTS;
+ info->lsr |= UART_LSR_TEMT;
+ }
+ info->xmit_count += cc;
+ }
+ if ((info->vonline & 3) == 1) {
+ /* Do NOT handle Ctrl-Q or Ctrl-S
+ * when in full-duplex audio mode.
+ */
+ if (isdn_tty_end_vrx(buf, c, from_user)) {
+ info->vonline &= ~1;
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG
+ "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",
+ info->line);
+#endif
+ isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
+ }
+ }
+ } else
#endif
- if (info->dialing) {
- info->dialing = 0;
+ info->xmit_count += c;
+ if (m->mdmreg[13] & 1) {
+ isdn_tty_senddown(info);
+ isdn_tty_tint(info);
+ }
+ } else {
+ info->msr |= UART_MSR_CTS;
+ info->lsr |= UART_LSR_TEMT;
+ if (info->dialing) {
+ info->dialing = 0;
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
+ printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
#endif
- isdn_tty_modem_result(3, info);
- isdn_tty_modem_hup(info);
- } else
- c = isdn_tty_edit_at(buf, c, info, from_user);
+ isdn_tty_modem_result(3, info);
+ isdn_tty_modem_hup(info, 1);
+ } else
+ c = isdn_tty_edit_at(buf, c, info, from_user);
}
buf += c;
count -= c;
@@ -895,11 +1139,12 @@
}
if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
- restore_flags(flags);
+ restore_flags(flags);
return total;
}
-static int isdn_tty_write_room(struct tty_struct *tty)
+static int
+isdn_tty_write_room(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
int ret;
@@ -912,7 +1157,8 @@
return (ret < 0) ? 0 : ret;
}
-static int isdn_tty_chars_in_buffer(struct tty_struct *tty)
+static int
+isdn_tty_chars_in_buffer(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
@@ -923,32 +1169,34 @@
return (info->xmit_count);
}
-static void isdn_tty_flush_buffer(struct tty_struct *tty)
+static void
+isdn_tty_flush_buffer(struct tty_struct *tty)
{
modem_info *info;
- unsigned long flags;
+ unsigned long flags;
- save_flags(flags);
- cli();
- if (!tty) {
- restore_flags(flags);
- return;
- }
- info = (modem_info *) tty->driver_data;
+ save_flags(flags);
+ cli();
+ if (!tty) {
+ restore_flags(flags);
+ return;
+ }
+ info = (modem_info *) tty->driver_data;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer")) {
- restore_flags(flags);
+ restore_flags(flags);
return;
- }
- isdn_tty_cleanup_xmit(info);
- info->xmit_count = 0;
- restore_flags(flags);
+ }
+ isdn_tty_cleanup_xmit(info);
+ info->xmit_count = 0;
+ restore_flags(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup) (tty);
}
-static void isdn_tty_flush_chars(struct tty_struct *tty)
+static void
+isdn_tty_flush_chars(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
@@ -961,12 +1209,13 @@
/*
* ------------------------------------------------------------
* isdn_tty_throttle()
- *
+ *
* This routine is called by the upper-layer tty layer to signal that
* incoming characters should be throttled.
* ------------------------------------------------------------
*/
-static void isdn_tty_throttle(struct tty_struct *tty)
+static void
+isdn_tty_throttle(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
@@ -977,7 +1226,8 @@
info->mcr &= ~UART_MCR_RTS;
}
-static void isdn_tty_unthrottle(struct tty_struct *tty)
+static void
+isdn_tty_unthrottle(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
@@ -1006,9 +1256,10 @@
* release the bus after transmitting. This must be done when
* the transmit shift register is empty, not be done when the
* transmit holding register is empty. This functionality
- * allows RS485 driver to be written in user space.
+ * allows RS485 driver to be written in user space.
*/
-static int isdn_tty_get_lsr_info(modem_info * info, uint * value)
+static int
+isdn_tty_get_lsr_info(modem_info * info, uint * value)
{
u_char status;
uint result;
@@ -1024,9 +1275,11 @@
}
-static int isdn_tty_get_modem_info(modem_info * info, uint * value)
+static int
+isdn_tty_get_modem_info(modem_info * info, uint * value)
{
- u_char control, status;
+ u_char control,
+ status;
uint result;
ulong flags;
@@ -1045,76 +1298,78 @@
return 0;
}
-static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
+static int
+isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
{
uint arg;
- int pre_dtr;
+ int pre_dtr;
- GET_USER(arg, (uint *)value);
+ GET_USER(arg, (uint *) value);
switch (cmd) {
- case TIOCMBIS:
+ case TIOCMBIS:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);
#endif
- if (arg & TIOCM_RTS) {
- info->mcr |= UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
- info->mcr |= UART_MCR_DTR;
- isdn_tty_modem_ncarrier(info);
- }
- break;
- case TIOCMBIC:
+ if (arg & TIOCM_RTS) {
+ info->mcr |= UART_MCR_RTS;
+ }
+ if (arg & TIOCM_DTR) {
+ info->mcr |= UART_MCR_DTR;
+ isdn_tty_modem_ncarrier(info);
+ }
+ break;
+ case TIOCMBIC:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);
#endif
- if (arg & TIOCM_RTS) {
- info->mcr &= ~UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
- info->mcr &= ~UART_MCR_DTR;
- if (info->emu.mdmreg[13] & 4) {
- isdn_tty_modem_reset_regs(info, 0);
+ if (arg & TIOCM_RTS) {
+ info->mcr &= ~UART_MCR_RTS;
+ }
+ if (arg & TIOCM_DTR) {
+ info->mcr &= ~UART_MCR_DTR;
+ if (info->emu.mdmreg[13] & 4) {
+ isdn_tty_modem_reset_regs(info, 0);
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
+ printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
#endif
- if (info->online)
- info->ncarrier = 1;
- isdn_tty_modem_hup(info);
- }
- }
- break;
- case TIOCMSET:
+ if (info->online)
+ info->ncarrier = 1;
+ isdn_tty_modem_hup(info, 1);
+ }
+ }
+ break;
+ case TIOCMSET:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);
#endif
- pre_dtr = (info->mcr & UART_MCR_DTR);
- info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
- if (!(info->mcr & UART_MCR_DTR)) {
- if (info->emu.mdmreg[13] & 4) {
- isdn_tty_modem_reset_regs(info, 0);
+ pre_dtr = (info->mcr & UART_MCR_DTR);
+ info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
+ | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+ | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+ if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
+ if (!(info->mcr & UART_MCR_DTR)) {
+ if (info->emu.mdmreg[13] & 4) {
+ isdn_tty_modem_reset_regs(info, 0);
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "Mhup in TIOCMSET\n");
+ printk(KERN_DEBUG "Mhup in TIOCMSET\n");
#endif
- if (info->online)
- info->ncarrier = 1;
- isdn_tty_modem_hup(info);
- }
- } else
- isdn_tty_modem_ncarrier(info);
- }
- break;
- default:
- return -EINVAL;
+ if (info->online)
+ info->ncarrier = 1;
+ isdn_tty_modem_hup(info, 1);
+ }
+ } else
+ isdn_tty_modem_ncarrier(info);
+ }
+ break;
+ default:
+ return -EINVAL;
}
return 0;
}
-static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
- uint cmd, ulong arg)
+static int
+isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
+ uint cmd, ulong arg)
{
modem_info *info = (modem_info *) tty->driver_data;
int error;
@@ -1122,97 +1377,98 @@
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl"))
return -ENODEV;
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TCSBRK\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TCSBRK\n", info->line);
#endif
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TCSBRKP\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TCSBRKP\n", info->line);
#endif
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- return 0;
- case TIOCGSOFTCAR:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ return 0;
+ case TIOCGSOFTCAR:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
#endif
- error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
- if (error)
- return error;
- put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
- return 0;
- case TIOCSSOFTCAR:
+ error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
+ if (error)
+ return error;
+ put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
+ return 0;
+ case TIOCSSOFTCAR:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
#endif
- error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
- if (error)
- return error;
- GET_USER(arg, (ulong *) arg);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
- case TIOCMGET:
+ error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
+ if (error)
+ return error;
+ GET_USER(arg, (ulong *) arg);
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+ case TIOCMGET:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
#endif
- error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
- if (error)
- return error;
- return isdn_tty_get_modem_info(info, (uint *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
- if (error)
- return error;
- return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
- case TIOCSERGETLSR: /* Get line status register */
+ error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
+ if (error)
+ return error;
+ return isdn_tty_get_modem_info(info, (uint *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
+ if (error)
+ return error;
+ return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
+ printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
#endif
- error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
- if (error)
- return error;
- else
- return isdn_tty_get_lsr_info(info, (uint *) arg);
-
- default:
+ error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
+ if (error)
+ return error;
+ else
+ return isdn_tty_get_lsr_info(info, (uint *) arg);
+
+ default:
#ifdef ISDN_DEBUG_MODEM_IOCTL
- printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
+ printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
#endif
- return -ENOIOCTLCMD;
+ return -ENOIOCTLCMD;
}
return 0;
}
-static void isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void
+isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
modem_info *info = (modem_info *) tty->driver_data;
- if (!old_termios)
- isdn_tty_change_speed(info);
- else {
- if (tty->termios->c_cflag == old_termios->c_cflag)
- return;
- isdn_tty_change_speed(info);
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- }
- }
+ if (!old_termios)
+ isdn_tty_change_speed(info);
+ else {
+ if (tty->termios->c_cflag == old_termios->c_cflag)
+ return;
+ isdn_tty_change_speed(info);
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ }
+ }
}
/*
@@ -1220,9 +1476,11 @@
* isdn_tty_open() and friends
* ------------------------------------------------------------
*/
-static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
+static int
+isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
{
- struct wait_queue wait = {current, NULL};
+ struct wait_queue wait =
+ {current, NULL};
int do_clocal = 0;
unsigned long flags;
int retval;
@@ -1233,8 +1491,8 @@
*/
if (tty_hung_up_p(filp) ||
(info->flags & ISDN_ASYNC_CLOSING)) {
- if (info->flags & ISDN_ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ if (info->flags & ISDN_ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
#ifdef MODEM_DO_RESTART
if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -1267,7 +1525,7 @@
* and then exit.
*/
if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
+ (tty->flags & (1 << TTY_IO_ERROR))) {
if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
return -EBUSY;
info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
@@ -1293,11 +1551,11 @@
printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
info->line, info->count);
#endif
- save_flags(flags);
- cli();
- if (!(tty_hung_up_p(filp)))
- info->count--;
- restore_flags(flags);
+ save_flags(flags);
+ cli();
+ if (!(tty_hung_up_p(filp)))
+ info->count--;
+ restore_flags(flags);
info->blocked_open++;
while (1) {
current->state = TASK_INTERRUPTIBLE;
@@ -1349,10 +1607,12 @@
* the IRQ chain. It also performs the serial-specific
* initialization for the tty structure.
*/
-static int isdn_tty_open(struct tty_struct *tty, struct file *filp)
+static int
+isdn_tty_open(struct tty_struct *tty, struct file *filp)
{
modem_info *info;
- int retval, line;
+ int retval,
+ line;
line = MINOR(tty->device) - tty->driver.minor_start;
if (line < 0 || line > ISDN_MAX_CHANNELS)
@@ -1403,7 +1663,8 @@
return 0;
}
-static void isdn_tty_close(struct tty_struct *tty, struct file *filp)
+static void
+isdn_tty_close(struct tty_struct *tty, struct file *filp)
{
modem_info *info = (modem_info *) tty->driver_data;
ulong flags;
@@ -1454,7 +1715,7 @@
if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
info->callout_termios = *tty->termios;
- tty->closing = 1;
+ tty->closing = 1;
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
@@ -1462,7 +1723,7 @@
* line status register.
*/
if (info->flags & ISDN_ASYNC_INITIALIZED) {
- tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+ tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@@ -1484,12 +1745,12 @@
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
info->tty = 0;
- info->ncarrier = 0;
+ info->ncarrier = 0;
tty->closing = 0;
if (info->blocked_open) {
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 50;
- schedule();
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 50;
+ schedule();
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
@@ -1504,7 +1765,8 @@
/*
* isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
*/
-static void isdn_tty_hangup(struct tty_struct *tty)
+static void
+isdn_tty_hangup(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
@@ -1519,7 +1781,8 @@
/* This routine initializes all emulator-data.
*/
-static void isdn_tty_reset_profile(atemu * m)
+static void
+isdn_tty_reset_profile(atemu * m)
{
m->profile[0] = 0;
m->profile[1] = 0;
@@ -1545,27 +1808,34 @@
m->pmsn[0] = '\0';
}
-static void isdn_tty_modem_reset_vpar(atemu *m)
+#ifdef CONFIG_ISDN_AUDIO
+static void
+isdn_tty_modem_reset_vpar(atemu * m)
{
- m->vpar[0] = 2; /* Voice-device (2 = phone line) */
- 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[0] = 2; /* Voice-device (2 = phone line) */
+ 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 ) */
}
+#endif
-static void isdn_tty_modem_reset_regs(modem_info *info, int force)
+static void
+isdn_tty_modem_reset_regs(modem_info * info, int force)
{
- atemu *m = &info->emu;
+ atemu *m = &info->emu;
if ((m->mdmreg[12] & 32) || force) {
memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
- info->xmit_size = m->mdmreg[16] * 16;
+ info->xmit_size = m->mdmreg[16] * 16;
}
- isdn_tty_modem_reset_vpar(m);
+#ifdef CONFIG_ISDN_AUDIO
+ isdn_tty_modem_reset_vpar(m);
+#endif
m->mdmcmdl = 0;
}
-static void modem_write_profile(atemu * m)
+static void
+modem_write_profile(atemu * m)
{
memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
@@ -1573,7 +1843,8 @@
send_sig(SIGIO, dev->profd, 1);
}
-int isdn_tty_modem_init(void)
+int
+isdn_tty_modem_init(void)
{
modem *m;
int i;
@@ -1630,6 +1901,12 @@
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
+ sprintf(info->last_cause, "0000");
+ sprintf(info->last_num, "none");
+ info->last_dir = 0;
+ info->last_lhup = 1;
+ info->last_l2 = 0;
+ info->last_si = 0;
isdn_tty_reset_profile(&info->emu);
isdn_tty_modem_reset_regs(info, 1);
info->magic = ISDN_ASYNC_MAGIC;
@@ -1646,14 +1923,16 @@
info->isdn_channel = -1;
info->drv_index = -1;
info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
- skb_queue_head_init(&info->xmit_queue);
- skb_queue_head_init(&info->dtmf_queue);
- if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
- printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
- return -3;
- }
- /* Make room for T.70 header */
- info->xmit_buf += 4;
+ skb_queue_head_init(&info->xmit_queue);
+#ifdef CONFIG_ISDN_AUDIO
+ skb_queue_head_init(&info->dtmf_queue);
+#endif
+ if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
+ printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
+ return -3;
+ }
+ /* Make room for T.70 header */
+ info->xmit_buf += 4;
}
return 0;
}
@@ -1664,61 +1943,46 @@
* it to the ISDN-Channel.
* Return Index to dev->mdm or -1 if none found.
*/
-int isdn_tty_find_icall(int di, int ch, char *num)
+int
+isdn_tty_find_icall(int di, int ch, setup_parm setup)
{
char *eaz;
int i;
int idx;
int si1;
int si2;
- char *s;
- char nr[31];
+ char nr[32];
ulong flags;
save_flags(flags);
cli();
- if (num[0] == ',') {
+ if (!setup.phone[0]) {
nr[0] = '0';
- strncpy(&nr[1], num, 29);
+ nr[1] = '\0';
printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
} else
- strncpy(nr, num, 30);
- s = strtok(nr, ",");
- s = strtok(NULL, ",");
- if (!s) {
- printk(KERN_WARNING "isdn_tty: Incoming callinfo garbled, ignored: %s\n",
- num);
- restore_flags(flags);
- return -1;
- }
- si1 = (int)simple_strtoul(s,NULL,10);
- s = strtok(NULL, ",");
- if (!s) {
- printk(KERN_WARNING "isdn_tty: Incoming callinfo garbled, ignored: %s\n",
- num);
- restore_flags(flags);
- return -1;
- }
- si2 = (int)simple_strtoul(s,NULL,10);
- eaz = strtok(NULL, ",");
- if (!eaz) {
+ strcpy(nr, setup.phone);
+ si1 = (int) setup.si1;
+ si2 = (int) setup.si2;
+ if (!setup.eazmsn[0]) {
printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
eaz = "0";
- }
+ } else
+ eaz = setup.eazmsn;
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
#endif
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- modem_info *info = &dev->mdm.info[i];
+ modem_info *info = &dev->mdm.info[i];
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di),
info->emu.mdmreg[18], info->emu.mdmreg[19]);
#endif
if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di),
- eaz)) && /* EAZ is matching */
- (info->emu.mdmreg[18] & si2bit[si1]) && /* SI1 is matching */
- ((info->emu.mdmreg[19] == si2) || !si2)) { /* SI2 is matching or 0 */
+ eaz)) && /* EAZ is matching */
+ (info->emu.mdmreg[18] & si2bit[si1]) && /* SI1 is matching */
+ ((info->emu.mdmreg[19] == si2) || !si2)) { /* SI2 is matching or 0 */
idx = isdn_dc2minor(di, ch);
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: match1\n");
@@ -1735,13 +1999,18 @@
info->drv_index = idx;
dev->m_idx[idx] = info->line;
dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
- dev->usage[idx] |= (si1==1)?ISDN_USAGE_VOICE:ISDN_USAGE_MODEM;
+ dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
strcpy(dev->num[idx], nr);
- info->emu.mdmreg[20] = si2bit[si1];
+ info->emu.mdmreg[20] = si2bit[si1];
+ info->emu.mdmreg[21] = setup.plan;
+ info->emu.mdmreg[22] = setup.screen;
isdn_info_update();
restore_flags(flags);
printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
info->line);
+ info->msr |= UART_MSR_RI;
+ isdn_tty_modem_result(2, info);
+ isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
return info->line;
}
}
@@ -1752,6 +2021,140 @@
return -1;
}
+#define TTY_IS_ACTIVE(info) \
+ (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
+
+int
+isdn_tty_stat_callback(int i, isdn_ctrl * c)
+{
+ int mi;
+ modem_info *info;
+
+ if (i < 0)
+ return 0;
+ if ((mi = dev->m_idx[i]) >= 0) {
+ info = &dev->mdm.info[mi];
+ switch (c->command) {
+ case ISDN_STAT_BSENT:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
+#endif
+ if ((info->isdn_driver == c->driver) &&
+ (info->isdn_channel == c->arg)) {
+ info->msr |= UART_MSR_CTS;
+ if (info->send_outstanding)
+ if (!(--info->send_outstanding))
+ info->lsr |= UART_LSR_TEMT;
+ isdn_tty_tint(info);
+ return 1;
+ }
+ break;
+ case ISDN_STAT_CAUSE:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
+#endif
+ /* Signal cause to tty-device */
+ strncpy(info->last_cause, c->parm.num, 5);
+ return 1;
+ case ISDN_STAT_DCONN:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
+#endif
+ if (TTY_IS_ACTIVE(info)) {
+ if (info->dialing == 1) {
+ info->dialing = 2;
+ return 1;
+ }
+ }
+ break;
+ case ISDN_STAT_DHUP:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
+#endif
+ if (TTY_IS_ACTIVE(info)) {
+ if (info->dialing == 1) {
+ info->dialing = 0;
+ isdn_tty_modem_result(7, info);
+ }
+#ifdef ISDN_DEBUG_MODEM_HUP
+ printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
+#endif
+ isdn_tty_modem_hup(info, 0);
+ return 1;
+ }
+ break;
+ case ISDN_STAT_BCONN:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
+#endif
+ /* Schedule CONNECT-Message to any tty
+ * waiting for it and
+ * set DCD-bit of its modem-status.
+ */
+ if (TTY_IS_ACTIVE(info)) {
+ info->msr |= UART_MSR_DCD;
+ if (info->dialing) {
+ info->dialing = 0;
+ info->last_dir = 1;
+ } else
+ info->last_dir = 0;
+ info->rcvsched = 1;
+ if (USG_MODEM(dev->usage[i]))
+ isdn_tty_modem_result(5, info);
+ if (USG_VOICE(dev->usage[i]))
+ isdn_tty_modem_result(11, info);
+ return 1;
+ }
+ break;
+ case ISDN_STAT_BHUP:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);
+#endif
+ if (TTY_IS_ACTIVE(info)) {
+#ifdef ISDN_DEBUG_MODEM_HUP
+ printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
+#endif
+ isdn_tty_modem_hup(info, 0);
+ return 1;
+ }
+ break;
+ case ISDN_STAT_NODCH:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
+#endif
+ if (TTY_IS_ACTIVE(info)) {
+ if (info->dialing) {
+ info->dialing = 0;
+ info->last_l2 = -1;
+ info->last_si = 0;
+ sprintf(info->last_cause, "0000");
+ isdn_tty_modem_result(6, info);
+ }
+ info->msr &= ~UART_MSR_DCD;
+ if (info->online) {
+ isdn_tty_modem_result(3, info);
+ info->online = 0;
+ }
+ return 1;
+ }
+ break;
+ case ISDN_STAT_UNLOAD:
+#ifdef ISDN_TTY_STAT_DEBUG
+ printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
+#endif
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ info = &dev->mdm.info[i];
+ if (info->isdn_driver == c->driver) {
+ if (info->online)
+ isdn_tty_modem_hup(info, 1);
+ }
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
/*********************************************************************
Modem-Emulator-Routines
*********************************************************************/
@@ -1762,7 +2165,8 @@
* Put a message from the AT-emulator into receive-buffer of tty,
* convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
*/
-static void isdn_tty_at_cout(char *msg, modem_info * info)
+static void
+isdn_tty_at_cout(char *msg, modem_info * info)
{
struct tty_struct *tty;
atemu *m = &info->emu;
@@ -1779,17 +2183,17 @@
tty = info->tty;
for (p = msg; *p; p++) {
switch (*p) {
- case '\r':
- c = m->mdmreg[3];
- break;
- case '\n':
- c = m->mdmreg[4];
- break;
- case '\b':
- c = m->mdmreg[5];
- break;
- default:
- c = *p;
+ case '\r':
+ c = m->mdmreg[3];
+ break;
+ case '\n':
+ c = m->mdmreg[4];
+ break;
+ case '\b':
+ c = m->mdmreg[5];
+ break;
+ default:
+ c = *p;
}
if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
restore_flags(flags);
@@ -1806,24 +2210,25 @@
/*
* Perform ATH Hangup
*/
-static void isdn_tty_on_hook(modem_info * info)
+static void
+isdn_tty_on_hook(modem_info * info)
{
if (info->isdn_channel >= 0) {
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
#endif
- isdn_tty_modem_result(3, info);
- isdn_tty_modem_hup(info);
+ isdn_tty_modem_hup(info, 1);
}
}
-static void isdn_tty_off_hook(void)
+static void
+isdn_tty_off_hook(void)
{
printk(KERN_DEBUG "isdn_tty_off_hook\n");
}
-#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
-#define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */
+#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
+#define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */
/*
* Check Buffer for Modem-escape-sequence, activate timer-callback to
@@ -1836,8 +2241,9 @@
* pluscount count of valid escape-characters so far
* lastplus timestamp of last character
*/
-static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
- int *lastplus, int from_user)
+static void
+isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
+ int *lastplus, int from_user)
{
char cbuf[3];
@@ -1880,7 +2286,8 @@
* For CONNECT-messages also switch to online-mode.
* For RING-message handle auto-ATA if register 0 != 0
*/
-void isdn_tty_modem_result(int code, modem_info * info)
+static void
+isdn_tty_modem_result(int code, modem_info * info)
{
atemu *m = &info->emu;
static char *msg[] =
@@ -1888,47 +2295,66 @@
"CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
"RINGING", "NO MSN/EAZ", "VCON"};
ulong flags;
- char s[4];
+ char s[10];
switch (code) {
- case 2:
- m->mdmreg[1]++; /* RING */
- if (m->mdmreg[1] == m->mdmreg[0])
- /* Automatically accept incoming call */
- isdn_tty_cmd_ATA(info);
- break;
- case 3:
- /* NO CARRIER */
- save_flags(flags);
- cli();
+ case 2:
+ m->mdmreg[1]++; /* RING */
+ if (m->mdmreg[1] == m->mdmreg[0])
+ /* Automatically accept incoming call */
+ isdn_tty_cmd_ATA(info);
+ break;
+ case 3:
+ /* NO CARRIER */
#ifdef ISDN_DEBUG_MODEM_HUP
- printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
- (info->flags & ISDN_ASYNC_CLOSING),
- (!info->tty));
-#endif
- if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
- restore_flags(flags);
- return;
- }
- restore_flags(flags);
- if (info->vonline & 1) {
- /* voice-recording, add DLE-ETX */
- isdn_tty_at_cout("\020\003", info);
- }
- if (info->vonline & 2) {
- /* voice-playing, add DLE-DC4 */
- isdn_tty_at_cout("\020\024", info);
- }
- break;
- case 1:
- case 5:
- if (!info->online)
- info->online = 2;
- break;
- case 11:
- if (!info->online)
- info->online = 1;
- break;
+ printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
+ (info->flags & ISDN_ASYNC_CLOSING),
+ (!info->tty));
+#endif
+ save_flags(flags);
+ cli();
+ m->mdmreg[1] = 0;
+ del_timer(&info->nc_timer);
+ info->ncarrier = 0;
+ if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
+ restore_flags(flags);
+ return;
+ }
+ restore_flags(flags);
+#ifdef CONFIG_ISDN_AUDIO
+ if (info->vonline & 1) {
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",
+ info->line);
+#endif
+ /* voice-recording, add DLE-ETX */
+ isdn_tty_at_cout("\020\003", info);
+ }
+ if (info->vonline & 2) {
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n",
+ info->line);
+#endif
+ /* voice-playing, add DLE-DC4 */
+ isdn_tty_at_cout("\020\024", info);
+ }
+#endif
+ break;
+ case 1:
+ case 5:
+ sprintf(info->last_cause, "0000");
+ if (!info->online)
+ info->online = 2;
+ break;
+ case 11:
+#ifdef ISDN_DEBUG_MODEM_VOICE
+ printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
+ info->line);
+#endif
+ sprintf(info->last_cause, "0000");
+ if (!info->online)
+ info->online = 1;
+ break;
}
if (m->mdmreg[12] & 1) {
/* Show results */
@@ -1938,17 +2364,38 @@
sprintf(s, "%d", code);
isdn_tty_at_cout(s, info);
} else {
- if (code == 2) {
+ if ((code == 2) && (!(m->mdmreg[13] & 16))) {
isdn_tty_at_cout("CALLER NUMBER: ", info);
isdn_tty_at_cout(dev->num[info->drv_index], info);
isdn_tty_at_cout("\r\n", info);
}
isdn_tty_at_cout(msg[code], info);
- if (code == 5) {
- /* Append Protocol to CONNECT message */
- isdn_tty_at_cout((m->mdmreg[14] != 3) ? "/X.75" : "/HDLC", info);
- if (m->mdmreg[13] & 2)
- isdn_tty_at_cout("/T.70", info);
+ switch (code) {
+ case 2:
+ /* Print CID only once, _after_ 1.st RING */
+ if ((m->mdmreg[13] & 16) && (m->mdmreg[1] == 1)) {
+ isdn_tty_at_cout("\r\n", info);
+ isdn_tty_at_cout("CALLER NUMBER: ", info);
+ isdn_tty_at_cout(dev->num[info->drv_index], info);
+ }
+ break;
+ case 3:
+ case 6:
+ case 7:
+ case 8:
+ m->mdmreg[1] = 0;
+ /* Append Cause-Message if enabled */
+ if (m->mdmreg[13] & 8) {
+ sprintf(s, "/%s", info->last_cause);
+ isdn_tty_at_cout(s, info);
+ }
+ break;
+ case 5:
+ /* Append Protocol to CONNECT message */
+ isdn_tty_at_cout((m->mdmreg[14] != 3) ? "/X.75" : "/HDLC", info);
+ if (m->mdmreg[13] & 2)
+ isdn_tty_at_cout("/T.70", info);
+ break;
}
}
isdn_tty_at_cout("\r\n", info);
@@ -1960,13 +2407,13 @@
restore_flags(flags);
return;
}
- if (info->tty->ldisc.flush_buffer)
- info->tty->ldisc.flush_buffer(info->tty);
+ if (info->tty->ldisc.flush_buffer)
+ info->tty->ldisc.flush_buffer(info->tty);
if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
(!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
(info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
tty_hangup(info->tty);
- }
+ }
restore_flags(flags);
}
}
@@ -1974,7 +2421,8 @@
/*
* Display a modem-register-value.
*/
-static void isdn_tty_show_profile(int ridx, modem_info * info)
+static void
+isdn_tty_show_profile(int ridx, modem_info * info)
{
char v[6];
@@ -1985,7 +2433,8 @@
/*
* Get MSN-string from char-pointer, set pointer to end of number
*/
-static void isdn_tty_get_msnstr(char *n, char **p)
+static void
+isdn_tty_get_msnstr(char *n, char **p)
{
while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
*n++ = *p[0]++;
@@ -1995,13 +2444,17 @@
/*
* Get phone-number from modem-commandbuffer
*/
-static void isdn_tty_getdial(char *p, char *q)
+static void
+isdn_tty_getdial(char *p, char *q, int max)
{
int first = 1;
- while (strchr("0123456789,#.*WPTS-", *p) && *p) {
- if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first))
+ max--;
+ while (strchr("0123456789,#.*WPTS-", *p) && *p && (max > 0)) {
+ if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first)) {
*q++ = *p;
+ max--;
+ }
p++;
first = 0;
}
@@ -2011,648 +2464,775 @@
#define PARSE_ERROR { isdn_tty_modem_result(4, info); return; }
#define PARSE_ERROR1 { isdn_tty_modem_result(4, info); return 1; }
+static void
+isdn_tty_report(modem_info * info)
+{
+ atemu *m = &info->emu;
+ char s[80];
+
+ isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info);
+ sprintf(s, " Remote Number: %s\r\n", info->last_num);
+ isdn_tty_at_cout(s, info);
+ sprintf(s, " Direction: %s\r\n", info->last_dir ? "outgoing" : "incoming");
+ isdn_tty_at_cout(s, info);
+ isdn_tty_at_cout(" Layer-2 Protocol: ", info);
+ switch (info->last_l2) {
+ case ISDN_PROTO_L2_X75I:
+ isdn_tty_at_cout("x75i", info);
+ break;
+ case ISDN_PROTO_L2_X75UI:
+ isdn_tty_at_cout("x75ui", info);
+ break;
+ case ISDN_PROTO_L2_X75BUI:
+ isdn_tty_at_cout("x75bui", info);
+ break;
+ case ISDN_PROTO_L2_HDLC:
+ isdn_tty_at_cout("hdlc", info);
+ break;
+ case ISDN_PROTO_L2_TRANS:
+ isdn_tty_at_cout("transparent", info);
+ break;
+ default:
+ isdn_tty_at_cout("unknown", info);
+ break;
+ }
+ isdn_tty_at_cout((m->mdmreg[13] & 2) ? "/t.70\r\n" : "\r\n", info);
+ isdn_tty_at_cout(" Service: ", info);
+ switch (info->last_si) {
+ case 1:
+ isdn_tty_at_cout("audio\r\n", info);
+ break;
+ case 5:
+ isdn_tty_at_cout("btx\r\n", info);
+ break;
+ case 7:
+ isdn_tty_at_cout("data\r\n", info);
+ break;
+ default:
+ sprintf(s, "%d\r\n", info->last_si);
+ isdn_tty_at_cout(s, info);
+ break;
+ }
+ sprintf(s, " Hangup location: %s\r\n", info->last_lhup ? "local" : "remote");
+ isdn_tty_at_cout(s, info);
+ sprintf(s, " Last cause: %s\r\n", info->last_cause);
+ isdn_tty_at_cout(s, info);
+}
+
/*
* Parse AT&.. commands.
*/
-static int isdn_tty_cmd_ATand(char **p, modem_info * info)
+static int
+isdn_tty_cmd_ATand(char **p, modem_info * info)
{
- atemu *m = &info->emu;
- int i;
- char rb[100];
-
- switch (*p[0]) {
- case 'B':
- /* &B - Set Buffersize */
- p[0]++;
- i = isdn_getnum(p);
- if ((i < 0) || (i > ISDN_SERIAL_XMIT_SIZE))
- PARSE_ERROR1;
-#ifdef CONFIG_ISDN_AUDIO
- if ((m->mdmreg[18] & 1) && (i > VBUF))
- PARSE_ERROR1;
-#endif
- m->mdmreg[16] = i / 16;
- info->xmit_size = m->mdmreg[16] * 16;
- break;
- case 'D':
- /* &D - Set DCD-Low-behavior */
- p[0]++;
- switch (isdn_getnum(p)) {
- case 0:
- m->mdmreg[13] &= ~4;
- m->mdmreg[12] &= ~32;
- break;
- case 2:
- m->mdmreg[13] |= 4;
- m->mdmreg[12] &= ~32;
- break;
- case 3:
- m->mdmreg[13] |= 4;
- m->mdmreg[12] |= 32;
- break;
- default:
- PARSE_ERROR1
- }
- break;
- case 'E':
- /* &E -Set EAZ/MSN */
- p[0]++;
- isdn_tty_get_msnstr(m->msn, p);
- break;
- case 'F':
- /* &F -Set Factory-Defaults */
- p[0]++;
- isdn_tty_reset_profile(m);
- isdn_tty_modem_reset_regs(info, 1);
- break;
- case 'S':
- /* &S - Set Windowsize */
- p[0]++;
- i = isdn_getnum(p);
- if ((i > 0) && (i < 9))
- m->mdmreg[17] = i;
- else
- PARSE_ERROR1;
- break;
- case 'V':
- /* &V - Show registers */
- p[0]++;
- for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
- sprintf(rb, "S%d=%d%s", i,
- m->mdmreg[i], (i == 6) ? "\r\n" : " ");
- isdn_tty_at_cout(rb, info);
- }
- sprintf(rb, "\r\nEAZ/MSN: %s\r\n",
- strlen(m->msn) ? m->msn : "None");
- isdn_tty_at_cout(rb, info);
- break;
- case 'W':
- /* &W - Write Profile */
- p[0]++;
- switch (*p[0]) {
- case '0':
- p[0]++;
- modem_write_profile(m);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- case 'X':
- /* &X - Switch to BTX-Mode */
- p[0]++;
- switch (isdn_getnum(p)) {
- case 0:
- m->mdmreg[13] &= ~2;
- info->xmit_size = m->mdmreg[16] * 16;
- break;
- case 1:
- m->mdmreg[13] |= 2;
- m->mdmreg[14] = 0;
- info->xmit_size = 112;
- m->mdmreg[18] = 4;
- m->mdmreg[19] = 0;
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
+ atemu *m = &info->emu;
+ int i;
+ char rb[100];
+
+ switch (*p[0]) {
+ case 'B':
+ /* &B - Set Buffersize */
+ p[0]++;
+ i = isdn_getnum(p);
+ if ((i < 0) || (i > ISDN_SERIAL_XMIT_SIZE))
+ PARSE_ERROR1;
+#ifdef CONFIG_ISDN_AUDIO
+ if ((m->mdmreg[18] & 1) && (i > VBUF))
+ PARSE_ERROR1;
+#endif
+ m->mdmreg[16] = i / 16;
+ info->xmit_size = m->mdmreg[16] * 16;
+ break;
+ case 'D':
+ /* &D - Set DCD-Low-behavior */
+ p[0]++;
+ switch (isdn_getnum(p)) {
+ case 0:
+ m->mdmreg[13] &= ~4;
+ m->mdmreg[12] &= ~32;
+ break;
+ case 2:
+ m->mdmreg[13] |= 4;
+ m->mdmreg[12] &= ~32;
+ break;
+ case 3:
+ m->mdmreg[13] |= 4;
+ m->mdmreg[12] |= 32;
+ break;
+ default:
+ PARSE_ERROR1
+ }
+ break;
+ case 'E':
+ /* &E -Set EAZ/MSN */
+ p[0]++;
+ isdn_tty_get_msnstr(m->msn, p);
+ break;
+ case 'F':
+ /* &F -Set Factory-Defaults */
+ p[0]++;
+ isdn_tty_reset_profile(m);
+ isdn_tty_modem_reset_regs(info, 1);
+ break;
+ case 'S':
+ /* &S - Set Windowsize */
+ p[0]++;
+ i = isdn_getnum(p);
+ if ((i > 0) && (i < 9))
+ m->mdmreg[17] = i;
+ else
+ PARSE_ERROR1;
+ break;
+ case 'V':
+ /* &V - Show registers */
+ p[0]++;
+ isdn_tty_at_cout("\r\n", info);
+ for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
+ sprintf(rb, "S%02d=%03d%s", i,
+ m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
+ isdn_tty_at_cout(rb, info);
+ }
+ sprintf(rb, "\r\nEAZ/MSN: %s\r\n",
+ strlen(m->msn) ? m->msn : "None");
+ isdn_tty_at_cout(rb, info);
+ break;
+ case 'W':
+ /* &W - Write Profile */
+ p[0]++;
+ switch (*p[0]) {
+ case '0':
+ p[0]++;
+ modem_write_profile(m);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case 'X':
+ /* &X - Switch to BTX-Mode */
+ p[0]++;
+ switch (isdn_getnum(p)) {
+ case 0:
+ m->mdmreg[13] &= ~2;
+ info->xmit_size = m->mdmreg[16] * 16;
+ break;
+ case 1:
+ m->mdmreg[13] |= 2;
+ m->mdmreg[14] = 0;
+ info->xmit_size = 112;
+ m->mdmreg[18] = 4;
+ m->mdmreg[19] = 0;
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
+}
+
+static int
+isdn_tty_check_ats(int mreg, int mval, modem_info * info, atemu * m)
+{
+ /* Some plausibility checks */
+ switch (mreg) {
+ case 14:
+ if (mval > ISDN_PROTO_L2_TRANS)
+ return 1;
+ break;
+ case 16:
+ if ((mval * 16) > ISDN_SERIAL_XMIT_SIZE)
+ return 1;
+#ifdef CONFIG_ISDN_AUDIO
+ if ((m->mdmreg[18] & 1) && (mval > VBUFX))
+ return 1;
+#endif
+ info->xmit_size = mval * 16;
+ break;
+ case 20:
+ case 21:
+ case 22:
+ /* readonly registers */
+ return 1;
+ }
+ return 0;
}
/*
* Perform ATS command
*/
-static int isdn_tty_cmd_ATS(char **p, modem_info * info)
+static int
+isdn_tty_cmd_ATS(char **p, modem_info * info)
{
- atemu *m = &info->emu;
- int mreg;
- int mval;
-
- mreg = isdn_getnum(p);
- if (mreg < 0 || mreg > ISDN_MODEM_ANZREG)
- PARSE_ERROR1;
- switch (*p[0]) {
- case '=':
- p[0]++;
- mval = isdn_getnum(p);
- if (mval < 0 || mval > 255)
- PARSE_ERROR1;
- switch (mreg) {
- /* Some plausibility checks */
- case 14:
- if (mval > ISDN_PROTO_L2_TRANS)
- PARSE_ERROR1;
- break;
- case 16:
- if ((mval * 16) > ISDN_SERIAL_XMIT_SIZE)
- PARSE_ERROR1;
-#ifdef CONFIG_ISDN_AUDIO
- if ((m->mdmreg[18] & 1) && (mval > VBUFX))
- PARSE_ERROR1;
-#endif
- info->xmit_size = mval * 16;
- break;
- case 20:
- PARSE_ERROR1;
- }
- m->mdmreg[mreg] = mval;
- break;
- case '?':
- p[0]++;
- isdn_tty_show_profile(mreg, info);
- break;
- default:
- PARSE_ERROR1;
- break;
- }
- return 0;
+ atemu *m = &info->emu;
+ int bitpos;
+ int mreg;
+ int mval;
+ int bval;
+
+ mreg = isdn_getnum(p);
+ if (mreg < 0 || mreg > ISDN_MODEM_ANZREG)
+ PARSE_ERROR1;
+ switch (*p[0]) {
+ case '=':
+ p[0]++;
+ mval = isdn_getnum(p);
+ if (mval < 0 || mval > 255)
+ PARSE_ERROR1;
+ if (isdn_tty_check_ats(mreg, mval, info, m))
+ PARSE_ERROR1;
+ m->mdmreg[mreg] = mval;
+ break;
+ case '.':
+ /* Set/Clear a single bit */
+ p[0]++;
+ bitpos = isdn_getnum(p);
+ if ((bitpos < 0) || (bitpos > 7))
+ PARSE_ERROR1;
+ switch (*p[0]) {
+ case '=':
+ p[0]++;
+ bval = isdn_getnum(p);
+ if (bval < 0 || bval > 1)
+ PARSE_ERROR1;
+ if (bval)
+ mval = m->mdmreg[mreg] | (1 << bitpos);
+ else
+ mval = m->mdmreg[mreg] & ~(1 << bitpos);
+ if (isdn_tty_check_ats(mreg, mval, info, m))
+ PARSE_ERROR1;
+ m->mdmreg[mreg] = mval;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n", info);
+ isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0",
+ info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_show_profile(mreg, info);
+ break;
+ default:
+ PARSE_ERROR1;
+ break;
+ }
+ return 0;
}
/*
* Perform ATA command
*/
-static void isdn_tty_cmd_ATA(modem_info * info)
+static void
+isdn_tty_cmd_ATA(modem_info * info)
{
- atemu *m = &info->emu;
- isdn_ctrl cmd;
- int l2;
-
- if (info->msr & UART_MSR_RI) {
- /* Accept incoming call */
- m->mdmreg[1] = 0;
- info->msr &= ~UART_MSR_RI;
- l2 = m->mdmreg[14];
-#ifdef CONFIG_ISDN_AUDIO
- /* If more than one bit set in reg18, autoselect Layer2 */
- if ((m->mdmreg[18] & m->mdmreg[20]) != m->mdmreg[18])
- if (m->mdmreg[20] == 1) l2 = 4;
-#endif
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_SETL2;
- cmd.arg = info->isdn_channel + (l2 << 8);
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- cmd.driver = info->isdn_driver;
- cmd.command = ISDN_CMD_SETL3;
- cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- cmd.driver = info->isdn_driver;
- cmd.arg = info->isdn_channel;
- cmd.command = ISDN_CMD_ACCEPTD;
- dev->drv[info->isdn_driver]->interface->command(&cmd);
- } else
- isdn_tty_modem_result(8, info);
+ atemu *m = &info->emu;
+ isdn_ctrl cmd;
+ int l2;
+
+ if (info->msr & UART_MSR_RI) {
+ /* Accept incoming call */
+ info->last_dir = 0;
+ strcpy(info->last_num, dev->num[info->drv_index]);
+ m->mdmreg[1] = 0;
+ info->msr &= ~UART_MSR_RI;
+ l2 = m->mdmreg[14];
+#ifdef CONFIG_ISDN_AUDIO
+ /* If more than one bit set in reg18, autoselect Layer2 */
+ if ((m->mdmreg[18] & m->mdmreg[20]) != m->mdmreg[18]) {
+ if (m->mdmreg[20] == 1)
+ l2 = 4;
+ else
+ l2 = 0;
+ }
+#endif
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL2;
+ cmd.arg = info->isdn_channel + (l2 << 8);
+ info->last_l2 = l2;
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL3;
+ cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.command = ISDN_CMD_ACCEPTD;
+ dev->drv[info->isdn_driver]->interface->command(&cmd);
+ } else
+ isdn_tty_modem_result(8, info);
}
#ifdef CONFIG_ISDN_AUDIO
/*
* Parse AT+F.. commands
*/
-static int isdn_tty_cmd_PLUSF(char **p, modem_info * info)
+static int
+isdn_tty_cmd_PLUSF(char **p, modem_info * info)
{
- atemu *m = &info->emu;
- int par;
+ atemu *m = &info->emu;
+ int par;
char rs[20];
- if (!strncmp(p[0],"CLASS",5)) {
- p[0] += 5;
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs,"\r\n%d",
- (m->mdmreg[18]&1)?8:0);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- switch (*p[0]) {
- case '0':
- p[0]++;
- m->mdmreg[18] = 4;
- info->xmit_size =
- m->mdmreg[16] * 16;
- break;
- case '8':
- p[0]++;
- m->mdmreg[18] = 5;
- info->xmit_size = VBUF;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n0,8",
- info);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
- if (!strncmp(p[0],"AA",2)) {
- p[0] += 2;
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs,"\r\n%d",
- m->mdmreg[0]);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- m->mdmreg[0]=par;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
- PARSE_ERROR1;
+ if (!strncmp(p[0], "CLASS", 5)) {
+ p[0] += 5;
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ sprintf(rs, "\r\n%d",
+ (m->mdmreg[18] & 1) ? 8 : 0);
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+ p[0]++;
+ switch (*p[0]) {
+ case '0':
+ p[0]++;
+ m->mdmreg[18] = 4;
+ info->xmit_size =
+ m->mdmreg[16] * 16;
+ break;
+ case '8':
+ p[0]++;
+ m->mdmreg[18] = 5;
+ info->xmit_size = VBUF;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n0,8",
+ info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
+ }
+ if (!strncmp(p[0], "AA", 2)) {
+ p[0] += 2;
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ sprintf(rs, "\r\n%d",
+ m->mdmreg[0]);
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+ p[0]++;
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ m->mdmreg[0] = par;
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
+ }
+ PARSE_ERROR1;
}
/*
* Parse AT+V.. commands
*/
-static int isdn_tty_cmd_PLUSV(char **p, modem_info * info)
+static int
+isdn_tty_cmd_PLUSV(char **p, modem_info * info)
{
- atemu *m = &info->emu;
- static char *vcmd[] = {"NH","IP","LS","RX","SD","SM","TX",NULL};
- int i;
+ atemu *m = &info->emu;
+ static char *vcmd[] =
+ {"NH", "IP", "LS", "RX", "SD", "SM", "TX", NULL};
+ int i;
int par1;
int par2;
char rs[20];
- i = 0;
- while (vcmd[i]) {
- if (!strncmp(vcmd[i],p[0],2)) {
- p[0] += 2;
- break;
- }
- i++;
- }
- switch (i) {
- case 0:
- /* AT+VNH - Auto hangup feature */
- switch (*p[0]) {
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n1", info);
- break;
- case '=':
- p[0]++;
- switch (*p[0]) {
- case '1':
- p[0]++;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n1", info);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- case 1:
- /* AT+VIP - Reset all voice parameters */
- isdn_tty_modem_reset_vpar(m);
- break;
- case 2:
- /* AT+VLS - Select device, accept incoming call */
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs,"\r\n%d",m->vpar[0]);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- switch (*p[0]) {
- case '0':
- p[0]++;
- m->vpar[0] = 0;
- break;
- case '2':
- p[0]++;
- m->vpar[0] = 2;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n0,2", info);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- case 3:
- /* AT+VRX - Start recording */
- if (!m->vpar[0])
- PARSE_ERROR1;
- if (info->online != 1) {
- isdn_tty_modem_result(8, info);
- return 1;
- }
- info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
- if (!info->dtmf_state) {
- printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
- PARSE_ERROR1;
- }
- if (m->vpar[3] < 5) {
- info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
- if (!info->adpcmr) {
- printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
- PARSE_ERROR1;
- }
- }
- info->vonline = 1;
- isdn_tty_modem_result(1, info);
- return 1;
- break;
- case 4:
- /* AT+VSD - Silence detection */
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs,"\r\n<%d>,<%d>",
- m->vpar[1],
- m->vpar[2]);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- switch (*p[0]) {
- case '0':
- case '1':
- case '2':
- case '3':
- par1 = isdn_getnum(p);
- if ((par1 < 0) || (par1 > 31))
- PARSE_ERROR1;
- if (*p[0] != ',')
- PARSE_ERROR1;
- p[0]++;
- par2 = isdn_getnum(p);
- if ((par2 < 0) || (par2 > 255))
- PARSE_ERROR1;
- m->vpar[1] = par1;
- m->vpar[2] = par2;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n<0-31>,<0-255>",
- info);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- case 5:
- /* AT+VSM - Select compression */
- switch (*p[0]) {
- case '?':
- p[0]++;
- sprintf(rs,"\r\n<%d>,<%d><8000>",
- m->vpar[3],
- m->vpar[1]);
- isdn_tty_at_cout(rs, info);
- break;
- case '=':
- p[0]++;
- switch (*p[0]) {
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- par1 = isdn_getnum(p);
- if ((par1 < 2) || (par1 > 6))
- PARSE_ERROR1;
- m->vpar[3] = par1;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
- info);
- isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
- info);
- isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
- info);
- isdn_tty_at_cout("5;ALAW;8;0;(8000)",
- info);
- isdn_tty_at_cout("6;ULAW;8;0;(8000)",
- info);
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- default:
- PARSE_ERROR1;
- }
- break;
- case 6:
- /* AT+VTX - Start sending */
- if (!m->vpar[0])
- PARSE_ERROR1;
- if (info->online != 1) {
- isdn_tty_modem_result(8, info);
- return 1;
- }
- info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
- if (!info->dtmf_state) {
- printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
- PARSE_ERROR1;
- }
- if (m->vpar[3] < 5) {
- info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
- if (!info->adpcms) {
- printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
- PARSE_ERROR1;
- }
- }
- m->lastDLE = 0;
- info->vonline = 2;
- isdn_tty_modem_result(1, info);
- return 1;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
+ i = 0;
+ while (vcmd[i]) {
+ if (!strncmp(vcmd[i], p[0], 2)) {
+ p[0] += 2;
+ break;
+ }
+ i++;
+ }
+ switch (i) {
+ case 0:
+ /* AT+VNH - Auto hangup feature */
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n1", info);
+ break;
+ case '=':
+ p[0]++;
+ switch (*p[0]) {
+ case '1':
+ p[0]++;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n1", info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case 1:
+ /* AT+VIP - Reset all voice parameters */
+ isdn_tty_modem_reset_vpar(m);
+ break;
+ case 2:
+ /* AT+VLS - Select device, accept incoming call */
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ sprintf(rs, "\r\n%d", m->vpar[0]);
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+ p[0]++;
+ switch (*p[0]) {
+ case '0':
+ p[0]++;
+ m->vpar[0] = 0;
+ break;
+ case '2':
+ p[0]++;
+ m->vpar[0] = 2;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n0,2", info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case 3:
+ /* AT+VRX - Start recording */
+ if (!m->vpar[0])
+ PARSE_ERROR1;
+ if (info->online != 1) {
+ isdn_tty_modem_result(8, info);
+ return 1;
+ }
+ info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
+ if (!info->dtmf_state) {
+ printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
+ PARSE_ERROR1;
+ }
+ if (m->vpar[3] < 5) {
+ info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
+ if (!info->adpcmr) {
+ printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
+ PARSE_ERROR1;
+ }
+ }
+#ifdef ISDN_DEBUG_AT
+ printk(KERN_DEBUG "AT: +VRX\n");
+#endif
+ info->vonline |= 1;
+ isdn_tty_modem_result(1, info);
+ return 0;
+ break;
+ case 4:
+ /* AT+VSD - Silence detection */
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ sprintf(rs, "\r\n<%d>,<%d>",
+ m->vpar[1],
+ m->vpar[2]);
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+ p[0]++;
+ switch (*p[0]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ par1 = isdn_getnum(p);
+ if ((par1 < 0) || (par1 > 31))
+ PARSE_ERROR1;
+ if (*p[0] != ',')
+ PARSE_ERROR1;
+ p[0]++;
+ par2 = isdn_getnum(p);
+ if ((par2 < 0) || (par2 > 255))
+ PARSE_ERROR1;
+ m->vpar[1] = par1;
+ m->vpar[2] = par2;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n<0-31>,<0-255>",
+ info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case 5:
+ /* AT+VSM - Select compression */
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ sprintf(rs, "\r\n<%d>,<%d><8000>",
+ m->vpar[3],
+ m->vpar[1]);
+ isdn_tty_at_cout(rs, info);
+ break;
+ case '=':
+ p[0]++;
+ switch (*p[0]) {
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ par1 = isdn_getnum(p);
+ if ((par1 < 2) || (par1 > 6))
+ PARSE_ERROR1;
+ m->vpar[3] = par1;
+ break;
+ case '?':
+ p[0]++;
+ isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
+ info);
+ isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
+ info);
+ isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
+ info);
+ isdn_tty_at_cout("5;ALAW;8;0;(8000)",
+ info);
+ isdn_tty_at_cout("6;ULAW;8;0;(8000)",
+ info);
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ break;
+ case 6:
+ /* AT+VTX - Start sending */
+ if (!m->vpar[0])
+ PARSE_ERROR1;
+ if (info->online != 1) {
+ isdn_tty_modem_result(8, info);
+ return 1;
+ }
+ info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
+ if (!info->dtmf_state) {
+ printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
+ PARSE_ERROR1;
+ }
+ if (m->vpar[3] < 5) {
+ info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
+ if (!info->adpcms) {
+ printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
+ PARSE_ERROR1;
+ }
+ }
+#ifdef ISDN_DEBUG_AT
+ printk(KERN_DEBUG "AT: +VTX\n");
+#endif
+ m->lastDLE = 0;
+ info->vonline |= 2;
+ isdn_tty_modem_result(1, info);
+ return 0;
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
}
-#endif /* CONFIG_ISDN_AUDIO */
+#endif /* CONFIG_ISDN_AUDIO */
/*
* Parse and perform an AT-command-line.
*/
-static void isdn_tty_parse_at(modem_info * info)
+static void
+isdn_tty_parse_at(modem_info * info)
{
- atemu *m = &info->emu;
- char *p;
- char ds[40];
+ atemu *m = &info->emu;
+ char *p;
+ char ds[40];
#ifdef ISDN_DEBUG_AT
- printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
+ printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
+#endif
+ for (p = &m->mdmcmd[2]; *p;) {
+ switch (*p) {
+ case 'A':
+ /* A - Accept incoming call */
+ p++;
+ isdn_tty_cmd_ATA(info);
+ return;
+ break;
+ case 'D':
+ /* D - Dial */
+ isdn_tty_getdial(++p, ds, sizeof(ds));
+ p += strlen(p);
+ if (!strlen(m->msn))
+ isdn_tty_modem_result(10, info);
+ else if (strlen(ds))
+ isdn_tty_dial(ds, info, m);
+ else
+ PARSE_ERROR;
+ return;
+ case 'E':
+ /* E - Turn Echo on/off */
+ p++;
+ switch (isdn_getnum(&p)) {
+ case 0:
+ m->mdmreg[12] &= ~4;
+ break;
+ case 1:
+ m->mdmreg[12] |= 4;
+ break;
+ default:
+ PARSE_ERROR;
+ }
+ break;
+ case 'H':
+ /* H - On/Off-hook */
+ p++;
+ switch (*p) {
+ case '0':
+ p++;
+ isdn_tty_on_hook(info);
+ break;
+ case '1':
+ p++;
+ isdn_tty_off_hook();
+ break;
+ default:
+ isdn_tty_on_hook(info);
+ break;
+ }
+ break;
+ case 'I':
+ /* I - Information */
+ p++;
+ isdn_tty_at_cout("\r\nLinux ISDN", info);
+ switch (*p) {
+ case '0':
+ case '1':
+ p++;
+ break;
+ case '2':
+ p++;
+ isdn_tty_report(info);
+ break;
+ default:
+ }
+ break;
+ case 'O':
+ /* O - Go online */
+ p++;
+ if (info->msr & UART_MSR_DCD)
+ /* if B-Channel is up */
+ isdn_tty_modem_result(5, info);
+ else
+ isdn_tty_modem_result(3, info);
+ return;
+ case 'Q':
+ /* Q - Turn Emulator messages on/off */
+ p++;
+ switch (isdn_getnum(&p)) {
+ case 0:
+ m->mdmreg[12] |= 1;
+ break;
+ case 1:
+ m->mdmreg[12] &= ~1;
+ break;
+ default:
+ PARSE_ERROR;
+ }
+ break;
+ case 'S':
+ /* S - Set/Get Register */
+ p++;
+ if (isdn_tty_cmd_ATS(&p, info))
+ return;
+ break;
+ case 'V':
+ /* V - Numeric or ASCII Emulator-messages */
+ p++;
+ switch (isdn_getnum(&p)) {
+ case 0:
+ m->mdmreg[12] |= 2;
+ break;
+ case 1:
+ m->mdmreg[12] &= ~2;
+ break;
+ default:
+ PARSE_ERROR;
+ }
+ break;
+ case 'Z':
+ /* Z - Load Registers from Profile */
+ p++;
+ isdn_tty_modem_reset_regs(info, 1);
+ break;
+#ifdef CONFIG_ISDN_AUDIO
+ case '+':
+ p++;
+ switch (*p) {
+ case 'F':
+ p++;
+ if (isdn_tty_cmd_PLUSF(&p, info))
+ return;
+ break;
+ case 'V':
+ if (!(m->mdmreg[18] & 1))
+ PARSE_ERROR;
+ p++;
+ if (isdn_tty_cmd_PLUSV(&p, info))
+ return;
+ break;
+ default:
+ PARSE_ERROR;
+ }
+ break;
+#endif /* CONFIG_ISDN_AUDIO */
+ case '&':
+ p++;
+ if (isdn_tty_cmd_ATand(&p, info))
+ return;
+ break;
+ default:
+ PARSE_ERROR;
+ }
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ if (!info->vonline)
#endif
- for (p = &m->mdmcmd[2]; *p;) {
- switch (*p) {
- case 'A':
- /* A - Accept incoming call */
- p++;
- isdn_tty_cmd_ATA(info);
- return;
- break;
- case 'D':
- /* D - Dial */
- isdn_tty_getdial(++p, ds);
- p += strlen(p);
- if (!strlen(m->msn))
- isdn_tty_modem_result(10, info);
- else if (strlen(ds))
- isdn_tty_dial(ds, info, m);
- else
- isdn_tty_modem_result(4, info);
- return;
- case 'E':
- /* E - Turn Echo on/off */
- p++;
- switch (isdn_getnum(&p)) {
- case 0:
- m->mdmreg[12] &= ~4;
- break;
- case 1:
- m->mdmreg[12] |= 4;
- break;
- default:
- PARSE_ERROR;
- }
- break;
- case 'H':
- /* H - On/Off-hook */
- p++;
- switch (*p) {
- case '0':
- p++;
- isdn_tty_on_hook(info);
- break;
- case '1':
- p++;
- isdn_tty_off_hook();
- break;
- default:
- isdn_tty_on_hook(info);
- break;
- }
- break;
- case 'I':
- /* I - Information */
- p++;
- isdn_tty_at_cout("\r\nLinux ISDN", info);
- switch (*p) {
- case '0':
- case '1':
- p++;
- break;
- default:
- }
- break;
- case 'O':
- /* O - Go online */
- p++;
- if (info->msr & UART_MSR_DCD)
- /* if B-Channel is up */
- isdn_tty_modem_result(5, info);
- else
- isdn_tty_modem_result(3, info);
- return;
- case 'Q':
- /* Q - Turn Emulator messages on/off */
- p++;
- switch (isdn_getnum(&p)) {
- case 0:
- m->mdmreg[12] |= 1;
- break;
- case 1:
- m->mdmreg[12] &= ~1;
- break;
- default:
- PARSE_ERROR;
- }
- break;
- case 'S':
- /* S - Set/Get Register */
- p++;
- if (isdn_tty_cmd_ATS(&p, info))
- return;
- break;
- case 'V':
- /* V - Numeric or ASCII Emulator-messages */
- p++;
- switch (isdn_getnum(&p)) {
- case 0:
- m->mdmreg[12] |= 2;
- break;
- case 1:
- m->mdmreg[12] &= ~2;
- break;
- default:
- PARSE_ERROR;
- }
- break;
- case 'Z':
- /* Z - Load Registers from Profile */
- p++;
- isdn_tty_modem_reset_regs(info, 1);
- break;
-#ifdef CONFIG_ISDN_AUDIO
- case '+':
- p++;
- switch (*p) {
- case 'F':
- p++;
- if (isdn_tty_cmd_PLUSF(&p, info))
- return;
- break;
- case 'V':
- if (!(m->mdmreg[18] & 1))
- PARSE_ERROR;
- p++;
- if (isdn_tty_cmd_PLUSV(&p, info))
- return;
- break;
- }
- break;
-#endif /* CONFIG_ISDN_AUDIO */
- case '&':
- p++;
- if (isdn_tty_cmd_ATand(&p, info))
- return;
- break;
- default:
- isdn_tty_modem_result(4, info);
- return;
- }
- }
- isdn_tty_modem_result(0, info);
+ isdn_tty_modem_result(0, info);
}
/* Need own toupper() because standard-toupper is not available
@@ -2669,7 +3249,8 @@
* channel index to line (minor-device)
* user flag: buffer is in userspace
*/
-static int isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
+static int
+isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
{
atemu *m = &info->emu;
int total = 0;
@@ -2715,16 +3296,16 @@
if (m->mdmcmdl < 255) {
c = my_toupper(c);
switch (m->mdmcmdl) {
- case 0:
- if (c == 'A')
- m->mdmcmd[m->mdmcmdl++] = c;
- break;
- case 1:
- if (c == 'T')
- m->mdmcmd[m->mdmcmdl++] = c;
- break;
- default:
- m->mdmcmd[m->mdmcmdl++] = c;
+ case 0:
+ if (c == 'A')
+ m->mdmcmd[m->mdmcmdl++] = c;
+ break;
+ case 1:
+ if (c == 'T')
+ m->mdmcmd[m->mdmcmdl++] = c;
+ break;
+ default:
+ m->mdmcmd[m->mdmcmdl++] = c;
}
}
}
@@ -2735,10 +3316,11 @@
/*
* Switch all modem-channels who are online and got a valid
* escape-sequence 1.5 seconds ago, to command-mode.
- * This function is called every second via timer-interrupt from within
+ * This function is called every second via timer-interrupt from within
* timer-dispatcher isdn_timer_function()
*/
-void isdn_tty_modem_escape(void)
+void
+isdn_tty_modem_escape(void)
{
int ton = 0;
int i;
@@ -2747,7 +3329,7 @@
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (USG_MODEM(dev->usage[i]))
if ((midx = dev->m_idx[i]) >= 0) {
- modem_info *info = &dev->mdm.info[midx];
+ modem_info *info = &dev->mdm.info[midx];
if (info->online) {
ton = 1;
if ((info->emu.pluscount == 3) &&
@@ -2757,27 +3339,28 @@
isdn_tty_modem_result(0, info);
}
}
- }
+ }
isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
}
/*
* Put a RING-message to all modem-channels who have the RI-bit set.
- * This function is called every second via timer-interrupt from within
+ * This function is called every second via timer-interrupt from within
* timer-dispatcher isdn_timer_function()
*/
-void isdn_tty_modem_ring(void)
+void
+isdn_tty_modem_ring(void)
{
int ton = 0;
int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- modem_info *info = &dev->mdm.info[i];
- if (info->msr & UART_MSR_RI) {
- ton = 1;
- isdn_tty_modem_result(2, info);
- }
- }
+ modem_info *info = &dev->mdm.info[i];
+ if (info->msr & UART_MSR_RI) {
+ ton = 1;
+ isdn_tty_modem_result(2, info);
+ }
+ }
isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
}
@@ -2785,41 +3368,19 @@
* For all online tty's, try sending data to
* the lower levels.
*/
-void isdn_tty_modem_xmit(void)
+void
+isdn_tty_modem_xmit(void)
{
int ton = 1;
int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- modem_info *info = &dev->mdm.info[i];
- if (info->online) {
- ton = 1;
- isdn_tty_senddown(info);
- isdn_tty_tint(info);
- }
- }
+ modem_info *info = &dev->mdm.info[i];
+ if (info->online) {
+ ton = 1;
+ isdn_tty_senddown(info);
+ isdn_tty_tint(info);
+ }
+ }
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
-}
-
-/*
- * A packet has been output successfully.
- * Search the tty-devices for an appropriate device, decrement its
- * counter for outstanding packets, and set CTS.
- */
-void isdn_tty_bsent(int drv, int chan)
-{
- int i;
-
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- modem_info *info = &dev->mdm.info[i];
- if ((info->isdn_driver == drv) &&
- (info->isdn_channel == chan) ) {
- info->msr |= UART_MSR_CTS;
- if (info->send_outstanding)
- if (!(--info->send_outstanding))
- info->lsr |= UART_LSR_TEMT;
- isdn_tty_tint(info);
- }
- }
- return;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov