/* sample to test yoy!
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <devices/timer.h>
#include <devices/inputevent.h>

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

#include <stdio.h>
#include <stdlib.h>
#include "timerhandle.h"

#define TIMEOUT_SECONDS (10)

void wait_4_completion(struct IORequest * TimerIO);

extern struct ExecBase *SysBase;

/*
 * clear the buffer.  do this before you begin to be sure you
 * start in a known state.
 */
VOID flush_buffer(struct IOStdReq *game_io_msg)
{
    game_io_msg->io_Command = CMD_CLEAR;
    game_io_msg->io_Flags   = IOF_QUICK;
    game_io_msg->io_Data    = NULL;
    game_io_msg->io_Length  = 0;
    DoIO((struct IORequest *)game_io_msg);
}


/*
 * All I/O requests must be complete before CloseDevice().  If any requests
 * are still pending, abort them with AbortIO() and remove them with WaitIO().
 */
void wait_4_completion(struct IORequest * io_msg)
{

    if (!(CheckIO(io_msg)))
    {
        AbortIO(io_msg);  /* Ask device to abort request, if pending */
    }
    WaitIO(io_msg);   /* Wait for abort, then clean up */
}


/*
 * add a timer event
 */

void send_timer(struct timerequest *tr, struct timeval *tv )
{
    tr->tr_node.io_Command = TR_ADDREQUEST;        /* add a new timer request */

    tr->tr_time = *tv;                      /* timevalue structure assignment */

                      /* post request to the timer -- will return immediately */
    SendIO((struct IORequest *) tr );

#ifdef VERBOSE
    printf("timerhandle.c: sending a timer wait request\n");
#endif
}

void wait_for_timer(struct timerequest *tr, struct timeval *tv )
{
    tr->tr_node.io_Command = TR_ADDREQUEST;            /* add a new timer request */

                                                      /* structure assignment */
    tr->tr_time = *tv;

                   /* post request to the timer -- will go to sleep till done */
    DoIO((struct IORequest *) tr );
}

/*
 * cleanup timer
 */
void delete_timer(struct timerequest *tr )
{
    struct MsgPort *tp;

    wait_4_completion((struct IORequest *) tr);

    if (tr != NULL )
    {
        tp = tr->tr_node.io_Message.mn_ReplyPort;

        if (tp != NULL) DeletePort(tp);

    CloseDevice( (struct IORequest *) tr );
    DeleteExtIO( (struct IORequest *) tr );
    }
}

/*
 * timer setup
 */
struct timerequest * create_timer( ULONG unit )
{
/* return a pointer to a timer request.  If any problem, return NULL */
    LONG error;
    struct MsgPort * timerport;
    struct timerequest * TimerIO;

    timerport = CreatePort( "Timer_test_port", 0 );
    if (timerport == NULL )
    {
#ifdef DEBUG
        printf("timerhandle.c: Setup_Timer() has problems creating the message port\n");
#endif
        return(NULL);
    }
#ifdef VERBOSE
    printf("timer message port created\n");
#endif

    TimerIO = (struct timerequest *) CreateExtIO(timerport, sizeof(struct timerequest) );
    if (TimerIO == NULL )
    {
        DeletePort(timerport);   /* Delete message port */
#ifdef DEBUG
        printf("timerhandle.c: Setup_Timer() has problems creating the message block\n");
#endif
        return(NULL);
    }
#ifdef VERBOSE
    printf("timer message block for device I/O created\n");
#endif

    error = OpenDevice(TIMERNAME, unit,(struct IORequest *) TimerIO, 0L );
    if (error != 0 )
    {
        delete_timer( TimerIO );
#ifdef DEBUG
        printf("timerhandle.c: Setup_Timer() has problems opening the timer.device\n");
#endif
        return(NULL);
    }
#ifdef VERBOSE
    printf("timer.device opened\n");
#endif

    return( TimerIO );
}
