|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.