home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 199.lha / GimmeLib / communic.c < prev    next >
C/C++ Source or Header  |  1988-12-27  |  9KB  |  379 lines

  1. /*
  2.  *  FILE: communic.c
  3.  *  Support routines for accessing, reading and writing to the serial port.
  4.  *
  5.  *  NOTE: these routines provide EXCLUSIVE access to the serial port for one
  6.  *  task only.    This shouldn't be too great a problem given the nature of the
  7.  *  serial port.
  8.  *
  9.  *  Public Domain, but keep our names in it as the original authors.
  10.  *  11-May-87    Scotte Zinn        created
  11.  *  15-Mar-88    Jan Sven Trabandt   changed c_set_error to a macro
  12.  *                    made sure it works with short (16 bit) ints
  13.  *  27-Apr-88    Jan Sven Trabandt   lots of goodies
  14.  *  31-Oct-88    Jan Sven Trabandt   added to gimme.lib (finally)
  15.  */
  16.  
  17.  
  18. #define I_AM_COMMUNIC
  19. #include "gimmelib/gimmefuncs.h"
  20. #include "gimmelib/communic.h"
  21. #include <devices/serial.h>
  22.  
  23.  
  24. #define C_NOT_OPEN    0
  25. #define BUFFER_LENGTH    4096
  26. #define INIT_VALUE    29451
  27.  
  28. #define initialized()       ((SHORT)initial != 0)
  29. #define channel_open()      ((SHORT)system_state != C_NOT_OPEN)
  30. #define c_set_error(err)    (c_error = err)
  31.  
  32. static struct IOExtSer    *IORser = NULL;
  33. static struct MsgPort    *SPort = NULL;
  34. static struct timerequest *treq = NULL;
  35. static char EOLchar = DEFAULT_EOL;
  36. static SHORT system_state = C_NOT_OPEN;
  37. static SHORT initial = 0;
  38.  
  39. short c_error;
  40.  
  41. /* forward declarations */
  42. static short c_getchar();
  43.  
  44.  
  45. short c_init()
  46. {
  47.     if( !initialized() ) {
  48.     /* Set system state to channel not open and set initialized flag */
  49.     Forbid();
  50.     initial = INIT_VALUE;
  51.     system_state = C_NOT_OPEN;
  52.     Permit();
  53.     }
  54.     return( c_set_error(C_ERR_OK) );
  55. } /* c_init */
  56.  
  57.  
  58. short c_open( parms )
  59.     struct c_parameters *parms;
  60. {
  61.     short   error;
  62.  
  63.     if( !parms ) {
  64.     return( c_set_error(C_ERR_BADPARM) );
  65.     }
  66.     if( !initialized() )
  67.     return( c_set_error(C_ERR_INITIAL) );
  68.     if( channel_open() )
  69.     return( c_set_error(C_ERR_OPEN) );
  70.  
  71.     /* Now access timer device for future time-outs and to get a Port */
  72.     if( !(treq = accessTimer(UNIT_VBLANK, &SPort)) ) {
  73.     return( c_set_error(C_ERR_CANT) );
  74.     }
  75.  
  76.     IORser = (struct IOExtSer *) CreateExtIO( SPort,
  77.                     (ULONG)sizeof(struct IOExtSer) );
  78.     if( !IORser ) {
  79.     releaseTimer( treq, NULL );
  80.     return( c_set_error(C_ERR_CANT) );
  81.     }
  82.  
  83.     if( parms->C_MODE == C_SER_7 ) {
  84.     IORser->io_SerFlags = SERB_7WIRE | SERB_XDISABLED;
  85.     }
  86.     if( OpenDevice(SERIALNAME, 0L, IORser, 0L) ) {
  87.     DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
  88.     releaseTimer( treq, NULL );
  89.     return( c_set_error(C_ERR_CANT) );
  90.     }
  91.  
  92.     system_state = -1;            /* Now set channel opened */
  93.  
  94.     if( error = c_setup(parms) ) {
  95.     CloseDevice( IORser );
  96.     DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
  97.     releaseTimer( treq, NULL );
  98.     system_state = C_NOT_OPEN;
  99.     return( c_set_error(error) );
  100.     }
  101.     EOLchar = DEFAULT_EOL;
  102.  
  103.     /* Channel is now successfully opened */
  104.     return( c_set_error(C_ERR_OK) );
  105. } /* c_open */
  106.  
  107.  
  108. short c_setup( parms )
  109.     struct c_parameters *parms;
  110. {
  111.     if( !(initialized() && channel_open()) )    /* important to check here */
  112.     return( c_set_error(C_ERR_CHAN) );
  113.     if( !parms ) {
  114.     return( c_set_error(C_ERR_BADPARM) );
  115.     }
  116.  
  117.     /* Now set parameters as requested */
  118.     IORser->io_ReadLen    = parms->C_RLEN;
  119.     IORser->io_BrkTime    = 750000L;
  120.     IORser->io_Baud    = parms->C_BAUD;
  121.     IORser->io_WriteLen = parms->C_WLEN;
  122.     IORser->io_StopBits = parms->C_STOP;
  123.     IORser->io_RBufLen     = BUFFER_LENGTH;
  124.  
  125.     /* Setup parity bits with validation */
  126.     IORser->io_SerFlags &= ~(SERB_PARTY_ODD & SERB_PARTY_ON);
  127.  
  128.     switch( parms->C_PARITY ) {
  129.       case C_NO_PARITY:
  130.     break;
  131.       case C_ODD_PARITY:
  132.     IORser->io_SerFlags |= SERB_PARTY_ODD | SERB_PARTY_ON;
  133.     break;
  134.       case C_EVEN_PARITY:
  135.     IORser->io_SerFlags |= SERB_PARTY_ON;
  136.     break;
  137.       default:
  138.     return( c_set_error(C_ERR_PARITY) );
  139.     } /* switch */
  140.  
  141.     IORser->IOSer.io_Command = SDCMD_SETPARAMS;
  142.     IORser->io_TermArray.TermArray0 = 0x51040303;
  143.     IORser->io_TermArray.TermArray1 = 0x03030303;
  144.  
  145.     if( DoIO(IORser) )
  146.     return( c_set_error(C_ERR_PARAMS) );
  147.  
  148.     /* Parameters were changed as needed */
  149.     return( c_set_error(C_ERR_OK) );
  150. } /* c_setup */
  151.  
  152.  
  153. /* internal use only!
  154. static short c_getchar( cinput, secs, micros )
  155.     char    *cinput;
  156.     ULONG   secs, micros;
  157. {
  158.     APTR    myptr;
  159.     short   iodone = 0;
  160.  
  161.     /* Send request for read a character */
  162.     IORser->IOSer.io_Data = (APTR) cinput;
  163.     IORser->IOSer.io_Length = 1;
  164.     IORser->IOSer.io_Command = CMD_READ;
  165.     SendIO( IORser );
  166.  
  167.     if( CheckIO(IORser) ) {
  168.     Remove( IORser );
  169.     return( c_set_error(C_ERR_OK) );
  170.     } else {
  171.     timeDelayAsync( secs, micros, UNIT_VBLANK, treq );
  172.     WaitPort( SPort );
  173.     while( myptr = (APTR) GetMsg(SPort) ) {
  174.         if( myptr == (APTR) IORser ) {
  175.         iodone = -1;
  176.         }
  177.     } /* while */
  178.     if( iodone ) {
  179.         killTimeDelay( treq );
  180.         return( c_set_error(C_ERR_OK) );
  181.     }
  182.     }
  183.  
  184.     /* Abort the requested IO and return error condition */
  185.     AbortIO( IORser );
  186.     Remove( IORser );
  187.     return( c_set_error(C_ERR_GET) );
  188. } /* c_getchar */
  189.  
  190.  
  191. short c_getc( cinput )
  192.     char    *cinput;
  193. {
  194. #ifdef GIMME_WIMPY
  195.     if( !(initialized() && channel_open()) )
  196.     return( c_set_error(C_ERR_CHAN) );
  197.     if( !buffer ) {
  198.     return( c_set_error(C_ERR_BADPARM) );
  199.     }
  200. #endif
  201.     return( c_getchar(cinput, BIG_SECS, BIG_MICROS) );
  202. } /* c_getc */
  203.  
  204.  
  205. short c_emptyc()
  206. {
  207.     short   err;
  208.     char    cinput;
  209.  
  210. #ifdef GIMME_WIMPY
  211.     if( !(initialized() && channel_open()) )
  212.     return( c_set_error(C_ERR_CHAN) );
  213. #endif
  214.     /* Empty the buffer */
  215.     while( (err = c_getchar(&cinput, SMALL_SECS, SMALL_MICROS)) == C_ERR_OK ) {
  216.     } /* while */
  217.  
  218.     /* Check for a buffer empty error and replace with ok status */
  219.     if( err == C_ERR_GET ) {
  220.     c_set_error(err = C_ERR_OK);
  221.     }
  222.     /* Return status of empty */
  223.     return( err );
  224. } /* c_emptyc */
  225.  
  226.  
  227. short c_putc( coutput )
  228.     char coutput;
  229. {
  230. #ifdef GIMME_WIMPY
  231.     if( !(initialized() && channel_open()) )
  232.     return( c_set_error(C_ERR_CHAN) );
  233. #endif
  234.     /* Now send character thru channel */
  235.     IORser->IOSer.io_Data = (APTR) &coutput;
  236.     IORser->IOSer.io_Length = 1;
  237.     IORser->IOSer.io_Command = CMD_WRITE;
  238.     if( DoIO(IORser) ) {
  239.     return( c_set_error(C_ERR_PUT) );
  240.     }
  241.     return( c_set_error(C_ERR_OK) );
  242. } /* c_putc */
  243.  
  244.  
  245. short c_gets( buffer, num_to_get )
  246.     char    *buffer;
  247.     SHORT   num_to_get;
  248. {
  249.     register SHORT  i;
  250.     short        error;
  251.  
  252. #ifdef GIMME_WIMPY
  253.     if( !(initialized() && channel_open()) )
  254.     return( c_set_error(C_ERR_CHAN) );
  255.     if( !buffer ) {
  256.     return( c_set_error(C_ERR_BADPARM) );
  257.     }
  258. #endif
  259.     if( num_to_get <= 0 ) {
  260.     return( c_set_error(C_ERR_ILLEGAL) );
  261.     }
  262.  
  263.     /* Now get the specified number of characters */
  264.     for( i = num_to_get; --i >= 0; ++buffer ) {
  265.     if( error = c_getchar(buffer, BIG_SECS, BIG_MICROS) ) {
  266.         return( c_set_error(error) );
  267.     }
  268.     } /* for */
  269.  
  270.     return( c_set_error(C_ERR_OK) );
  271. } /* c_gets */
  272.  
  273.  
  274. short c_getline( buffer, num_to_get )
  275.     char    *buffer;
  276.     SHORT   num_to_get;
  277. {
  278.     register SHORT  i;
  279.     short        error;
  280.  
  281. #ifdef GIMME_WIMPY
  282.     if( !(initialized() && channel_open()) )
  283.     return( c_set_error(C_ERR_CHAN) );
  284.     if( !buffer ) {
  285.     return( c_set_error(C_ERR_BADPARM) );
  286.     }
  287. #endif
  288.     if( num_to_get <= 0 ) {
  289.     return( c_set_error(C_ERR_ILLEGAL) );
  290.     }
  291.  
  292.     /* Now get the specified number of characters */
  293.     for( i = num_to_get; --i >= 0; ++buffer ) {
  294.     if( error = c_getchar(buffer, SMALL_SECS, SMALL_MICROS) ) {
  295.         *buffer = '\0';
  296.         return( c_set_error(error) );
  297.     }
  298.     if( *buffer == EOLchar ) {
  299.         break;
  300.     }
  301.     } /* for */
  302.  
  303.     return( c_set_error(C_ERR_OK) );
  304. } /* c_getline */
  305.  
  306.  
  307. short c_setEOL( character )
  308.     char character;
  309. {
  310. #ifdef GIMME_WIMPY
  311.     if( !(initialized() && channel_open()) )
  312.     return( c_set_error(C_ERR_CHAN) );
  313. #endif
  314.     EOLchar = character;
  315.     return( c_set_error(C_ERR_OK) );
  316. } /* c_setEOL */
  317.  
  318.  
  319. short c_puts( buffer, num_to_put )
  320.     char    *buffer;
  321.     SHORT   num_to_put;
  322. {
  323.     short   error;
  324.  
  325. #ifdef GIMME_WIMPY
  326.     if( !(initialized() && channel_open()) )
  327.     return( c_set_error(C_ERR_CHAN) );
  328.     if( !buffer ) {
  329.     return( c_set_error(C_ERR_BADPARM) );
  330.     }
  331. #endif
  332.     if( num_to_put <= 0 ) {
  333.     return( c_set_error(C_ERR_ILLEGAL) );
  334.     }
  335.     /* Now send the characters thru channel */
  336.     IORser->IOSer.io_Data = (APTR) buffer;
  337.     IORser->IOSer.io_Length = num_to_put;
  338.     IORser->IOSer.io_Command = CMD_WRITE;
  339.     if( DoIO(IORser) ) {
  340.     return( c_set_error(C_ERR_PUT) );
  341.     }
  342.     return( c_set_error(C_ERR_OK) );
  343. } /* c_puts */
  344.  
  345.  
  346. short c_close()
  347. {
  348.     short   err;
  349.  
  350. #ifdef GIMME_WIMPY
  351.     if( !(initialized() && channel_open()) )
  352.     return( c_set_error(C_ERR_CHAN) );
  353. #endif
  354.  
  355.     if( err = c_emptyc() ) {            /* Empty the buffer */
  356.     return( err );
  357.     }
  358.     /* Now close device and channel */
  359.     CloseDevice( IORser );
  360.     DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
  361.     releaseTimer( treq, NULL );         /* Now close timer device */
  362.     SPort = NULL;
  363.     system_state = C_NOT_OPEN;
  364.     return( c_set_error(C_ERR_OK) );
  365. } /* c_close */
  366.  
  367.  
  368. short c_done()
  369. {
  370.     if( initialized() ) {
  371.     /* Set system state to channel not open and clear initialized flag */
  372.     Forbid();
  373.     initial = 0;
  374.     system_state = C_NOT_OPEN;
  375.     Permit();
  376.     }
  377.     return( c_set_error(C_ERR_OK) );
  378. } /* c_done */
  379.