home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: OtherApp / OtherApp.zip / PSFAX2.ZIP / psfax2 / modem.c < prev    next >
C/C++ Source or Header  |  1992-10-16  |  16KB  |  489 lines

  1. /* modem.c */
  2. /*---------------------------------------------------------------------------*/
  3. /* This file is part of PSFax/2.                                             */
  4. /*                                                                           */
  5. /* Written By: Gary L. Hennigan                                              */
  6. /*                                                                           */
  7. /* This code can modified as much as you like provided you follow the        */
  8. /* guidelines as described in the file install.doc which you should have     */
  9. /* received with this file. If you did not please notify the author for a    */
  10. /* copy of this file via Internet email. The address is:             */
  11. /*            ghenniga@NMSU.Edu                     */
  12. /*---------------------------------------------------------------------------*/
  13.  
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #include "psfax2.h"
  19.  
  20. #define DevIOCtl DosDevIOCtl32
  21.  
  22. /**Global variables defined in psfax2.c **/
  23. extern char cGlobResp[];
  24.  
  25. ULONG ulTemp;           /* Used by various functions in modem.c */
  26. USHORT usTemp;
  27.  
  28. void vFlushIO( HFILE );
  29. unsigned char swap_bits( unsigned char );
  30. USHORT usSetTTYTime( HFILE, DCBINFO *, int );
  31. int iGetResp( HFILE, DCBINFO *, char *, int, int, char * );
  32.  
  33. /****************************************************************************/
  34. /*************************Used for simplifying*******************************/
  35. /*************************IOCtl function calls*******************************/
  36. /****************************************************************************/
  37. USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,
  38.              USHORT usFunction, USHORT usCategory, HFILE hDevice)
  39. {
  40.    ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
  41.    return (USHORT)DosDevIOCtl(hDevice, usCategory, usFunction,
  42.                   pParms, cbParms, &ulParmLengthInOut,
  43.                   pData, cbData, &ulDataLengthInOut);
  44. }
  45. /****************************************************************************/
  46. /***************************Open the COM Port********************************/
  47. /****************************************************************************/
  48. ULONG ulOpenPort(char *cPort, HFILE *hTTY)
  49. {
  50.  
  51.    return DosOpen(cPort, hTTY, &ulTemp, 0L, 0, FILE_OPEN,
  52.           OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
  53.           OPEN_FLAGS_FAIL_ON_ERROR, 0L);
  54. }
  55. /****************************************************************************/
  56. /**********************Get the current port settings*************************/
  57. /****************************************************************************/
  58. int iPortGetSet(HFILE hTTY, DCBINFO *dcbCom)
  59. {
  60.    usTemp = DevIOCtl(dcbCom,sizeof(*dcbCom),NULL,0,
  61.              ASYNC_GETDCBINFO, IOCTL_ASYNC, hTTY);
  62.  
  63.    if(usTemp != 0)
  64.       return 1;
  65.    
  66.    return 0;
  67. }
  68. /****************************************************************************/
  69. /**************************Initialize the Port*******************************/
  70. /****************************************************************************/
  71. int iPortInit(HFILE hTTY, DCBINFO *dcbCom)
  72. {
  73.    MODEMSTATUS ms;
  74.    UINT data;
  75. /*-------------------------------End Declarations---------------------------*/
  76.  
  77. /**Set XON/XOFF flow control. **/   
  78.    dcbCom->fbCtlHndShake = MODE_DTR_CONTROL;
  79.    dcbCom->fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
  80.                   MODE_RTS_CONTROL | MODE_RTS_HANDSHAKE);
  81.    dcbCom->fbFlowReplace |= (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
  82.                  MODE_RTS_CONTROL);
  83.    ms.fbModemOn = RTS_ON;
  84.    ms.fbModemOff = 255;
  85.    
  86.    usTemp = DevIOCtl(NULL,0,dcbCom,sizeof(*dcbCom),ASYNC_SETDCBINFO,
  87.              IOCTL_ASYNC, hTTY);
  88.    if(usTemp != 0)
  89.       return -1;
  90.    
  91.    usTemp = DevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  92.              ASYNC_SETMODEMCTRL,IOCTL_ASYNC,hTTY);
  93.    if(usTemp != 0)
  94.       return -1;
  95.  
  96.    return 0;
  97. }
  98. /****************************************************************************/
  99. /**************************Initialize the Modem******************************/
  100. /****************************************************************************/
  101. int iModemInit(HFILE hTTY, DCBINFO *dcbCom)
  102. {
  103.    char cBuff[256];
  104.    int iCnt=0;
  105. /*-------------------------------End Declarations---------------------------*/
  106.  
  107.    strcpy(cBuff,"ATZ\r");       /* Use the default profile of the modem. */
  108.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  109.    if(iGetResp(hTTY, dcbCom, cBuff, 10*sizeof(char), 3, NULL) <= 0 ||
  110.       !strstr(cBuff,"OK\r") )
  111.       return 1;
  112.  
  113.    strcpy(cBuff,"AT&K4V0Q0E0L2M1W2S0=0S2=255S12=255 +FCLASS=2\r");
  114.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  115.    if(iGetResp(hTTY, dcbCom, cBuff, strlen(cBuff)+2*sizeof(char), 
  116.            2, NULL) <= 0 || !strstr(cBuff,"0\r"))
  117.       return 1;
  118.  
  119.    strcpy(cBuff,"ATS7=120 +FCR=1\r");
  120.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
  121.    if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
  122.       !strstr(cBuff,"0\r"))
  123.       return 1;
  124.  
  125.    strcpy(cBuff,"AT+FDCC=1,3\r");
  126.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
  127.    if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
  128.       !strstr(cBuff,"0\r"))
  129.       return 1;
  130.  
  131.    strcpy(cBuff,"AT+FBOR=0\r");
  132.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
  133.    if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
  134.       !strstr(cBuff,"0\r"))
  135.       return 1;
  136.  
  137. /**Flush all the I/O, set the timeout for reads, and see if the modem **/
  138. /**is responding properly.                           **/
  139.    vFlushIO(hTTY);
  140.    usSetTTYTime(hTTY, dcbCom, 2);
  141.  
  142.    strcpy(cBuff, "AT\r");
  143.    do
  144.    {
  145.       DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  146.       iCnt++;
  147.       DosRead(hTTY, cBuff, 2, &ulTemp);
  148.    }
  149.    while(ulTemp == 0 && iCnt <= MAXTIMEOUTS);
  150.  
  151.    if(ulTemp == 0 && iCnt >= MAXTIMEOUTS)return 1;
  152.    
  153.    if(strncmp(cBuff,"0\r",2) != 0)
  154.    {
  155.       printf("Bad modem response while attempting to sync!\n");
  156.       return 1;
  157.    }
  158.  
  159.    return 0;
  160. }
  161. /****************************************************************************/
  162. /****************************Dial the Phone**********************************/
  163. /****************************************************************************/
  164. int iModemDial( HFILE hTTY, char *cPhoneNum, DCBINFO *dcbCom, int iWait )
  165. {
  166.    int iRedial;
  167.    char cBuff[256];
  168. /*-------------------------------End Declarations---------------------------*/
  169.  
  170.    strcpy(cBuff,"ATD");
  171.    strcat(cBuff,cPhoneNum);
  172.    strcat(cBuff,"\r");
  173.  
  174.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
  175.    if(iGetResp(hTTY, dcbCom, cBuff, 2, iWait, NULL) <= 0)
  176.    {
  177.       cBuff[0] = 0x1b;
  178.       cBuff[1] = 0x00;
  179.       DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(2);
  180.       vFlushIO(hTTY);
  181.       return DIAL_NOANSWER;
  182.    }
  183.  
  184.    if( cBuff[0] )
  185.    {
  186.       switch(cBuff[0])
  187.       {
  188.          case '3':
  189.         iRedial = DIAL_NOCARRIER;
  190.         vFlushIO(hTTY);
  191.         return iRedial;
  192.  
  193.      case '6':
  194.         iRedial = DIAL_NODIALTONE;
  195.         vFlushIO(hTTY);
  196.         return iRedial;
  197.  
  198.      case '7':
  199.         iRedial = DIAL_BUSY;
  200.         vFlushIO(hTTY);
  201.         return iRedial;
  202.  
  203.      case '8':
  204.         iRedial = DIAL_NOANSWER;
  205.         vFlushIO(hTTY);
  206.         return iRedial;
  207.         
  208.      default:
  209.         iRedial = 0;
  210.         break;
  211.       }
  212.    }
  213.    else
  214.    {
  215.       vFlushIO(hTTY);
  216.       return DIAL_NOANSWER;
  217.    }
  218.    
  219. /**Make sure the remote responds with a connection indication. **/
  220.    if(iGetResp(hTTY, dcbCom, &cBuff[2], 8, -20, "+FCON\r") <= 0)
  221.    {
  222.       printf("Incorrect response \"%s\" received...\n",cBuff);
  223.       vFlushIO(hTTY);
  224.       return DIAL_UNKNOWN;
  225.    }
  226.    else
  227.       strcpy(cGlobResp,cBuff);
  228.    
  229.    puts("Fax connection established!");
  230.    return iRedial;
  231. }
  232. /****************************************************************************/
  233. /*******************Initialize the fax-fax connection************************/
  234. /****************************************************************************/
  235. int iFaxInit(HFILE hTTY, DCBINFO *dcbCom, int df, int vr, int wd, int ln)
  236. {
  237.    char cBuff[256];
  238. /*-------------------------------End Declarations---------------------------*/
  239.  
  240. /**Make sure the remote responded correctly. **/
  241.    if(iGetResp(hTTY, dcbCom, cBuff, 50, -15, "0\r") <= 0)
  242.    {
  243.       puts("Remote fax is not responding....");
  244.       return 1;
  245.    }
  246.  
  247. /**Set transmission parameters. **/
  248.    sprintf(cBuff,"AT+FDT=%d,%d,%d,%d\r", df, vr, wd, ln);
  249.    vFlushIO(hTTY);
  250.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
  251.  
  252. /**Make sure the remote responds with a CONNECT. **/
  253.    if(iGetResp(hTTY, dcbCom, cBuff, 50, -15, "1\r") <= 0)
  254.    {
  255.       puts("Remote fax is not responding....");
  256.       return 1;
  257.    }
  258.    vFlushIO(hTTY);
  259.  
  260.    return 0;
  261. }
  262. /****************************************************************************/
  263. /*********************Send a page via the Fax/Modem**************************/
  264. /****************************************************************************/
  265. int iFaxSendPage(HFILE hTTY, DCBINFO *dcbCom, FILE *fStream, int iLast)
  266. {
  267.    unsigned char cBuff[SENDCHUNK], cBuff2[2*SENDCHUNK];
  268.    int iNumRead, iNumWrite, i1, iPPRCode;
  269. /*-------------------------------End Declarations---------------------------*/
  270.  
  271.    iNumRead = fread(cBuff, sizeof(char), SENDCHUNK, fStream);
  272.    usSetTTYTime(hTTY, dcbCom, -15);
  273.  
  274.    while(iNumRead > 0)
  275.    {
  276.       iNumWrite = 0;
  277.  
  278. /**   Swap the bits and pad DLE characters. **/
  279.       for(i1=0; i1 < iNumRead; i1++)
  280.       {
  281.      cBuff2[iNumWrite] = swap_bits(cBuff[i1]);
  282.      if(cBuff2[iNumWrite++] == DLE)
  283.         cBuff2[iNumWrite++] = DLE;
  284.       }
  285.  
  286. /**   Write the stuff out to the modem. **/
  287.       DosWrite(hTTY, cBuff2, iNumWrite, &ulTemp);
  288.  
  289. /**   Check for a response, if any, from the modem. **/
  290.       DosRead(hTTY, cBuff, sizeof(cBuff), &ulTemp);
  291.       if(ulTemp != 0)
  292.       {
  293.      for(i1=0; i1 < ulTemp; i1++)
  294.      {
  295.         if((cBuff[i1] & 0x7f) == CAN)
  296.         {
  297.            printf("Remote has canceled transmission!\n");
  298.            sprintf(cBuff,"%c%c",DLE,ETX);
  299.            DosWrite(hTTY, cBuff, 2*sizeof(char), &ulTemp);
  300.            return -1;
  301.         }
  302.      }
  303.       }
  304.       
  305.       iNumRead = fread(cBuff, sizeof(char), SENDCHUNK, fStream);
  306.    }
  307.    sprintf(cBuff,"%c%c",DLE,ETX);
  308.    DosWrite(hTTY, cBuff, 2*sizeof(char), &ulTemp);
  309.    i1 = iGetResp(hTTY, dcbCom, cBuff, 2, -15, "0\r");
  310.    if(i1 <= 0)
  311.    {
  312.       puts("Incorrect response from remote to end-of-page message!\n");
  313.       return -1;
  314.    }
  315.    
  316.    switch(iLast)
  317.    {
  318.       case PEND_ANOTHER:
  319.          strcpy(cBuff,"AT+FET=0\r");
  320.      DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  321.      break;
  322.       case PEND_ENDTRAN:
  323.      strcpy(cBuff,"AT+FET=2\r");
  324.      DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  325.      break;
  326.    }
  327.  
  328. /**Get the post-page response. **/
  329.    if(iGetResp(hTTY, dcbCom, cBuff, 20, -10, "0\r") <= 0)
  330.    {
  331.       puts("No post-page response from remote!");
  332.       return -1;
  333.    }
  334.    if(iLast == PEND_ANOTHER)
  335.       DosWrite(hTTY, "AT+FDT\r", sizeof("AT+FDT\r"), &ulTemp);
  336.  
  337.    strtok(&cBuff[8],"\r");
  338.    i1 = sscanf(&cBuff[8], "%d", &iPPRCode);
  339.    if(i1 <= 0)
  340.    {
  341.       puts("Incorrect post-page response from remote!");
  342.       return -1;
  343.    }
  344.    if(iLast == PEND_ANOTHER)
  345.    {
  346.       if(iGetResp(hTTY, dcbCom, cBuff, 2, -10, "1\r") <= 0)
  347.       {
  348.      puts("Unable to continue transmission!");
  349.      return -1;
  350.       }
  351.    }
  352.    else
  353.    {
  354.       if(iGetResp(hTTY, dcbCom, cBuff, 2, -15, "0\r") <= 0)
  355.       {
  356.      puts("Failed to properly end transmission!");
  357.      return -1;
  358.       }
  359.    }
  360.    
  361.    return iPPRCode;
  362. }
  363. /****************************************************************************/
  364. /************Tell the remote to intterrupt the transmission******************/
  365. /****************************************************************************/
  366. int iFaxInterrupt(HFILE hTTY, DCBINFO *dcbCom)
  367. {
  368.    char cBuff[20];
  369. /*-------------------------------End Declarations---------------------------*/
  370.  
  371.    strcpy(cBuff,"AT+FK\r");
  372.    DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
  373.    
  374.    return 0;
  375. }
  376. /****************************************************************************/
  377. /**************************Close the COM Port********************************/
  378. /****************************************************************************/
  379. ULONG ulClosePort(HFILE hTTY)
  380. {
  381.    return DosClose(hTTY);
  382. }
  383. /****************************************************************************/
  384. /********************Read the response from the modem************************/
  385. /****************************************************************************/
  386. int iGetResp( HFILE hTTY, DCBINFO *dcbCom, char *cBuff, int iExpSize, 
  387.           int iTimeout, char *cSearch )
  388. {
  389.    int iStart=0, iCnt=0;
  390.    
  391. /**Initialize the buffer. **/
  392.    cBuff[0] = '\000';
  393.    
  394. /**Set the desired timeout for this read. **/
  395.    usSetTTYTime(hTTY, dcbCom, iTimeout);
  396.  
  397. /**Read the response. **/
  398.    if(!cSearch)
  399.    {
  400.       DosRead(hTTY, cBuff, iExpSize, &ulTemp);
  401.       cBuff[ulTemp] = '\000';  /* For string manipulation functions. */
  402.       iStart = ulTemp;
  403.    }
  404.    else
  405.    {
  406.       do
  407.       {
  408.      DosRead(hTTY, &cBuff[iStart], iExpSize, &ulTemp);
  409.      iStart += ulTemp;
  410.      cBuff[iStart] = '\000';
  411.      iCnt++;
  412.       }
  413.       while(!strstr(cBuff,cSearch) && iCnt <= MAXTIMEOUTS);
  414.    }
  415.  
  416.    if(iCnt > MAXTIMEOUTS)
  417.       return -1;
  418.    
  419.    return iStart;
  420. }
  421. /****************************************************************************/
  422. /***********************Set the read timeout on******************************/
  423. /******************************the COM port**********************************/
  424. /****************************************************************************/
  425. USHORT usSetTTYTime(HFILE hTTY, DCBINFO *dcbCom, int iTime)
  426. {
  427.    if(iTime >= 0)
  428.       iTime *= 100;
  429.    else
  430.       iTime *= -1;
  431.  
  432.    dcbCom->usReadTimeout = iTime;
  433.    return (DevIOCtl(NULL,0,dcbCom,sizeof(*dcbCom),ASYNC_SETDCBINFO,
  434.            IOCTL_ASYNC, hTTY));
  435. }
  436. /****************************************************************************/
  437. /*************************Flush all pending I/O******************************/
  438. /****************************************************************************/
  439. void vFlushIO(HFILE hTTY)
  440. {
  441.    UINT data;
  442.    char parm=0;
  443. /*-------------------------------End Declarations---------------------------*/
  444.    
  445.    DevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
  446.         DEV_FLUSHINPUT, IOCTL_GENERAL, hTTY);
  447.    DevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
  448.         DEV_FLUSHOUTPUT, IOCTL_GENERAL, hTTY);
  449.    
  450. }
  451. /****************************************************************************/
  452. /************************Builds table to swap the****************************/
  453. /******************low order 4 bits with the high order**********************/
  454. /****************************************************************************/
  455. static void init_swaptable(unsigned char *swaptable)
  456. {
  457.     int i, j;
  458. /*-------------------------------End Declarations---------------------------*/
  459.  
  460.     for (i = 0; i < 256; i++) {
  461.     j = ( ((i & 0x01) << 7) |
  462.          ((i & 0x02) << 5) |
  463.          ((i & 0x04) << 3) |
  464.          ((i & 0x08) << 1) |
  465.          ((i & 0x10) >> 1) |
  466.          ((i & 0x20) >> 3) |
  467.          ((i & 0x40) >> 5) |
  468.          ((i & 0x80) >> 7) );
  469.     swaptable[i] = j;
  470.     }
  471. }
  472.  
  473. /****************************************************************************/
  474. /********************Reverses the low order 4 bits of a byte*****************/
  475. /****************************************************************************/
  476. unsigned char swap_bits(unsigned char c)
  477. {
  478.     static unsigned char swaptable[256];
  479.     static int swaptable_init = FALSE;
  480. /*-------------------------------End Declarations---------------------------*/
  481.  
  482.     if (!swaptable_init) {
  483.     init_swaptable(swaptable);
  484.     swaptable_init = TRUE;
  485.     }
  486.  
  487.     return(swaptable[c]);
  488. }
  489.