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