Merge with Linux 2.4.0-test6-pre9.
[linux-2.6/linux-mips.git] / drivers / isdn / isdn_tty.c
blob25e1139b9bec3de2a9ac607485bb89b6fde9d62b
1 /* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $
3 * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #undef ISDN_TTY_STAT_DEBUG
25 #define __NO_VERSION__
26 #include <linux/config.h>
27 #include <linux/module.h>
28 #include <linux/isdn.h>
29 #include "isdn_common.h"
30 #include "isdn_tty.h"
31 #ifdef CONFIG_ISDN_AUDIO
32 #include "isdn_audio.h"
33 #define VBUF 0x3e0
34 #define VBUFX (VBUF/16)
35 #endif
37 #define FIX_FILE_TRANSFER
38 #define DUMMY_HAYES_AT
40 /* Prototypes */
42 static int isdn_tty_edit_at(const char *, int, modem_info *, int);
43 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
44 static void isdn_tty_modem_reset_regs(modem_info *, int);
45 static void isdn_tty_cmd_ATA(modem_info *);
46 static void isdn_tty_flush_buffer(struct tty_struct *);
47 static void isdn_tty_modem_result(int, modem_info *);
48 #ifdef CONFIG_ISDN_AUDIO
49 static int isdn_tty_countDLE(unsigned char *, int);
50 #endif
52 /* Leave this unchanged unless you know what you do! */
53 #define MODEM_PARANOIA_CHECK
54 #define MODEM_DO_RESTART
56 #ifdef CONFIG_DEVFS_FS
57 static char *isdn_ttyname_ttyI = "isdn/ttyI%d";
58 static char *isdn_ttyname_cui = "isdn/cui%d";
59 #else
60 static char *isdn_ttyname_ttyI = "ttyI";
61 static char *isdn_ttyname_cui = "cui";
62 #endif
64 static int bit2si[8] =
65 {1, 5, 7, 7, 7, 7, 7, 7};
66 static int si2bit[8] =
67 {4, 1, 4, 4, 4, 4, 4, 4};
69 char *isdn_tty_revision = "$Revision: 1.93 $";
72 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
73 * to stuff incoming data directly into a tty's flip-buffer. This
74 * is done to speed up tty-receiving if the receive-queue is empty.
75 * This routine MUST be called with interrupts off.
76 * Return:
77 * 1 = Success
78 * 0 = Failure, data has to be buffered and later processed by
79 * isdn_tty_readmodem().
81 static int
82 isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
84 int c;
85 int len;
86 struct tty_struct *tty;
88 if (info->online) {
89 if ((tty = info->tty)) {
90 if (info->mcr & UART_MCR_RTS) {
91 c = TTY_FLIPBUF_SIZE - tty->flip.count;
92 len = skb->len
93 #ifdef CONFIG_ISDN_AUDIO
94 + ISDN_AUDIO_SKB_DLECOUNT(skb)
95 #endif
97 if (c >= len) {
98 #ifdef CONFIG_ISDN_AUDIO
99 if (ISDN_AUDIO_SKB_DLECOUNT(skb))
100 while (skb->len--) {
101 if (*skb->data == DLE)
102 tty_insert_flip_char(tty, DLE, 0);
103 tty_insert_flip_char(tty, *skb->data++, 0);
104 } else {
105 #endif
106 memcpy(tty->flip.char_buf_ptr,
107 skb->data, len);
108 tty->flip.count += len;
109 tty->flip.char_buf_ptr += len;
110 memset(tty->flip.flag_buf_ptr, 0, len);
111 tty->flip.flag_buf_ptr += len;
112 #ifdef CONFIG_ISDN_AUDIO
114 #endif
115 if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
116 tty->flip.flag_buf_ptr[len - 1] = 0xff;
117 queue_task(&tty->flip.tqueue, &tq_timer);
118 kfree_skb(skb);
119 return 1;
124 return 0;
127 /* isdn_tty_readmodem() is called periodically from within timer-interrupt.
128 * It tries getting received data from the receive queue an stuff it into
129 * the tty's flip-buffer.
131 void
132 isdn_tty_readmodem(void)
134 int resched = 0;
135 int midx;
136 int i;
137 int c;
138 int r;
139 ulong flags;
140 struct tty_struct *tty;
141 modem_info *info;
143 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
144 if ((midx = dev->m_idx[i]) >= 0) {
145 info = &dev->mdm.info[midx];
146 if (info->online) {
147 r = 0;
148 #ifdef CONFIG_ISDN_AUDIO
149 isdn_audio_eval_dtmf(info);
150 if ((info->vonline & 1) && (info->emu.vpar[1]))
151 isdn_audio_eval_silence(info);
152 #endif
153 if ((tty = info->tty)) {
154 if (info->mcr & UART_MCR_RTS) {
155 c = TTY_FLIPBUF_SIZE - tty->flip.count;
156 if (c > 0) {
157 save_flags(flags);
158 cli();
159 r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
160 tty->flip.char_buf_ptr,
161 tty->flip.flag_buf_ptr, c, 0);
162 /* CISCO AsyncPPP Hack */
163 if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
164 memset(tty->flip.flag_buf_ptr, 0, r);
165 tty->flip.count += r;
166 tty->flip.flag_buf_ptr += r;
167 tty->flip.char_buf_ptr += r;
168 if (r)
169 queue_task(&tty->flip.tqueue, &tq_timer);
170 restore_flags(flags);
172 } else
173 r = 1;
174 } else
175 r = 1;
176 if (r) {
177 info->rcvsched = 0;
178 resched = 1;
179 } else
180 info->rcvsched = 1;
184 if (!resched)
185 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
189 isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
191 ulong flags;
192 int midx;
193 #ifdef CONFIG_ISDN_AUDIO
194 int ifmt;
195 #endif
196 modem_info *info;
198 if ((midx = dev->m_idx[i]) < 0) {
199 /* if midx is invalid, packet is not for tty */
200 return 0;
202 info = &dev->mdm.info[midx];
203 #ifdef CONFIG_ISDN_AUDIO
204 ifmt = 1;
206 if ((info->vonline) && (!info->emu.vpar[4]))
207 isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
208 if ((info->vonline & 1) && (info->emu.vpar[1]))
209 isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
210 #endif
211 if ((info->online < 2)
212 #ifdef CONFIG_ISDN_AUDIO
213 && (!(info->vonline & 1))
214 #endif
216 /* If Modem not listening, drop data */
217 kfree_skb(skb);
218 return 1;
220 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
221 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) {
222 /* T.70 decoding: throw away the T.70 header (2 or 4 bytes) */
223 if (skb->data[0] == 3) /* pure data packet -> 4 byte headers */
224 skb_pull(skb, 4);
225 else
226 if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr */
227 skb_pull(skb, 2);
228 } else
229 /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
230 if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
231 skb_pull(skb, 4);
233 #ifdef CONFIG_ISDN_AUDIO
234 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
235 printk(KERN_WARNING
236 "isdn_audio: insufficient skb_headroom, dropping\n");
237 kfree_skb(skb);
238 return 1;
240 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
241 ISDN_AUDIO_SKB_LOCK(skb) = 0;
242 if (info->vonline & 1) {
243 /* voice conversion/compression */
244 switch (info->emu.vpar[3]) {
245 case 2:
246 case 3:
247 case 4:
248 /* adpcm
249 * Since compressed data takes less
250 * space, we can overwrite the buffer.
252 skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr,
253 ifmt,
254 skb->data,
255 skb->data,
256 skb->len));
257 break;
258 case 5:
259 /* a-law */
260 if (!ifmt)
261 isdn_audio_ulaw2alaw(skb->data, skb->len);
262 break;
263 case 6:
264 /* u-law */
265 if (ifmt)
266 isdn_audio_alaw2ulaw(skb->data, skb->len);
267 break;
269 ISDN_AUDIO_SKB_DLECOUNT(skb) =
270 isdn_tty_countDLE(skb->data, skb->len);
272 #ifdef CONFIG_ISDN_TTY_FAX
273 else {
274 if (info->faxonline & 2) {
275 isdn_tty_fax_bitorder(info, skb);
276 ISDN_AUDIO_SKB_DLECOUNT(skb) =
277 isdn_tty_countDLE(skb->data, skb->len);
280 #endif
281 #endif
282 /* Try to deliver directly via tty-flip-buf if queue is empty */
283 save_flags(flags);
284 cli();
285 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
286 if (isdn_tty_try_read(info, skb)) {
287 restore_flags(flags);
288 return 1;
290 /* Direct deliver failed or queue wasn't empty.
291 * Queue up for later dequeueing via timer-irq.
293 __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
294 dev->drv[di]->rcvcount[channel] +=
295 (skb->len
296 #ifdef CONFIG_ISDN_AUDIO
297 + ISDN_AUDIO_SKB_DLECOUNT(skb)
298 #endif
300 restore_flags(flags);
301 /* Schedule dequeuing */
302 if ((dev->modempoll) && (info->rcvsched))
303 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
304 return 1;
307 void
308 isdn_tty_cleanup_xmit(modem_info * info)
310 struct sk_buff *skb;
311 unsigned long flags;
313 save_flags(flags);
314 cli();
315 if (skb_queue_len(&info->xmit_queue))
316 while ((skb = skb_dequeue(&info->xmit_queue)))
317 kfree_skb(skb);
318 #ifdef CONFIG_ISDN_AUDIO
319 if (skb_queue_len(&info->dtmf_queue))
320 while ((skb = skb_dequeue(&info->dtmf_queue)))
321 kfree_skb(skb);
322 #endif
323 restore_flags(flags);
326 static void
327 isdn_tty_tint(modem_info * info)
329 struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
330 int len,
331 slen;
333 if (!skb)
334 return;
335 len = skb->len;
336 if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
337 info->isdn_channel, 1, skb)) == len) {
338 struct tty_struct *tty = info->tty;
339 info->send_outstanding++;
340 info->msr &= ~UART_MSR_CTS;
341 info->lsr &= ~UART_LSR_TEMT;
342 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
343 tty->ldisc.write_wakeup)
344 (tty->ldisc.write_wakeup) (tty);
345 wake_up_interruptible(&tty->write_wait);
346 return;
348 if (slen < 0) {
349 /* Error: no channel, already shutdown, or wrong parameter */
350 dev_kfree_skb(skb);
351 return;
353 skb_queue_head(&info->xmit_queue, skb);
356 #ifdef CONFIG_ISDN_AUDIO
357 static int
358 isdn_tty_countDLE(unsigned char *buf, int len)
360 int count = 0;
362 while (len--)
363 if (*buf++ == DLE)
364 count++;
365 return count;
368 /* This routine is called from within isdn_tty_write() to perform
369 * DLE-decoding when sending audio-data.
371 static int
372 isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len)
374 unsigned char *p = &info->xmit_buf[info->xmit_count];
375 int count = 0;
377 while (len > 0) {
378 if (m->lastDLE) {
379 m->lastDLE = 0;
380 switch (*p) {
381 case DLE:
382 /* Escape code */
383 if (len > 1)
384 memmove(p, p + 1, len - 1);
385 p--;
386 count++;
387 break;
388 case ETX:
389 /* End of data */
390 info->vonline |= 4;
391 return count;
392 case DC4:
393 /* Abort RX */
394 info->vonline &= ~1;
395 #ifdef ISDN_DEBUG_MODEM_VOICE
396 printk(KERN_DEBUG
397 "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n",
398 info->line);
399 #endif
400 isdn_tty_at_cout("\020\003", info);
401 if (!info->vonline) {
402 #ifdef ISDN_DEBUG_MODEM_VOICE
403 printk(KERN_DEBUG
404 "DLEdown: send VCON on ttyI%d\n",
405 info->line);
406 #endif
407 isdn_tty_at_cout("\r\nVCON\r\n", info);
409 /* Fall through */
410 case 'q':
411 case 's':
412 /* Silence */
413 if (len > 1)
414 memmove(p, p + 1, len - 1);
415 p--;
416 break;
418 } else {
419 if (*p == DLE)
420 m->lastDLE = 1;
421 else
422 count++;
424 p++;
425 len--;
427 if (len < 0) {
428 printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
429 return 0;
431 return count;
434 /* This routine is called from within isdn_tty_write() when receiving
435 * audio-data. It interrupts receiving, if an character other than
436 * ^S or ^Q is sent.
438 static int
439 isdn_tty_end_vrx(const char *buf, int c, int from_user)
441 char ch;
443 while (c--) {
444 if (from_user)
445 get_user(ch, buf);
446 else
447 ch = *buf;
448 if ((ch != 0x11) && (ch != 0x13))
449 return 1;
450 buf++;
452 return 0;
455 static int voice_cf[7] =
456 {0, 0, 4, 3, 2, 0, 0};
458 #endif /* CONFIG_ISDN_AUDIO */
460 /* isdn_tty_senddown() is called either directly from within isdn_tty_write()
461 * or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
462 * outgoing data from the tty's xmit-buffer, handles voice-decompression or
463 * T.70 if necessary, and finally queues it up for sending via isdn_tty_tint.
465 static void
466 isdn_tty_senddown(modem_info * info)
468 int buflen;
469 int skb_res;
470 #ifdef CONFIG_ISDN_AUDIO
471 int audio_len;
472 #endif
473 struct sk_buff *skb;
475 #ifdef CONFIG_ISDN_AUDIO
476 if (info->vonline & 4) {
477 info->vonline &= ~6;
478 if (!info->vonline) {
479 #ifdef ISDN_DEBUG_MODEM_VOICE
480 printk(KERN_DEBUG
481 "senddown: send VCON on ttyI%d\n",
482 info->line);
483 #endif
484 isdn_tty_at_cout("\r\nVCON\r\n", info);
487 #endif
488 if (!(buflen = info->xmit_count))
489 return;
490 if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
491 info->msr &= ~UART_MSR_CTS;
492 info->lsr &= ~UART_LSR_TEMT;
493 /* info->xmit_count is modified here and in isdn_tty_write().
494 * So we return here if isdn_tty_write() is in the
495 * critical section.
497 atomic_inc(&info->xmit_lock);
498 if (!(atomic_dec_and_test(&info->xmit_lock)))
499 return;
500 if (info->isdn_driver < 0) {
501 info->xmit_count = 0;
502 return;
504 skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
505 #ifdef CONFIG_ISDN_AUDIO
506 if (info->vonline & 2)
507 audio_len = buflen * voice_cf[info->emu.vpar[3]];
508 else
509 audio_len = 0;
510 skb = dev_alloc_skb(skb_res + buflen + audio_len);
511 #else
512 skb = dev_alloc_skb(skb_res + buflen);
513 #endif
514 if (!skb) {
515 printk(KERN_WARNING
516 "isdn_tty: Out of memory in ttyI%d senddown\n",
517 info->line);
518 return;
520 skb_reserve(skb, skb_res);
521 memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
522 info->xmit_count = 0;
523 #ifdef CONFIG_ISDN_AUDIO
524 if (info->vonline & 2) {
525 /* For now, ifmt is fixed to 1 (alaw), since this
526 * is used with ISDN everywhere in the world, except
527 * US, Canada and Japan.
528 * Later, when US-ISDN protocols are implemented,
529 * this setting will depend on the D-channel protocol.
531 int ifmt = 1;
533 /* voice conversion/decompression */
534 switch (info->emu.vpar[3]) {
535 case 2:
536 case 3:
537 case 4:
538 /* adpcm, compatible to ZyXel 1496 modem
539 * with ROM revision 6.01
541 audio_len = isdn_audio_adpcm2xlaw(info->adpcms,
542 ifmt,
543 skb->data,
544 skb_put(skb, audio_len),
545 buflen);
546 skb_pull(skb, buflen);
547 skb_trim(skb, audio_len);
548 break;
549 case 5:
550 /* a-law */
551 if (!ifmt)
552 isdn_audio_alaw2ulaw(skb->data,
553 buflen);
554 break;
555 case 6:
556 /* u-law */
557 if (ifmt)
558 isdn_audio_ulaw2alaw(skb->data,
559 buflen);
560 break;
563 #endif /* CONFIG_ISDN_AUDIO */
564 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
565 /* Add T.70 simplified header */
566 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)
567 memcpy(skb_push(skb, 2), "\1\0", 2);
568 else
569 memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
571 skb_queue_tail(&info->xmit_queue, skb);
574 /************************************************************
576 * Modem-functions
578 * mostly "stolen" from original Linux-serial.c and friends.
580 ************************************************************/
582 /* The next routine is called once from within timer-interrupt
583 * triggered within isdn_tty_modem_ncarrier(). It calls
584 * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
585 * into the tty's flip-buffer.
587 static void
588 isdn_tty_modem_do_ncarrier(unsigned long data)
590 modem_info *info = (modem_info *) data;
591 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
594 /* Next routine is called, whenever the DTR-signal is raised.
595 * It checks the ncarrier-flag, and triggers the above routine
596 * when necessary. The ncarrier-flag is set, whenever DTR goes
597 * low.
599 static void
600 isdn_tty_modem_ncarrier(modem_info * info)
602 if (info->ncarrier) {
603 info->nc_timer.expires = jiffies + HZ;
604 info->nc_timer.function = isdn_tty_modem_do_ncarrier;
605 info->nc_timer.data = (unsigned long) info;
606 add_timer(&info->nc_timer);
611 * return the usage calculated by si and layer 2 protocol
614 isdn_calc_usage(int si, int l2)
616 int usg = ISDN_USAGE_MODEM;
618 #ifdef CONFIG_ISDN_AUDIO
619 if (si == 1) {
620 switch(l2) {
621 case ISDN_PROTO_L2_MODEM:
622 usg = ISDN_USAGE_MODEM;
623 break;
624 #ifdef CONFIG_ISDN_TTY_FAX
625 case ISDN_PROTO_L2_FAX:
626 usg = ISDN_USAGE_FAX;
627 break;
628 #endif
629 case ISDN_PROTO_L2_TRANS:
630 default:
631 usg = ISDN_USAGE_VOICE;
632 break;
635 #endif
636 return(usg);
639 /* isdn_tty_dial() performs dialing of a tty an the necessary
640 * setup of the lower levels before that.
642 static void
643 isdn_tty_dial(char *n, modem_info * info, atemu * m)
645 int usg = ISDN_USAGE_MODEM;
646 int si = 7;
647 int l2 = m->mdmreg[REG_L2PROT];
648 isdn_ctrl cmd;
649 ulong flags;
650 int i;
651 int j;
653 for (j = 7; j >= 0; j--)
654 if (m->mdmreg[REG_SI1] & (1 << j)) {
655 si = bit2si[j];
656 break;
658 usg = isdn_calc_usage(si, l2);
659 #ifdef CONFIG_ISDN_AUDIO
660 if ((si == 1) &&
661 (l2 != ISDN_PROTO_L2_MODEM)
662 #ifdef CONFIG_ISDN_TTY_FAX
663 && (l2 != ISDN_PROTO_L2_FAX)
664 #endif
666 l2 = ISDN_PROTO_L2_TRANS;
667 usg = ISDN_USAGE_VOICE;
669 #endif
670 m->mdmreg[REG_SI1I] = si2bit[si];
671 save_flags(flags);
672 cli();
673 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
674 if (i < 0) {
675 restore_flags(flags);
676 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
677 } else {
678 info->isdn_driver = dev->drvmap[i];
679 info->isdn_channel = dev->chanmap[i];
680 info->drv_index = i;
681 dev->m_idx[i] = info->line;
682 dev->usage[i] |= ISDN_USAGE_OUTGOING;
683 info->last_dir = 1;
684 strcpy(info->last_num, n);
685 isdn_info_update();
686 restore_flags(flags);
687 cmd.driver = info->isdn_driver;
688 cmd.arg = info->isdn_channel;
689 cmd.command = ISDN_CMD_CLREAZ;
690 isdn_command(&cmd);
691 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
692 cmd.driver = info->isdn_driver;
693 cmd.command = ISDN_CMD_SETEAZ;
694 isdn_command(&cmd);
695 cmd.driver = info->isdn_driver;
696 cmd.command = ISDN_CMD_SETL2;
697 info->last_l2 = l2;
698 cmd.arg = info->isdn_channel + (l2 << 8);
699 isdn_command(&cmd);
700 cmd.driver = info->isdn_driver;
701 cmd.command = ISDN_CMD_SETL3;
702 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
703 #ifdef CONFIG_ISDN_TTY_FAX
704 if (l2 == ISDN_PROTO_L2_FAX) {
705 cmd.parm.fax = info->fax;
706 info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
708 #endif
709 isdn_command(&cmd);
710 cmd.driver = info->isdn_driver;
711 cmd.arg = info->isdn_channel;
712 sprintf(cmd.parm.setup.phone, "%s", n);
713 sprintf(cmd.parm.setup.eazmsn, "%s",
714 isdn_map_eaz2msn(m->msn, info->isdn_driver));
715 cmd.parm.setup.si1 = si;
716 cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
717 cmd.command = ISDN_CMD_DIAL;
718 info->dialing = 1;
719 info->emu.carrierwait = 0;
720 strcpy(dev->num[i], n);
721 isdn_info_update();
722 isdn_command(&cmd);
723 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
727 /* isdn_tty_hangup() disassociates a tty from the real
728 * ISDN-line (hangup). The usage-status is cleared
729 * and some cleanup is done also.
731 void
732 isdn_tty_modem_hup(modem_info * info, int local)
734 isdn_ctrl cmd;
736 if (!info)
737 return;
738 #ifdef ISDN_DEBUG_MODEM_HUP
739 printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
740 #endif
741 info->rcvsched = 0;
742 isdn_tty_flush_buffer(info->tty);
743 if (info->online) {
744 info->last_lhup = local;
745 info->online = 0;
746 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
748 #ifdef CONFIG_ISDN_AUDIO
749 info->vonline = 0;
750 #ifdef CONFIG_ISDN_TTY_FAX
751 info->faxonline = 0;
752 info->fax->phase = ISDN_FAX_PHASE_IDLE;
753 #endif
754 info->emu.vpar[4] = 0;
755 info->emu.vpar[5] = 8;
756 if (info->dtmf_state) {
757 kfree(info->dtmf_state);
758 info->dtmf_state = NULL;
760 if (info->silence_state) {
761 kfree(info->silence_state);
762 info->silence_state = NULL;
764 if (info->adpcms) {
765 kfree(info->adpcms);
766 info->adpcms = NULL;
768 if (info->adpcmr) {
769 kfree(info->adpcmr);
770 info->adpcmr = NULL;
772 #endif
773 if ((info->msr & UART_MSR_RI) &&
774 (info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
775 isdn_tty_modem_result(RESULT_RUNG, info);
776 info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
777 info->lsr |= UART_LSR_TEMT;
778 if (info->isdn_driver >= 0) {
779 if (local) {
780 cmd.driver = info->isdn_driver;
781 cmd.command = ISDN_CMD_HANGUP;
782 cmd.arg = info->isdn_channel;
783 isdn_command(&cmd);
785 isdn_all_eaz(info->isdn_driver, info->isdn_channel);
786 info->emu.mdmreg[REG_RINGCNT] = 0;
787 isdn_free_channel(info->isdn_driver, info->isdn_channel, 0);
789 info->isdn_driver = -1;
790 info->isdn_channel = -1;
791 if (info->drv_index >= 0) {
792 dev->m_idx[info->drv_index] = -1;
793 info->drv_index = -1;
798 * Begin of a CAPI like interface, currently used only for
799 * supplementary service (CAPI 2.0 part III)
801 #include "avmb1/capicmd.h" /* this should be moved in a common place */
804 isdn_tty_capi_facility(capi_msg *cm) {
805 return(-1); /* dummy */
808 /* isdn_tty_suspend() tries to suspend the current tty connection
810 static void
811 isdn_tty_suspend(char *id, modem_info * info, atemu * m)
813 isdn_ctrl cmd;
815 int l;
817 if (!info)
818 return;
820 #ifdef ISDN_DEBUG_MODEM_SERVICES
821 printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
822 #endif
823 l = strlen(id);
824 if ((info->isdn_driver >= 0)) {
825 cmd.parm.cmsg.Length = l+18;
826 cmd.parm.cmsg.Command = CAPI_FACILITY;
827 cmd.parm.cmsg.Subcommand = CAPI_REQ;
828 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
829 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
830 cmd.parm.cmsg.para[1] = 0;
831 cmd.parm.cmsg.para[2] = l + 3;
832 cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
833 cmd.parm.cmsg.para[4] = 0;
834 cmd.parm.cmsg.para[5] = l;
835 strncpy(&cmd.parm.cmsg.para[6], id, l);
836 cmd.command = CAPI_PUT_MESSAGE;
837 cmd.driver = info->isdn_driver;
838 cmd.arg = info->isdn_channel;
839 isdn_command(&cmd);
843 /* isdn_tty_resume() tries to resume a suspended call
844 * setup of the lower levels before that. unfortunatly here is no
845 * checking for compatibility of used protocols implemented by Q931
846 * It does the same things like isdn_tty_dial, the last command
847 * is different, may be we can merge it.
850 static void
851 isdn_tty_resume(char *id, modem_info * info, atemu * m)
853 int usg = ISDN_USAGE_MODEM;
854 int si = 7;
855 int l2 = m->mdmreg[REG_L2PROT];
856 isdn_ctrl cmd;
857 ulong flags;
858 int i;
859 int j;
860 int l;
862 l = strlen(id);
863 for (j = 7; j >= 0; j--)
864 if (m->mdmreg[REG_SI1] & (1 << j)) {
865 si = bit2si[j];
866 break;
868 usg = isdn_calc_usage(si, l2);
869 #ifdef CONFIG_ISDN_AUDIO
870 if ((si == 1) &&
871 (l2 != ISDN_PROTO_L2_MODEM)
872 #ifdef CONFIG_ISDN_TTY_FAX
873 && (l2 != ISDN_PROTO_L2_FAX)
874 #endif
876 l2 = ISDN_PROTO_L2_TRANS;
877 usg = ISDN_USAGE_VOICE;
879 #endif
880 m->mdmreg[REG_SI1I] = si2bit[si];
881 save_flags(flags);
882 cli();
883 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
884 if (i < 0) {
885 restore_flags(flags);
886 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
887 } else {
888 info->isdn_driver = dev->drvmap[i];
889 info->isdn_channel = dev->chanmap[i];
890 info->drv_index = i;
891 dev->m_idx[i] = info->line;
892 dev->usage[i] |= ISDN_USAGE_OUTGOING;
893 info->last_dir = 1;
894 // strcpy(info->last_num, n);
895 isdn_info_update();
896 restore_flags(flags);
897 cmd.driver = info->isdn_driver;
898 cmd.arg = info->isdn_channel;
899 cmd.command = ISDN_CMD_CLREAZ;
900 isdn_command(&cmd);
901 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
902 cmd.driver = info->isdn_driver;
903 cmd.command = ISDN_CMD_SETEAZ;
904 isdn_command(&cmd);
905 cmd.driver = info->isdn_driver;
906 cmd.command = ISDN_CMD_SETL2;
907 info->last_l2 = l2;
908 cmd.arg = info->isdn_channel + (l2 << 8);
909 isdn_command(&cmd);
910 cmd.driver = info->isdn_driver;
911 cmd.command = ISDN_CMD_SETL3;
912 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
913 isdn_command(&cmd);
914 cmd.driver = info->isdn_driver;
915 cmd.arg = info->isdn_channel;
916 cmd.parm.cmsg.Length = l+18;
917 cmd.parm.cmsg.Command = CAPI_FACILITY;
918 cmd.parm.cmsg.Subcommand = CAPI_REQ;
919 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
920 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
921 cmd.parm.cmsg.para[1] = 0;
922 cmd.parm.cmsg.para[2] = l+3;
923 cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
924 cmd.parm.cmsg.para[4] = 0;
925 cmd.parm.cmsg.para[5] = l;
926 strncpy(&cmd.parm.cmsg.para[6], id, l);
927 cmd.command =CAPI_PUT_MESSAGE;
928 info->dialing = 1;
929 // strcpy(dev->num[i], n);
930 isdn_info_update();
931 isdn_command(&cmd);
932 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
936 /* isdn_tty_send_msg() sends a message to a HL driver
937 * This is used for hybrid modem cards to send AT commands to it
940 static void
941 isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
943 int usg = ISDN_USAGE_MODEM;
944 int si = 7;
945 int l2 = m->mdmreg[REG_L2PROT];
946 isdn_ctrl cmd;
947 ulong flags;
948 int i;
949 int j;
950 int l;
952 l = strlen(msg);
953 if (!l) {
954 isdn_tty_modem_result(RESULT_ERROR, info);
955 return;
957 for (j = 7; j >= 0; j--)
958 if (m->mdmreg[REG_SI1] & (1 << j)) {
959 si = bit2si[j];
960 break;
962 usg = isdn_calc_usage(si, l2);
963 #ifdef CONFIG_ISDN_AUDIO
964 if ((si == 1) &&
965 (l2 != ISDN_PROTO_L2_MODEM)
966 #ifdef CONFIG_ISDN_TTY_FAX
967 && (l2 != ISDN_PROTO_L2_FAX)
968 #endif
970 l2 = ISDN_PROTO_L2_TRANS;
971 usg = ISDN_USAGE_VOICE;
973 #endif
974 m->mdmreg[REG_SI1I] = si2bit[si];
975 save_flags(flags);
976 cli();
977 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
978 if (i < 0) {
979 restore_flags(flags);
980 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
981 } else {
982 info->isdn_driver = dev->drvmap[i];
983 info->isdn_channel = dev->chanmap[i];
984 info->drv_index = i;
985 dev->m_idx[i] = info->line;
986 dev->usage[i] |= ISDN_USAGE_OUTGOING;
987 info->last_dir = 1;
988 isdn_info_update();
989 restore_flags(flags);
990 cmd.driver = info->isdn_driver;
991 cmd.arg = info->isdn_channel;
992 cmd.command = ISDN_CMD_CLREAZ;
993 isdn_command(&cmd);
994 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
995 cmd.driver = info->isdn_driver;
996 cmd.command = ISDN_CMD_SETEAZ;
997 isdn_command(&cmd);
998 cmd.driver = info->isdn_driver;
999 cmd.command = ISDN_CMD_SETL2;
1000 info->last_l2 = l2;
1001 cmd.arg = info->isdn_channel + (l2 << 8);
1002 isdn_command(&cmd);
1003 cmd.driver = info->isdn_driver;
1004 cmd.command = ISDN_CMD_SETL3;
1005 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
1006 isdn_command(&cmd);
1007 cmd.driver = info->isdn_driver;
1008 cmd.arg = info->isdn_channel;
1009 cmd.parm.cmsg.Length = l+14;
1010 cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
1011 cmd.parm.cmsg.Subcommand = CAPI_REQ;
1012 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
1013 cmd.parm.cmsg.para[0] = l+1;
1014 strncpy(&cmd.parm.cmsg.para[1], msg, l);
1015 cmd.parm.cmsg.para[l+1] = 0xd;
1016 cmd.command =CAPI_PUT_MESSAGE;
1017 /* info->dialing = 1;
1018 strcpy(dev->num[i], n);
1019 isdn_info_update();
1021 isdn_command(&cmd);
1025 static inline int
1026 isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
1028 #ifdef MODEM_PARANOIA_CHECK
1029 if (!info) {
1030 printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",
1031 MAJOR(device), MINOR(device), routine);
1032 return 1;
1034 if (info->magic != ISDN_ASYNC_MAGIC) {
1035 printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",
1036 MAJOR(device), MINOR(device), routine);
1037 return 1;
1039 #endif
1040 return 0;
1044 * This routine is called to set the UART divisor registers to match
1045 * the specified baud rate for a serial port.
1047 static void
1048 isdn_tty_change_speed(modem_info * info)
1050 uint cflag,
1051 cval,
1052 fcr,
1053 quot;
1054 int i;
1056 if (!info->tty || !info->tty->termios)
1057 return;
1058 cflag = info->tty->termios->c_cflag;
1060 quot = i = cflag & CBAUD;
1061 if (i & CBAUDEX) {
1062 i &= ~CBAUDEX;
1063 if (i < 1 || i > 2)
1064 info->tty->termios->c_cflag &= ~CBAUDEX;
1065 else
1066 i += 15;
1068 if (quot) {
1069 info->mcr |= UART_MCR_DTR;
1070 isdn_tty_modem_ncarrier(info);
1071 } else {
1072 info->mcr &= ~UART_MCR_DTR;
1073 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1074 #ifdef ISDN_DEBUG_MODEM_HUP
1075 printk(KERN_DEBUG "Mhup in changespeed\n");
1076 #endif
1077 if (info->online)
1078 info->ncarrier = 1;
1079 isdn_tty_modem_reset_regs(info, 0);
1080 isdn_tty_modem_hup(info, 1);
1082 return;
1084 /* byte size and parity */
1085 cval = cflag & (CSIZE | CSTOPB);
1086 cval >>= 4;
1087 if (cflag & PARENB)
1088 cval |= UART_LCR_PARITY;
1089 if (!(cflag & PARODD))
1090 cval |= UART_LCR_EPAR;
1091 fcr = 0;
1093 /* CTS flow control flag and modem status interrupts */
1094 if (cflag & CRTSCTS) {
1095 info->flags |= ISDN_ASYNC_CTS_FLOW;
1096 } else
1097 info->flags &= ~ISDN_ASYNC_CTS_FLOW;
1098 if (cflag & CLOCAL)
1099 info->flags &= ~ISDN_ASYNC_CHECK_CD;
1100 else {
1101 info->flags |= ISDN_ASYNC_CHECK_CD;
1105 static int
1106 isdn_tty_startup(modem_info * info)
1108 ulong flags;
1110 if (info->flags & ISDN_ASYNC_INITIALIZED)
1111 return 0;
1112 save_flags(flags);
1113 cli();
1114 isdn_MOD_INC_USE_COUNT();
1115 #ifdef ISDN_DEBUG_MODEM_OPEN
1116 printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
1117 #endif
1119 * Now, initialize the UART
1121 info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
1122 if (info->tty)
1123 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1125 * and set the speed of the serial port
1127 isdn_tty_change_speed(info);
1129 info->flags |= ISDN_ASYNC_INITIALIZED;
1130 info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
1131 info->send_outstanding = 0;
1132 restore_flags(flags);
1133 return 0;
1137 * This routine will shutdown a serial port; interrupts are disabled, and
1138 * DTR is dropped if the hangup on close termio flag is on.
1140 static void
1141 isdn_tty_shutdown(modem_info * info)
1143 ulong flags;
1145 if (!(info->flags & ISDN_ASYNC_INITIALIZED))
1146 return;
1147 #ifdef ISDN_DEBUG_MODEM_OPEN
1148 printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
1149 #endif
1150 save_flags(flags);
1151 cli(); /* Disable interrupts */
1152 isdn_MOD_DEC_USE_COUNT();
1153 info->msr &= ~UART_MSR_RI;
1154 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
1155 info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
1156 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1157 isdn_tty_modem_reset_regs(info, 0);
1158 #ifdef ISDN_DEBUG_MODEM_HUP
1159 printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
1160 #endif
1161 isdn_tty_modem_hup(info, 1);
1164 if (info->tty)
1165 set_bit(TTY_IO_ERROR, &info->tty->flags);
1167 info->flags &= ~ISDN_ASYNC_INITIALIZED;
1168 restore_flags(flags);
1171 /* isdn_tty_write() is the main send-routine. It is called from the upper
1172 * levels within the kernel to perform sending data. Depending on the
1173 * online-flag it either directs output to the at-command-interpreter or
1174 * to the lower level. Additional tasks done here:
1175 * - If online, check for escape-sequence (+++)
1176 * - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes.
1177 * - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
1178 * - If dialing, abort dial.
1180 static int
1181 isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
1183 int c;
1184 int total = 0;
1185 modem_info *info = (modem_info *) tty->driver_data;
1186 atemu *m = &info->emu;
1188 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
1189 return 0;
1190 if (!tty)
1191 return 0;
1192 if (from_user)
1193 down(&info->write_sem);
1194 /* See isdn_tty_senddown() */
1195 atomic_inc(&info->xmit_lock);
1196 while (1) {
1197 c = MIN(count, info->xmit_size - info->xmit_count);
1198 if (info->isdn_driver >= 0)
1199 c = MIN(c, dev->drv[info->isdn_driver]->maxbufsize);
1200 if (c <= 0)
1201 break;
1202 if ((info->online > 1)
1203 #ifdef CONFIG_ISDN_AUDIO
1204 || (info->vonline & 3)
1205 #endif
1207 #ifdef CONFIG_ISDN_AUDIO
1208 if (!info->vonline)
1209 #endif
1210 isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
1211 &(m->pluscount),
1212 &(m->lastplus),
1213 from_user);
1214 if (from_user)
1215 copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
1216 else
1217 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
1218 #ifdef CONFIG_ISDN_AUDIO
1219 if (info->vonline) {
1220 int cc = isdn_tty_handleDLEdown(info, m, c);
1221 if (info->vonline & 2) {
1222 if (!cc) {
1223 /* If DLE decoding results in zero-transmit, but
1224 * c originally was non-zero, do a wakeup.
1226 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1227 tty->ldisc.write_wakeup)
1228 (tty->ldisc.write_wakeup) (tty);
1229 wake_up_interruptible(&tty->write_wait);
1230 info->msr |= UART_MSR_CTS;
1231 info->lsr |= UART_LSR_TEMT;
1233 info->xmit_count += cc;
1235 if ((info->vonline & 3) == 1) {
1236 /* Do NOT handle Ctrl-Q or Ctrl-S
1237 * when in full-duplex audio mode.
1239 if (isdn_tty_end_vrx(buf, c, from_user)) {
1240 info->vonline &= ~1;
1241 #ifdef ISDN_DEBUG_MODEM_VOICE
1242 printk(KERN_DEBUG
1243 "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",
1244 info->line);
1245 #endif
1246 isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
1249 } else
1250 if (TTY_IS_FCLASS1(info)) {
1251 int cc = isdn_tty_handleDLEdown(info, m, c);
1253 if (info->vonline & 4) { /* ETX seen */
1254 isdn_ctrl c;
1256 c.command = ISDN_CMD_FAXCMD;
1257 c.driver = info->isdn_driver;
1258 c.arg = info->isdn_channel;
1259 c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
1260 c.parm.aux.subcmd = ETX;
1261 isdn_command(&c);
1263 info->vonline = 0;
1264 #ifdef ISDN_DEBUG_MODEM_VOICE
1265 printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);
1266 #endif
1267 info->xmit_count += cc;
1268 } else
1269 #endif
1270 info->xmit_count += c;
1271 } else {
1272 info->msr |= UART_MSR_CTS;
1273 info->lsr |= UART_LSR_TEMT;
1274 if (info->dialing) {
1275 info->dialing = 0;
1276 #ifdef ISDN_DEBUG_MODEM_HUP
1277 printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
1278 #endif
1279 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
1280 isdn_tty_modem_hup(info, 1);
1281 } else
1282 c = isdn_tty_edit_at(buf, c, info, from_user);
1284 buf += c;
1285 count -= c;
1286 total += c;
1288 atomic_dec(&info->xmit_lock);
1289 if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {
1290 if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
1291 isdn_tty_senddown(info);
1292 isdn_tty_tint(info);
1294 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1296 if (from_user)
1297 up(&info->write_sem);
1298 return total;
1301 static int
1302 isdn_tty_write_room(struct tty_struct *tty)
1304 modem_info *info = (modem_info *) tty->driver_data;
1305 int ret;
1307 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write_room"))
1308 return 0;
1309 if (!info->online)
1310 return info->xmit_size;
1311 ret = info->xmit_size - info->xmit_count;
1312 return (ret < 0) ? 0 : ret;
1315 static int
1316 isdn_tty_chars_in_buffer(struct tty_struct *tty)
1318 modem_info *info = (modem_info *) tty->driver_data;
1320 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_chars_in_buffer"))
1321 return 0;
1322 if (!info->online)
1323 return 0;
1324 return (info->xmit_count);
1327 static void
1328 isdn_tty_flush_buffer(struct tty_struct *tty)
1330 modem_info *info;
1331 unsigned long flags;
1333 save_flags(flags);
1334 cli();
1335 if (!tty) {
1336 restore_flags(flags);
1337 return;
1339 info = (modem_info *) tty->driver_data;
1340 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer")) {
1341 restore_flags(flags);
1342 return;
1344 isdn_tty_cleanup_xmit(info);
1345 info->xmit_count = 0;
1346 restore_flags(flags);
1347 wake_up_interruptible(&tty->write_wait);
1348 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1349 tty->ldisc.write_wakeup)
1350 (tty->ldisc.write_wakeup) (tty);
1353 static void
1354 isdn_tty_flush_chars(struct tty_struct *tty)
1356 modem_info *info = (modem_info *) tty->driver_data;
1358 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars"))
1359 return;
1360 if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
1361 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1365 * ------------------------------------------------------------
1366 * isdn_tty_throttle()
1368 * This routine is called by the upper-layer tty layer to signal that
1369 * incoming characters should be throttled.
1370 * ------------------------------------------------------------
1372 static void
1373 isdn_tty_throttle(struct tty_struct *tty)
1375 modem_info *info = (modem_info *) tty->driver_data;
1377 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_throttle"))
1378 return;
1379 if (I_IXOFF(tty))
1380 info->x_char = STOP_CHAR(tty);
1381 info->mcr &= ~UART_MCR_RTS;
1384 static void
1385 isdn_tty_unthrottle(struct tty_struct *tty)
1387 modem_info *info = (modem_info *) tty->driver_data;
1389 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_unthrottle"))
1390 return;
1391 if (I_IXOFF(tty)) {
1392 if (info->x_char)
1393 info->x_char = 0;
1394 else
1395 info->x_char = START_CHAR(tty);
1397 info->mcr |= UART_MCR_RTS;
1401 * ------------------------------------------------------------
1402 * isdn_tty_ioctl() and friends
1403 * ------------------------------------------------------------
1407 * isdn_tty_get_lsr_info - get line status register info
1409 * Purpose: Let user call ioctl() to get info when the UART physically
1410 * is emptied. On bus types like RS485, the transmitter must
1411 * release the bus after transmitting. This must be done when
1412 * the transmit shift register is empty, not be done when the
1413 * transmit holding register is empty. This functionality
1414 * allows RS485 driver to be written in user space.
1416 static int
1417 isdn_tty_get_lsr_info(modem_info * info, uint * value)
1419 u_char status;
1420 uint result;
1421 ulong flags;
1423 save_flags(flags);
1424 cli();
1425 status = info->lsr;
1426 restore_flags(flags);
1427 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
1428 put_user(result, (uint *) value);
1429 return 0;
1433 static int
1434 isdn_tty_get_modem_info(modem_info * info, uint * value)
1436 u_char control,
1437 status;
1438 uint result;
1439 ulong flags;
1441 control = info->mcr;
1442 save_flags(flags);
1443 cli();
1444 status = info->msr;
1445 restore_flags(flags);
1446 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
1447 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
1448 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
1449 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
1450 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
1451 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
1452 put_user(result, (uint *) value);
1453 return 0;
1456 static int
1457 isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
1459 uint arg;
1460 int pre_dtr;
1462 get_user(arg, (uint *) value);
1463 switch (cmd) {
1464 case TIOCMBIS:
1465 #ifdef ISDN_DEBUG_MODEM_IOCTL
1466 printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);
1467 #endif
1468 if (arg & TIOCM_RTS) {
1469 info->mcr |= UART_MCR_RTS;
1471 if (arg & TIOCM_DTR) {
1472 info->mcr |= UART_MCR_DTR;
1473 isdn_tty_modem_ncarrier(info);
1475 break;
1476 case TIOCMBIC:
1477 #ifdef ISDN_DEBUG_MODEM_IOCTL
1478 printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);
1479 #endif
1480 if (arg & TIOCM_RTS) {
1481 info->mcr &= ~UART_MCR_RTS;
1483 if (arg & TIOCM_DTR) {
1484 info->mcr &= ~UART_MCR_DTR;
1485 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1486 isdn_tty_modem_reset_regs(info, 0);
1487 #ifdef ISDN_DEBUG_MODEM_HUP
1488 printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
1489 #endif
1490 if (info->online)
1491 info->ncarrier = 1;
1492 isdn_tty_modem_hup(info, 1);
1495 break;
1496 case TIOCMSET:
1497 #ifdef ISDN_DEBUG_MODEM_IOCTL
1498 printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);
1499 #endif
1500 pre_dtr = (info->mcr & UART_MCR_DTR);
1501 info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))
1502 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
1503 | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
1504 if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
1505 if (!(info->mcr & UART_MCR_DTR)) {
1506 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1507 isdn_tty_modem_reset_regs(info, 0);
1508 #ifdef ISDN_DEBUG_MODEM_HUP
1509 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
1510 #endif
1511 if (info->online)
1512 info->ncarrier = 1;
1513 isdn_tty_modem_hup(info, 1);
1515 } else
1516 isdn_tty_modem_ncarrier(info);
1518 break;
1519 default:
1520 return -EINVAL;
1522 return 0;
1525 static int
1526 isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
1527 uint cmd, ulong arg)
1529 modem_info *info = (modem_info *) tty->driver_data;
1530 int error;
1531 int retval;
1533 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl"))
1534 return -ENODEV;
1535 if (tty->flags & (1 << TTY_IO_ERROR))
1536 return -EIO;
1537 switch (cmd) {
1538 case TCSBRK: /* SVID version: non-zero arg --> no break */
1539 #ifdef ISDN_DEBUG_MODEM_IOCTL
1540 printk(KERN_DEBUG "ttyI%d ioctl TCSBRK\n", info->line);
1541 #endif
1542 retval = tty_check_change(tty);
1543 if (retval)
1544 return retval;
1545 tty_wait_until_sent(tty, 0);
1546 return 0;
1547 case TCSBRKP: /* support for POSIX tcsendbreak() */
1548 #ifdef ISDN_DEBUG_MODEM_IOCTL
1549 printk(KERN_DEBUG "ttyI%d ioctl TCSBRKP\n", info->line);
1550 #endif
1551 retval = tty_check_change(tty);
1552 if (retval)
1553 return retval;
1554 tty_wait_until_sent(tty, 0);
1555 return 0;
1556 case TIOCGSOFTCAR:
1557 #ifdef ISDN_DEBUG_MODEM_IOCTL
1558 printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
1559 #endif
1560 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
1561 if (error)
1562 return error;
1563 put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
1564 return 0;
1565 case TIOCSSOFTCAR:
1566 #ifdef ISDN_DEBUG_MODEM_IOCTL
1567 printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
1568 #endif
1569 error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
1570 if (error)
1571 return error;
1572 get_user(arg, (ulong *) arg);
1573 tty->termios->c_cflag =
1574 ((tty->termios->c_cflag & ~CLOCAL) |
1575 (arg ? CLOCAL : 0));
1576 return 0;
1577 case TIOCMGET:
1578 #ifdef ISDN_DEBUG_MODEM_IOCTL
1579 printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
1580 #endif
1581 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
1582 if (error)
1583 return error;
1584 return isdn_tty_get_modem_info(info, (uint *) arg);
1585 case TIOCMBIS:
1586 case TIOCMBIC:
1587 case TIOCMSET:
1588 error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
1589 if (error)
1590 return error;
1591 return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
1592 case TIOCSERGETLSR: /* Get line status register */
1593 #ifdef ISDN_DEBUG_MODEM_IOCTL
1594 printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
1595 #endif
1596 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
1597 if (error)
1598 return error;
1599 else
1600 return isdn_tty_get_lsr_info(info, (uint *) arg);
1601 default:
1602 #ifdef ISDN_DEBUG_MODEM_IOCTL
1603 printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
1604 #endif
1605 return -ENOIOCTLCMD;
1607 return 0;
1610 static void
1611 isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
1613 modem_info *info = (modem_info *) tty->driver_data;
1615 if (!old_termios)
1616 isdn_tty_change_speed(info);
1617 else {
1618 if (tty->termios->c_cflag == old_termios->c_cflag)
1619 return;
1620 isdn_tty_change_speed(info);
1621 if ((old_termios->c_cflag & CRTSCTS) &&
1622 !(tty->termios->c_cflag & CRTSCTS)) {
1623 tty->hw_stopped = 0;
1629 * ------------------------------------------------------------
1630 * isdn_tty_open() and friends
1631 * ------------------------------------------------------------
1633 static int
1634 isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
1636 DECLARE_WAITQUEUE(wait, NULL);
1637 int do_clocal = 0;
1638 unsigned long flags;
1639 int retval;
1642 * If the device is in the middle of being closed, then block
1643 * until it's done, and then try again.
1645 if (tty_hung_up_p(filp) ||
1646 (info->flags & ISDN_ASYNC_CLOSING)) {
1647 if (info->flags & ISDN_ASYNC_CLOSING)
1648 interruptible_sleep_on(&info->close_wait);
1649 #ifdef MODEM_DO_RESTART
1650 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
1651 return -EAGAIN;
1652 else
1653 return -ERESTARTSYS;
1654 #else
1655 return -EAGAIN;
1656 #endif
1659 * If this is a callout device, then just make sure the normal
1660 * device isn't being used.
1662 if (tty->driver.subtype == ISDN_SERIAL_TYPE_CALLOUT) {
1663 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
1664 return -EBUSY;
1665 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1666 (info->flags & ISDN_ASYNC_SESSION_LOCKOUT) &&
1667 (info->session != current->session))
1668 return -EBUSY;
1669 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1670 (info->flags & ISDN_ASYNC_PGRP_LOCKOUT) &&
1671 (info->pgrp != current->pgrp))
1672 return -EBUSY;
1673 info->flags |= ISDN_ASYNC_CALLOUT_ACTIVE;
1674 return 0;
1677 * If non-blocking mode is set, then make the check up front
1678 * and then exit.
1680 if ((filp->f_flags & O_NONBLOCK) ||
1681 (tty->flags & (1 << TTY_IO_ERROR))) {
1682 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1683 return -EBUSY;
1684 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
1685 return 0;
1687 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
1688 if (info->normal_termios.c_cflag & CLOCAL)
1689 do_clocal = 1;
1690 } else {
1691 if (tty->termios->c_cflag & CLOCAL)
1692 do_clocal = 1;
1695 * Block waiting for the carrier detect and the line to become
1696 * free (i.e., not in use by the callout). While we are in
1697 * this loop, info->count is dropped by one, so that
1698 * isdn_tty_close() knows when to free things. We restore it upon
1699 * exit, either normal or abnormal.
1701 retval = 0;
1702 add_wait_queue(&info->open_wait, &wait);
1703 #ifdef ISDN_DEBUG_MODEM_OPEN
1704 printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
1705 info->line, info->count);
1706 #endif
1707 save_flags(flags);
1708 cli();
1709 if (!(tty_hung_up_p(filp)))
1710 info->count--;
1711 restore_flags(flags);
1712 info->blocked_open++;
1713 while (1) {
1714 set_current_state(TASK_INTERRUPTIBLE);
1715 if (tty_hung_up_p(filp) ||
1716 !(info->flags & ISDN_ASYNC_INITIALIZED)) {
1717 #ifdef MODEM_DO_RESTART
1718 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
1719 retval = -EAGAIN;
1720 else
1721 retval = -ERESTARTSYS;
1722 #else
1723 retval = -EAGAIN;
1724 #endif
1725 break;
1727 if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1728 !(info->flags & ISDN_ASYNC_CLOSING) &&
1729 (do_clocal || (info->msr & UART_MSR_DCD))) {
1730 break;
1732 if (signal_pending(current)) {
1733 retval = -ERESTARTSYS;
1734 break;
1736 #ifdef ISDN_DEBUG_MODEM_OPEN
1737 printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n",
1738 info->line, info->count);
1739 #endif
1740 schedule();
1742 current->state = TASK_RUNNING;
1743 remove_wait_queue(&info->open_wait, &wait);
1744 if (!tty_hung_up_p(filp))
1745 info->count++;
1746 info->blocked_open--;
1747 #ifdef ISDN_DEBUG_MODEM_OPEN
1748 printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n",
1749 info->line, info->count);
1750 #endif
1751 if (retval)
1752 return retval;
1753 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
1754 return 0;
1758 * This routine is called whenever a serial port is opened. It
1759 * enables interrupts for a serial port, linking in its async structure into
1760 * the IRQ chain. It also performs the serial-specific
1761 * initialization for the tty structure.
1763 static int
1764 isdn_tty_open(struct tty_struct *tty, struct file *filp)
1766 modem_info *info;
1767 int retval,
1768 line;
1770 line = MINOR(tty->device) - tty->driver.minor_start;
1771 if (line < 0 || line > ISDN_MAX_CHANNELS)
1772 return -ENODEV;
1773 info = &dev->mdm.info[line];
1774 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_open"))
1775 return -ENODEV;
1776 #ifdef ISDN_DEBUG_MODEM_OPEN
1777 printk(KERN_DEBUG "isdn_tty_open %s%d, count = %d\n", tty->driver.name,
1778 info->line, info->count);
1779 #endif
1780 info->count++;
1781 tty->driver_data = info;
1782 info->tty = tty;
1784 * Start up serial port
1786 retval = isdn_tty_startup(info);
1787 if (retval) {
1788 #ifdef ISDN_DEBUG_MODEM_OPEN
1789 printk(KERN_DEBUG "isdn_tty_open return after startup\n");
1790 #endif
1791 return retval;
1793 retval = isdn_tty_block_til_ready(tty, filp, info);
1794 if (retval) {
1795 #ifdef ISDN_DEBUG_MODEM_OPEN
1796 printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
1797 #endif
1798 return retval;
1800 if ((info->count == 1) && (info->flags & ISDN_ASYNC_SPLIT_TERMIOS)) {
1801 if (tty->driver.subtype == ISDN_SERIAL_TYPE_NORMAL)
1802 *tty->termios = info->normal_termios;
1803 else
1804 *tty->termios = info->callout_termios;
1805 isdn_tty_change_speed(info);
1807 info->session = current->session;
1808 info->pgrp = current->pgrp;
1809 #ifdef ISDN_DEBUG_MODEM_OPEN
1810 printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
1811 #endif
1812 dev->modempoll++;
1813 #ifdef ISDN_DEBUG_MODEM_OPEN
1814 printk(KERN_DEBUG "isdn_tty_open normal exit\n");
1815 #endif
1816 return 0;
1819 static void
1820 isdn_tty_close(struct tty_struct *tty, struct file *filp)
1822 modem_info *info = (modem_info *) tty->driver_data;
1823 ulong flags;
1824 ulong timeout;
1826 if (!info || isdn_tty_paranoia_check(info, tty->device, "isdn_tty_close"))
1827 return;
1828 save_flags(flags);
1829 cli();
1830 if (tty_hung_up_p(filp)) {
1831 restore_flags(flags);
1832 #ifdef ISDN_DEBUG_MODEM_OPEN
1833 printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
1834 #endif
1835 return;
1837 if ((tty->count == 1) && (info->count != 1)) {
1839 * Uh, oh. tty->count is 1, which means that the tty
1840 * structure will be freed. Info->count should always
1841 * be one in these conditions. If it's greater than
1842 * one, we've got real problems, since it means the
1843 * serial port won't be shutdown.
1845 printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
1846 "info->count is %d\n", info->count);
1847 info->count = 1;
1849 if (--info->count < 0) {
1850 printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
1851 info->line, info->count);
1852 info->count = 0;
1854 if (info->count) {
1855 restore_flags(flags);
1856 #ifdef ISDN_DEBUG_MODEM_OPEN
1857 printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
1858 #endif
1859 return;
1861 info->flags |= ISDN_ASYNC_CLOSING;
1863 * Save the termios structure, since this port may have
1864 * separate termios for callout and dialin.
1866 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
1867 info->normal_termios = *tty->termios;
1868 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1869 info->callout_termios = *tty->termios;
1871 tty->closing = 1;
1873 * At this point we stop accepting input. To do this, we
1874 * disable the receive line status interrupts, and tell the
1875 * interrupt driver to stop checking the data ready bit in the
1876 * line status register.
1878 if (info->flags & ISDN_ASYNC_INITIALIZED) {
1879 tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
1881 * Before we drop DTR, make sure the UART transmitter
1882 * has completely drained; this is especially
1883 * important if there is a transmit FIFO!
1885 timeout = jiffies + HZ;
1886 while (!(info->lsr & UART_LSR_TEMT)) {
1887 set_current_state(TASK_INTERRUPTIBLE);
1888 schedule_timeout(20);
1889 if (time_after(jiffies,timeout))
1890 break;
1893 dev->modempoll--;
1894 isdn_tty_shutdown(info);
1895 if (tty->driver.flush_buffer)
1896 tty->driver.flush_buffer(tty);
1897 if (tty->ldisc.flush_buffer)
1898 tty->ldisc.flush_buffer(tty);
1899 info->tty = 0;
1900 info->ncarrier = 0;
1901 tty->closing = 0;
1902 if (info->blocked_open) {
1903 set_current_state(TASK_INTERRUPTIBLE);
1904 schedule_timeout(50);
1905 wake_up_interruptible(&info->open_wait);
1907 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
1908 ISDN_ASYNC_CLOSING);
1909 wake_up_interruptible(&info->close_wait);
1910 restore_flags(flags);
1911 #ifdef ISDN_DEBUG_MODEM_OPEN
1912 printk(KERN_DEBUG "isdn_tty_close normal exit\n");
1913 #endif
1917 * isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
1919 static void
1920 isdn_tty_hangup(struct tty_struct *tty)
1922 modem_info *info = (modem_info *) tty->driver_data;
1924 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_hangup"))
1925 return;
1926 isdn_tty_shutdown(info);
1927 info->count = 0;
1928 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
1929 info->tty = 0;
1930 wake_up_interruptible(&info->open_wait);
1933 /* This routine initializes all emulator-data.
1935 static void
1936 isdn_tty_reset_profile(atemu * m)
1938 m->profile[0] = 0;
1939 m->profile[1] = 0;
1940 m->profile[2] = 43;
1941 m->profile[3] = 13;
1942 m->profile[4] = 10;
1943 m->profile[5] = 8;
1944 m->profile[6] = 3;
1945 m->profile[7] = 60;
1946 m->profile[8] = 2;
1947 m->profile[9] = 6;
1948 m->profile[10] = 7;
1949 m->profile[11] = 70;
1950 m->profile[12] = 0x45;
1951 m->profile[13] = 4;
1952 m->profile[14] = ISDN_PROTO_L2_X75I;
1953 m->profile[15] = ISDN_PROTO_L3_TRANS;
1954 m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
1955 m->profile[17] = ISDN_MODEM_WINSIZE;
1956 m->profile[18] = 4;
1957 m->profile[19] = 0;
1958 m->profile[20] = 0;
1959 m->profile[23] = 0;
1960 m->pmsn[0] = '\0';
1961 m->plmsn[0] = '\0';
1964 #ifdef CONFIG_ISDN_AUDIO
1965 static void
1966 isdn_tty_modem_reset_vpar(atemu * m)
1968 m->vpar[0] = 2; /* Voice-device (2 = phone line) */
1969 m->vpar[1] = 0; /* Silence detection level (0 = none ) */
1970 m->vpar[2] = 70; /* Silence interval (7 sec. ) */
1971 m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */
1972 m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */
1973 m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */
1975 #endif
1977 #ifdef CONFIG_ISDN_TTY_FAX
1978 static void
1979 isdn_tty_modem_reset_faxpar(modem_info * info)
1981 T30_s *f = info->fax;
1983 f->code = 0;
1984 f->phase = ISDN_FAX_PHASE_IDLE;
1985 f->direction = 0;
1986 f->resolution = 1; /* fine */
1987 f->rate = 5; /* 14400 bit/s */
1988 f->width = 0;
1989 f->length = 0;
1990 f->compression = 0;
1991 f->ecm = 0;
1992 f->binary = 0;
1993 f->scantime = 0;
1994 memset(&f->id[0], 32, FAXIDLEN - 1);
1995 f->id[FAXIDLEN - 1] = 0;
1996 f->badlin = 0;
1997 f->badmul = 0;
1998 f->bor = 0;
1999 f->nbc = 0;
2000 f->cq = 0;
2001 f->cr = 0;
2002 f->ctcrty = 0;
2003 f->minsp = 0;
2004 f->phcto = 30;
2005 f->rel = 0;
2006 memset(&f->pollid[0], 32, FAXIDLEN - 1);
2007 f->pollid[FAXIDLEN - 1] = 0;
2009 #endif
2011 static void
2012 isdn_tty_modem_reset_regs(modem_info * info, int force)
2014 atemu *m = &info->emu;
2015 if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
2016 memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
2017 memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
2018 memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
2019 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2021 #ifdef CONFIG_ISDN_AUDIO
2022 isdn_tty_modem_reset_vpar(m);
2023 #endif
2024 #ifdef CONFIG_ISDN_TTY_FAX
2025 isdn_tty_modem_reset_faxpar(info);
2026 #endif
2027 m->mdmcmdl = 0;
2030 static void
2031 modem_write_profile(atemu * m)
2033 memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
2034 memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
2035 memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
2036 if (dev->profd)
2037 send_sig(SIGIO, dev->profd, 1);
2041 isdn_tty_modem_init(void)
2043 modem *m;
2044 int i;
2045 modem_info *info;
2047 m = &dev->mdm;
2048 memset(&m->tty_modem, 0, sizeof(struct tty_driver));
2049 m->tty_modem.magic = TTY_DRIVER_MAGIC;
2050 m->tty_modem.name = isdn_ttyname_ttyI;
2051 m->tty_modem.major = ISDN_TTY_MAJOR;
2052 m->tty_modem.minor_start = 0;
2053 m->tty_modem.num = ISDN_MAX_CHANNELS;
2054 m->tty_modem.type = TTY_DRIVER_TYPE_SERIAL;
2055 m->tty_modem.subtype = ISDN_SERIAL_TYPE_NORMAL;
2056 m->tty_modem.init_termios = tty_std_termios;
2057 m->tty_modem.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2058 m->tty_modem.flags = TTY_DRIVER_REAL_RAW;
2059 m->tty_modem.refcount = &m->refcount;
2060 m->tty_modem.table = m->modem_table;
2061 m->tty_modem.termios = m->modem_termios;
2062 m->tty_modem.termios_locked = m->modem_termios_locked;
2063 m->tty_modem.open = isdn_tty_open;
2064 m->tty_modem.close = isdn_tty_close;
2065 m->tty_modem.write = isdn_tty_write;
2066 m->tty_modem.put_char = NULL;
2067 m->tty_modem.flush_chars = isdn_tty_flush_chars;
2068 m->tty_modem.write_room = isdn_tty_write_room;
2069 m->tty_modem.chars_in_buffer = isdn_tty_chars_in_buffer;
2070 m->tty_modem.flush_buffer = isdn_tty_flush_buffer;
2071 m->tty_modem.ioctl = isdn_tty_ioctl;
2072 m->tty_modem.throttle = isdn_tty_throttle;
2073 m->tty_modem.unthrottle = isdn_tty_unthrottle;
2074 m->tty_modem.set_termios = isdn_tty_set_termios;
2075 m->tty_modem.stop = NULL;
2076 m->tty_modem.start = NULL;
2077 m->tty_modem.hangup = isdn_tty_hangup;
2078 m->tty_modem.driver_name = "isdn_tty";
2080 * The callout device is just like normal device except for
2081 * major number and the subtype code.
2083 m->cua_modem = m->tty_modem;
2084 m->cua_modem.name = isdn_ttyname_cui;
2085 m->cua_modem.major = ISDN_TTYAUX_MAJOR;
2086 m->tty_modem.minor_start = 0;
2087 m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT;
2089 if (tty_register_driver(&m->tty_modem)) {
2090 printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
2091 return -1;
2093 if (tty_register_driver(&m->cua_modem)) {
2094 printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n");
2095 return -2;
2097 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2098 info = &m->info[i];
2099 #ifdef CONFIG_ISDN_TTY_FAX
2100 if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
2101 printk(KERN_ERR "Could not allocate fax t30-buffer\n");
2102 return -3;
2104 #endif
2105 init_MUTEX(&info->write_sem);
2106 sprintf(info->last_cause, "0000");
2107 sprintf(info->last_num, "none");
2108 info->last_dir = 0;
2109 info->last_lhup = 1;
2110 info->last_l2 = -1;
2111 info->last_si = 0;
2112 isdn_tty_reset_profile(&info->emu);
2113 isdn_tty_modem_reset_regs(info, 1);
2114 info->magic = ISDN_ASYNC_MAGIC;
2115 info->line = i;
2116 info->tty = 0;
2117 info->x_char = 0;
2118 info->count = 0;
2119 info->blocked_open = 0;
2120 info->callout_termios = m->cua_modem.init_termios;
2121 info->normal_termios = m->tty_modem.init_termios;
2122 init_waitqueue_head(&info->open_wait);
2123 init_waitqueue_head(&info->close_wait);
2124 info->isdn_driver = -1;
2125 info->isdn_channel = -1;
2126 info->drv_index = -1;
2127 info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
2128 skb_queue_head_init(&info->xmit_queue);
2129 #ifdef CONFIG_ISDN_AUDIO
2130 skb_queue_head_init(&info->dtmf_queue);
2131 #endif
2132 if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
2133 printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
2134 return -3;
2136 /* Make room for T.70 header */
2137 info->xmit_buf += 4;
2139 return 0;
2144 * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
2145 * match the MSN against the MSNs (glob patterns) defined for tty_emulator,
2146 * and return 0 for match, 1 for no match, 2 if MSN could match if longer.
2149 static int
2150 isdn_tty_match_icall(char *cid, atemu *emu, int di)
2152 #ifdef ISDN_DEBUG_MODEM_ICALL
2153 printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
2154 emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
2155 emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
2156 #endif
2157 if (strlen(emu->lmsn)) {
2158 char *p = emu->lmsn;
2159 char *q;
2160 int tmp;
2161 int ret = 0;
2163 while (1) {
2164 if ((q = strchr(p, ';')))
2165 *q = '\0';
2166 if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret)
2167 ret = tmp;
2168 #ifdef ISDN_DEBUG_MODEM_ICALL
2169 printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
2170 p, isdn_map_eaz2msn(emu->msn, di), tmp);
2171 #endif
2172 if (q) {
2173 *q = ';';
2174 p = q;
2175 p++;
2177 if (!tmp)
2178 return 0;
2179 if (!q)
2180 break;
2182 return ret;
2183 } else {
2184 int tmp;
2185 tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));
2186 #ifdef ISDN_DEBUG_MODEM_ICALL
2187 printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
2188 isdn_map_eaz2msn(emu->msn, di), tmp);
2189 #endif
2190 return tmp;
2195 * An incoming call-request has arrived.
2196 * Search the tty-devices for an appropriate device and bind
2197 * it to the ISDN-Channel.
2198 * Return:
2200 * 0 = No matching device found.
2201 * 1 = A matching device found.
2202 * 3 = No match found, but eventually would match, if
2203 * CID is longer.
2206 isdn_tty_find_icall(int di, int ch, setup_parm *setup)
2208 char *eaz;
2209 int i;
2210 int wret;
2211 int idx;
2212 int si1;
2213 int si2;
2214 char *nr;
2215 ulong flags;
2217 if (!setup->phone[0]) {
2218 nr = "0";
2219 printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
2220 } else
2221 nr = setup->phone;
2222 si1 = (int) setup->si1;
2223 si2 = (int) setup->si2;
2224 if (!setup->eazmsn[0]) {
2225 printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
2226 eaz = "0";
2227 } else
2228 eaz = setup->eazmsn;
2229 #ifdef ISDN_DEBUG_MODEM_ICALL
2230 printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
2231 #endif
2232 wret = 0;
2233 save_flags(flags);
2234 cli();
2235 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2236 modem_info *info = &dev->mdm.info[i];
2238 if (info->count == 0)
2239 continue;
2240 if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
2241 (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
2242 idx = isdn_dc2minor(di, ch);
2243 #ifdef ISDN_DEBUG_MODEM_ICALL
2244 printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
2245 printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
2246 info->flags, info->isdn_driver, info->isdn_channel,
2247 dev->usage[idx]);
2248 #endif
2249 if (
2250 #ifndef FIX_FILE_TRANSFER
2251 (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
2252 #endif
2253 (info->isdn_driver == -1) &&
2254 (info->isdn_channel == -1) &&
2255 (USG_NONE(dev->usage[idx]))) {
2256 int matchret;
2258 if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
2259 wret = matchret;
2260 if (!matchret) { /* EAZ is matching */
2261 info->isdn_driver = di;
2262 info->isdn_channel = ch;
2263 info->drv_index = idx;
2264 dev->m_idx[idx] = info->line;
2265 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2266 dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
2267 strcpy(dev->num[idx], nr);
2268 strcpy(info->emu.cpn, eaz);
2269 info->emu.mdmreg[REG_SI1I] = si2bit[si1];
2270 info->emu.mdmreg[REG_PLAN] = setup->plan;
2271 info->emu.mdmreg[REG_SCREEN] = setup->screen;
2272 isdn_info_update();
2273 restore_flags(flags);
2274 printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
2275 info->line);
2276 info->msr |= UART_MSR_RI;
2277 isdn_tty_modem_result(RESULT_RING, info);
2278 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
2279 return 1;
2284 restore_flags(flags);
2285 printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
2286 ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
2287 return (wret == 2)?3:0;
2290 #define TTY_IS_ACTIVE(info) \
2291 (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
2294 isdn_tty_stat_callback(int i, isdn_ctrl *c)
2296 int mi;
2297 modem_info *info;
2298 char *e;
2300 if (i < 0)
2301 return 0;
2302 if ((mi = dev->m_idx[i]) >= 0) {
2303 info = &dev->mdm.info[mi];
2304 switch (c->command) {
2305 case ISDN_STAT_CINF:
2306 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
2307 info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
2308 if (e == (char *)c->parm.num)
2309 info->emu.charge = 0;
2311 break;
2312 case ISDN_STAT_BSENT:
2313 #ifdef ISDN_TTY_STAT_DEBUG
2314 printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
2315 #endif
2316 if ((info->isdn_driver == c->driver) &&
2317 (info->isdn_channel == c->arg)) {
2318 info->msr |= UART_MSR_CTS;
2319 if (info->send_outstanding)
2320 if (!(--info->send_outstanding))
2321 info->lsr |= UART_LSR_TEMT;
2322 isdn_tty_tint(info);
2323 return 1;
2325 break;
2326 case ISDN_STAT_CAUSE:
2327 #ifdef ISDN_TTY_STAT_DEBUG
2328 printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
2329 #endif
2330 /* Signal cause to tty-device */
2331 strncpy(info->last_cause, c->parm.num, 5);
2332 return 1;
2333 case ISDN_STAT_DISPLAY:
2334 #ifdef ISDN_TTY_STAT_DEBUG
2335 printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
2336 #endif
2337 /* Signal display to tty-device */
2338 if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) &&
2339 !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
2340 isdn_tty_at_cout("\r\n", info);
2341 isdn_tty_at_cout("DISPLAY: ", info);
2342 isdn_tty_at_cout(c->parm.display, info);
2343 isdn_tty_at_cout("\r\n", info);
2345 return 1;
2346 case ISDN_STAT_DCONN:
2347 #ifdef ISDN_TTY_STAT_DEBUG
2348 printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
2349 #endif
2350 if (TTY_IS_ACTIVE(info)) {
2351 if (info->dialing == 1) {
2352 info->dialing = 2;
2353 return 1;
2356 break;
2357 case ISDN_STAT_DHUP:
2358 #ifdef ISDN_TTY_STAT_DEBUG
2359 printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
2360 #endif
2361 if (TTY_IS_ACTIVE(info)) {
2362 if (info->dialing == 1)
2363 isdn_tty_modem_result(RESULT_BUSY, info);
2364 if (info->dialing > 1)
2365 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
2366 info->dialing = 0;
2367 #ifdef ISDN_DEBUG_MODEM_HUP
2368 printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
2369 #endif
2370 isdn_tty_modem_hup(info, 0);
2371 return 1;
2373 break;
2374 case ISDN_STAT_BCONN:
2375 #ifdef ISDN_TTY_STAT_DEBUG
2376 printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
2377 #endif
2378 /* Wake up any processes waiting
2379 * for incoming call of this device when
2380 * DCD follow the state of incoming carrier
2382 if (info->blocked_open &&
2383 (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
2384 wake_up_interruptible(&info->open_wait);
2387 /* Schedule CONNECT-Message to any tty
2388 * waiting for it and
2389 * set DCD-bit of its modem-status.
2391 if (TTY_IS_ACTIVE(info) ||
2392 (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
2393 info->msr |= UART_MSR_DCD;
2394 info->emu.charge = 0;
2395 if (info->dialing & 0xf)
2396 info->last_dir = 1;
2397 else
2398 info->last_dir = 0;
2399 info->dialing = 0;
2400 info->rcvsched = 1;
2401 if (USG_MODEM(dev->usage[i])) {
2402 if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
2403 strcpy(info->emu.connmsg, c->parm.num);
2404 isdn_tty_modem_result(RESULT_CONNECT, info);
2405 } else
2406 isdn_tty_modem_result(RESULT_CONNECT64000, info);
2408 if (USG_VOICE(dev->usage[i]))
2409 isdn_tty_modem_result(RESULT_VCON, info);
2410 return 1;
2412 break;
2413 case ISDN_STAT_BHUP:
2414 #ifdef ISDN_TTY_STAT_DEBUG
2415 printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);
2416 #endif
2417 if (TTY_IS_ACTIVE(info)) {
2418 #ifdef ISDN_DEBUG_MODEM_HUP
2419 printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
2420 #endif
2421 isdn_tty_modem_hup(info, 0);
2422 return 1;
2424 break;
2425 case ISDN_STAT_NODCH:
2426 #ifdef ISDN_TTY_STAT_DEBUG
2427 printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
2428 #endif
2429 if (TTY_IS_ACTIVE(info)) {
2430 if (info->dialing) {
2431 info->dialing = 0;
2432 info->last_l2 = -1;
2433 info->last_si = 0;
2434 sprintf(info->last_cause, "0000");
2435 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
2437 isdn_tty_modem_hup(info, 0);
2438 return 1;
2440 break;
2441 case ISDN_STAT_UNLOAD:
2442 #ifdef ISDN_TTY_STAT_DEBUG
2443 printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
2444 #endif
2445 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2446 info = &dev->mdm.info[i];
2447 if (info->isdn_driver == c->driver) {
2448 if (info->online)
2449 isdn_tty_modem_hup(info, 1);
2452 return 1;
2453 #ifdef CONFIG_ISDN_TTY_FAX
2454 case ISDN_STAT_FAXIND:
2455 if (TTY_IS_ACTIVE(info)) {
2456 isdn_tty_fax_command(info, c);
2458 break;
2459 #endif
2460 #ifdef CONFIG_ISDN_AUDIO
2461 case ISDN_STAT_AUDIO:
2462 if (TTY_IS_ACTIVE(info)) {
2463 switch(c->parm.num[0]) {
2464 case ISDN_AUDIO_DTMF:
2465 if (info->vonline) {
2466 isdn_audio_put_dle_code(info,
2467 c->parm.num[1]);
2469 break;
2472 break;
2473 #endif
2476 return 0;
2479 /*********************************************************************
2480 Modem-Emulator-Routines
2481 *********************************************************************/
2483 #define cmdchar(c) ((c>=' ')&&(c<=0x7f))
2486 * Put a message from the AT-emulator into receive-buffer of tty,
2487 * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
2489 void
2490 isdn_tty_at_cout(char *msg, modem_info * info)
2492 struct tty_struct *tty;
2493 atemu *m = &info->emu;
2494 char *p;
2495 char c;
2496 ulong flags;
2497 struct sk_buff *skb = 0;
2498 char *sp = 0;
2500 if (!msg) {
2501 printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
2502 return;
2504 save_flags(flags);
2505 cli();
2506 tty = info->tty;
2507 if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
2508 restore_flags(flags);
2509 return;
2512 /* use queue instead of direct flip, if online and */
2513 /* data is in queue or flip buffer is full */
2514 if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
2515 (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
2516 skb = alloc_skb(strlen(msg)
2517 #ifdef CONFIG_ISDN_AUDIO
2518 + sizeof(isdn_audio_skb)
2519 #endif
2520 , GFP_ATOMIC);
2521 if (!skb) {
2522 restore_flags(flags);
2523 return;
2525 #ifdef CONFIG_ISDN_AUDIO
2526 skb_reserve(skb, sizeof(isdn_audio_skb));
2527 #endif
2528 sp = skb_put(skb, strlen(msg));
2529 #ifdef CONFIG_ISDN_AUDIO
2530 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
2531 ISDN_AUDIO_SKB_LOCK(skb) = 0;
2532 #endif
2535 for (p = msg; *p; p++) {
2536 switch (*p) {
2537 case '\r':
2538 c = m->mdmreg[REG_CR];
2539 break;
2540 case '\n':
2541 c = m->mdmreg[REG_LF];
2542 break;
2543 case '\b':
2544 c = m->mdmreg[REG_BS];
2545 break;
2546 default:
2547 c = *p;
2549 if (skb) {
2550 *sp++ = c;
2551 } else {
2552 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2553 break;
2554 tty_insert_flip_char(tty, c, 0);
2557 if (skb) {
2558 __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
2559 dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
2560 restore_flags(flags);
2561 /* Schedule dequeuing */
2562 if ((dev->modempoll) && (info->rcvsched))
2563 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
2565 } else {
2566 restore_flags(flags);
2567 queue_task(&tty->flip.tqueue, &tq_timer);
2572 * Perform ATH Hangup
2574 static void
2575 isdn_tty_on_hook(modem_info * info)
2577 if (info->isdn_channel >= 0) {
2578 #ifdef ISDN_DEBUG_MODEM_HUP
2579 printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
2580 #endif
2581 isdn_tty_modem_hup(info, 1);
2585 static void
2586 isdn_tty_off_hook(void)
2588 printk(KERN_DEBUG "isdn_tty_off_hook\n");
2591 #define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
2592 #define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */
2595 * Check Buffer for Modem-escape-sequence, activate timer-callback to
2596 * isdn_tty_modem_escape() if sequence found.
2598 * Parameters:
2599 * p pointer to databuffer
2600 * plus escape-character
2601 * count length of buffer
2602 * pluscount count of valid escape-characters so far
2603 * lastplus timestamp of last character
2605 static void
2606 isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
2607 int *lastplus, int from_user)
2609 char cbuf[3];
2611 if (plus > 127)
2612 return;
2613 if (count > 3) {
2614 p += count - 3;
2615 count = 3;
2616 *pluscount = 0;
2618 if (from_user) {
2619 copy_from_user(cbuf, p, count);
2620 p = cbuf;
2622 while (count > 0) {
2623 if (*(p++) == plus) {
2624 if ((*pluscount)++) {
2625 /* Time since last '+' > 0.5 sec. ? */
2626 if ((jiffies - *lastplus) > PLUSWAIT1)
2627 *pluscount = 1;
2628 } else {
2629 /* Time since last non-'+' < 1.5 sec. ? */
2630 if ((jiffies - *lastplus) < PLUSWAIT2)
2631 *pluscount = 0;
2633 if ((*pluscount == 3) && (count == 1))
2634 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
2635 if (*pluscount > 3)
2636 *pluscount = 1;
2637 } else
2638 *pluscount = 0;
2639 *lastplus = jiffies;
2640 count--;
2645 * Return result of AT-emulator to tty-receive-buffer, depending on
2646 * modem-register 12, bit 0 and 1.
2647 * For CONNECT-messages also switch to online-mode.
2648 * For RING-message handle auto-ATA if register 0 != 0
2651 static void
2652 isdn_tty_modem_result(int code, modem_info * info)
2654 atemu *m = &info->emu;
2655 static char *msg[] =
2656 {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
2657 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
2658 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
2659 ulong flags;
2660 char s[ISDN_MSNLEN+10];
2662 switch (code) {
2663 case RESULT_RING:
2664 m->mdmreg[REG_RINGCNT]++;
2665 if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
2666 /* Automatically accept incoming call */
2667 isdn_tty_cmd_ATA(info);
2668 break;
2669 case RESULT_NO_CARRIER:
2670 #ifdef ISDN_DEBUG_MODEM_HUP
2671 printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
2672 (info->flags & ISDN_ASYNC_CLOSING),
2673 (!info->tty));
2674 #endif
2675 save_flags(flags);
2676 cli();
2677 m->mdmreg[REG_RINGCNT] = 0;
2678 del_timer(&info->nc_timer);
2679 info->ncarrier = 0;
2680 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
2681 restore_flags(flags);
2682 return;
2684 restore_flags(flags);
2685 #ifdef CONFIG_ISDN_AUDIO
2686 if (info->vonline & 1) {
2687 #ifdef ISDN_DEBUG_MODEM_VOICE
2688 printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",
2689 info->line);
2690 #endif
2691 /* voice-recording, add DLE-ETX */
2692 isdn_tty_at_cout("\020\003", info);
2694 if (info->vonline & 2) {
2695 #ifdef ISDN_DEBUG_MODEM_VOICE
2696 printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n",
2697 info->line);
2698 #endif
2699 /* voice-playing, add DLE-DC4 */
2700 isdn_tty_at_cout("\020\024", info);
2702 #endif
2703 break;
2704 case RESULT_CONNECT:
2705 case RESULT_CONNECT64000:
2706 sprintf(info->last_cause, "0000");
2707 if (!info->online)
2708 info->online = 2;
2709 break;
2710 case RESULT_VCON:
2711 #ifdef ISDN_DEBUG_MODEM_VOICE
2712 printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
2713 info->line);
2714 #endif
2715 sprintf(info->last_cause, "0000");
2716 if (!info->online)
2717 info->online = 1;
2718 break;
2719 } /* switch(code) */
2721 if (m->mdmreg[REG_RESP] & BIT_RESP) {
2722 /* Show results */
2723 if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
2724 /* Show numeric results only */
2725 sprintf(s, "\r\n%d\r\n", code);
2726 isdn_tty_at_cout(s, info);
2727 } else {
2728 if (code == RESULT_RING) {
2729 /* return if "show RUNG" and ringcounter>1 */
2730 if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
2731 (m->mdmreg[REG_RINGCNT] > 1))
2732 return;
2733 /* print CID, _before_ _every_ ring */
2734 if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
2735 isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
2736 isdn_tty_at_cout(dev->num[info->drv_index], info);
2739 isdn_tty_at_cout("\r\n", info);
2740 isdn_tty_at_cout(msg[code], info);
2741 switch (code) {
2742 case RESULT_CONNECT:
2743 switch (m->mdmreg[REG_L2PROT]) {
2744 case ISDN_PROTO_L2_MODEM:
2745 isdn_tty_at_cout(" ", info);
2746 isdn_tty_at_cout(m->connmsg, info);
2747 break;
2749 break;
2750 case RESULT_RING:
2751 /* Append CPN, if enabled */
2752 if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
2753 sprintf(s, "/%s", m->cpn);
2754 isdn_tty_at_cout(s, info);
2756 /* Print CID only once, _after_ 1st RING */
2757 if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
2758 (m->mdmreg[REG_RINGCNT] == 1)) {
2759 isdn_tty_at_cout("\r\n", info);
2760 isdn_tty_at_cout("CALLER NUMBER: ", info);
2761 isdn_tty_at_cout(dev->num[info->drv_index], info);
2763 break;
2764 case RESULT_NO_CARRIER:
2765 case RESULT_NO_DIALTONE:
2766 case RESULT_BUSY:
2767 case RESULT_NO_ANSWER:
2768 m->mdmreg[REG_RINGCNT] = 0;
2769 /* Append Cause-Message if enabled */
2770 if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
2771 sprintf(s, "/%s", info->last_cause);
2772 isdn_tty_at_cout(s, info);
2774 break;
2775 case RESULT_CONNECT64000:
2776 /* Append Protocol to CONNECT message */
2777 switch (m->mdmreg[REG_L2PROT]) {
2778 case ISDN_PROTO_L2_X75I:
2779 case ISDN_PROTO_L2_X75UI:
2780 case ISDN_PROTO_L2_X75BUI:
2781 isdn_tty_at_cout("/X.75", info);
2782 break;
2783 case ISDN_PROTO_L2_HDLC:
2784 isdn_tty_at_cout("/HDLC", info);
2785 break;
2786 case ISDN_PROTO_L2_V11096:
2787 isdn_tty_at_cout("/V110/9600", info);
2788 break;
2789 case ISDN_PROTO_L2_V11019:
2790 isdn_tty_at_cout("/V110/19200", info);
2791 break;
2792 case ISDN_PROTO_L2_V11038:
2793 isdn_tty_at_cout("/V110/38400", info);
2794 break;
2796 if (m->mdmreg[REG_T70] & BIT_T70) {
2797 isdn_tty_at_cout("/T.70", info);
2798 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2799 isdn_tty_at_cout("+", info);
2801 break;
2803 isdn_tty_at_cout("\r\n", info);
2806 if (code == RESULT_NO_CARRIER) {
2807 save_flags(flags);
2808 cli();
2809 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
2810 restore_flags(flags);
2811 return;
2813 if (info->tty->ldisc.flush_buffer)
2814 info->tty->ldisc.flush_buffer(info->tty);
2815 if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
2816 (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
2817 (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
2818 tty_hangup(info->tty);
2820 restore_flags(flags);
2826 * Display a modem-register-value.
2828 static void
2829 isdn_tty_show_profile(int ridx, modem_info * info)
2831 char v[6];
2833 sprintf(v, "\r\n%d", info->emu.mdmreg[ridx]);
2834 isdn_tty_at_cout(v, info);
2838 * Get MSN-string from char-pointer, set pointer to end of number
2840 static void
2841 isdn_tty_get_msnstr(char *n, char **p)
2843 int limit = ISDN_MSNLEN - 1;
2845 while (((*p[0] >= '0' && *p[0] <= '9') ||
2846 /* Why a comma ??? */
2847 (*p[0] == ',') || (*p[0] == ':')) &&
2848 (limit--))
2849 *n++ = *p[0]++;
2850 *n = '\0';
2854 * Get phone-number from modem-commandbuffer
2856 static void
2857 isdn_tty_getdial(char *p, char *q,int cnt)
2859 int first = 1;
2860 int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid
2861 buffer overflow */
2863 while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
2864 if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
2865 (*p == '*') || (*p == '#')) {
2866 *q++ = *p;
2867 limit--;
2869 if(!limit)
2870 break;
2871 p++;
2872 first = 0;
2874 *q = 0;
2877 #define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
2878 #define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
2880 static void
2881 isdn_tty_report(modem_info * info)
2883 atemu *m = &info->emu;
2884 char s[80];
2886 isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info);
2887 sprintf(s, " Remote Number: %s\r\n", info->last_num);
2888 isdn_tty_at_cout(s, info);
2889 sprintf(s, " Direction: %s\r\n", info->last_dir ? "outgoing" : "incoming");
2890 isdn_tty_at_cout(s, info);
2891 isdn_tty_at_cout(" Layer-2 Protocol: ", info);
2892 switch (info->last_l2) {
2893 case ISDN_PROTO_L2_X75I:
2894 isdn_tty_at_cout("X.75i", info);
2895 break;
2896 case ISDN_PROTO_L2_X75UI:
2897 isdn_tty_at_cout("X.75ui", info);
2898 break;
2899 case ISDN_PROTO_L2_X75BUI:
2900 isdn_tty_at_cout("X.75bui", info);
2901 break;
2902 case ISDN_PROTO_L2_HDLC:
2903 isdn_tty_at_cout("HDLC", info);
2904 break;
2905 case ISDN_PROTO_L2_V11096:
2906 isdn_tty_at_cout("V.110 9600 Baud", info);
2907 break;
2908 case ISDN_PROTO_L2_V11019:
2909 isdn_tty_at_cout("V.110 19200 Baud", info);
2910 break;
2911 case ISDN_PROTO_L2_V11038:
2912 isdn_tty_at_cout("V.110 38400 Baud", info);
2913 break;
2914 case ISDN_PROTO_L2_TRANS:
2915 isdn_tty_at_cout("transparent", info);
2916 break;
2917 case ISDN_PROTO_L2_MODEM:
2918 isdn_tty_at_cout("modem", info);
2919 break;
2920 case ISDN_PROTO_L2_FAX:
2921 isdn_tty_at_cout("fax", info);
2922 break;
2923 default:
2924 isdn_tty_at_cout("unknown", info);
2925 break;
2927 if (m->mdmreg[REG_T70] & BIT_T70) {
2928 isdn_tty_at_cout("/T.70", info);
2929 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2930 isdn_tty_at_cout("+", info);
2932 isdn_tty_at_cout("\r\n", info);
2933 isdn_tty_at_cout(" Service: ", info);
2934 switch (info->last_si) {
2935 case 1:
2936 isdn_tty_at_cout("audio\r\n", info);
2937 break;
2938 case 5:
2939 isdn_tty_at_cout("btx\r\n", info);
2940 break;
2941 case 7:
2942 isdn_tty_at_cout("data\r\n", info);
2943 break;
2944 default:
2945 sprintf(s, "%d\r\n", info->last_si);
2946 isdn_tty_at_cout(s, info);
2947 break;
2949 sprintf(s, " Hangup location: %s\r\n", info->last_lhup ? "local" : "remote");
2950 isdn_tty_at_cout(s, info);
2951 sprintf(s, " Last cause: %s\r\n", info->last_cause);
2952 isdn_tty_at_cout(s, info);
2956 * Parse AT&.. commands.
2958 static int
2959 isdn_tty_cmd_ATand(char **p, modem_info * info)
2961 atemu *m = &info->emu;
2962 int i;
2963 char rb[100];
2965 #define MAXRB (sizeof(rb) - 1)
2967 switch (*p[0]) {
2968 case 'B':
2969 /* &B - Set Buffersize */
2970 p[0]++;
2971 i = isdn_getnum(p);
2972 if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX))
2973 PARSE_ERROR1;
2974 #ifdef CONFIG_ISDN_AUDIO
2975 if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF))
2976 PARSE_ERROR1;
2977 #endif
2978 m->mdmreg[REG_PSIZE] = i / 16;
2979 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2980 switch (m->mdmreg[REG_L2PROT]) {
2981 case ISDN_PROTO_L2_V11096:
2982 case ISDN_PROTO_L2_V11019:
2983 case ISDN_PROTO_L2_V11038:
2984 info->xmit_size /= 10;
2986 break;
2987 case 'C':
2988 /* &C - DCD Status */
2989 p[0]++;
2990 switch (isdn_getnum(p)) {
2991 case 0:
2992 m->mdmreg[REG_DCD] &= ~BIT_DCD;
2993 break;
2994 case 1:
2995 m->mdmreg[REG_DCD] |= BIT_DCD;
2996 break;
2997 default:
2998 PARSE_ERROR1
3000 break;
3001 case 'D':
3002 /* &D - Set DTR-Low-behavior */
3003 p[0]++;
3004 switch (isdn_getnum(p)) {
3005 case 0:
3006 m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP;
3007 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
3008 break;
3009 case 2:
3010 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
3011 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
3012 break;
3013 case 3:
3014 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
3015 m->mdmreg[REG_DTRR] |= BIT_DTRR;
3016 break;
3017 default:
3018 PARSE_ERROR1
3020 break;
3021 case 'E':
3022 /* &E -Set EAZ/MSN */
3023 p[0]++;
3024 isdn_tty_get_msnstr(m->msn, p);
3025 break;
3026 case 'F':
3027 /* &F -Set Factory-Defaults */
3028 p[0]++;
3029 if (info->msr & UART_MSR_DCD)
3030 PARSE_ERROR1;
3031 isdn_tty_reset_profile(m);
3032 isdn_tty_modem_reset_regs(info, 1);
3033 break;
3034 #ifdef DUMMY_HAYES_AT
3035 case 'K':
3036 /* only for be compilant with common scripts */
3037 /* &K Flowcontrol - no function */
3038 p[0]++;
3039 isdn_getnum(p);
3040 break;
3041 #endif
3042 case 'L':
3043 /* &L -Set Numbers to listen on */
3044 p[0]++;
3045 i = 0;
3046 while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
3047 (i < ISDN_LMSNLEN))
3048 m->lmsn[i++] = *p[0]++;
3049 m->lmsn[i] = '\0';
3050 break;
3051 case 'R':
3052 /* &R - Set V.110 bitrate adaption */
3053 p[0]++;
3054 i = isdn_getnum(p);
3055 switch (i) {
3056 case 0:
3057 /* Switch off V.110, back to X.75 */
3058 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3059 m->mdmreg[REG_SI2] = 0;
3060 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
3061 break;
3062 case 9600:
3063 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096;
3064 m->mdmreg[REG_SI2] = 197;
3065 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
3066 break;
3067 case 19200:
3068 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019;
3069 m->mdmreg[REG_SI2] = 199;
3070 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
3071 break;
3072 case 38400:
3073 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038;
3074 m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
3075 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
3076 break;
3077 default:
3078 PARSE_ERROR1;
3080 /* Switch off T.70 */
3081 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
3082 /* Set Service 7 */
3083 m->mdmreg[REG_SI1] |= 4;
3084 break;
3085 case 'S':
3086 /* &S - Set Windowsize */
3087 p[0]++;
3088 i = isdn_getnum(p);
3089 if ((i > 0) && (i < 9))
3090 m->mdmreg[REG_WSIZE] = i;
3091 else
3092 PARSE_ERROR1;
3093 break;
3094 case 'V':
3095 /* &V - Show registers */
3096 p[0]++;
3097 isdn_tty_at_cout("\r\n", info);
3098 for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
3099 sprintf(rb, "S%02d=%03d%s", i,
3100 m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
3101 isdn_tty_at_cout(rb, info);
3103 sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
3104 strlen(m->msn) ? m->msn : "None");
3105 isdn_tty_at_cout(rb, info);
3106 if (strlen(m->lmsn)) {
3107 isdn_tty_at_cout("\r\nListen: ", info);
3108 isdn_tty_at_cout(m->lmsn, info);
3109 isdn_tty_at_cout("\r\n", info);
3111 break;
3112 case 'W':
3113 /* &W - Write Profile */
3114 p[0]++;
3115 switch (*p[0]) {
3116 case '0':
3117 p[0]++;
3118 modem_write_profile(m);
3119 break;
3120 default:
3121 PARSE_ERROR1;
3123 break;
3124 case 'X':
3125 /* &X - Switch to BTX-Mode and T.70 */
3126 p[0]++;
3127 switch (isdn_getnum(p)) {
3128 case 0:
3129 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
3130 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
3131 break;
3132 case 1:
3133 m->mdmreg[REG_T70] |= BIT_T70;
3134 m->mdmreg[REG_T70] &= ~BIT_T70_EXT;
3135 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3136 info->xmit_size = 112;
3137 m->mdmreg[REG_SI1] = 4;
3138 m->mdmreg[REG_SI2] = 0;
3139 break;
3140 case 2:
3141 m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT);
3142 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3143 info->xmit_size = 112;
3144 m->mdmreg[REG_SI1] = 4;
3145 m->mdmreg[REG_SI2] = 0;
3146 break;
3147 default:
3148 PARSE_ERROR1;
3150 break;
3151 default:
3152 PARSE_ERROR1;
3154 return 0;
3157 static int
3158 isdn_tty_check_ats(int mreg, int mval, modem_info * info, atemu * m)
3160 /* Some plausibility checks */
3161 switch (mreg) {
3162 case REG_L2PROT:
3163 if (mval > ISDN_PROTO_L2_MAX)
3164 return 1;
3165 break;
3166 case REG_PSIZE:
3167 if ((mval * 16) > ISDN_SERIAL_XMIT_MAX)
3168 return 1;
3169 #ifdef CONFIG_ISDN_AUDIO
3170 if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX))
3171 return 1;
3172 #endif
3173 info->xmit_size = mval * 16;
3174 switch (m->mdmreg[REG_L2PROT]) {
3175 case ISDN_PROTO_L2_V11096:
3176 case ISDN_PROTO_L2_V11019:
3177 case ISDN_PROTO_L2_V11038:
3178 info->xmit_size /= 10;
3180 break;
3181 case REG_SI1I:
3182 case REG_PLAN:
3183 case REG_SCREEN:
3184 /* readonly registers */
3185 return 1;
3187 return 0;
3191 * Perform ATS command
3193 static int
3194 isdn_tty_cmd_ATS(char **p, modem_info * info)
3196 atemu *m = &info->emu;
3197 int bitpos;
3198 int mreg;
3199 int mval;
3200 int bval;
3202 mreg = isdn_getnum(p);
3203 if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
3204 PARSE_ERROR1;
3205 switch (*p[0]) {
3206 case '=':
3207 p[0]++;
3208 mval = isdn_getnum(p);
3209 if (mval < 0 || mval > 255)
3210 PARSE_ERROR1;
3211 if (isdn_tty_check_ats(mreg, mval, info, m))
3212 PARSE_ERROR1;
3213 m->mdmreg[mreg] = mval;
3214 break;
3215 case '.':
3216 /* Set/Clear a single bit */
3217 p[0]++;
3218 bitpos = isdn_getnum(p);
3219 if ((bitpos < 0) || (bitpos > 7))
3220 PARSE_ERROR1;
3221 switch (*p[0]) {
3222 case '=':
3223 p[0]++;
3224 bval = isdn_getnum(p);
3225 if (bval < 0 || bval > 1)
3226 PARSE_ERROR1;
3227 if (bval)
3228 mval = m->mdmreg[mreg] | (1 << bitpos);
3229 else
3230 mval = m->mdmreg[mreg] & ~(1 << bitpos);
3231 if (isdn_tty_check_ats(mreg, mval, info, m))
3232 PARSE_ERROR1;
3233 m->mdmreg[mreg] = mval;
3234 break;
3235 case '?':
3236 p[0]++;
3237 isdn_tty_at_cout("\r\n", info);
3238 isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0",
3239 info);
3240 break;
3241 default:
3242 PARSE_ERROR1;
3244 break;
3245 case '?':
3246 p[0]++;
3247 isdn_tty_show_profile(mreg, info);
3248 break;
3249 default:
3250 PARSE_ERROR1;
3251 break;
3253 return 0;
3257 * Perform ATA command
3259 static void
3260 isdn_tty_cmd_ATA(modem_info * info)
3262 atemu *m = &info->emu;
3263 isdn_ctrl cmd;
3264 int l2;
3266 if (info->msr & UART_MSR_RI) {
3267 /* Accept incoming call */
3268 info->last_dir = 0;
3269 strcpy(info->last_num, dev->num[info->drv_index]);
3270 m->mdmreg[REG_RINGCNT] = 0;
3271 info->msr &= ~UART_MSR_RI;
3272 l2 = m->mdmreg[REG_L2PROT];
3273 #ifdef CONFIG_ISDN_AUDIO
3274 /* If more than one bit set in reg18, autoselect Layer2 */
3275 if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
3276 if (m->mdmreg[REG_SI1I] == 1) {
3277 if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
3278 l2 = ISDN_PROTO_L2_TRANS;
3279 } else
3280 l2 = ISDN_PROTO_L2_X75I;
3282 #endif
3283 cmd.driver = info->isdn_driver;
3284 cmd.command = ISDN_CMD_SETL2;
3285 cmd.arg = info->isdn_channel + (l2 << 8);
3286 info->last_l2 = l2;
3287 isdn_command(&cmd);
3288 cmd.driver = info->isdn_driver;
3289 cmd.command = ISDN_CMD_SETL3;
3290 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
3291 #ifdef CONFIG_ISDN_TTY_FAX
3292 if (l2 == ISDN_PROTO_L2_FAX) {
3293 cmd.parm.fax = info->fax;
3294 info->fax->direction = ISDN_TTY_FAX_CONN_IN;
3296 #endif
3297 isdn_command(&cmd);
3298 cmd.driver = info->isdn_driver;
3299 cmd.arg = info->isdn_channel;
3300 cmd.command = ISDN_CMD_ACCEPTD;
3301 info->dialing = 16;
3302 info->emu.carrierwait = 0;
3303 isdn_command(&cmd);
3304 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
3305 } else
3306 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3309 #ifdef CONFIG_ISDN_AUDIO
3311 * Parse AT+F.. commands
3313 static int
3314 isdn_tty_cmd_PLUSF(char **p, modem_info * info)
3316 atemu *m = &info->emu;
3317 char rs[20];
3319 if (!strncmp(p[0], "CLASS", 5)) {
3320 p[0] += 5;
3321 switch (*p[0]) {
3322 case '?':
3323 p[0]++;
3324 sprintf(rs, "\r\n%d",
3325 (m->mdmreg[REG_SI1] & 1) ? 8 : 0);
3326 #ifdef CONFIG_ISDN_TTY_FAX
3327 if (TTY_IS_FCLASS2(info))
3328 sprintf(rs, "\r\n2");
3329 else if (TTY_IS_FCLASS1(info))
3330 sprintf(rs, "\r\n1");
3331 #endif
3332 isdn_tty_at_cout(rs, info);
3333 break;
3334 case '=':
3335 p[0]++;
3336 switch (*p[0]) {
3337 case '0':
3338 p[0]++;
3339 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3340 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3341 m->mdmreg[REG_SI1] = 4;
3342 info->xmit_size =
3343 m->mdmreg[REG_PSIZE] * 16;
3344 break;
3345 #ifdef CONFIG_ISDN_TTY_FAX
3346 case '1':
3347 p[0]++;
3348 if (!(dev->global_features &
3349 ISDN_FEATURE_L3_FCLASS1))
3350 PARSE_ERROR1;
3351 m->mdmreg[REG_SI1] = 1;
3352 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3353 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
3354 info->xmit_size =
3355 m->mdmreg[REG_PSIZE] * 16;
3356 break;
3357 case '2':
3358 p[0]++;
3359 if (!(dev->global_features &
3360 ISDN_FEATURE_L3_FCLASS2))
3361 PARSE_ERROR1;
3362 m->mdmreg[REG_SI1] = 1;
3363 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3364 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
3365 info->xmit_size =
3366 m->mdmreg[REG_PSIZE] * 16;
3367 break;
3368 #endif
3369 case '8':
3370 p[0]++;
3371 /* L2 will change on dialout with si=1 */
3372 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3373 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3374 m->mdmreg[REG_SI1] = 5;
3375 info->xmit_size = VBUF;
3376 break;
3377 case '?':
3378 p[0]++;
3379 strcpy(rs, "\r\n0,");
3380 #ifdef CONFIG_ISDN_TTY_FAX
3381 if (dev->global_features &
3382 ISDN_FEATURE_L3_FCLASS1)
3383 strcat(rs, "1,");
3384 if (dev->global_features &
3385 ISDN_FEATURE_L3_FCLASS2)
3386 strcat(rs, "2,");
3387 #endif
3388 strcat(rs, "8");
3389 isdn_tty_at_cout(rs, info);
3390 break;
3391 default:
3392 PARSE_ERROR1;
3394 break;
3395 default:
3396 PARSE_ERROR1;
3398 return 0;
3400 #ifdef CONFIG_ISDN_TTY_FAX
3401 return (isdn_tty_cmd_PLUSF_FAX(p, info));
3402 #else
3403 PARSE_ERROR1;
3404 #endif
3408 * Parse AT+V.. commands
3410 static int
3411 isdn_tty_cmd_PLUSV(char **p, modem_info * info)
3413 atemu *m = &info->emu;
3414 isdn_ctrl cmd;
3415 static char *vcmd[] =
3416 {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
3417 int i;
3418 int par1;
3419 int par2;
3420 char rs[20];
3422 i = 0;
3423 while (vcmd[i]) {
3424 if (!strncmp(vcmd[i], p[0], 2)) {
3425 p[0] += 2;
3426 break;
3428 i++;
3430 switch (i) {
3431 case 0:
3432 /* AT+VNH - Auto hangup feature */
3433 switch (*p[0]) {
3434 case '?':
3435 p[0]++;
3436 isdn_tty_at_cout("\r\n1", info);
3437 break;
3438 case '=':
3439 p[0]++;
3440 switch (*p[0]) {
3441 case '1':
3442 p[0]++;
3443 break;
3444 case '?':
3445 p[0]++;
3446 isdn_tty_at_cout("\r\n1", info);
3447 break;
3448 default:
3449 PARSE_ERROR1;
3451 break;
3452 default:
3453 PARSE_ERROR1;
3455 break;
3456 case 1:
3457 /* AT+VIP - Reset all voice parameters */
3458 isdn_tty_modem_reset_vpar(m);
3459 break;
3460 case 2:
3461 /* AT+VLS - Select device, accept incoming call */
3462 switch (*p[0]) {
3463 case '?':
3464 p[0]++;
3465 sprintf(rs, "\r\n%d", m->vpar[0]);
3466 isdn_tty_at_cout(rs, info);
3467 break;
3468 case '=':
3469 p[0]++;
3470 switch (*p[0]) {
3471 case '0':
3472 p[0]++;
3473 m->vpar[0] = 0;
3474 break;
3475 case '2':
3476 p[0]++;
3477 m->vpar[0] = 2;
3478 break;
3479 case '?':
3480 p[0]++;
3481 isdn_tty_at_cout("\r\n0,2", info);
3482 break;
3483 default:
3484 PARSE_ERROR1;
3486 break;
3487 default:
3488 PARSE_ERROR1;
3490 break;
3491 case 3:
3492 /* AT+VRX - Start recording */
3493 if (!m->vpar[0])
3494 PARSE_ERROR1;
3495 if (info->online != 1) {
3496 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3497 return 1;
3499 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3500 if (!info->dtmf_state) {
3501 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3502 PARSE_ERROR1;
3504 info->silence_state = isdn_audio_silence_init(info->silence_state);
3505 if (!info->silence_state) {
3506 printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
3507 PARSE_ERROR1;
3509 if (m->vpar[3] < 5) {
3510 info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
3511 if (!info->adpcmr) {
3512 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3513 PARSE_ERROR1;
3516 #ifdef ISDN_DEBUG_AT
3517 printk(KERN_DEBUG "AT: +VRX\n");
3518 #endif
3519 info->vonline |= 1;
3520 isdn_tty_modem_result(RESULT_CONNECT, info);
3521 return 0;
3522 break;
3523 case 4:
3524 /* AT+VSD - Silence detection */
3525 switch (*p[0]) {
3526 case '?':
3527 p[0]++;
3528 sprintf(rs, "\r\n<%d>,<%d>",
3529 m->vpar[1],
3530 m->vpar[2]);
3531 isdn_tty_at_cout(rs, info);
3532 break;
3533 case '=':
3534 p[0]++;
3535 if ((*p[0]>='0') && (*p[0]<='9')) {
3536 par1 = isdn_getnum(p);
3537 if ((par1 < 0) || (par1 > 31))
3538 PARSE_ERROR1;
3539 if (*p[0] != ',')
3540 PARSE_ERROR1;
3541 p[0]++;
3542 par2 = isdn_getnum(p);
3543 if ((par2 < 0) || (par2 > 255))
3544 PARSE_ERROR1;
3545 m->vpar[1] = par1;
3546 m->vpar[2] = par2;
3547 break;
3548 } else
3549 if (*p[0] == '?') {
3550 p[0]++;
3551 isdn_tty_at_cout("\r\n<0-31>,<0-255>",
3552 info);
3553 break;
3554 } else
3555 PARSE_ERROR1;
3556 break;
3557 default:
3558 PARSE_ERROR1;
3560 break;
3561 case 5:
3562 /* AT+VSM - Select compression */
3563 switch (*p[0]) {
3564 case '?':
3565 p[0]++;
3566 sprintf(rs, "\r\n<%d>,<%d><8000>",
3567 m->vpar[3],
3568 m->vpar[1]);
3569 isdn_tty_at_cout(rs, info);
3570 break;
3571 case '=':
3572 p[0]++;
3573 switch (*p[0]) {
3574 case '2':
3575 case '3':
3576 case '4':
3577 case '5':
3578 case '6':
3579 par1 = isdn_getnum(p);
3580 if ((par1 < 2) || (par1 > 6))
3581 PARSE_ERROR1;
3582 m->vpar[3] = par1;
3583 break;
3584 case '?':
3585 p[0]++;
3586 isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
3587 info);
3588 isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
3589 info);
3590 isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
3591 info);
3592 isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
3593 info);
3594 isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
3595 info);
3596 break;
3597 default:
3598 PARSE_ERROR1;
3600 break;
3601 default:
3602 PARSE_ERROR1;
3604 break;
3605 case 6:
3606 /* AT+VTX - Start sending */
3607 if (!m->vpar[0])
3608 PARSE_ERROR1;
3609 if (info->online != 1) {
3610 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3611 return 1;
3613 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3614 if (!info->dtmf_state) {
3615 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3616 PARSE_ERROR1;
3618 if (m->vpar[3] < 5) {
3619 info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
3620 if (!info->adpcms) {
3621 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3622 PARSE_ERROR1;
3625 #ifdef ISDN_DEBUG_AT
3626 printk(KERN_DEBUG "AT: +VTX\n");
3627 #endif
3628 m->lastDLE = 0;
3629 info->vonline |= 2;
3630 isdn_tty_modem_result(RESULT_CONNECT, info);
3631 return 0;
3632 break;
3633 case 7:
3634 /* AT+VDD - DTMF detection */
3635 switch (*p[0]) {
3636 case '?':
3637 p[0]++;
3638 sprintf(rs, "\r\n<%d>,<%d>",
3639 m->vpar[4],
3640 m->vpar[5]);
3641 isdn_tty_at_cout(rs, info);
3642 break;
3643 case '=':
3644 p[0]++;
3645 if ((*p[0]>='0') && (*p[0]<='9')) {
3646 if (info->online != 1)
3647 PARSE_ERROR1;
3648 par1 = isdn_getnum(p);
3649 if ((par1 < 0) || (par1 > 15))
3650 PARSE_ERROR1;
3651 if (*p[0] != ',')
3652 PARSE_ERROR1;
3653 p[0]++;
3654 par2 = isdn_getnum(p);
3655 if ((par2 < 0) || (par2 > 255))
3656 PARSE_ERROR1;
3657 m->vpar[4] = par1;
3658 m->vpar[5] = par2;
3659 cmd.driver = info->isdn_driver;
3660 cmd.command = ISDN_CMD_AUDIO;
3661 cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
3662 cmd.parm.num[0] = par1;
3663 cmd.parm.num[1] = par2;
3664 isdn_command(&cmd);
3665 break;
3666 } else
3667 if (*p[0] == '?') {
3668 p[0]++;
3669 isdn_tty_at_cout("\r\n<0-15>,<0-255>",
3670 info);
3671 break;
3672 } else
3673 PARSE_ERROR1;
3674 break;
3675 default:
3676 PARSE_ERROR1;
3678 break;
3679 default:
3680 PARSE_ERROR1;
3682 return 0;
3684 #endif /* CONFIG_ISDN_AUDIO */
3687 * Parse and perform an AT-command-line.
3689 static void
3690 isdn_tty_parse_at(modem_info * info)
3692 atemu *m = &info->emu;
3693 char *p;
3694 char ds[40];
3696 #ifdef ISDN_DEBUG_AT
3697 printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
3698 #endif
3699 for (p = &m->mdmcmd[2]; *p;) {
3700 switch (*p) {
3701 case ' ':
3702 p++;
3703 break;
3704 case 'A':
3705 /* A - Accept incoming call */
3706 p++;
3707 isdn_tty_cmd_ATA(info);
3708 return;
3709 break;
3710 case 'D':
3711 /* D - Dial */
3712 if (info->msr & UART_MSR_DCD)
3713 PARSE_ERROR;
3714 if (info->msr & UART_MSR_RI) {
3715 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3716 return;
3718 isdn_tty_getdial(++p, ds, sizeof ds);
3719 p += strlen(p);
3720 if (!strlen(m->msn))
3721 isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
3722 else if (strlen(ds))
3723 isdn_tty_dial(ds, info, m);
3724 else
3725 PARSE_ERROR;
3726 return;
3727 case 'E':
3728 /* E - Turn Echo on/off */
3729 p++;
3730 switch (isdn_getnum(&p)) {
3731 case 0:
3732 m->mdmreg[REG_ECHO] &= ~BIT_ECHO;
3733 break;
3734 case 1:
3735 m->mdmreg[REG_ECHO] |= BIT_ECHO;
3736 break;
3737 default:
3738 PARSE_ERROR;
3740 break;
3741 case 'H':
3742 /* H - On/Off-hook */
3743 p++;
3744 switch (*p) {
3745 case '0':
3746 p++;
3747 isdn_tty_on_hook(info);
3748 break;
3749 case '1':
3750 p++;
3751 isdn_tty_off_hook();
3752 break;
3753 default:
3754 isdn_tty_on_hook(info);
3755 break;
3757 break;
3758 case 'I':
3759 /* I - Information */
3760 p++;
3761 isdn_tty_at_cout("\r\nLinux ISDN", info);
3762 switch (*p) {
3763 case '0':
3764 case '1':
3765 p++;
3766 break;
3767 case '2':
3768 p++;
3769 isdn_tty_report(info);
3770 break;
3771 case '3':
3772 p++;
3773 sprintf(ds, "\r\n%d", info->emu.charge);
3774 isdn_tty_at_cout(ds, info);
3775 break;
3776 default:
3778 break;
3779 #ifdef DUMMY_HAYES_AT
3780 case 'L':
3781 case 'M':
3782 /* only for be compilant with common scripts */
3783 /* no function */
3784 p++;
3785 isdn_getnum(&p);
3786 break;
3787 #endif
3788 case 'O':
3789 /* O - Go online */
3790 p++;
3791 if (info->msr & UART_MSR_DCD)
3792 /* if B-Channel is up */
3793 isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT:RESULT_CONNECT64000, info);
3794 else
3795 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3796 return;
3797 case 'Q':
3798 /* Q - Turn Emulator messages on/off */
3799 p++;
3800 switch (isdn_getnum(&p)) {
3801 case 0:
3802 m->mdmreg[REG_RESP] |= BIT_RESP;
3803 break;
3804 case 1:
3805 m->mdmreg[REG_RESP] &= ~BIT_RESP;
3806 break;
3807 default:
3808 PARSE_ERROR;
3810 break;
3811 case 'S':
3812 /* S - Set/Get Register */
3813 p++;
3814 if (isdn_tty_cmd_ATS(&p, info))
3815 return;
3816 break;
3817 case 'V':
3818 /* V - Numeric or ASCII Emulator-messages */
3819 p++;
3820 switch (isdn_getnum(&p)) {
3821 case 0:
3822 m->mdmreg[REG_RESP] |= BIT_RESPNUM;
3823 break;
3824 case 1:
3825 m->mdmreg[REG_RESP] &= ~BIT_RESPNUM;
3826 break;
3827 default:
3828 PARSE_ERROR;
3830 break;
3831 case 'Z':
3832 /* Z - Load Registers from Profile */
3833 p++;
3834 if (info->msr & UART_MSR_DCD) {
3835 info->online = 0;
3836 isdn_tty_on_hook(info);
3838 isdn_tty_modem_reset_regs(info, 1);
3839 break;
3840 case '+':
3841 p++;
3842 switch (*p) {
3843 #ifdef CONFIG_ISDN_AUDIO
3844 case 'F':
3845 p++;
3846 if (isdn_tty_cmd_PLUSF(&p, info))
3847 return;
3848 break;
3849 case 'V':
3850 if ((!(m->mdmreg[REG_SI1] & 1)) ||
3851 (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
3852 PARSE_ERROR;
3853 p++;
3854 if (isdn_tty_cmd_PLUSV(&p, info))
3855 return;
3856 break;
3857 #endif /* CONFIG_ISDN_AUDIO */
3858 case 'S': /* SUSPEND */
3859 p++;
3860 isdn_tty_get_msnstr(ds, &p);
3861 isdn_tty_suspend(ds, info, m);
3862 break;
3863 case 'R': /* RESUME */
3864 p++;
3865 isdn_tty_get_msnstr(ds, &p);
3866 isdn_tty_resume(ds, info, m);
3867 break;
3868 case 'M': /* MESSAGE */
3869 p++;
3870 isdn_tty_send_msg(info, m, p);
3871 break;
3872 default:
3873 PARSE_ERROR;
3875 break;
3876 case '&':
3877 p++;
3878 if (isdn_tty_cmd_ATand(&p, info))
3879 return;
3880 break;
3881 default:
3882 PARSE_ERROR;
3885 #ifdef CONFIG_ISDN_AUDIO
3886 if (!info->vonline)
3887 #endif
3888 isdn_tty_modem_result(RESULT_OK, info);
3891 /* Need own toupper() because standard-toupper is not available
3892 * within modules.
3894 #define my_toupper(c) (((c>='a')&&(c<='z'))?(c&0xdf):c)
3897 * Perform line-editing of AT-commands
3899 * Parameters:
3900 * p inputbuffer
3901 * count length of buffer
3902 * channel index to line (minor-device)
3903 * user flag: buffer is in userspace
3905 static int
3906 isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
3908 atemu *m = &info->emu;
3909 int total = 0;
3910 u_char c;
3911 char eb[2];
3912 int cnt;
3914 for (cnt = count; cnt > 0; p++, cnt--) {
3915 if (user)
3916 get_user(c, p);
3917 else
3918 c = *p;
3919 total++;
3920 if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
3921 /* Separator (CR or LF) */
3922 m->mdmcmd[m->mdmcmdl] = 0;
3923 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3924 eb[0] = c;
3925 eb[1] = 0;
3926 isdn_tty_at_cout(eb, info);
3928 if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
3929 isdn_tty_parse_at(info);
3930 m->mdmcmdl = 0;
3931 continue;
3933 if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
3934 /* Backspace-Function */
3935 if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
3936 if (m->mdmcmdl)
3937 m->mdmcmdl--;
3938 if (m->mdmreg[REG_ECHO] & BIT_ECHO)
3939 isdn_tty_at_cout("\b", info);
3941 continue;
3943 if (cmdchar(c)) {
3944 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3945 eb[0] = c;
3946 eb[1] = 0;
3947 isdn_tty_at_cout(eb, info);
3949 if (m->mdmcmdl < 255) {
3950 c = my_toupper(c);
3951 switch (m->mdmcmdl) {
3952 case 1:
3953 if (c == 'T') {
3954 m->mdmcmd[m->mdmcmdl] = c;
3955 m->mdmcmd[++m->mdmcmdl] = 0;
3956 break;
3957 } else
3958 m->mdmcmdl = 0;
3959 /* Fall through, check for 'A' */
3960 case 0:
3961 if (c == 'A') {
3962 m->mdmcmd[m->mdmcmdl] = c;
3963 m->mdmcmd[++m->mdmcmdl] = 0;
3965 break;
3966 default:
3967 m->mdmcmd[m->mdmcmdl] = c;
3968 m->mdmcmd[++m->mdmcmdl] = 0;
3973 return total;
3977 * Switch all modem-channels who are online and got a valid
3978 * escape-sequence 1.5 seconds ago, to command-mode.
3979 * This function is called every second via timer-interrupt from within
3980 * timer-dispatcher isdn_timer_function()
3982 void
3983 isdn_tty_modem_escape(void)
3985 int ton = 0;
3986 int i;
3987 int midx;
3989 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
3990 if (USG_MODEM(dev->usage[i]))
3991 if ((midx = dev->m_idx[i]) >= 0) {
3992 modem_info *info = &dev->mdm.info[midx];
3993 if (info->online) {
3994 ton = 1;
3995 if ((info->emu.pluscount == 3) &&
3996 ((jiffies - info->emu.lastplus) > PLUSWAIT2)) {
3997 info->emu.pluscount = 0;
3998 info->online = 0;
3999 isdn_tty_modem_result(RESULT_OK, info);
4003 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
4007 * Put a RING-message to all modem-channels who have the RI-bit set.
4008 * This function is called every second via timer-interrupt from within
4009 * timer-dispatcher isdn_timer_function()
4011 void
4012 isdn_tty_modem_ring(void)
4014 int ton = 0;
4015 int i;
4017 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
4018 modem_info *info = &dev->mdm.info[i];
4019 if (info->msr & UART_MSR_RI) {
4020 ton = 1;
4021 isdn_tty_modem_result(RESULT_RING, info);
4024 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
4028 * For all online tty's, try sending data to
4029 * the lower levels.
4031 void
4032 isdn_tty_modem_xmit(void)
4034 int ton = 1;
4035 int i;
4037 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
4038 modem_info *info = &dev->mdm.info[i];
4039 if (info->online) {
4040 ton = 1;
4041 isdn_tty_senddown(info);
4042 isdn_tty_tint(info);
4045 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
4049 * Check all channels if we have a 'no carrier' timeout.
4050 * Timeout value is set by Register S7.
4052 void
4053 isdn_tty_carrier_timeout(void)
4055 int ton = 0;
4056 int i;
4058 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
4059 modem_info *info = &dev->mdm.info[i];
4060 if (info->dialing) {
4061 if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
4062 info->dialing = 0;
4063 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
4064 isdn_tty_modem_hup(info, 1);
4066 else
4067 ton = 1;
4070 isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);