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