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