home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term23_2.lha / Source_Code / termSource / termSerial.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  21KB  |  1,091 lines

  1. /*
  2. **    $Id: termSerial.c,v 1.3 92/08/15 20:15:13 olsen Sta Locker: olsen $
  3. **    $Revision: 1.3 $
  4. **    $Date: 92/08/15 20:15:13 $
  5. **
  6. **    Serial driver support routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Include the OwnDevUnit definitions. */
  15.  
  16. #include "OwnDevUnit.h"
  17.  
  18.     /* Local copy of serial driver name and unit number. */
  19.  
  20. STATIC UBYTE    SerialDevice[40];
  21. STATIC LONG    UnitNumber = -1;
  22.  
  23.     /* SetFlags(struct IOExtSer *SomeRequest):
  24.      *
  25.      *    Set the contents of a serial device request according
  26.      *    to the current configuration settings.
  27.      */
  28.  
  29. VOID __regargs
  30. SetFlags(struct IOExtSer *SomeRequest)
  31. {
  32.     SomeRequest -> io_Baud        = Config . BaudRate;
  33.     SomeRequest -> io_BrkTime    = Config . BreakLength;
  34.     SomeRequest -> io_ReadLen    = Config . BitsPerChar;
  35.     SomeRequest -> io_WriteLen    = Config . BitsPerChar;
  36.     SomeRequest -> io_StopBits    = Config . StopBits;
  37.  
  38.     SomeRequest -> io_ExtFlags    &= ~(SEXTF_MSPON|SEXTF_MARK);
  39.     SomeRequest -> io_SerFlags    &= ~(SERF_PARTY_ON|SERF_PARTY_ODD|SERF_7WIRE|SERF_RAD_BOOGIE);
  40.  
  41.     switch(Config . Parity)
  42.     {
  43.         case PARITY_EVEN:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  44.                     break;
  45.  
  46.         case PARITY_ODD:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON|SERF_PARTY_ODD;
  47.                     break;
  48.  
  49.         case PARITY_MARK:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  50.                     SomeRequest -> io_ExtFlags |= SEXTF_MSPON|SEXTF_MARK;
  51.                     break;
  52.  
  53.         case PARITY_SPACE:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  54.                     SomeRequest -> io_ExtFlags |= SEXTF_MSPON;
  55.                     break;
  56.  
  57.         default:        break;
  58.     }
  59.  
  60.     if(Config . HandshakingProtocol != HANDSHAKING_NONE)
  61.         SomeRequest -> io_SerFlags |= SERF_7WIRE;
  62.  
  63.     if(Config . HighSpeed & ~SERIAL_SHARED)
  64.         SomeRequest -> io_SerFlags |= SERF_RAD_BOOGIE;
  65.  
  66.     if(Config . HighSpeed & SERIAL_SHARED)
  67.         SomeRequest -> io_SerFlags |= SERF_SHARED;
  68.  
  69.     SomeRequest -> io_SerFlags |= SERF_XDISABLED;
  70. }
  71.  
  72.     /* GetFlags(struct Configuration *Config,struct IOExtSer *SomeRequest):
  73.      *
  74.      *    Update configuration with serial settings.
  75.      */
  76.  
  77. VOID __regargs
  78. GetFlags(struct Configuration *Config,struct IOExtSer *SomeRequest)
  79. {
  80.     Config -> BaudRate    = SomeRequest -> io_Baud;
  81.     Config -> BreakLength    = SomeRequest -> io_BrkTime;
  82.     Config -> BitsPerChar    = SomeRequest -> io_ReadLen;
  83.     Config -> BitsPerChar    = SomeRequest -> io_WriteLen;
  84.     Config -> StopBits    = SomeRequest -> io_StopBits;
  85.  
  86.     if(SomeRequest -> io_SerFlags & SERF_PARTY_ON)
  87.     {
  88.         if(SomeRequest -> io_SerFlags & SERF_PARTY_ODD)
  89.             Config -> Parity = PARITY_ODD;
  90.         else
  91.         {
  92.             if(SomeRequest -> io_ExtFlags & SEXTF_MSPON)
  93.             {
  94.                 if(SomeRequest -> io_ExtFlags & SEXTF_MARK)
  95.                     Config -> Parity = PARITY_MARK;
  96.                 else
  97.                     Config -> Parity = PARITY_SPACE;
  98.             }
  99.         }
  100.     }
  101.     else
  102.         Config -> Parity = PARITY_NONE;
  103.  
  104.     if(SomeRequest -> io_SerFlags & SERF_7WIRE)
  105.         Config -> HandshakingProtocol = HANDSHAKING_RTSCTS;
  106.     else
  107.         Config -> HandshakingProtocol = HANDSHAKING_NONE;
  108.  
  109.     if(SomeRequest -> io_SerFlags & SERF_RAD_BOOGIE)
  110.         Config -> HighSpeed = TRUE;
  111.     else
  112.         Config -> HighSpeed = FALSE;
  113.  
  114.     if(SomeRequest -> io_SerFlags & SERF_SHARED)
  115.         Config -> HighSpeed |= SERIAL_SHARED;
  116.  
  117.     SomeRequest -> io_SerFlags |= SERF_XDISABLED;
  118. }
  119.  
  120.     /* CallMenu(UBYTE *Name,ULONG Code):
  121.      *
  122.      *    Call a menu function either through the name of the corresponding
  123.      *    menu item or a menu number.
  124.      */
  125.  
  126. STATIC VOID __regargs
  127. CallMenu(UBYTE *Name,ULONG Code)
  128. {
  129.     WORD MenuNum = -1,Item = 0,Sub = 0,i;
  130.  
  131.         /* Are we to look for a name? */
  132.  
  133.     if(Name)
  134.     {
  135.         WORD Len = strlen(Name);
  136.  
  137.             /* Scan the menu list... */
  138.  
  139.         for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
  140.         {
  141.             switch(TermMenu[i] . nm_Type)
  142.             {
  143.                 case NM_TITLE:    MenuNum++;
  144.                         Item = Sub = 0;
  145.                         break;
  146.  
  147.                 case NM_ITEM:    Sub = 0;
  148.                         break;
  149.             }
  150.  
  151.                 /* Did we get a valid name string? */
  152.  
  153.             if(TermMenu[i] . nm_Label != NM_BARLABEL)
  154.             {
  155.                     /* Does the name match our template? */
  156.  
  157.                 if(!Strnicmp(TermMenu[i] . nm_Label,Name,Len))
  158.                 {
  159.                     struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
  160.  
  161.                     if(MenuItem)
  162.                         HandleCode((ULONG)TermMenu[i] . nm_UserData,NULL,MenuItem);
  163.  
  164.                     break;
  165.                 }
  166.             }
  167.  
  168.             switch(TermMenu[i] . nm_Type)
  169.             {
  170.                 case NM_ITEM:    Item++;
  171.                         break;
  172.  
  173.                 case NM_SUB:    Sub++;
  174.                         break;
  175.             }
  176.         }
  177.     }
  178.     else
  179.     {
  180.         WORD    TheMenu    =  Code % 100,
  181.             TheItem    = (Code / 100) % 100,
  182.             TheSub    =  Code / 10000;
  183.  
  184.             /* Scan the menu list... */
  185.  
  186.         for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
  187.         {
  188.             switch(TermMenu[i] . nm_Type)
  189.             {
  190.                 case NM_TITLE:    MenuNum++;
  191.                         Item = Sub = 0;
  192.                         break;
  193.  
  194.                 case NM_ITEM:    Sub = 0;
  195.                         break;
  196.             }
  197.  
  198.                 /* Is it the menu number we want? */
  199.  
  200.             if(TheMenu == MenuNum && TheItem == Item && TheSub == Sub)
  201.             {
  202.                 if(TermMenu[i] . nm_Label != NM_BARLABEL)
  203.                 {
  204.                     struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
  205.  
  206.                     if(MenuItem)
  207.                         HandleCode((ULONG)TermMenu[i] . nm_UserData,NULL,MenuItem);
  208.                 }
  209.  
  210.                 break;
  211.             }
  212.  
  213.             switch(TermMenu[i] . nm_Type)
  214.             {
  215.                 case NM_ITEM:    Item++;
  216.                         break;
  217.  
  218.                 case NM_SUB:    Sub++;
  219.                         break;
  220.             }
  221.         }
  222.     }
  223. }
  224.  
  225.     /* SerialCommand(UBYTE *String):
  226.      *
  227.      *    Send a command string to the serial line and
  228.      *    interprete the control sequences.
  229.      */
  230.  
  231. VOID __regargs
  232. SerialCommand(UBYTE *String)
  233. {
  234.     LONG    Count = 0,i,Len = strlen(String);
  235.  
  236.     BYTE    GotControl    = FALSE,
  237.         GotEscape    = FALSE,
  238.  
  239.         OldStatus,
  240.         BlockSet;
  241.  
  242.         /* Scan the string. */
  243.  
  244.     for(i = 0 ; i < Len ; i++)
  245.     {
  246.             /* We are looking for plain characters
  247.              * and the control ('\') and escape
  248.              * ('^') characters.
  249.              */
  250.  
  251.         if(!GotControl && !GotEscape)
  252.         {
  253.                 /* Got a control character,
  254.                  * the next byte will probably be
  255.                  * a command sequence.
  256.                  */
  257.  
  258.             if(String[i] == '\\')
  259.             {
  260.                 GotControl = TRUE;
  261.                 continue;
  262.             }
  263.  
  264.                 /* Got an escape character,
  265.                  * the next byte will be some
  266.                  * kind of control character
  267.                  * (such as XON, XOF, bell, etc.).
  268.                  */
  269.  
  270.             if(String[i] == '^')
  271.             {
  272.                 GotEscape = TRUE;
  273.                 continue;
  274.             }
  275.  
  276.                 /* This tells us to wait another
  277.                  * second before continuing with
  278.                  * the scanning.
  279.                  */
  280.  
  281.             if(String[i] == '~')
  282.             {
  283.                 if(Count)
  284.                 {
  285.                     SerWrite(SharedBuffer,Count);
  286.  
  287.                     Count = 0;
  288.                 }
  289.  
  290.                 WaitTime(0,MILLION / 2);
  291.                 HandleSerial();
  292.  
  293.                 continue;
  294.             }
  295.  
  296.                 /* Stuff the character into the
  297.                  * buffer.
  298.                  */
  299.  
  300.             SharedBuffer[Count++] = String[i];
  301.         }
  302.         else
  303.         {
  304.                 /* Convert the character to a control
  305.                  * style character (^C, etc.).
  306.                  */
  307.  
  308.             if(GotEscape)
  309.             {
  310.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  311.                     SharedBuffer[Count++] = ToUpper(String[i]) - '@';
  312.                 else
  313.                     SharedBuffer[Count++] = String[i];
  314.  
  315.                 GotEscape = FALSE;
  316.             }
  317.  
  318.                 /* The next character represents a command. */
  319.  
  320.             if(GotControl)
  321.             {
  322.                 switch(ToUpper(String[i]))
  323.                 {
  324.                         /* Execute an AmigaDOS command. */
  325.  
  326.                     case 'D':    if(!WeAreBlocking)
  327.                             {
  328.                                 BlockSet = TRUE;
  329.  
  330.                                 BlockWindows();
  331.                             }
  332.                             else
  333.                                 BlockSet = FALSE;
  334.  
  335.                             SendAmigaDOSCommand(&String[i + 1]);
  336.  
  337.                             if(BlockSet)
  338.                                 ReleaseWindows();
  339.  
  340.                             return;
  341.  
  342.                         /* Execute an ARexx command. */
  343.  
  344.                     case 'A':    if(!WeAreBlocking)
  345.                             {
  346.                                 BlockSet = TRUE;
  347.  
  348.                                 BlockWindows();
  349.                             }
  350.                             else
  351.                                 BlockSet = FALSE;
  352.  
  353.                             SendARexxCommand(&String[i + 1]);
  354.  
  355.                             if(BlockSet)
  356.                                 ReleaseWindows();
  357.  
  358.                             return;
  359.  
  360.                         /* Add the control character ('\'). */
  361.  
  362.                     case '\\':    SharedBuffer[Count++] = '\\';
  363.                             break;
  364.  
  365.                         /* This is a backspace. */
  366.  
  367.                     case 'B':    SharedBuffer[Count++] = '\b';
  368.                             break;
  369.  
  370.                         /* This is a form feed. */
  371.  
  372.                     case 'F':    SharedBuffer[Count++] = '\f';
  373.                             break;
  374.  
  375.                         /* This is a line feed. */
  376.  
  377.                     case 'N':    SharedBuffer[Count++] = '\n';
  378.                             break;
  379.  
  380.                         /* Send the current password. */
  381.  
  382.                     case 'P':    if(Password[0])
  383.                             {
  384.                                 if(Count)
  385.                                 {
  386.                                     SerWrite(SharedBuffer,Count);
  387.  
  388.                                     Count = 0;
  389.                                 }
  390.  
  391.                                 SerWrite(Password,strlen(Password));
  392.                             }
  393.  
  394.                             break;
  395.  
  396.                         /* This is a carriage return. */
  397.  
  398.                     case 'R':    SharedBuffer[Count++] = '\r';
  399.                             break;
  400.  
  401.                         /* This is a tab. */
  402.  
  403.                     case 'T':    SharedBuffer[Count++] = '\t';
  404.                             break;
  405.  
  406.                         /* Send the current user name. */
  407.  
  408.                     case 'U':    if(UserName[0])
  409.                             {
  410.                                 if(Count)
  411.                                 {
  412.                                     SerWrite(SharedBuffer,Count);
  413.  
  414.                                     Count = 0;
  415.                                 }
  416.  
  417.                                 SerWrite(UserName,strlen(UserName));
  418.                             }
  419.  
  420.                             break;
  421.  
  422.                         /* Send a break across the serial line. */
  423.  
  424.                     case 'X':    if(Count)
  425.                             {
  426.                                 SerWrite(SharedBuffer,Count);
  427.  
  428.                                 Count = 0;
  429.                             }
  430.  
  431.                             if(WriteRequest)
  432.                             {
  433.                                 OldStatus = Status;
  434.  
  435.                                 Status = STATUS_BREAKING;
  436.  
  437.                                 WriteRequest -> IOSer . io_Command = SDCMD_BREAK;
  438.  
  439.                                 DoIO(WriteRequest);
  440.  
  441.                                 Status = OldStatus;
  442.                             }
  443.  
  444.                             break;
  445.  
  446.                         /* Feed the contents of the
  447.                          * clipboard into the input
  448.                          * stream.
  449.                          */
  450.  
  451.                     case 'I':    if(Count)
  452.                                 SerWrite(SharedBuffer,Count);
  453.  
  454.                             Count = LoadClip(SharedBuffer,256);
  455.  
  456.                             break;
  457.  
  458.                         /* Send a string to the clipboard. */
  459.  
  460.                     case 'G':    if(String[i + 1])
  461.                                 SaveClip(&String[i + 1],strlen(&String[i + 1]));
  462.  
  463.                             return;
  464.  
  465.                         /* Produce the escape character. */
  466.  
  467.                     case 'E':    SharedBuffer[Count++] = ESC;
  468.                             break;
  469.  
  470.                         /* Call a menu item. */
  471.  
  472.                     case 'C':    i++;
  473.  
  474.                                 /* Scan for a menu number or
  475.                                  * a single quote...
  476.                                  */
  477.  
  478.                             while(i < Len)
  479.                             {
  480.                                 if(String[i] >= '0' && String[i] <= '9')
  481.                                     break;
  482.  
  483.                                 if(String[i] == '\'')
  484.                                     break;
  485.  
  486.                                 if(String[i] != ' ')
  487.                                     break;
  488.  
  489.                                 i++;
  490.                             }
  491.  
  492.                             if(i < Len)
  493.                             {
  494.                                 UBYTE DummyBuffer[256];
  495.  
  496.                                     /* Did we get a quote? */
  497.  
  498.                                 if(String[i] == '\'')
  499.                                 {
  500.                                     LONG Start = ++i;
  501.  
  502.                                     if(String[Start])
  503.                                     {
  504.                                         WORD Length;
  505.  
  506.                                         while(i < Len)
  507.                                         {
  508.                                             if(String[i] != '\'')
  509.                                                 i++;
  510.                                             else
  511.                                                 break;
  512.                                         }
  513.  
  514.                                         if(String[i] == '\'')
  515.                                             Length = i - Start;
  516.                                         else
  517.                                             Length = i - Start + 1;
  518.  
  519.                                         memcpy(DummyBuffer,&String[Start],Length);
  520.  
  521.                                         DummyBuffer[Length] = 0;
  522.  
  523.                                         CallMenu(DummyBuffer,0);
  524.                                     }
  525.                                 }
  526.                                 else
  527.                                 {
  528.                                     if(String[i] >= '0' && String[i] <= '9')
  529.                                     {
  530.                                         LONG Start = i,Length;
  531.  
  532.                                         while(i < Len)
  533.                                         {
  534.                                             if(String[i] >= '0' && String[i] <= '9')
  535.                                                 i++;
  536.                                             else
  537.                                                 break;
  538.                                         }
  539.  
  540.                                         if(i == Start)
  541.                                             Length = 1;
  542.                                         else
  543.                                             Length = i - Start;
  544.  
  545.                                         memcpy(DummyBuffer,&String[Start],Length);
  546.  
  547.                                         DummyBuffer[Length] = 0;
  548.  
  549.                                         CallMenu(NULL,atol(DummyBuffer));
  550.                                     }
  551.                                 }
  552.                             }
  553.  
  554.                             break;
  555.  
  556.                         /* Stuff the character into the buffer. */
  557.  
  558.                     default:    SharedBuffer[Count++] = String[i];
  559.                             break;
  560.                 }
  561.  
  562.                 GotControl = FALSE;
  563.             }
  564.         }
  565.  
  566.             /* If the buffer is full, release it. */
  567.  
  568.         if(Count == 256)
  569.         {
  570.             SerWrite(SharedBuffer,Count);
  571.  
  572.             Count = 0;
  573.         }
  574.     }
  575.  
  576.     if(Count)
  577.         SerWrite(SharedBuffer,Count);
  578. }
  579.  
  580.     /* SerWrite(APTR Buffer,LONG Size):
  581.      *
  582.      *    Send a number of bytes across the serial line.
  583.      */
  584.  
  585. VOID __regargs
  586. SerWrite(APTR Buffer,LONG Size)
  587. {
  588.     if(WriteRequest && Size)
  589.     {
  590.         if(XProtocolBase)
  591.         {
  592.                 /* xpr wants to see the data before it is
  593.                  * transferred.
  594.                  */
  595.  
  596.             if(TransferBits & XPRS_USERMON)
  597.             {
  598.                 if(!(Size = XProtocolUserMon(XprIO,Buffer,Size,Size)))
  599.                     return;
  600.             }
  601.         }
  602.  
  603.         BytesOut += Size;
  604.  
  605.             /* If full duplex is enabled, send the entire
  606.              * buffer.
  607.              */
  608.  
  609.         if(Config . Duplex == DUPLEX_FULL)
  610.         {
  611.             WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  612.             WriteRequest -> IOSer . io_Data        = Buffer;
  613.             WriteRequest -> IOSer . io_Length    = Size;
  614.  
  615.             DoIO(WriteRequest);
  616.         }
  617.         else
  618.         {
  619.             if(XEmulatorBase)
  620.             {
  621.                 WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  622.                 WriteRequest -> IOSer . io_Data        = Buffer;
  623.                 WriteRequest -> IOSer . io_Length    = Size;
  624.  
  625.                 SendIO(WriteRequest);
  626.  
  627.                 ConProcess(Buffer,Size);
  628.  
  629.                 WaitIO(WriteRequest);
  630.             }
  631.             else
  632.             {
  633.                 UBYTE *ByteBuffer = Buffer;
  634.  
  635.                     /* Half duplex is enabled, send only
  636.                      * a single character at a time.
  637.                      */
  638.  
  639.                 while(Size--)
  640.                 {
  641.                     WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  642.                     WriteRequest -> IOSer . io_Length    = 1;
  643.                     WriteRequest -> IOSer . io_Data        = ByteBuffer;
  644.  
  645.                     SendIO(WriteRequest);
  646.  
  647.                     ConProcess(ByteBuffer,1);
  648.  
  649.                     WaitIO(WriteRequest);
  650.  
  651.                     ByteBuffer++;
  652.                 }
  653.             }
  654.         }
  655.     }
  656. }
  657.  
  658.     /* ClearSerial():
  659.      *
  660.      *    Terminate all read/write activity on the serial
  661.      *    line.
  662.      */
  663.  
  664. VOID
  665. ClearSerial()
  666. {
  667.     if(ReadRequest)
  668.     {
  669.         if(!CheckIO(ReadRequest))
  670.             AbortIO(ReadRequest);
  671.  
  672.         WaitIO(ReadRequest);
  673.     }
  674.  
  675.     if(WriteRequest)
  676.     {
  677.         WriteRequest -> IOSer . io_Command = CMD_CLEAR;
  678.  
  679.         DoIO(WriteRequest);
  680.     }
  681. }
  682.  
  683.     /* DropDTR():
  684.      *
  685.      *    Drop the data terminal ready signal (i.e. close, wait a bit
  686.      *    and then reopen the serial drive).
  687.      */
  688.  
  689. BYTE
  690. DropDTR()
  691. {
  692.         /* Finish all serial read activity. */
  693.  
  694.     ClearSerial();
  695.  
  696.         /* Do we have any channels to work with? */
  697.  
  698.     if(ReadRequest && WriteRequest)
  699.     {
  700.             /* Close the device. */
  701.  
  702.         CloseDevice(ReadRequest);
  703.  
  704.             /* Wait a bit. */
  705.  
  706.         WaitTime(1,0);
  707.  
  708.             /* Set up the original configuration data. */
  709.  
  710.         SetFlags(ReadRequest);
  711.  
  712.         ReadRequest -> io_RBufLen = Config . SerBuffSize;
  713.  
  714.             /* Reopen the driver. */
  715.  
  716.         if(!OpenDevice(Config . SerialDevice,Config . UnitNumber,ReadRequest,0))
  717.         {
  718.             struct MsgPort *WritePort = WriteRequest -> IOSer . io_Message . mn_ReplyPort;
  719.  
  720.                 /* Fill in the rest. */
  721.  
  722.             CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
  723.  
  724.             WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  725.  
  726.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  727.  
  728.             SetFlags(WriteRequest);
  729.  
  730.             DoIO(WriteRequest);
  731.  
  732.                 /* Restart read activity. */
  733.  
  734.             ReadRequest -> IOSer . io_Command    = CMD_READ;
  735.             ReadRequest -> IOSer . io_Data        = ReadBuffer;
  736.             ReadRequest -> IOSer . io_Length    = 1;
  737.  
  738.             SetSignal(0,SIG_SERIAL);
  739.  
  740.             SendIO(ReadRequest);
  741.  
  742.             return(TRUE);
  743.         }
  744.         else
  745.             DeleteSerial();
  746.     }
  747.     else
  748.     {
  749.         DeleteSerial();
  750.  
  751.         return(TRUE);
  752.     }
  753.  
  754.     return(FALSE);
  755. }
  756.  
  757.     /* DeleteSerial():
  758.      *
  759.      *    Close the serial device and release all associated
  760.      *    resources.
  761.      */
  762.  
  763. VOID
  764. DeleteSerial()
  765. {
  766.     BYTE Closed = FALSE;
  767.  
  768.     if(ReadRequest)
  769.     {
  770.         if(ReadRequest -> IOSer . io_Device)
  771.         {
  772.             if(!(Config . HighSpeed & SERIAL_SHARED))
  773.             {
  774.                 ReadRequest -> IOSer . io_Command = CMD_RESET;
  775.  
  776.                 DoIO(ReadRequest);
  777.             }
  778.  
  779.             CloseDevice(ReadRequest);
  780.  
  781.             Closed = TRUE;
  782.         }
  783.  
  784.         DeleteIORequest(ReadRequest);
  785.  
  786.         ReadRequest = NULL;
  787.     }
  788.  
  789.     if(WriteRequest)
  790.     {
  791.         if(WriteRequest -> IOSer . io_Device && !Closed)
  792.         {
  793.             if(!(Config . HighSpeed & SERIAL_SHARED))
  794.             {
  795.                 ReadRequest -> IOSer . io_Command = CMD_RESET;
  796.  
  797.                 DoIO(ReadRequest);
  798.             }
  799.  
  800.             CloseDevice(WriteRequest);
  801.         }
  802.  
  803.         if(WriteRequest -> IOSer . io_Message . mn_ReplyPort)
  804.             DeleteMsgPort(WriteRequest -> IOSer . io_Message . mn_ReplyPort);
  805.  
  806.         DeleteIORequest(WriteRequest);
  807.  
  808.         WriteRequest = NULL;
  809.     }
  810.  
  811.     if(ReadPort)
  812.     {
  813.         DeleteMsgPort(ReadPort);
  814.  
  815.         ReadPort = NULL;
  816.     }
  817.  
  818.     if(ReadBuffer)
  819.     {
  820.         FreeVec(ReadBuffer);
  821.  
  822.         ReadBuffer = NULL;
  823.     }
  824.  
  825.     if(HostReadBuffer)
  826.     {
  827.         FreeVec(HostReadBuffer);
  828.  
  829.         HostReadBuffer = NULL;
  830.     }
  831.  
  832.     if(OwnDevUnitBase && SerialDevice[0] && UnitNumber != -1)
  833.     {
  834.         FreeDevUnit(SerialDevice,UnitNumber);
  835.  
  836.         SerialDevice[0] = 0;
  837.  
  838.         UnitNumber = -1;
  839.     }
  840. }
  841.  
  842.     /* GetSerialError(LONG Error,BYTE *Reset):
  843.      *
  844.      *    Return an error message for each possible serial device error.
  845.      */
  846.  
  847. STRPTR
  848. GetSerialError(LONG Error,BYTE *Reset)
  849. {
  850.     switch(Error)
  851.     {
  852.         case SerErr_DevBusy:        if(Reset)
  853.                             *Reset = FALSE;
  854.  
  855.                         return(LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT));
  856.  
  857.         case SerErr_BaudMismatch:    if(Reset)
  858.                             *Reset = TRUE;
  859.  
  860.                         return(LocaleString(MSG_SERIAL_ERROR_BAUDMISMATCH_TXT));
  861.  
  862.         case SerErr_BufErr:        if(Reset)
  863.                             *Reset = FALSE;
  864.  
  865.                         return(LocaleString(MSG_SERIAL_ERROR_BUFERR_TXT));
  866.  
  867.         case SerErr_InvParam:        if(Reset)
  868.                             *Reset = TRUE;
  869.  
  870.                         return(LocaleString(MSG_SERIAL_ERROR_INVPARAM_TXT));
  871.  
  872.         case SerErr_LineErr:        if(Reset)
  873.                             *Reset = FALSE;
  874.  
  875.                         return(LocaleString(MSG_SERIAL_ERROR_LINEERR_TXT));
  876.  
  877.         case SerErr_ParityErr:        if(Reset)
  878.                             *Reset = TRUE;
  879.  
  880.                         return(LocaleString(MSG_SERIAL_ERROR_PARITYERR_TXT));
  881.  
  882.         case SerErr_TimerErr:        if(Reset)
  883.                             *Reset = FALSE;
  884.  
  885.                         return(LocaleString(MSG_SERIAL_ERROR_TIMERERR_TXT));
  886.  
  887.         case SerErr_BufOverflow:    if(Reset)
  888.                             *Reset = FALSE;
  889.  
  890.                         return(LocaleString(MSG_SERIAL_ERROR_BUFOVERFLOW_TXT));
  891.  
  892.         case SerErr_NoDSR:        if(Reset)
  893.                             *Reset = FALSE;
  894.  
  895.                         return(LocaleString(MSG_SERIAL_ERROR_NODSR_TXT));
  896.  
  897.     /*    case SerErr_UnitBusy:    */
  898.         case 16:            if(Reset)
  899.                             *Reset = FALSE;
  900.  
  901.                         return(LocaleString(MSG_SERIAL_ERROR_UNIT_BUSY_TXT));
  902.  
  903.         default:            return(NULL);
  904.     }
  905. }
  906.  
  907.     /* CreateSerial():
  908.      *
  909.      *    Create handles for the serial device and open it.
  910.      */
  911.  
  912. UBYTE *
  913. CreateSerial()
  914. {
  915.     struct MsgPort *WritePort;
  916.  
  917.         /* If OwnDevUnit.library is available, try to lock
  918.          * the serial driver.
  919.          */
  920.  
  921. Start:    if(OwnDevUnitBase)
  922.     {
  923.         UBYTE *Error;
  924.  
  925.             /* Attempt to lock the device unit... */
  926.  
  927.         if(Error = AttemptDevUnit(Config . SerialDevice,Config . UnitNumber,TermIDString,NULL))
  928.         {
  929.                 /* Check for error type if any. */
  930.  
  931.             if(!Strnicmp(Error,ODUERR_LEADCHAR,1))
  932.                 SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_ERROR_ACCESSING_TXT),Config . SerialDevice,Config . UnitNumber,&Error[1]);
  933.             else
  934.                 SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_DEVICE_IN_USE_TXT),Config . SerialDevice,Config . UnitNumber,Error);
  935.  
  936.             SerialDevice[0] = 0;
  937.  
  938.             UnitNumber = -1;
  939.  
  940.             return(SharedBuffer);
  941.         }
  942.         else
  943.         {
  944.             strcpy(SerialDevice,Config . SerialDevice);
  945.  
  946.             UnitNumber = Config . UnitNumber;
  947.         }
  948.     }
  949.  
  950.     if(ReadBuffer = AllocVec(Config . SerBuffSize,MEMF_ANY))
  951.     {
  952.         if(XProtocolBase && (TransferBits & XPRS_HOSTNOWAIT))
  953.             HostReadBuffer = AllocVec(Config . SerBuffSize,MEMF_ANY);
  954.         else
  955.             HostReadBuffer = NULL;
  956.  
  957.         if(ReadPort = (struct MsgPort *)CreateMsgPort())
  958.         {
  959.             if(ReadRequest = (struct IOExtSer *)CreateIORequest(ReadPort,sizeof(struct IOExtSer)))
  960.             {
  961.                 LONG Error;
  962.  
  963.                 SetFlags(ReadRequest);
  964.  
  965.                 ReadRequest -> io_RBufLen = Config . SerBuffSize;
  966.  
  967.                 if(!(Error = OpenDevice(Config . SerialDevice,Config . UnitNumber,ReadRequest,0)))
  968.                 {
  969.                     if(WritePort = (struct MsgPort *)CreateMsgPort())
  970.                     {
  971.                         if(WriteRequest = (struct IOExtSer *)CreateIORequest(WritePort,sizeof(struct IOExtSer)))
  972.                         {
  973.                             CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
  974.  
  975.                             WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  976.  
  977.                             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  978.  
  979.                             SetFlags(WriteRequest);
  980.  
  981.                             DoIO(WriteRequest);
  982.  
  983.                             /* If RTS/CTS (7 wire handshaking) is
  984.                              * selected, have a look at the DSR
  985.                              * line to see whether the modem
  986.                              * connected is willing to support
  987.                              * this handshaking mode.
  988.                              */
  989.  
  990.                             if(Config . HandshakingProtocol == HANDSHAKING_RTSCTS_DSR)
  991.                             {
  992. Retry:                                WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  993.  
  994.                                 DoIO(WriteRequest);
  995.  
  996.                                     /* If the line happens to
  997.                                      * be high, there is no
  998.                                      * DSR signal present.
  999.                                      */
  1000.  
  1001.                                 if(WriteRequest -> io_Status & (1 << 3))
  1002.                                 {
  1003.                                     if(MyEasyRequest(Window,LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_TXT),LocaleString(MSG_SERIAL_RETRY_CANCEL_TXT)))
  1004.                                         goto Retry;
  1005.                                     else
  1006.                                     {
  1007.                                         DeleteSerial();
  1008.  
  1009.                                         Config . HandshakingProtocol = HANDSHAKING_NONE;
  1010.  
  1011.                                         SerialMessage = LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_HANDSHAKING_DISABLED_TXT);
  1012.  
  1013.                                         goto Start;
  1014.                                     }
  1015.                                 }
  1016.                             }
  1017.  
  1018.                             ReadRequest -> IOSer . io_Command    = CMD_READ;
  1019.                             ReadRequest -> IOSer . io_Data        = ReadBuffer;
  1020.                             ReadRequest -> IOSer . io_Length    = 1;
  1021.  
  1022.                             SetSignal(0,SIG_SERIAL);
  1023.  
  1024.                             SendIO(ReadRequest);
  1025.  
  1026.                             return(NULL);
  1027.                         }
  1028.                         else
  1029.                         {
  1030.                             SerialMessage = NULL;
  1031.  
  1032.                             DeleteSerial();
  1033.  
  1034.                             return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  1035.                         }
  1036.                     }
  1037.                     else
  1038.                     {
  1039.                         SerialMessage = NULL;
  1040.  
  1041.                         DeleteSerial();
  1042.  
  1043.                         return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_WRITE_PORT_TXT));
  1044.                     }
  1045.                 }
  1046.                 else
  1047.                 {
  1048.                     STRPTR String;
  1049.  
  1050.                     ReadRequest -> IOSer . io_Device = NULL;
  1051.  
  1052.                     DeleteSerial();
  1053.  
  1054.                     SerialMessage = NULL;
  1055.  
  1056.                     if(!(String = GetSerialError(Error,NULL)))
  1057.                         String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
  1058.  
  1059.                     SPrintf(SharedBuffer,String,Config . SerialDevice,Config . UnitNumber);
  1060.  
  1061.                     return(SharedBuffer);
  1062.                 }
  1063.             }
  1064.             else
  1065.             {
  1066.                 SerialMessage = NULL;
  1067.  
  1068.                 DeleteSerial();
  1069.  
  1070.                 return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  1071.             }
  1072.         }
  1073.         else
  1074.         {
  1075.             SerialMessage = NULL;
  1076.  
  1077.             DeleteSerial();
  1078.  
  1079.             return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_READ_PORT_TXT));
  1080.         }
  1081.     }
  1082.     else
  1083.     {
  1084.         SerialMessage = NULL;
  1085.  
  1086.         DeleteSerial();
  1087.  
  1088.         return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  1089.     }
  1090. }
  1091.