/*
**  $Filename: utilities/portswitch.c $
**  $Release: 1.2 $
**  $Revision: 1.2 $
**
**  Utility to switch mouse control to a different port
**
**  © Software Ambience 1995/96
**  All Rights Reserved
*/

/****i* PortSwitch **************************************************
*
*   NAME
*       PortSwitch -- Switch mouse control to a different port.
*
*   COPYRIGHT
*       © Software Ambience 1995/96
*
*   PROGRAMMER
*       Steve Sloggett of Software Ambience
*
*   STATUS
*       Freeware
*
*   LANGUAGE
*       C
*
*   CURRENT VERSION
*       1.2
*
*   USAGE
*       PortSwitch PORT/N/A
*
*   HISTORY
*       1.0 : 28th December 1995 : Initial version
*       1.1 : 29th December 1995 : Added command line parameters and
*                                  various code improvements
*       1.2 : 17th February 1996 : Miscellaneous changes
*
*   NOTES
*       Requires Kickstart 2.0 or higher.
*
*       This source code can be used as part of any program provided
*       that I am given credit for my work by means of the following
*       statement:
*
*           Part of this program is based upon Port Switch v1.2
*           which is © Software Ambience 1995/96
*
*       I would also appreciate being notified of this fact. Thanks.
*
**********************************************************************
*
*/

#include <exec/types.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <devices/input.h>

#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

/* Function prototypes */
void Terminate(STRPTR message, UBYTE code);

/* Personal habit :-) */
#define NOT !

/* Kickstart identification */
#define KICKSTART_2_0 36

/* Option identification */
#define OPTION_TEMPLATE "PORT/N/A"

#define OPTION_PORT  0
#define OPTION_COUNT 1

/* Library bases */
extern struct ExecBase *SysBase;

struct Library *DosBase = NULL;

/* Define program version string for use by command: version */
STRPTR version = "\0$VER: PortSwitch 1.2 (17.02.96)";

/****** PortSwitch/main **********************************************
*
*   NAME
*       main -- Logical start and end of the program.
*
*   SYNOPSIS
*       main()
*
*       void main(void);
*
*   FUNCTION
*       main() is the point where execution logically begins and ends.
*
*   INPUTS
*       void
*
*   RESULT
*       void
*
*   EXAMPLE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
**********************************************************************
*
*/

void main(void)
{
    BYTE port;
    LONG options[OPTION_COUNT];
    struct IOStdReq *request;
    struct MsgPort *messagePort;
    struct RDArgs *arguments;

    /* Default options */
    options[OPTION_PORT] = 0;
    /* Display program credits */
    printf("\nPort Switch v1.2 © Software Ambience 1995/96 (Freeware)\n");
    printf("Programmed by Steve Sloggett\n\n");
    /* Check if Kickstart 2.0 or higher is available */
    if(SysBase->LibNode.lib_Version < KICKSTART_2_0)
        Terminate("This program requires Kickstart 2.0 or higher", RETURN_WARN);
    /* Open dos.library */
    DosBase = OpenLibrary("dos.library", 36);
    if(NOT DosBase)
        /* Terminate execution */
        Terminate("Unable to open dos.library v36 or higher", RETURN_FAIL);
    /* Obtain the options supplied from the command line */
    arguments = ReadArgs(OPTION_TEMPLATE, options, NULL);
    /* Obtain the new mouse control port number */
    port = *((LONG *) options[OPTION_PORT]);
    /* Check the options supplied from the command line are valid */
    if(NOT arguments || (port != 0 && port != 1))
    {
        /* Close dos.library */
        CloseLibrary(DosBase);
        /* Terminate execution */
        Terminate("Mouse control port number is invalid", RETURN_FAIL);
    }
    /* Create the message port */
    messagePort = CreatePort(NULL, 0);
    if(NOT messagePort)
    {
        /* Free the arguments */ 
        FreeArgs(arguments);
        /* Close dos.library */
        CloseLibrary(DosBase);
        /* Terminate execution */
        Terminate("Unable to create a message port", RETURN_FAIL);
    }
    /* Create the request structure */
    request = CreateStdIO(messagePort);
    if(NOT request)
    {
        /* Remove the message port */
        DeletePort(messagePort);
        /* Free the arguments */ 
        FreeArgs(arguments);
        /* Close dos.library */
        CloseLibrary(DosBase);
        /* Terminate execution */
        Terminate("Unable to create a request", RETURN_FAIL);
    }
    /* Open the input device */
    if(OpenDevice("input.device", 0, request, NULL) != 0)
    {
        /* Free the request */
        DeleteStdIO(request);
        /* Remove the message port */
        DeletePort(messagePort);
        /* Free the arguments */ 
        FreeArgs(arguments);
        /* Close dos.library */
        CloseLibrary(DosBase);
        /* Terminate execution */
        Terminate("Unable to open input.device", RETURN_FAIL);
    }
    /* Create the request to change the mouse port */
    request->io_Message.mn_ReplyPort = messagePort;
    request->io_Command = IND_SETMPORT;
    request->io_Flags = NULL;
    request->io_Length = 1;
    request->io_Data = &port;
    /* Submit the request and wait for it to be carried out */
    DoIO(request);
    /* Close the input device */
    CloseDevice(request);
    /* Free the request */
    DeleteStdIO(request);
    /* Remove the message port */
    DeletePort(messagePort);
    /* Free the arguments */ 
    FreeArgs(arguments);
    /* Close dos.library */
    CloseLibrary(DosBase);
    /* Terminate execution */
    Terminate("Mouse control port is now changed", RETURN_OK);
}

/****** PortSwitch/Terminate *****************************************
*
*   NAME
*       Terminate -- Display an error message and return to AmigaDOS.
*
*   SYNOPSIS
*       Terminate(message, code)
*
*       void Terminate(STRPTR, UBYTE);
*
*   FUNCTION
*       Terminate() displays the supplied error message and then
*       terminates the program with the error code sprecified.
*
*   INPUTS
*       message - Error message to be displayed.
*       code    - Error code to return to AmigaDOS.
*
*   RESULT
*       void
*
*   EXAMPLE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
**********************************************************************
*
*/

void Terminate(STRPTR message, UBYTE code)
{
    /* Display termination message */
    printf("%s\n\n", message);
    /* Return error code to AmigaDOS */
    exit(code);
}
