home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / lib / c / ser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  13.0 KB  |  580 lines

  1. /* << ACE >> - db.lib module: Serial Port functions.
  2. ** Copyright (C) 1998 David Benn
  3. ** 
  4. ** This program is free software; you can redistribute it and/or
  5. ** modify it under the terms of the GNU General Public License
  6. ** as published by the Free Software Foundation; either version 2
  7. ** of the License, or (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  
  18.    Author: David J Benn
  19.      Date: 22nd-25th September 1991, 
  20.        2nd October 1991, 
  21.        18th January 1992,
  22.        6th August 1993,
  23.        4th-6th,12th,25th September 1993,
  24.        18th December 1993,
  25.        19th March 1994,
  26.        10th,11th September 1994,
  27.        2nd October 1994
  28. */
  29.  
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <exec/io.h>
  33. #include <devices/serial.h>
  34.  
  35. #define BRK_TIME 750000L
  36.  
  37. /* error codes */
  38. #define OPEN_ERR    300L
  39. #define CLOSE_ERR    301L
  40. #define READ_ERR    302L
  41. #define WRITE_ERR    303L
  42. #define BAD_CHANNEL    304L
  43.  
  44. #define DEFDEVNAME    "serial.device"
  45. #define MAXCHANNELS    255
  46. #define MAXPARAMS    7
  47.  
  48. /* function protos */
  49. void    OpenSerial();
  50. void    CloseSerial();
  51. void    SetParameters();
  52. ULONG    BytesIncoming();
  53. ULONG     SerialStatus();
  54. void    ReadSerial();
  55. void    WriteSerial();
  56.  
  57. /* external functions */
  58. extern    void     stringcopy();
  59. extern    ULONG    stringlength();
  60.  
  61. /* external variables */
  62. extern     ULONG     error_code;
  63.  
  64. /* serial port structures */
  65. typedef struct serialsym {
  66.               struct MsgPort  *SerRPort;    
  67.               struct MsgPort  *SerWPort;    /* message ports */
  68.  
  69.               struct IOExtSer *SerRdReq;
  70.               struct IOExtSer *SerWtReq;    /* I/O requests */
  71.  
  72.               char   *device_name;        /* name of device */
  73.  
  74.               ULONG     unit;            /* unit number */
  75.               ULONG     baud;            /* baud rate */    
  76.               ULONG     parity;        /* parity (NEOMS) */    
  77.               ULONG     data;            /* data bits */    
  78.               ULONG     stop;            /* stop bits */    
  79.               ULONG     wires;            /* # of wires (7,3) */    
  80.               ULONG     Xon;            /* Xon (0,1) */    
  81.               ULONG     shared;        /* access (0,1) */
  82.               ULONG  fast;            /* fast mode (0,1) */    
  83.               ULONG     bufsize;        /* bufsize */    
  84.              } SERIAL;
  85.  
  86. /* globals */
  87. SERIAL     serial[MAXCHANNELS];
  88. BOOL     first_time=TRUE;
  89.  
  90. /* functions */
  91.  
  92. void GetParameters(params,parity,data,stop,wires,Xon,shared,fast)
  93. UBYTE *params,*parity,*data,*stop,*wires,*Xon,*shared,*fast;
  94. {
  95. int  i,j;
  96. UBYTE p[MAXPARAMS];
  97.  
  98.      /* extract parameters from string */
  99.     
  100.     for (i=0;i<MAXPARAMS && params[i];i++) p[i] = params[i];
  101.     
  102.     for (j=i;j<MAXPARAMS;j++) p[j] = '?'; /* non-specified parameters='?' */
  103.  
  104.     /* essential */
  105.     *parity    = p[0];
  106.     *data     = p[1]-'0';
  107.     *stop     = p[2]-'0';
  108.  
  109.     /* optional */
  110.     *wires  = '?';
  111.     *Xon    = '?';
  112.     *shared = '?';
  113.     *fast    = '?';
  114.  
  115.     for (i=3;i<MAXPARAMS;i++)
  116.            { 
  117.        switch(p[i])
  118.        {
  119.            case '3' : *wires = '3';
  120.                break;
  121.  
  122.         case 'X' : 
  123.         case 'x' : *Xon    = 'X';
  124.                break;
  125.  
  126.         case 'S' : 
  127.         case 's' : *shared = 'S';
  128.                break;
  129.  
  130.         case 'F' : 
  131.         case 'f' : *fast = 'F';
  132.                break;
  133.         }
  134.     }
  135. }
  136.  
  137. void OpenSerial(devname,rbuf_len,params,baud,unit,channel)
  138. char  *devname;
  139. ULONG rbuf_len;
  140. UBYTE *params;
  141. ULONG baud;
  142. ULONG unit;
  143. ULONG channel;
  144. {
  145. ULONG error;
  146. ULONG i,length;    
  147. BYTE  *b,*c;
  148. char  msgportname[40];
  149. UBYTE  parity,data,stop,wires,Xon,shared,fast;
  150.  
  151.         /* open a serial port channel */
  152.  
  153.     if (first_time)
  154.     {
  155.         /* clear all channels first */
  156.         first_time = FALSE;
  157.         for (i=0;i<MAXCHANNELS;i++) 
  158.         {
  159.             serial[i].SerRdReq = NULL;
  160.             serial[i].SerWtReq = NULL;
  161.             serial[i].SerRPort = NULL;
  162.             serial[i].SerWPort = NULL;
  163.             serial[i].device_name  = NULL;
  164.         }
  165.     }
  166.  
  167.     channel--;
  168.  
  169.     if (channel < 0 || channel > 254) 
  170.        { error_code = BAD_CHANNEL; return; }
  171.  
  172.     GetParameters(params,&parity,&data,&stop,&wires,&Xon,&shared,&fast);
  173.  
  174.     if (baud == '?' || data == '?' || stop == '?') 
  175.        { error_code = OPEN_ERR; return; }
  176.  
  177.     /* store information -> rest is stored later */
  178.     serial[channel].baud = baud;
  179.     serial[channel].data = data;
  180.     serial[channel].stop = stop;
  181.     serial[channel].bufsize = rbuf_len;
  182.  
  183.     /* create a reply port to which serial device can return request */
  184.     stringcopy(msgportname,"serial_read_port");
  185.     length = stringlength(msgportname);
  186.     msgportname[length] = (char)channel + '0';    
  187.     msgportname[length+1] = '\0';
  188.     serial[channel].SerRPort = (struct MsgPort *)CreatePort(msgportname,0);
  189.     if (serial[channel].SerRPort == NULL) 
  190.     {
  191.         error_code = OPEN_ERR;
  192.         return;        
  193.  
  194.     }
  195.  
  196.     /* create a serial read request block */    
  197.     serial[channel].SerRdReq = (struct IOExtSer *)
  198.         CreateExtIO(serial[channel].SerRPort,sizeof(struct IOExtSer));
  199.  
  200.     if (serial[channel].SerRdReq == NULL)
  201.     {
  202.         DeletePort(serial[channel].SerRPort);
  203.         error_code = OPEN_ERR;
  204.         return;
  205.     }
  206.  
  207.     /* use 3 or 7 wires? */
  208.      if (wires == '3')
  209.     {
  210.         /* three wires */
  211.         serial[channel].SerRdReq->io_SerFlags = 0;        
  212.         serial[channel].wires = 3;
  213.     }    
  214.     else
  215.     {
  216.         /* seven wires */ 
  217.         serial[channel].SerRdReq->io_SerFlags = SERF_7WIRE;
  218.         serial[channel].wires = 7;
  219.     }
  220.         
  221.     /* shared access to serial port */
  222.     if (shared == 'S')
  223.     {
  224.         /* shared access */
  225.         serial[channel].SerRdReq->io_SerFlags |= SERF_SHARED;
  226.         serial[channel].shared = 1;
  227.     }
  228.     else
  229.         /* exclusive access */
  230.         serial[channel].shared = 0;    
  231.  
  232.     /* open serial device */
  233.  
  234.     /* store serial device name */
  235.     if (devname == NULL) devname = DEFDEVNAME;
  236.     
  237.     serial[channel].device_name = 
  238.         (char *)AllocMem(stringlength(devname)+1,MEMF_ANY);
  239.  
  240.     stringcopy(serial[channel].device_name,devname);
  241.  
  242.     /* store unit number */
  243.     serial[channel].unit = unit;
  244.  
  245.     /* open device */
  246.     error = (ULONG)OpenDevice(serial[channel].device_name,unit,
  247.                       serial[channel].SerRdReq,0L);
  248.  
  249.     if (error != 0)
  250.     {
  251.         DeleteExtIO(serial[channel].SerRdReq,sizeof(struct IOExtSer));
  252.         DeletePort(serial[channel].SerRPort);
  253.         error_code = OPEN_ERR;
  254.         return;
  255.     }
  256.  
  257.     /* clone a serial write request block */
  258.     stringcopy(msgportname,"serial_write_port");
  259.     length = stringlength(msgportname);
  260.     msgportname[length] = (char)channel + '0';    
  261.     msgportname[length+1] = '\0';
  262.     serial[channel].SerWPort = (struct MsgPort *)CreatePort(msgportname,0);
  263.  
  264.     serial[channel].SerWtReq = (struct IOExtSer *)
  265.         CreateExtIO(serial[channel].SerWPort,sizeof(struct IOExtSer));
  266.  
  267.     b = (BYTE *)serial[channel].SerRdReq;
  268.     c = (BYTE *)serial[channel].SerWtReq;
  269.  
  270.     for (i=0;i<sizeof(struct IOExtSer);i++) *c++ = *b++;
  271.  
  272.     serial[channel].SerWtReq->IOSer.io_Message.mn_ReplyPort = 
  273.                                   serial[channel].SerWPort;
  274.  
  275.     /* disable Xon/Xoff feature? */
  276.     if (Xon != 'X')
  277.     {
  278.         /* disable Xon/off feature */
  279.            serial[channel].SerRdReq->io_SerFlags |= SERF_XDISABLED;
  280.         serial[channel].Xon = 0;
  281.     }
  282.     else
  283.         /* enable Xon/off feature */
  284.         serial[channel].Xon = 1;
  285.  
  286.     /* enable fast mode? */
  287.     if (fast == 'F')
  288.     {
  289.         /* enable fast (RAD_BOOGIE) mode */
  290.         serial[channel].SerRdReq->io_SerFlags |= SERF_RAD_BOOGIE;
  291.         serial[channel].fast = 1;
  292.     }
  293.     else
  294.         /* don't enable fast mode */
  295.         serial[channel].fast = 0;
  296.  
  297.     SetParameters(rbuf_len,baud,parity,data,stop,channel);
  298. }
  299.  
  300. void CloseSerial(channel)
  301. ULONG channel;
  302. {
  303.     /* close serial device */
  304.  
  305.     channel--;
  306.  
  307.     if (channel < 0 || channel > 254) 
  308.        { error_code = BAD_CHANNEL; return; }
  309.  
  310.     if (serial[channel].SerRdReq != NULL && 
  311.         serial[channel].SerWtReq != NULL &&
  312.         serial[channel].SerRPort != NULL &&
  313.         serial[channel].SerWPort != NULL)
  314.         {
  315.         CloseDevice(serial[channel].SerRdReq);
  316.  
  317.         DeleteExtIO(serial[channel].SerRdReq);
  318.         DeleteExtIO(serial[channel].SerWtReq);
  319.  
  320.         DeletePort(serial[channel].SerRPort);
  321.         DeletePort(serial[channel].SerWPort);
  322.     }
  323.     else 
  324.           { error_code = CLOSE_ERR; return; }
  325.  
  326.     if (serial[channel].device_name)
  327.          FreeMem(serial[channel].device_name,
  328.            stringlength(serial[channel].device_name)+1);
  329.  
  330.     /* clear this channel's stored information */
  331.     serial[channel].SerRdReq = NULL;
  332.     serial[channel].SerWtReq = NULL;
  333.     serial[channel].SerRPort = NULL;
  334.     serial[channel].SerWPort = NULL;
  335.       serial[channel].device_name = NULL;
  336.       serial[channel].unit=0;
  337.     serial[channel].baud=0;    
  338.     serial[channel].parity='?';
  339.     serial[channel].data=0;
  340.     serial[channel].stop=0;
  341.     serial[channel].wires=0;
  342.     serial[channel].Xon=0;
  343.     serial[channel].shared=0;    
  344.     serial[channel].fast=0;
  345.     serial[channel].bufsize=0;
  346. }
  347.  
  348. void SetParameters(rbuf_len,baud,parity,data,stop,channel)
  349. ULONG rbuf_len;
  350. ULONG baud;
  351. UBYTE parity,data,stop;
  352. ULONG channel;
  353. {
  354. UBYTE flags;
  355. ULONG extflags;
  356.  
  357.     /* set serial port parameters */
  358.  
  359.     flags = serial[channel].SerRdReq->io_SerFlags;
  360.     extflags = 0;
  361.  
  362.     switch(parity)
  363.     {
  364.         /* NO parity */
  365.       case    'N' :
  366.       case    'n' :     flags |= 0;
  367.             serial[channel].parity = 'N';
  368.             break;
  369.  
  370.         /* EVEN parity */
  371.       case    'E' :
  372.       case    'e' :     flags |= SERF_PARTY_ON;    
  373.             flags &= ~SERF_PARTY_ODD;    
  374.             serial[channel].parity = 'E';
  375.             break;
  376.  
  377.         /* ODD parity */
  378.       case    'O' :
  379.       case    'o' :    flags |= (SERF_PARTY_ON | SERF_PARTY_ODD);
  380.             serial[channel].parity = 'O';
  381.             break;
  382.  
  383.         /* MARK parity */
  384.       case    'M' :
  385.       case    'm' :    flags |= SERF_PARTY_ON;
  386.             extflags = SEXTF_MSPON | SEXTF_MARK;
  387.             serial[channel].parity = 'M';
  388.             break;
  389.  
  390.         /* SPACE parity */
  391.       case    'S' :
  392.       case    's' :    flags |= SERF_PARTY_ON;
  393.             extflags = SEXTF_MSPON;
  394.             serial[channel].parity = 'S';
  395.             break;
  396.  
  397.         /* default is NO parity */
  398.       default:    flags |= 0;
  399.             serial[channel].parity = 'N';
  400.             break;
  401.     }
  402.  
  403.     if (serial[channel].SerWtReq)
  404.     {
  405.      serial[channel].SerWtReq->io_ReadLen    = data;
  406.      serial[channel].SerWtReq->io_BrkTime    = BRK_TIME;
  407.      serial[channel].SerWtReq->io_Baud    = baud;
  408.      serial[channel].SerWtReq->io_WriteLen    = data;
  409.      serial[channel].SerWtReq->io_StopBits    = stop;
  410.      serial[channel].SerWtReq->io_RBufLen    = rbuf_len;
  411.      serial[channel].SerWtReq->io_ExtFlags    = extflags;
  412.      serial[channel].SerWtReq->io_SerFlags    = flags;
  413.      serial[channel].SerWtReq->IOSer.io_Command = SDCMD_SETPARAMS;
  414.  
  415.      if (DoIO(serial[channel].SerWtReq)) 
  416.         error_code = OPEN_ERR;
  417.     }
  418.     else
  419.         error_code = OPEN_ERR;
  420. }
  421.  
  422. ULONG BytesIncoming(channel)
  423. ULONG channel;
  424. {
  425.     /* return number of bytes in serial port buffer */
  426.     
  427.     if (serial[channel].SerRdReq)
  428.     {
  429.          serial[channel].SerRdReq->IOSer.io_Command = SDCMD_QUERY;
  430.  
  431.          if (DoIO(serial[channel].SerRdReq))
  432.             error_code = READ_ERR;
  433.     }
  434.     else
  435.         { error_code = BAD_CHANNEL; return(0); }
  436.  
  437.     /* # of bytes incoming */
  438.     return(serial[channel].SerRdReq->IOSer.io_Actual);  
  439. }
  440.  
  441. ULONG SerialStatus(channel)
  442. ULONG channel;
  443. {
  444.     /* return serial port status bits */
  445.     
  446.     if (serial[channel].SerRdReq)
  447.     {
  448.          serial[channel].SerRdReq->IOSer.io_Command = SDCMD_QUERY;
  449.  
  450.          if (DoIO(serial[channel].SerRdReq))
  451.             error_code = READ_ERR;
  452.     }
  453.     else
  454.         { error_code = BAD_CHANNEL; return(0); }
  455.  
  456.     /* status of lines and registers */
  457.     return((ULONG)serial[channel].SerRdReq->io_Status);
  458. }
  459.  
  460. void ReadSerial(len,buf,channel)
  461. ULONG len;
  462. UBYTE *buf;
  463. ULONG channel;
  464. {
  465.     /* read len bytes of data from serial port into buf */
  466.  
  467.     channel--;
  468.  
  469.     if (channel < 0 || channel > 254) 
  470.        { error_code = BAD_CHANNEL; return; }
  471.  
  472.     if (serial[channel].SerRdReq)
  473.     {
  474.       serial[channel].SerRdReq->IOSer.io_Data    = (APTR)buf;
  475.       serial[channel].SerRdReq->IOSer.io_Length    = len;
  476.       serial[channel].SerRdReq->IOSer.io_Command    = CMD_READ;
  477.  
  478.       if (DoIO(serial[channel].SerRdReq))
  479.         error_code = READ_ERR;
  480.     }
  481.     else
  482.         { error_code = BAD_CHANNEL; buf[0] = '\0'; return; }
  483.  
  484.     buf[len] = '\0';    /* NULL terminated C/ACE string */
  485. }
  486.  
  487. void WriteSerial(len,buf,channel)
  488. ULONG len;
  489. UBYTE *buf;
  490. ULONG channel;
  491. {
  492.     /* write len bytes of data to serial port from buf */
  493.  
  494.     channel--;
  495.  
  496.     if (channel < 0 || channel > 254) 
  497.        { error_code = BAD_CHANNEL; return; }
  498.  
  499.     if (serial[channel].SerWtReq)
  500.     {
  501.       serial[channel].SerWtReq->IOSer.io_Data    = (APTR)buf;
  502.       serial[channel].SerWtReq->IOSer.io_Length    = len;
  503.       serial[channel].SerWtReq->IOSer.io_Command    = CMD_WRITE;
  504.  
  505.       if (DoIO(serial[channel].SerWtReq))
  506.         error_code = WRITE_ERR;
  507.     }
  508.     else
  509.         error_code = BAD_CHANNEL;
  510. }
  511.  
  512. ULONG serial_func(n,channel)
  513. ULONG n;
  514. ULONG channel;
  515. {
  516. /* serial port function: returns status information about
  517.    a serial port channel. 
  518. */
  519.  
  520.  channel--;
  521.  
  522.  if (channel < 0 || channel > 254) 
  523.     { error_code = BAD_CHANNEL; return(0L); }
  524.  
  525.  switch(n)
  526.  {
  527.     /* # of pending characters */
  528.       case 0 :     return(BytesIncoming(channel));
  529.             break;
  530.  
  531.     /* device unit # being used */
  532.     case 1 :    return(serial[channel].unit);
  533.             break;
  534.  
  535.     /* baud rate being used */
  536.     case 2 :    return(serial[channel].baud);
  537.             break;
  538.  
  539.     /* parity being used */
  540.     case 3 :    return(serial[channel].parity);
  541.             break;
  542.  
  543.     /* data bits being used */
  544.     case 4 :    return(serial[channel].data);
  545.             break;
  546.  
  547.     /* stop bits being used */
  548.     case 5 :    return(serial[channel].stop);
  549.             break;
  550.  
  551.     /* number of wires being used */
  552.     case 6 :    return(serial[channel].wires);
  553.             break;
  554.  
  555.     /* Xon/Xoff ON or OFF? */
  556.     case 7 :    return(serial[channel].Xon);
  557.             break;
  558.  
  559.     /* shared access to serial device? */
  560.     case 8 :    return(serial[channel].shared);
  561.             break;
  562.  
  563.     /* fast mode? */
  564.     case 9 :    return(serial[channel].fast);
  565.             break;
  566.  
  567.     /* buffer size being used */
  568.     case 10 :    return(serial[channel].bufsize);
  569.             break;
  570.  
  571.     /* address of serial device name */
  572.     case 11 :    return((char *)serial[channel].device_name);
  573.             break;
  574.  
  575.     /* serial port line and register status */
  576.     case 12 :    return(SerialStatus(channel));
  577.             break;
  578.  }
  579. }
  580.