home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / me100.zip / ModemEngine.cpp < prev    next >
Text File  |  1996-06-22  |  39KB  |  1,001 lines

  1. //+----------------------------------------------------------------------------+
  2. //| MODEMENGINE.CPP                                                            |
  3. //|                                                                            |
  4. //| COPYRIGHT:                                                                 |
  5. //| ----------                                                                 |
  6. //|  Copyright (C) Sacha Prins, 1995, 1996.                                    |
  7. //|                                                                            |
  8. //| DISCLAIMER OF WARRANTIES:                                                  |
  9. //| -------------------------                                                  |
  10. //|  The following [enclosed] code is code created by Sacha Prins.             |
  11. //|  The code is provided "AS IS", without warranty of any kind. Sacha Prins   |
  12. //|  shall not be liable for any damages arising out of your use of the        |
  13. //|  [enclosed] code.                                                          |
  14. //|                                                                            |
  15. //| REVISION LEVEL: 1.0                                                        |
  16. //| ---------------                                                            |
  17. //|    22-jun-1996: Initial release to the public                              |
  18. //+----------------------------------------------------------------------------+
  19. #define INCL_DOSSEMAPHORES
  20. #define INCL_DOSFILEMGR
  21. #define INCL_DOSDEVIOCTL
  22. #define INCL_DOSDEVICES
  23. #define INCL_DOSPROCESS
  24. #define INCL_DOSSESMGR
  25. #define INCL_DOSQUEUES
  26. #define INCL_DOSERRORS
  27. #include <os2.h>
  28.  
  29. #include "\work\modemengine\ModemEngine.h"
  30. #include "\work\modemengine\ModemEngine.hpp"
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <stream.h>
  35.  
  36. #define BUFFERSIZE      1024
  37. #define PIPESIZE        65335
  38. #define MESSAGE_QUEUE_NAME              "\\QUEUES\\ANSWERING_MACHINE\\MESSAGE_QUEUE.QUEUE"
  39. #define DLE_QUEUE_NAME                  "\\QUEUES\\ANSWERING_MACHINE\\DLE_QUEUE.QUEUE"
  40.  
  41. void _System dummyMessageLoopThread (ULONG modem_engine);
  42.  
  43. void _System dummyRxLoopThread (ULONG modem_engine);
  44.  
  45. void _Optlink dummyMessageLoopThread2 (void * modem_engine);
  46.  
  47. void _Optlink dummyRxLoopThread2 (void * modem_engine);
  48.  
  49. //*****************************************************
  50. // MODEM_ENGINE(...) constructor
  51. //*****************************************************
  52. MODEM_ENGINE :: MODEM_ENGINE (PCHAR _deviceName, FLOW_CONTROL fc, int key) {
  53.         APIRET  rc;
  54.  
  55.    do {
  56.       operational= FALSE;
  57.       resultCode= noerror;
  58.  
  59. // // DATE & TIME CHECK
  60. //     DATETIME dateTime;
  61. //     DosGetDateTime (&dateTime);
  62. //     if (dateTime.year != 1995) {
  63. //        break;
  64. //     }
  65. // // END DATE & TIME CHECK
  66.    //---------------------------------------------------------
  67.    // INITIALIZE deviceName
  68.        deviceName = (PCHAR) malloc (strlen (_deviceName)+1);
  69.        strcpy (deviceName, _deviceName);
  70.  
  71.        if ( !mOpenCOM(fc) || key != 6127181) {
  72.           resultCode= errorOPENCOM;
  73.           break;
  74.        }
  75.  
  76.       UCHAR        paramPacket=0;
  77.       USHORT       dataPacket=0;
  78.       ULONG        cbParamPacket, cbDataPacket;
  79.  
  80.       DosDevIOCtl (hcom, IOCTL_GENERAL, DEV_FLUSHINPUT, ¶mPacket, sizeof(paramPacket), &cbParamPacket, &dataPacket, sizeof (dataPacket), &cbDataPacket);
  81.  
  82.  
  83.    // END INITIALIZE deviceName
  84.    //---------------------------------------------------------
  85.    // INITIALIZE hMessageQueue;
  86.        rc= DosCreateQueue (&hMessageQueue, QUE_FIFO | QUE_CONVERT_ADDRESS, MESSAGE_QUEUE_NAME);
  87.        if (rc) { resultCode= errorCREATEMESSAGEQUEUE; break; }
  88.    // END INITIALIZE hMessageQueue;
  89.    //---------------------------------------------------------
  90.    // INITIALIZE hDLEQueue;
  91.        rc= DosCreateQueue (&hDLEQueue, QUE_FIFO | QUE_CONVERT_ADDRESS, DLE_QUEUE_NAME);
  92.        if (rc) { resultCode= errorCREATEDLEQUEUE; break; }
  93.    // END INITIALIZE hMessageQueue;
  94.    //---------------------------------------------------------
  95.    // INITIALIZE state
  96.        state=idle;
  97.    // END INITIALIZE state
  98.    //---------------------------------------------------------
  99.    // INITIALIZE modemResponse
  100.        modemResponse.code=none;
  101.        modemResponse.verbose[0]=0;
  102.    // END INITIALIZE modemResponse
  103.  
  104.    // INITIALIZE AT#??? defaults
  105.        device=                 voice;
  106.        bitRange=               four;
  107.        vmLine=                 phone;
  108.        deadMan=                0;
  109.        silenceDetection=       TRUE;
  110.        silenceDetectionValue=  60;
  111.        silenceDeletion=        FALSE;
  112.    // END INITIALIZE AT#??? defaults
  113.    //---------------------------------------------------------
  114.    // INITIALIZE semaphores
  115.        DosCreateMutexSem (NULL, &hModemResponseSem, 0, FALSE);
  116.        DosCreateMutexSem (NULL, &hResultCodeSem, 0, FALSE);
  117.        DosCreateMutexSem (NULL, &hConnectStateSem, 0, FALSE);
  118.        DosCreateEventSem (NULL, &hevModemResponseSem, 0, FALSE);
  119.        DosCreateEventSem (NULL, &hevModemResponseSeenSem, 0, TRUE);
  120.    // END INITIALIZE semaphores
  121.    //---------------------------------------------------------
  122.    // INITIALIZE messageLoop thread
  123.        bRunMessageLoop= TRUE;
  124.        PFNTHREAD    pfnMessageLoop= &dummyMessageLoopThread;
  125. //       DosCreateThread (&tidMessageLoopThread, pfnMessageLoop, (ULONG) this, CREATE_READY, 4096);
  126.        tidMessageLoopThread= _beginthread (dummyMessageLoopThread2, NULL, 8192, this);
  127.  
  128.    // END INITIALIZE messageLoop thread
  129.    //---------------------------------------------------------
  130.    // INITIALIZE RxLoop thread
  131.        bRunRxLoop= TRUE;
  132.        PFNTHREAD    pfnRxLoop= &dummyRxLoopThread;
  133. //       DosCreateThread (&tidRxLoopThread, pfnRxLoop, (ULONG) this, CREATE_READY, 4096);
  134.        tidRxLoopThread= _beginthread (dummyRxLoopThread2, NULL, 8192, this);
  135.  
  136.    // END INITIALIZE RxLoop thread
  137.  
  138.       DosSetPriority (PRTYS_PROCESS, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0);
  139.       operational=TRUE;
  140.    } while (FALSE);
  141. };
  142.  
  143. //*****************************************************
  144. // mOpenCOM (...) member
  145. //*****************************************************
  146. BOOL    MODEM_ENGINE :: mOpenCOM (FLOW_CONTROL fc) {
  147.    ULONG ulAction, ulParamLen;
  148.    APIRET rc;
  149.    _LINECONTROL linecontrol;
  150.    WORD modemerror;
  151.    BYTE modemsignals;
  152.    _DCBINFO dcbinfo;
  153.    USHORT       usBPS=38400;
  154.  
  155.    do {
  156.    // OPEN COMMUNICATION PORT
  157.       rc=DosOpen(deviceName , &hcom, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
  158.                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, NULL);
  159.       if (rc) break;
  160.    // END OPEN COMMUNICATION PORT
  161.    //---------------------------------------------------------
  162.    // SET LINE CONTROL
  163.       linecontrol.bDataBits=0x08;
  164.       linecontrol.bParity=0x00;
  165.       linecontrol.bStopBits=0x00;
  166.  
  167.       ulParamLen=sizeof(linecontrol);
  168.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETLINECTRL, &linecontrol, sizeof(linecontrol), &ulParamLen, NULL, 0, NULL);
  169.       if (rc) break;
  170.    // END SET LINE CONTROL
  171.    //---------------------------------------------------------
  172.    // DISABLE BREAK
  173.       ulParamLen=sizeof(modemerror);
  174.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETBREAKOFF, NULL, 0, NULL, &modemerror, sizeof(modemerror), &ulParamLen);
  175.       if (rc) break;
  176.    // END DISABLE BREAK
  177.    //---------------------------------------------------------
  178.    // DROP DTR
  179.    // mDropDTR ();
  180.    // END DROP DTR
  181.    //---------------------------------------------------------
  182.    // SET BAUD RATE
  183.       ulParamLen= sizeof(usBPS);
  184.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETBAUDRATE, (PULONG) &usBPS, sizeof(usBPS), &ulParamLen, NULL, 0, NULL);
  185.       if (rc) {break;}
  186.  
  187.       ulParamLen = sizeof(dcbinfo);
  188.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_GETDCBINFO, NULL, 0, NULL, &dcbinfo, sizeof(dcbinfo), &ulParamLen);
  189.       if (rc) break;
  190.    // END SET BAUD RATE
  191.    //---------------------------------------------------------
  192.    // SET DCB INFO
  193.       dcbinfo.usReadTimeout= 99;
  194.       dcbinfo.usWriteTimeout= 99;
  195.  
  196.       dcbinfo.fbCtlHndShake = 0;
  197.       dcbinfo.fbFlowReplace = 0;
  198.  
  199.       switch (fc) {
  200.       case fc_none:
  201.          break;
  202.       case fc_rtscts:
  203.          dcbinfo.fbCtlHndShake += 8;
  204.          dcbinfo.fbFlowReplace += 32+64;
  205.          break;
  206.       case fc_xonxoff:
  207.          dcbinfo.fbFlowReplace += 1+2+32;
  208.          break;
  209.       case fc_rtscts_xonxoff:
  210.          dcbinfo.fbCtlHndShake += 8;
  211.          dcbinfo.fbFlowReplace += 1+2+32+64;
  212.          break;
  213.       } /* endswitch */
  214.  
  215.  
  216.       if (dcbinfo.fbTimeout&(8+16)) dcbinfo.fbTimeout= 2+16+64+128; // 16550 or equivalent UART
  217.       else dcbinfo.fbTimeout= 2;        // Stupid UART
  218.  
  219.       ulParamLen = sizeof(dcbinfo);
  220.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETDCBINFO,&dcbinfo, sizeof(dcbinfo), &ulParamLen, NULL, 0, NULL);
  221.       if (rc) break;
  222.    // END SET DCB INFO
  223.    //---------------------------------------------------------
  224.     } while (FALSE);
  225.  
  226.     if (rc) {resultCode= errorOPENCOM; return FALSE;}
  227.     else return TRUE;
  228.  
  229. // END INITIALIZE hcom
  230. //---------------------------------------------------------
  231. };
  232.  
  233.  
  234. //*****************************************************
  235. // ~MODEM_ENGINE(...) destructor
  236. //*****************************************************
  237. MODEM_ENGINE :: ~MODEM_ENGINE () {
  238.  
  239.    if (operational) {
  240.       TID          tid;
  241.       MESSAGE      *message = new (MESSAGE); message->message= quit;
  242.                                              message->data = NULL;
  243.  
  244.       DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  245.       bRunRxLoop= FALSE;
  246.       bRunMessageLoop= FALSE;
  247.       DosWaitThread (&tidMessageLoopThread, DCWW_WAIT);
  248.       DosWaitThread (&tidRxLoopThread, DCWW_WAIT);
  249.       CHAR c= RETURN;
  250.       ULONG cbWritten;
  251.       DosWrite (hcom, &c, sizeof (c), &cbWritten);
  252.       DosClose (hcom);
  253.       free (deviceName);
  254.       DosCloseQueue (hMessageQueue);
  255.       DosCloseQueue (hDLEQueue);
  256.       DosCloseMutexSem (hModemResponseSem);
  257.       DosCloseMutexSem (hResultCodeSem);
  258.       DosCloseMutexSem (hConnectStateSem);
  259.       DosCloseEventSem (hevModemResponseSem);
  260.    }
  261. };
  262.  
  263.  
  264. //*****************************************************
  265. // mWaitForModemResponseAndDLECode () member
  266. //*****************************************************
  267. void    MODEM_ENGINE :: mWaitForModemResponseAndDLECode (MODEMRESPONSE &mr, CHAR &ch, BYTE tsec) {
  268.         BYTE    i=0;
  269.    do {
  270.       mr= mWaitForModemResponse(1);
  271.       if (mr.code==none) ch= mWaitForDLECode(1);
  272.       i++;
  273.    } while ( (i*2 < tsec) && (ch==0) && (mr.code==none) ); /* enddo */
  274. };
  275.  
  276.  
  277. //*****************************************************
  278. // mWaitForDLECode () member
  279. //*****************************************************
  280. CHAR    MODEM_ENGINE :: mWaitForDLECode (BYTE tsec) {
  281.         REQUESTDATA  request = {0};
  282.         ULONG        DataLength, cbWritten;
  283.         PVOID        DataAddress=NULL;
  284.         BYTE         ElemPriority, temp[2];
  285.         HEV          hDLESem;
  286.         CHAR         ch=0;
  287.         int          i=0;
  288.  
  289.         DosCreateEventSem (NULL, &hDLESem, 0, FALSE);
  290.         if (DosReadQueue (hDLEQueue, &request, &DataLength, &DataAddress, 0L, 0, &ElemPriority, hDLESem)== ERROR_QUE_EMPTY) {
  291.            if (DosWaitEventSem (hDLESem, tsec*100)== NO_ERROR) {
  292.               DosReadQueue (hDLEQueue, &request, &DataLength, &DataAddress, 0L, 0, &ElemPriority, hDLESem);
  293.               ch= * (CHAR *) DataAddress;
  294.               delete (CHAR*) DataAddress;
  295.            }
  296.         } else {
  297.            ch= * (CHAR *) DataAddress;
  298.            delete (CHAR*) DataAddress;
  299.         }
  300.         DosCloseEventSem (hDLESem);
  301.         return ch;
  302. }
  303.  
  304.  
  305. //*****************************************************
  306. // mWaitForModemResponse ( ) member
  307. //*****************************************************
  308. MODEM_ENGINE::MODEMRESPONSE   MODEM_ENGINE :: mWaitForModemResponse (BYTE tsec) {
  309.         MODEMRESPONSE   mr;
  310.         ULONG           ulCount;
  311.         int             i=0;
  312.  
  313.    DosWaitEventSem (hevModemResponseSem, tsec*100);
  314.    mr= mModemResponse ();
  315.    return mr;
  316. };
  317.  
  318.  
  319. //*****************************************************
  320. // mModemResponse ( ) member
  321. //*****************************************************
  322. MODEM_ENGINE::MODEMRESPONSE   MODEM_ENGINE :: mModemResponse () {
  323.         MODEMRESPONSE   mr;
  324.         ULONG           ulCount;
  325.  
  326.    DosRequestMutexSem (hModemResponseSem, -1);
  327.    mr = modemResponse;
  328.    DosPostEventSem (hevModemResponseSeenSem);
  329.    modemResponse.code =none;
  330.    modemResponse.verbose[0] = 0;
  331.    DosResetEventSem (hevModemResponseSem, &ulCount);
  332.    DosReleaseMutexSem (hModemResponseSem);
  333.    return mr;
  334. };
  335.  
  336.  
  337. //*****************************************************
  338. // mResultCode ( ) member
  339. //*****************************************************
  340. MODEM_ENGINE::RESULTCODE      MODEM_ENGINE :: mResultCode () {
  341.         RESULTCODE rc;
  342.  
  343.    DosRequestMutexSem (hResultCodeSem, -1);
  344.    rc = resultCode;
  345. // resultCode= noerror;
  346.    DosReleaseMutexSem (hResultCodeSem);
  347.    return rc;
  348. };
  349.  
  350.  
  351. //*****************************************************
  352. // mDropDTR ( ) member
  353. //*****************************************************
  354. void    MODEM_ENGINE :: mDropDTR () {
  355.    ULONG        ulParamLen1, ulParamLen2;
  356.    _MODEMSTATUS modemstatus;
  357.    WORD         modemerror;
  358.    APIRET       rc;
  359.  
  360.    do {
  361.       ulParamLen1= sizeof(modemstatus); ulParamLen2 = sizeof(modemerror);
  362.       modemstatus.fbModemOff = 0xFF; modemstatus.fbModemOn= 0x01;
  363.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETMODEMCTRL, &modemstatus, sizeof(modemstatus), &ulParamLen1, &modemerror, sizeof(modemerror), &ulParamLen2);
  364.       if (rc) break;
  365.       DosSleep(500);
  366.  
  367.       ulParamLen1= sizeof(modemstatus); ulParamLen2 = sizeof(modemerror);
  368.       modemstatus.fbModemOff = 0xFE; modemstatus.fbModemOn= 0x00;
  369.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETMODEMCTRL, &modemstatus, sizeof(modemstatus), &ulParamLen1, &modemerror, sizeof(modemerror), &ulParamLen2);
  370.       if (rc) break;
  371.       DosSleep(1000);
  372.  
  373.       ulParamLen1= sizeof(modemstatus); ulParamLen2 = sizeof(modemerror);
  374.       modemstatus.fbModemOff = 0xFF; modemstatus.fbModemOn= 0x01;
  375.       rc=DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETMODEMCTRL, &modemstatus, sizeof(modemstatus), &ulParamLen1, &modemerror, sizeof(modemerror), &ulParamLen2);
  376.       if (rc) break;
  377.    } while (FALSE);
  378. }
  379.  
  380. //*****************************************************
  381. // messageLoop () member
  382. //*****************************************************
  383. void    MODEM_ENGINE :: messageLoop () {
  384.    MESSAGE      message;
  385.  
  386.    while (bRunMessageLoop) {
  387.       REQUESTDATA  request={0};
  388.       ULONG        DataLength, cbWritten;
  389.       PVOID        DataAddress;
  390.       BYTE         ElemPriority, temp[2];
  391.       CHAR         ch;
  392.       TID          tid;
  393.  
  394.       DosReadQueue(hMessageQueue, &request, &DataLength, &DataAddress, 0L, 0, &ElemPriority, 0L);
  395.       message = * (MESSAGE*) DataAddress;
  396.       delete (MESSAGE*) DataAddress;
  397.  
  398.       switch (message.message) {
  399.       case vmsetdevice:
  400.          device = * (DEVICE*) message.data;
  401.          mSendString (AT);
  402.          mSendString (SETDEVICE);
  403.          switch (device) {
  404.          case data: ch= '0';
  405.             break;
  406.          case class1fax: ch= '1';
  407.             break;
  408.          case class2fax: ch= '2';
  409.             break;
  410.          case voice: ch= '8';
  411.             break;
  412.          } /* endswitch */
  413.          mSendString (ch);
  414.          mSendString (13);
  415.          delete (DEVICE*) message.data;
  416.          break;
  417.       case vmsetbits:
  418.          bitRange = * (BITRANGE*) message.data;
  419.          mSendString (AT);
  420.          mSendString (SETBITS);
  421.          switch (bitRange) {
  422.          case two: ch= '2';
  423.             break;
  424.          case three: ch= '3';
  425.             break;
  426.          case four: ch= '4';
  427.             break;
  428.          case eight: ch= '8';
  429.             break;
  430.          } /* endswitch */
  431.          mSendString (ch);
  432.          mSendString (13);
  433.          delete (BITRANGE*) message.data;
  434.          break;
  435.       case vmsetdeadmantimer:
  436.          deadMan= * (BYTE*) message.data;
  437.          mSendString (AT);
  438.          mSendString (SETDEADMANTIMER);
  439.          ch = * (BYTE*) message.data;
  440.          { char buf[35];
  441.            mSendString (_itoa(ch, buf, 10));
  442.          }
  443. //         mSendString ((ch / 100) + 48);
  444. //         mSendString (((ch / 10) % 10) +48);
  445. //         mSendString ((ch % 10) +48);
  446.          mSendString (13);
  447.          delete (BYTE*) message.data;
  448.          break;
  449.       case vmsetspeed:
  450.          vmSpeed = * (BYTE*) message.data;
  451.          mSendString (AT);
  452.          mSendString (SETSPEED);
  453.          ch = * (BYTE*) message.data;
  454.          { char buf[35];
  455.            mSendString (_itoa(ch, buf, 10));
  456.          }
  457. //         mSendString ((ch / 100) + 48);
  458. //         mSendString (((ch / 10) % 10) +48);
  459. //         mSendString ((ch % 10) +48);
  460.          mSendString (13);
  461.          delete (BYTE*) message.data;
  462.          break;
  463.       case vmsetsilencedetection:
  464.          silenceDetection = * (BOOL*) message.data;
  465.          mSendString (AT);
  466.          mSendString (SETSILENCEDETECTION);
  467.          if (* (BOOL*) message.data) ch ='1';
  468.          else ch = '0';
  469.          mSendString (ch);
  470.          mSendString (13);
  471.          delete (BOOL*) message.data;
  472.          break;
  473.       case vmsetsilencedetectionvalue:
  474.          silenceDetectionValue = * (BYTE*) message.data;
  475.          mSendString (AT);
  476.          mSendString (SETSILENCEDETECTIONVALUE);
  477.          ch = * (BYTE*) message.data;
  478.          { char buf[35];
  479.            mSendString (_itoa(ch, buf, 10));
  480.          }
  481. //         mSendString ((ch / 100) + 48);
  482. //         mSendString (((ch / 10) % 10) +48);
  483. //         mSendString ((ch % 10) +48);
  484.          mSendString (13);
  485.          delete (BYTE*) message.data;
  486.          break;
  487.       case vmsetsilencedeletion:
  488.          silenceDeletion = * (BOOL*) message.data;
  489.          mSendString (AT);
  490.          mSendString (SETSILENCEDELETION);
  491.          if (* (BOOL*) message.data) ch= '1';
  492.          else ch= '0';
  493.          mSendString (ch);
  494.          mSendString (13);
  495.          delete (BOOL*) message.data;
  496.          break;
  497.       case vmsetline:
  498.          vmLine = * (LINE*) message.data;
  499.          mSendString (AT);
  500.          mSendString (SETLINE);
  501.          switch (vmLine) {
  502.          case line: ch= '0';
  503.             break;
  504.          case phone: ch= '1';
  505.             break;
  506.          case speaker: ch= '2';
  507.             break;
  508.          case mic: ch= '3';
  509.             break;
  510.          case lineMonitor: ch= '4';
  511.             break;
  512.          } /* endswitch */
  513.          mSendString (ch);
  514.          mSendString (13);
  515.          delete (LINE*) message.data;
  516.          break;
  517.       case vmbeep:
  518.          mSendATString (BEEP);
  519.          break;
  520.       case vmtransmit:
  521.          DosRequestMutexSem (hConnectStateSem, -1);
  522.          mSendATString (TRANSMIT);
  523.          connectState= transmit;
  524.          DosReleaseMutexSem (hConnectStateSem);
  525.          break;
  526.       case vmreceive:
  527.          DosRequestMutexSem (hConnectStateSem, -1);
  528.          mSendATString (RECEIVE);
  529.          connectState= receive;
  530.          DosReleaseMutexSem (hConnectStateSem);
  531.          break;
  532.       case vmstoptransmit:
  533.          mSendString (PLAYEND);
  534.          break;
  535.       case vmstopreceive:
  536.          mSendString ("!stop!");
  537.          break;
  538.       case vmquerydevice:
  539.          mSendATString (QUERYDEVICE);
  540.          break;
  541.       case vmquerymodel:
  542.          mSendATString (QUERYMODEL);
  543.          break;
  544.       case vmquerymanufacturer:
  545.          mSendATString (QUERYMANUFACTURER);
  546.          break;
  547.       case vmqueryrevision:
  548.          mSendATString (QUERYREVISION);
  549.          break;
  550.       case vmquerycompression:
  551.          mSendATString (QUERYCOMPRESSION);
  552.          break;
  553.       case vmquerydevices:
  554.          mSendATString (QUERYDEVICES);
  555.          break;
  556.       case minitialize:
  557.          mSendATString (INITIALIZE);
  558.          break;
  559.       case manswer:
  560.          mSendATString (ANSWER);
  561.          break;
  562.       case mhangup:
  563.          mSendATString (HANGUP);
  564.          break;
  565.       case quit:
  566.          bRunMessageLoop= FALSE;
  567.          break;
  568.       default:
  569.         break;
  570.       } /* endswitch */
  571.  
  572.    } /* endwhile */
  573.  
  574.    DosExit (0,0);
  575. };
  576.  
  577.  
  578. //*****************************************************
  579. // RxLoop () member
  580. //*****************************************************
  581. void    MODEM_ENGINE :: RxLoop () {
  582.    BYTE         buf[BUFFERSIZE];
  583.    ULONG        cbRead, cbWritten=0, cbParamPacket, cbDataPacket, ulPostCount;
  584.    BYTE         ch, response[25], prefix[2];
  585.    int          i;
  586.    UCHAR        paramPacket=0;
  587.    USHORT       dataPacket=0;
  588.  
  589.    while (bRunRxLoop) {
  590.  
  591.       switch (state) {
  592.       case Vcon:
  593.       case idle:
  594.          DosWaitEventSem (hevModemResponseSeenSem, -1);
  595. //       DosResetEventSem (hevModemResponseSeenSem, &ulPostCount);
  596.          i=0;
  597.          do DosRead (hcom, &ch, sizeof(ch), &cbRead); while (!cbRead && bRunRxLoop);
  598.          if (!bRunRxLoop) DosExit (0,0);
  599.          buf[i]= ch; i++;
  600.          do DosRead (hcom, &ch, sizeof(ch), &cbRead); while (!cbRead && bRunRxLoop);
  601.          if (!bRunRxLoop) DosExit (0,0);
  602.          buf[i]= ch; i++;
  603.          if (buf[0]==13 && buf[1]==10) {
  604.             do {
  605.                do DosRead (hcom, &ch, sizeof(ch), &cbRead); while (!cbRead && bRunRxLoop);
  606.                if (!bRunRxLoop) DosExit (0,0);
  607.                buf[i]= ch; i++;
  608.             } while ( ch != 13 ); /* enddo */
  609.             buf[i-1]=0;
  610.             do DosRead (hcom, &ch, sizeof(ch), &cbRead); while (!cbRead && bRunRxLoop);
  611.             if (!bRunRxLoop) DosExit (0,0);
  612.             DosRequestMutexSem (hModemResponseSem, -1);
  613.             if (!strcmp (OK,            &buf[2])) modemResponse.code= ok;
  614.             else if (!strcmp (CONNECT,       &buf[2])) {
  615.                     state= connected;
  616.                     modemResponse.code= connect;
  617.                  }
  618.             else if (!strcmp (RING,          &buf[2])) modemResponse.code= ring;
  619.             else if (!strcmp (NO_CARRIER,    &buf[2])) modemResponse.code= no_carrier;
  620.             else if (!strcmp (ERROR,         &buf[2])) modemResponse.code= error;
  621.             else if (!strcmp (NO_DIALTONE,   &buf[2])) modemResponse.code= no_dialtone;
  622.             else if (!strcmp (BUSY,          &buf[2])) modemResponse.code= busy;
  623.             else if (!strcmp (VCON,          &buf[2])) { modemResponse.code= vcon; state= Vcon; }
  624.             // ... Place for new commands
  625.             else /* Unknown answer */ modemResponse.code= unknown;
  626.             strcpy (modemResponse.verbose, &buf[2]);
  627.             DosResetEventSem (hevModemResponseSeenSem, &ulPostCount);
  628.             DosReleaseMutexSem (hModemResponseSem);
  629.             DosPostEventSem (hevModemResponseSem);
  630.  
  631.          } else {
  632.             if ((buf[0] & 223)== 'A' && (buf[1] & 223)== 'T') {
  633.                do {
  634.                   do DosRead (hcom, &ch, sizeof(ch), &cbRead); while (!cbRead && bRunRxLoop);
  635.                   if (!bRunRxLoop) DosExit (0,0);
  636.                   buf[i]= ch; i++;
  637.                } while ( ch != 13 ); /* enddo */
  638.                buf[i-1]=0;
  639.                DosRequestMutexSem (hModemResponseSem, -1);
  640.                modemResponse.code= atCommand;
  641.                strcpy (modemResponse.verbose, buf);
  642.                DosResetEventSem (hevModemResponseSeenSem, &ulPostCount);
  643.                DosReleaseMutexSem (hModemResponseSem);
  644.                DosPostEventSem (hevModemResponseSem);
  645.  
  646.             } else {
  647.                if (buf[0]==DLE) {
  648.                   // In case of state==Vcon
  649.                   BYTE  *b=new (BYTE); *b= buf[1];
  650.                   DosWriteQueue (hDLEQueue, 0, sizeof(BYTE), b, 0);
  651.                }
  652.  
  653.             } /* endif */
  654.          } /* endif */
  655.          break;
  656.  
  657.       case connected:
  658.          do {
  659.             BOOL        dlestate=FALSE;
  660.             CHAR        vconstate='v';
  661.  
  662.             DosRead (hcom, &buf, sizeof (buf), &cbRead);
  663.             for (i=0; i<cbRead ; i++ ) {
  664.                if ( (buf[i] & 223)=='V' && vconstate=='v') vconstate= 'c';
  665.                else if ( (buf[i] & 223)=='C' && vconstate=='c') vconstate= 'o';
  666.                else if ( (buf[i] & 223)=='O' && vconstate=='o') vconstate= 'n';
  667.                else if ( (buf[i] & 223)=='N' && vconstate=='n') {
  668.                                                                   state= Vcon;
  669.                                                                   DosRequestMutexSem (hModemResponseSem, -1);
  670.                                                                   modemResponse.code= vcon;
  671.                                                                   strcpy (modemResponse.verbose, VCON);
  672.                                                                   DosReleaseMutexSem (hModemResponseSem);
  673.                                                                   DosPostEventSem (hevModemResponseSem);
  674.                                                                   break; }
  675.                else { vconstate='v';
  676.                       if ( buf[i]==DLE ) dlestate= TRUE;
  677.                       else if ( dlestate== TRUE ) {
  678.                               dlestate=FALSE;
  679.                               BYTE  *b=new (BYTE); *b= buf[i];
  680.                               DosWriteQueue (hDLEQueue, 0, sizeof(BYTE), b, 0);
  681.                               if (buf[i]==EXT) { state= Vcon;
  682.                                                  DosRequestMutexSem (hModemResponseSem, -1);
  683.                                                  modemResponse.code=vcon;
  684.                                                  strcpy (modemResponse.verbose, VCON);
  685.                                                  DosReleaseMutexSem (hModemResponseSem);
  686.                                                  DosPostEventSem (hevModemResponseSem);
  687.                                                  break; }
  688.                            }
  689.                }
  690.             }
  691.  
  692.             DosRequestMutexSem (hConnectStateSem, -1);
  693.             if (connectState==receive) {
  694.                DosReleaseMutexSem (hConnectStateSem);
  695.                DosWrite (hfile, buf, i, &cbWritten);
  696.             } else DosReleaseMutexSem (hConnectStateSem);
  697.  
  698.          } while ( state==connected && bRunRxLoop); /* enddo */
  699.          cbParamPacket= sizeof (paramPacket); cbDataPacket= sizeof (dataPacket);
  700.          DosDevIOCtl (hcom, IOCTL_GENERAL, DEV_FLUSHINPUT, ¶mPacket, sizeof(paramPacket), &cbParamPacket, &dataPacket, sizeof (dataPacket), &cbDataPacket);
  701.          break;
  702.       default:
  703.         break;
  704.       } /* endswitch */
  705.  
  706.    } /* endwhile */
  707.  
  708.    DosExit (0,0);
  709.  
  710. };
  711.  
  712.  
  713. //*****************************************************
  714. // mSendString ( PCHAR ) member
  715. //*****************************************************
  716. void    MODEM_ENGINE :: mSendString (PCHAR p) {
  717.  
  718.         ULONG   cbWritten;
  719.         APIRET  rc=0;
  720.  
  721.    do {
  722.      rc=DosWrite (hcom, p, strlen(p), &cbWritten);
  723.      if (rc) break;
  724.      rc=DosDevIOCtl (hcom, IOCTL_ASYNC, ASYNC_STARTTRANSMIT, NULL, 0, NULL, NULL, 0, NULL);
  725.      if (rc) break;
  726.    } while (FALSE);
  727.    if (rc) resultCode= errorSENDSTRING;
  728. };
  729.  
  730.  
  731. //*****************************************************
  732. // mSendString ( CHAR ) member
  733. //*****************************************************
  734. void    MODEM_ENGINE :: mSendString (CHAR c) {
  735.  
  736.         ULONG   cbWritten;
  737.         APIRET  rc=0;
  738.         CHAR    p[1]; p[0]=c;
  739.  
  740.    do {
  741.      rc=DosWrite (hcom, &p, 1, &cbWritten);
  742.      if (rc) break;
  743.      rc=DosDevIOCtl (hcom, IOCTL_ASYNC, ASYNC_STARTTRANSMIT, NULL, 0, NULL, NULL, 0, NULL);
  744.      if (rc) break;
  745.    } while (FALSE);
  746.    if (rc) resultCode= errorSENDSTRING;
  747. };
  748.  
  749.  
  750. //*****************************************************
  751. // vmSetDevice (...) member
  752. //*****************************************************
  753. void    MODEM_ENGINE :: vmSetDevice (DEVICE d) {
  754.         DEVICE       *device = new (DEVICE); *device= d;
  755.         MESSAGE      *message = new (MESSAGE); message->message= vmsetdevice;
  756.                                                message->data = device;
  757.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  758. };
  759.  
  760.  
  761. //*****************************************************
  762. // vmSetBits (...) member
  763. //*****************************************************
  764. void    MODEM_ENGINE :: vmSetBits (BITRANGE b) {
  765.         BITRANGE     *bitrange = new (BITRANGE); *bitrange= b;
  766.         MESSAGE      *message = new (MESSAGE); message->message= vmsetbits;
  767.                                                message->data = bitrange;
  768.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  769. };
  770.  
  771. //*****************************************************
  772. // vmSetDeadmanTimer (...) member
  773. //*****************************************************
  774. void    MODEM_ENGINE :: vmSetDeadmanTimer (BYTE b) {
  775.         BYTE         *byte = new (BYTE); *byte= b;
  776.         MESSAGE      *message = new (MESSAGE); message->message= vmsetdeadmantimer;
  777.                                                message->data = byte;
  778.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  779. };
  780.  
  781. //*****************************************************
  782. // vmSetSpeed (...) member
  783. //*****************************************************
  784. void    MODEM_ENGINE :: vmSetSpeed (BYTE b) {
  785.         BYTE         *byte = new (BYTE); *byte= b;
  786.         MESSAGE      *message = new (MESSAGE); message->message= vmsetspeed;
  787.                                                message->data = byte;
  788.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  789. };
  790.  
  791. //*****************************************************
  792. // vmSetSilenceDetection (...) member
  793. //*****************************************************
  794. void    MODEM_ENGINE :: vmSetSilenceDetection (BOOL b) {
  795.         BOOL         *bool = new (BOOL); *bool= b;
  796.         MESSAGE      *message = new (MESSAGE); message->message= vmsetsilencedetection;
  797.                                                message->data = bool;
  798.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  799. };
  800.  
  801. //*****************************************************
  802. // vmSetSilenceDetectionValue (...) member
  803. //*****************************************************
  804. void    MODEM_ENGINE :: vmSetSilenceDetectionValue (BYTE b) {
  805.         BYTE         *byte = new (BYTE); *byte= b;
  806.         MESSAGE      *message = new (MESSAGE); message->message= vmsetsilencedetectionvalue;
  807.                                                message->data = byte;
  808.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  809. };
  810.  
  811. //*****************************************************
  812. // vmSetSilenceDeletion (...) member
  813. //*****************************************************
  814. void    MODEM_ENGINE :: vmSetSilenceDeletion (BOOL b) {
  815.         BOOL         *bool = new (BOOL); *bool= b;
  816.         MESSAGE      *message = new (MESSAGE); message->message= vmsetsilencedeletion;
  817.                                                message->data = bool;
  818.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  819. };
  820.  
  821. //*****************************************************
  822. // vmSetLine (...) member
  823. //*****************************************************
  824. void    MODEM_ENGINE :: vmSetLine (LINE l) {
  825.         LINE         *_line = new (LINE); *_line= l;
  826.         MESSAGE      *message = new (MESSAGE); message->message= vmsetline;
  827.                                                message->data = _line;
  828.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  829. };
  830.  
  831. //*****************************************************
  832. // vmBeep (...) member
  833. //*****************************************************
  834. void    MODEM_ENGINE :: vmBeep () {
  835.         MESSAGE      *message = new (MESSAGE); message->message= vmbeep;
  836.                                                message->data = NULL;
  837.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  838. };
  839.  
  840. //*****************************************************
  841. // vmTransmit (...) member
  842. //*****************************************************
  843. void    MODEM_ENGINE :: vmTransmit (HFILE& hf) {
  844.         MESSAGE      *message = new (MESSAGE); message->message= vmtransmit;
  845.                                                message->data = NULL;
  846.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  847.         hf= hcom;
  848. };
  849.  
  850. //*****************************************************
  851. // vmReceive (CHAR) member
  852. //*****************************************************
  853. void    MODEM_ENGINE :: vmReceive (HFILE hf) {
  854.         MESSAGE      *message = new (MESSAGE); message->message= vmreceive;
  855.                                                message->data = NULL;
  856.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  857.         hfile= hf;
  858. };
  859.  
  860. //*****************************************************
  861. // vmStopTransmit (...) member
  862. //*****************************************************
  863. void    MODEM_ENGINE :: vmStopTransmit () {
  864.         MESSAGE      *message = new (MESSAGE); message->message= vmstoptransmit;
  865.                                                message->data = NULL;
  866.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  867. };
  868.  
  869. //*****************************************************
  870. // vmStopreceive (...) member
  871. //*****************************************************
  872. void    MODEM_ENGINE :: vmStopReceive () {
  873.         MESSAGE      *message = new (MESSAGE); message->message= vmstopreceive;
  874.                                                message->data = NULL;
  875.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  876. };
  877.  
  878. //*****************************************************
  879. // vmQueryDevice (...) member
  880. //*****************************************************
  881. void    MODEM_ENGINE :: vmQueryDevice () {
  882.         MESSAGE      *message = new (MESSAGE); message->message= vmquerydevice;
  883.                                                message->data = NULL;
  884.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  885. };
  886.  
  887. //*****************************************************
  888. // vmQueryModel (...) member
  889. //*****************************************************
  890. void    MODEM_ENGINE :: vmQueryModel () {
  891.         MESSAGE      *message = new (MESSAGE); message->message= vmquerymodel;
  892.                                                message->data = NULL;
  893.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  894. };
  895.  
  896. //*****************************************************
  897. // vmQueryManufacturer(...) member
  898. //*****************************************************
  899. void    MODEM_ENGINE :: vmQueryManufacturer () {
  900.         MESSAGE      *message = new (MESSAGE); message->message= vmquerymanufacturer;
  901.                                                message->data = NULL;
  902.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  903. };
  904.  
  905. //*****************************************************
  906. // vmQueryRevision (...) member
  907. //*****************************************************
  908. void    MODEM_ENGINE :: vmQueryRevision () {
  909.         MESSAGE      *message = new (MESSAGE); message->message= vmqueryrevision;
  910.                                                message->data = NULL;
  911.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  912. };
  913.  
  914. //*****************************************************
  915. // vmQueryCompression (...) member
  916. //*****************************************************
  917. void    MODEM_ENGINE :: vmQueryCompression() {
  918.         MESSAGE      *message = new (MESSAGE); message->message= vmquerycompression;
  919.                                                message->data = NULL;
  920.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  921. };
  922.  
  923. //*****************************************************
  924. // vmQueryDevices (...) member
  925. //*****************************************************
  926. void    MODEM_ENGINE :: vmQueryDevices () {
  927.         MESSAGE      *message = new (MESSAGE); message->message= vmquerydevices;
  928.                                                message->data = NULL;
  929.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  930. };
  931.  
  932. //*****************************************************
  933. // mInitialize (...) member
  934. //*****************************************************
  935. void    MODEM_ENGINE :: mInitialize () {
  936.         MESSAGE      *message = new (MESSAGE); message->message= minitialize;
  937.                                                message->data = NULL;
  938.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  939. };
  940.  
  941.  
  942. //*****************************************************
  943. // mHangup (...) member
  944. //*****************************************************
  945. void    MODEM_ENGINE :: mHangup () {
  946.         MESSAGE      *message = new (MESSAGE); message->message= mhangup;
  947.                                                message->data = NULL;
  948.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  949. };
  950.  
  951.  
  952. //*****************************************************
  953. // mAnswer (...) member
  954. //*****************************************************
  955. void    MODEM_ENGINE :: mAnswer () {
  956.         MESSAGE      *message = new (MESSAGE); message->message= manswer;
  957.                                                message->data = NULL;
  958.         DosWriteQueue (hMessageQueue, 0, sizeof (MESSAGE), message, 0);
  959. };
  960.  
  961.  
  962. //*****************************************************
  963. // dummyMessageLoopThread (...)
  964. //*****************************************************
  965. void _System dummyMessageLoopThread (ULONG modem_engine) {
  966.  
  967.         ( (MODEM_ENGINE *) modem_engine ) ->messageLoop();
  968.         DosExit (0, 0);
  969.  
  970. };
  971.  
  972.  
  973. //*****************************************************
  974. // dummyRxLoopThread (...)
  975. //*****************************************************
  976. void _System dummyRxLoopThread (ULONG modem_engine) {
  977.  
  978.         ( (MODEM_ENGINE *) modem_engine ) ->RxLoop();
  979.         DosExit (0, 0);
  980.  
  981. };
  982.  
  983. //*****************************************************
  984. // dummyMessageLoopThread2 (...)
  985. //*****************************************************
  986. void _Optlink dummyMessageLoopThread2 (void * modem_engine) {
  987.  
  988.         ( (MODEM_ENGINE *) modem_engine ) ->messageLoop();
  989. };
  990.  
  991.  
  992. //*****************************************************
  993. // dummyRxLoopThread2 (...)
  994. //*****************************************************
  995. void _Optlink dummyRxLoopThread2 (void * modem_engine) {
  996.  
  997.         ( (MODEM_ENGINE *) modem_engine ) ->RxLoop();
  998. };
  999.  
  1000.  
  1001.