Annotation of os2sdk/demos/apps/terminal/modem.c, revision 1.1.1.1

1.1       root        1: /***   modem.c
                      2:  *
                      3:  * TITLE 
                      4:  *
                      5:  *     modem.c
                      6:  *     Copyright (C) Microsoft Corporation 1987
                      7:  *     March 1987
                      8:  *
                      9:  * DESCRIPTION
                     10:  *
                     11:  *     This module contains routines that support Hayes compatible modem. 
                     12:  *
                     13:  ***/
                     14: 
                     15: #include       <stdio.h>       
                     16: #include       <doscalls.h>
                     17: #include       <subcalls.h>
                     18: #include       <malloc.h>
                     19: #include       <string.h>
                     20: #include       <memory.h>
                     21: #include       <conio.h>
                     22: #include       "term.h"
                     23: 
                     24: #define min(a,b) (((a)<(b)) ? (a):(b)) /* This is pulled out of the old */
                     25:                                        /* v2tov3.h (c v2.0) header file */
                     26: 
                     27: extern char    *ErrMsg[]; 
                     28: extern unsigned FileHndl;
                     29: 
                     30: make_dial_cmd(char *, int);
                     31: void flush_ques(int);
                     32: void clr_com_error(void);
                     33: void com_clr_flush(void);
                     34: 
                     35: static char Init[]    = {'A', 'T', 'V', '0', 0x0d};
                     36: static char Attn[]    = {'A', 'T', 0x0d};
                     37: static char Esc[]     = {'+', '+', '+'};
                     38: static char OnHook[]  = {'A', 'T', 'H', '0', 0X0d};
                     39: static char OffHook[] = {'A', 'T', 'H', '1', 0x0d};
                     40: static char Reset[]   = {'A', 'T', 'Z', 0x0d};
                     41: 
                     42: struct s_Cmd{
                     43:         char *pCmd;
                     44:         int   CmdLen;
                     45: } Cmds[] = {
                     46:     {Init, sizeof(Init)},              /* Initialize modem */
                     47:     {Attn, sizeof(Attn)},              /* Attention cmd */
                     48:     {Esc, sizeof(Esc)},                /* Modem escape sequence*/
                     49:     {OnHook, sizeof(OnHook)},          /* Put phone on hook */
                     50:     {OffHook, sizeof(OffHook)},        /* Take phone off hook */
                     51:     {Reset, sizeof(Reset)}             /* Reset command */
                     52:   };
                     53: 
                     54: 
                     55: 
                     56: /***   make_modem_conn - make modem connection
                     57:  *
                     58:  *     This routine tries to setup the modem connection, retrying if 
                     59:  *     appropriate.
                     60:  *
                     61:  *     make_modem_conn()
                     62:  *
                     63:  *     ENTRY
                     64:  *
                     65:  *     EXIT
                     66:  *             TRUE if modem connection was made 
                     67:  *             FALSE if modem connection did not go through
                     68:  *
                     69:  *     WARNING
                     70:  *
                     71:  *     EFFECTS
                     72:  *
                     73:  ***/
                     74: 
                     75: make_modem_conn()
                     76: {
                     77:        unsigned        NumBytes,       /* number of bytes to be written    */
                     78:                        RetCode,        /* return code from system calls    */
                     79:                        Result = FALSE; /* to be returned by this routine */
                     80:        char            OutBuffer,
                     81:                        ModemRetry = TRUE,   /* retry for modem connection   */
                     82:                        NumRetries = 0;      /* no. times connection retried */
                     83: 
                     84:        printf("trying modem connection...\n");
                     85: 
                     86:        while (ModemRetry)
                     87:           switch (setup_modem_conn()) {
                     88:            case MS_CONNECT    :
                     89:            case MS_CONNECT1200: 
                     90:              Result = TRUE;
                     91:              ModemRetry = FALSE;
                     92:              OutBuffer = '\r';
                     93:              if ((RetCode = DOSWRITE(FileHndl, &OutBuffer, 1, 
                     94:                                       &NumBytes)) != 0)
                     95:                error(ERR_DOSWRITE, RetCode);
                     96:               break;
                     97:            case MS_NOCARRIER  :
                     98:            case MS_NODIALTONE :
                     99:              if (++NumRetries > NUM_RETRY) {
                    100:                printf("modem connection failed\n");
                    101:                ModemRetry = FALSE;
                    102:              }
                    103:              else
                    104:                printf("modem connection failed; retrying...\n");
                    105:              break;
                    106:            case MS_NOREPLY    :
                    107:             case MS_ERROR      : 
                    108:            case OT_FAILURE    :                /* OTher failure */
                    109:             case MS_BUSY       : 
                    110:            default            : 
                    111:              ModemRetry = FALSE;
                    112:               printf("modem connection failed\n");
                    113:               break;
                    114:          }             /* switch (setup_modem_conn()) */
                    115: 
                    116:        return(Result);
                    117: 
                    118: }
                    119: 
                    120: 
                    121: 
                    122: 
                    123: /***   setup_modem_conn - setup modem connection
                    124:  *
                    125:  *     This is the helper routine for the make_modem_conn(). It initialises
                    126:  *     the modem connection and sends out the dial command to the modem.
                    127:  *
                    128:  *     setup_modem_conn()
                    129:  *
                    130:  *     ENTRY
                    131:  *
                    132:  *     EXIT
                    133:  *             returns one of the following: MS_CONNECT MS_CONNECT1200 
                    134:  *             MS_NOCARRIER MS_NODIALTONE MS_NOREPLY MS_ERROR MS_BUSY 
                    135:  *             OT_FAILURE
                    136:  *
                    137:  *     WARNING
                    138:  *
                    139:  *     EFFECTS
                    140:  *
                    141:  ***/
                    142: 
                    143: int    setup_modem_conn()
                    144: {
                    145:        int             Result = OT_FAILURE;
                    146: 
                    147:        /* initialise modem connection */
                    148:        if (!(send_modem_cmd(MC_INIT)))
                    149:          return(Result);
                    150:        if (get_modem_reply() != MS_OK)
                    151:          return(Result);
                    152:        DOSSLEEP((long) 100);
                    153: 
                    154:        /* write AT string to the modem. This will cause the modem to
                    155:         * determine the communications rate of the terminal as well
                    156:         * as its parity setting.
                    157:         */
                    158:        if (!(send_modem_cmd(MC_ATTN)))
                    159:          return(Result);
                    160:        if (get_modem_reply() != MS_OK)
                    161:          return(Result);
                    162:        DOSSLEEP((long) 100);
                    163: 
                    164:        /* send DIAL command to the modem */
                    165:        if (!(send_modem_cmd(MC_DIAL)))
                    166:          return(Result);
                    167: 
                    168:        return(get_modem_reply());
                    169: };
                    170: 
                    171: 
                    172: 
                    173: 
                    174: /***   send_modem_cmd - send a command to modem
                    175:  *
                    176:  *     This routine sends a command to the modem and ensures that the echo 
                    177:  *     from the modem matches the input command.
                    178:  *
                    179:  *     send_modem_cmd(CmdType)
                    180:  *
                    181:  *     ENTRY
                    182:  *             CmdType - type of modem command: MC_INIT MC_ATTN MC_ESC 
                    183:  *                             MC_ONHOOK MC_OFFHOOK MC_RESET MC_DIAL
                    184:  *
                    185:  *     EXIT
                    186:  *             TRUE if command was sent succesfully
                    187:  *             FALSE if command failed
                    188:  *
                    189:  *     WARNING
                    190:  *
                    191:  *     EFFECTS
                    192:  *
                    193:  ***/
                    194: 
                    195: send_modem_cmd(CmdType)
                    196: int    CmdType;                /* The command to send */
                    197: {
                    198:        int             Result = TRUE,
                    199:                        ReadCnt,
                    200:                        WriteCnt,
                    201:                        CmdLen,
                    202:                        RetCode;
                    203:        char            Buf[80],
                    204:                        Cmd[80],
                    205:                        *pDst,
                    206:                        *pCmd;
                    207:        
                    208: 
                    209:        /* clear COM error and flush transmit/receive queues */
                    210:        com_clr_flush();
                    211: 
                    212:         if (CmdType == MC_INIT) {
                    213:          send_modem_cmd(MC_RESET);     /* modem command: ATZ */
                    214:          /* clear COM error and flush transmit/receive queues */
                    215:          com_clr_flush();
                    216:        };
                    217: 
                    218:        /* set pCmd -> command string; CmdLen = length of command string */
                    219:        if (CmdType == MC_DIAL) {
                    220:           CmdLen = make_dial_cmd(Cmd, sizeof(Cmd));
                    221:           pCmd = Cmd;
                    222:         }
                    223:        else {
                    224:           pCmd = Cmds[CmdType].pCmd;
                    225:           CmdLen = Cmds[CmdType].CmdLen;
                    226:         };
                    227: 
                    228:        /* write the command out to the modem */
                    229:        if (((RetCode = DOSWRITE(FileHndl, pCmd, CmdLen, &WriteCnt)) != 0)
                    230:            || (WriteCnt != CmdLen))
                    231:          return(FALSE);
                    232: 
                    233:         /* wait for the echo & wait for the command to clear */
                    234:         DOSSLEEP((long) 250); 
                    235:         if (CmdType == MC_DIAL || CmdType == MC_RESET)
                    236:           DOSSLEEP((long) 750); 
                    237: 
                    238:        /* read back the echo from the modem & check if it matches the input */
                    239:        RetCode = 
                    240:           DOSREAD(FileHndl, Buf, min(WriteCnt, sizeof(Buf)), &ReadCnt);
                    241:        if ((RetCode != 0) || (ReadCnt != WriteCnt))
                    242:          Result = FALSE;
                    243:         else {
                    244:           pDst = Buf;
                    245:           while (--ReadCnt >= 0) {
                    246:             if (*pDst++ != *pCmd++) {
                    247:              printf("send_modem_cmd: error in echo of modem input\n");
                    248:               Result = FALSE;
                    249:               break;
                    250:             }
                    251:           } /* while (--ReadCnt >= 0) */
                    252:         } 
                    253: 
                    254:        return(Result);
                    255: }
                    256: 
                    257: 
                    258: 
                    259: 
                    260: /***   make_dial_cmd - create a modem command for dialing 
                    261:  *
                    262:  *     builds the dial command string and returns its length in bytes
                    263:  *
                    264:  *     make_dial_cmd(pBuf, BufLen)
                    265:  *
                    266:  *     ENTRY
                    267:  *             pBuf - ptr to buffer
                    268:  *             BufLen - length of buffer in bytes
                    269:  *
                    270:  *     EXIT
                    271:  *             pBuf -> dial command string
                    272:  *             make_dial_cmd = length of dial command string in bytes 
                    273:  *
                    274:  *     WARNING
                    275:  *
                    276:  *     EFFECTS
                    277:  *
                    278:  ***/
                    279: 
                    280: make_dial_cmd(pBuf, BufLen)
                    281: char   *pBuf;
                    282: int    BufLen;
                    283: {
                    284:        char            *pSrc,
                    285:                        *pDst,
                    286:                        Ch,
                    287:                        Cmd[80],        /* allocate a huge command buffer */
                    288:                        *bin_to_dec();
                    289:        int             Len;
                    290:        structModemOptions sModemOptions;               /* modem options */
                    291: 
                    292:        get_modem_options(&sModemOptions);
                    293:        pDst = Cmd;
                    294:        *pDst++ = 'A';          /* get Modem's attention */
                    295:        *pDst++ = 'T';
                    296:        *pDst++ = 'S';          /* set R6 for wait for dial tone */
                    297:        *pDst++ = '6';
                    298:        *pDst++ = '=';
                    299:        pDst = bin_to_dec(pDst, sModemOptions.iWaitTone);
                    300:        *pDst++ = B_PAUSE;
                    301:        *pDst++ = 'S';          /* set R7 for wait for carrier time */
                    302:        *pDst++ = '7';
                    303:        *pDst++ = '=';
                    304:        pDst = bin_to_dec(pDst, sModemOptions.iWaitCarrier); 
                    305:        *pDst++ = B_PAUSE;
                    306:        *pDst++ = 'D';
                    307:        *pDst++ = (sModemOptions.chDialType == PULSE) ? 'P' : 'T';
                    308:        pSrc = sModemOptions.pPhoneNumber;
                    309:        while (Ch = *pSrc++) 
                    310:           if ((Ch >= '0' && Ch <= '9') || (Ch == ','))
                    311:             *pDst++ = Ch;
                    312:        *pDst++ = 0x0d;
                    313:        *pDst = 0;
                    314: 
                    315:        /* copy the command string into caller's buffer */
                    316:        pSrc = Cmd;
                    317:        pDst = pBuf;
                    318:        for (Len = 0; Len <= BufLen; ++Len)
                    319:           if (*pSrc==0)
                    320:             break;
                    321:           else
                    322:             *pDst++ = *pSrc++;
                    323:        return(Len);
                    324: }
                    325: 
                    326: 
                    327: 
                    328: 
                    329: /***   bin_to_dec - convert a binary number to ASCII decimal 
                    330:  *
                    331:  *     bin_to_dec(pDst, i)
                    332:  *
                    333:  *     ENTRY
                    334:  *             pDst -> buffer to place the ASCII decimal
                    335:  *             i = integer to be converted to ASCII decimal
                    336:  *
                    337:  *     EXIT
                    338:  *             ASCII decimal placed in the buffer pointed by pDst
                    339:  *             bin_to_dec -> byte next to ASCII decimal in the buffer
                    340:  *
                    341:  *     WARNING
                    342:  *
                    343:  *     EFFECTS
                    344:  *
                    345:  ***/
                    346: 
                    347: char *bin_to_dec(pDst, i)
                    348: char   *pDst;
                    349: int    i;
                    350: {
                    351:        if (i > 10)
                    352:           pDst = bin_to_dec (pDst, i/10);
                    353:        *pDst++ = '0' + (i % 10);
                    354:        return(pDst);
                    355: }
                    356: 
                    357: 
                    358: 
                    359: 
                    360: /***   get_modem_reply - get reply from modem
                    361:  *
                    362:  *     get_modem_reply()
                    363:  *
                    364:  *     ENTRY
                    365:  *
                    366:  *     EXIT
                    367:  *             get_modem_reply = MS_CONNECT MS_CONNECT1200 MS_NOCARRIER 
                    368:  *                               MS_NODIALTONE MS_NOREPLY MS_ERROR MS_BUSY
                    369:  *
                    370:  *     WARNING
                    371:  *
                    372:  *     EFFECTS
                    373:  *
                    374:  ***/
                    375: 
                    376: int get_modem_reply()
                    377: {
                    378:        char            Ch;
                    379:        int             Cnt,
                    380:                        Result,
                    381:                        RetCode;
                    382: 
                    383:        do              /* skip CR, LF and get resultcode */
                    384:          if ((RetCode = DOSREAD(FileHndl, &Ch, 1, &Cnt)) != 0) 
                    385:             Error(ERR_DOSREAD, RetCode);
                    386:         while ((Cnt == 1) && ((Ch == 0x0d) || (Ch == 0x0a)));
                    387: 
                    388:        switch(Cnt) {
                    389:           case 0:  Result = MS_NOREPLY;
                    390:                   break;
                    391:           case 1:  if ((Ch >= '0') && (Ch <= '7'))
                    392:                      Result = Ch - '0';
                    393:                    else
                    394:                      Result = MS_ERROR;
                    395:                    break;
                    396:           default: Result = MS_ERROR;
                    397:                    break;
                    398:         }
                    399: 
                    400:        return(Result);
                    401: }
                    402: 
                    403: 
                    404: 
                    405: 
                    406: /***   discon_modem - disconnect the modem 
                    407:  *
                    408:  *     discon_modem()
                    409:  *
                    410:  *     ENTRY
                    411:  *
                    412:  *     EXIT
                    413:  *             modem disconnected
                    414:  *
                    415:  *     WARNING
                    416:  *
                    417:  *     EFFECTS
                    418:  *
                    419:  ***/
                    420: 
                    421: void discon_modem()
                    422: {
                    423:        /* Wait for the last command to clear, then be quiet for 1.5 seconds */
                    424:        DOSSLEEP((long) 1000);          /* wait 1. second */
                    425:        flush_ques(FLUSHOUTPUT);        /* flush the transmit que */
                    426:        DOSSLEEP((long) 1500);          /* wait 1.5 seconds */
                    427: 
                    428:        send_modem_cmd(MC_ESC);         /* put modem in command mode */
                    429:        DOSSLEEP((long) 2000);          /* wait 2 seconds */
                    430: 
                    431:        send_modem_cmd(MC_ONHOOK);      /* place phone back on hook */
                    432:        DOSSLEEP((long) 200);           /* wait for command to clear*/
                    433: }
                    434: 
                    435: 
                    436: 
                    437: 
                    438: /***   com_clr_flush - clear COM error and flush transmit/receive queues
                    439:  *
                    440:  *     com_clr_flush()
                    441:  *
                    442:  *     ENTRY
                    443:  *
                    444:  *     EXIT
                    445:  *             com error cleared
                    446:  *             transmit and receive queues of com port flushed out
                    447:  *
                    448:  *     WARNING
                    449:  *
                    450:  *     EFFECTS
                    451:  *
                    452:  ***/
                    453: 
                    454: void com_clr_flush()
                    455: {
                    456:        /* retrieve and clear the com error information */
                    457:        clr_com_error();
                    458:        /* flush transmit and receive queues */
                    459:        flush_ques(FLUSHINPUT);
                    460:        flush_ques(FLUSHOUTPUT);
                    461: }
                    462: 
                    463: 
                    464: 
                    465: 
                    466: /***   flush_ques - flush COM transmit/receive queue 
                    467:  *
                    468:  *     flush_ques(FuncId)
                    469:  *
                    470:  *     ENTRY
                    471:  *             FuncId - set to one of: FLUSHINPUT FLUSHOUTPUT
                    472:  *
                    473:  *     EXIT
                    474:  *             transmit or receive queue of com port flushed
                    475:  *
                    476:  *     WARNING
                    477:  *
                    478:  *     EFFECTS
                    479:  *
                    480:  ***/
                    481: 
                    482: void flush_ques(FuncId)
                    483: int    FuncId;                 
                    484: {      
                    485:        char    FlushData,      /* data returned by flush IOCTL function */
                    486:                FlushParm = FLUSH_CMDINFO; /* param to flush IOCTL function */
                    487:        int     RetCode;
                    488:        
                    489:        /* flush transmit/receive queue */
                    490:        if ((RetCode = DOSDEVIOCTL(&FlushData, &FlushParm, 
                    491:                                   FuncId, GENERIC, FileHndl)) != 0) 
                    492:          Error(ERR_IOCTLFLUSHQUE, RetCode);
                    493: }
                    494: 
                    495: 
                    496: 
                    497: 
                    498: /***   clr_com_error - retrieve and clear COM error information
                    499:  *
                    500:  *     clr_com_error()
                    501:  *
                    502:  *     ENTRY
                    503:  *
                    504:  *     EXIT
                    505:  *             com error cleared
                    506:  *
                    507:  *     WARNING
                    508:  *
                    509:  *     EFFECTS
                    510:  *
                    511:  ***/
                    512: 
                    513: void clr_com_error()
                    514: 
                    515: {
                    516:        int     ComError,
                    517:                RetCode;
                    518: 
                    519:        if ((RetCode = DOSDEVIOCTL((char *) &ComError, 0L, GETCOMERROR, 
                    520:                                    SERIAL, FileHndl)) != 0)
                    521:          Error(ERR_IOCTLGETCOMERROR, RetCode);
                    522: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.