/*
 *
 *	DISCLAIMER:
 *
 *	This program is provided as a service to the programmer
 *	community to demonstrate one or more features of the Amiga
 *	personal computer.  These code samples may be freely used
 *	for commercial or noncommercial purposes.
 * 
 * 	Commodore Electronics, Ltd ("Commodore") makes no
 *	warranties, either expressed or implied, with respect
 *	to the program described herein, its quality, performance,
 *	merchantability, or fitness for any particular purpose.
 *	This program is provided "as is" and the entire risk
 *	as to its quality and performance is with the user.
 *	Should the program prove defective following its
 *	purchase, the user (and not the creator of the program,
 *	Commodore, their distributors or their retailers)
 *	assumes the entire cost of all necessary damages.  In 
 *	no event will Commodore be liable for direct, indirect,
 *	incidental or consequential damages resulting from any
 *	defect in the program even if it has been advised of the 
 *	possibility of such damages.  Some laws do not allow
 *	the exclusion or limitation of implied warranties or
 *	liabilities for incidental or consequential damages,
 *	so the above limitation or exclusion may not apply.
 *
 */

/* SetParallel allows the CLI user to dynamically change any particular
 * parallel port parameter.
 *
 * July 6, 1985  Version 1.0  Keith Stobie  Initial version (serial)
 * Aug 16, 1985  Version 1.1  Tom Pohorsky  cloned for parallel
 *
 */
char *prog_name;            /* Name of program being run */
char *prog_version = "1.0"; /* Version of the program */

#include        <exec/types.h>
#include        <exec/nodes.h>
#include        <exec/lists.h>
#include        <exec/memory.h>
#include        <exec/ports.h>
#include        <exec/libraries.h>
#include        <exec/devices.h>
#include        <exec/tasks.h>
#include        <exec/io.h>
#include        <devices/parallel.h>



extern struct MsgPort *CreatePort();

set_parallel( index, value )
   int   index;         /* which parameter to set */
   ULONG value;      /* The new value for paramter */
{
    struct IOExtPar IORpar;      /* Parallel port IO request block */
    int     error = 0;
    int     return_code = 0;
    
    IORpar.io_ParFlags |= PARF_SHARED;
    if ((error = OpenDevice (PARALLELNAME, 0, &IORpar, 0)) != 0) {
        printf( "Unable to open Parallel Device, error=%ld\n", error );
        return 20;
    }

    IORpar.IOPar.io_Flags   = 0;
    IORpar.IOPar.io_Command = PDCMD_QUERY;
    if ((error = DoIO( &IORpar )) != 0) {
        printf( "Parallel Device query error=%ld\n", error );
        return 20;
    }

    /* SET UP the read message port in the I/O request */
    if ((IORpar.IOPar.io_Message.mn_ReplyPort = CreatePort( "SetParallel", 0 ))
         == NULL) {
        printf( "Unable to create port for IO message\n" );
        CloseDevice( &IORpar );
        return 20;
      }

    switch( index ) {
      case 0:    print_request( &IORpar );         break;
      case 1:    IORpar.io_ParFlags      = value;  break;
      case 2:    IORpar.io_PTermArray.PTermArray0 = value;
                 /* ARRAY CAN BE SET ONLY IF EOFMODE */
                 /* SO SET MODE (x02) FROM CASE 1 */
                 /* fill out array with lowest valid value */
                 value = value & 0xFF;
                 IORpar.io_PTermArray.PTermArray1 
                     = value<<24 & value<<16 & value<<8 & value;
                 break;

      default:   printf( "Index value %ld is not in range 0-2!\n", index );
                 IORpar.IOPar.io_Error = 0;
                 return_code = 10;   
                 goto cleanup;
    } /* switch */

    IORpar.IOPar.io_Flags   = 0;
    IORpar.IOPar.io_Command = PDCMD_SETPARAMS;
    error = DoIO( &IORpar );
cleanup:
    DeletePort( IORpar.IOPar.io_Message.mn_ReplyPort );
    CloseDevice( &IORpar );
    if (error) {
       printf( "Error %ld doing IO to set params!\n", error );
       return 10;
    }
      
    if (IORpar.IOPar.io_Error) {
       printf( "Error %ld from parallel device doing set params!\n"
             , IORpar.IOPar.io_Error );
       return 10;
    }

    return (return_code);
}  /* set_parallel() */



print_request( IORpar )
    struct IOExtPar *IORpar;     /* Parallel port IO request block */
{
#define PRINT( field )     printf( "     %s = %8lx %8ld\n"\
                                 , "field", IORpar->field, IORpar->field)
#define IPRINT( index, field ) printf( " %2ld  %s = %8lx %8ld\n" \
                               , index, "field", IORpar->field, IORpar->field)

      printf( "index field name       hexadec  decimal\n" ); 
      IPRINT( 1, io_ParFlags  );
      IPRINT( 2, io_PTermArray.PTermArray0 );
          PRINT( io_PTermArray.PTermArray1 );
      printf( "\n" );   /* Not associated with an index */
          PRINT( io_Status    );
}  /* print_request() */


print_usage() {
   printf("%s: version %s\n", prog_name, prog_version );
   printf("usage: %s <index> <value>\n", prog_name );
   printf("  <index> is a decimal number indicating which parameter.\n" );
   printf("          0 indicates print current values (and indexes) \n");
   printf("            without changing them.\n" );
   printf("  <value> number to set the indexed parameter to.\n");
   printf("          value should be in decimal unless it starts with X\n" );
   printf("          or x in which case the number should be hexadecimal\n");
   exit( 5 );
}



ULONG get_hex( s )
   char *s;    /* String with hex digits */
{
   ULONG num=0;

   for (;*s != '\0'; s++) {
      switch( *s ) {
         case '0': case '1': case '2': case '3': case'4':
         case '5': case '6': case '7': case '8': case'9':
            num = num*16 + *s - '0'; break;
         case 'a': case 'b': case 'c': case 'd': case'e': case'f':
            num = num*16 + 10 + *s - 'a'; break;
         case 'A': case 'B': case 'C': case 'D': case'E': case'F':
            num = num*16 + 10 + *s - 'A'; break;
         default: return num;    /* return what we found */
      }
   }

   return num;
}  /* get_hex() */


int get_dec( s )
   char *s;    /* String with hex digits */
{
   int num=0;

   for (;*s != '\0'; s++) {
      switch( *s ) {
         case '0': case '1': case '2': case '3': case'4':
         case '5': case '6': case '7': case '8': case'9':
            num = num*10 + *s - '0'; break;
         default: return num;    /* return what we found */
      }
   }

   return num;
}  /* get_dec() */




main( argc, argv ) 
   int argc;
   char *argv[];
{
   int   index;
   ULONG value;

   if (argc <=0 ) { prog_name = "SetParallel"; }
   else { prog_name = argv[0];}

   if (argc == 1) { print_usage(); }

   if (argc < 2 ) { printf( "Too few parameters\n" ); print_usage();}
   if (argc > 3 ) { printf( "Too many parameters\n" ); print_usage();}

   index = get_dec( *++argv );

   if ((index != 0) && (argc < 3)) {
      printf( "Too few parameters\n" ); print_usage();
   }

   if (argc == 3) { 
      ++argv;
      if ((*argv[0] == 'x') || (*argv[0] == 'X')) {
         value = get_hex( *argv + 1 ); /* Skip x or X */
      } else {
         value = get_dec( *argv );
      }
   }

   exit( set_parallel( index, value ) ); 
   
}  /* main() */
