/*
 ******************************************************************************
 *  Copyright 1998 DeltaLink bv. All Rights Reserved.
 ******************************************************************************
 *
 * File: sapi_ev.c
 *
 * This module contains the events function for the sapi driver.
 *
 */
#ifdef WIN32

#define NOMSG             /* typedef MSG and associated routines */
#define _OLE2_H_          /* no ole */

#include  <windows.h>
#include  <process.h>

#undef ERROR

#endif


#include  <stdlib.h>
#include  <string.h>
#include  <stdio.h>
#include  <stdarg.h>


#include  <flib.h>						 /* FactoryLink definitions */
#include  <fl_utils.h>
#include  <g_utils.h>

#include  <imx.h>              /* Mailbox Communication Interface definitions */
#include  <imx_mt.h>           /* Mailbox Communication Interface definitions */
#include  <imx_fmt.h>          /* Mailbox Communication Interface definitions */

#include  <protocol.h>				 /*  DeltaLink SAPI definitions */
#include  <sapi_s7.h>					 /*  Siemens SAPI definitions   */
#include  <sapi.h>						 /*  DeltaLink SAPI definitions */


/*-----------------------------------------------------------------------------
 * FUNCTION: void  imx_event( IMXDS *ds )
 *
 * PURPOSE :  This function is not used
 *
 -----------------------------------------------------------------------------*/
int imx_event( IMXDS *ds )
{
  return GOOD;
}

/*-----------------------------------------------------------------------------
 * FUNCTION: disable_fnc
 *
 * PURPOSE: Set or reset the disable flag on the device of a specific function.
 -----------------------------------------------------------------------------*/
int disable_fnc( void *flag, VAL value)
{
  char * disable = ( char * )flag;

  /* set the value of the disable flag */

  disable[ INTERNAL ] = ( char)value.dig;
  disable[ USER     ] = ( char)value.dig;

  debug_log( &Task_win, "DBG_DISABLE", 5, (int)value.dig);

  return 0;
}


/*-----------------------------------------------------------------------------
 * FUNCTION: cyclic_read
 *
 * PURPOSE: Start or stop the cyclic read functionality
 -----------------------------------------------------------------------------*/
int cyclic_read( void *ds, VAL cyclic_rate )
{
  DS_INFO *ds_info = ( DS_INFO * )ds;

	/*
	 * check first if the device is connected
	 */
  if ( ds_info->device->connect != CS_CONNECTED )
	{
		return 0;
	}

  /*
   * perform the right action on the cyclic function
   */
  if ( cyclic_rate.ana != 0 )
  {
    /* update the cyclic rate variable */

    ds_info->cyclic_read = cyclic_rate.ana;

		/*
		 * the manipulation of the cyclic operations must be critical sections
		 */
		fl_enter_critical( FLS_NORMAL );

		/* check if the maximum number of pending requests has been reached */

		if ( ds_info->device->cyclic_pending[ CSTART ] == MAX_CYCLIC_REQ_PENDING )
		{
      update_status( &Task_win, ds_info->device, PD_MAX_CYCLIC );

			fl_status( &Task_win, "S7_CYCL_READ_MAX_REQ", FLS_ERROR );
		}
		else
		{
			ds_info->device->cyclic[ CSTART ][ ds_info->device->cyclic_head[ CSTART ] ] = ds_info;

			POINTER_UP( ds_info->device->cyclic_head[ CSTART ] );

			/*
			 * Check if there is already an cyclic read request pending. If so then
			 * buffer the request
			 */
			if ( !ds_info->device->cyclic_pending[ CSTART ] )
			{
				if ( sapi_start_cyclic ( &Task_win, ds_info ) != GOOD )
				{
					/*
					 * update the status tag of the device here
					 */
					update_status( &Task_win, ds_info->device, PD_START_CYCLIC );
				}
			}

			ds_info->device->cyclic_pending[ CSTART ]++;
		}

    /*
     * the manipulation of the cyclic operations must be critical sections
     */
    fl_leave_critical( FLS_NORMAL );

  }
  else
  {
    /*
     * Cylic queue manipulation must be a critical section
     */
    fl_enter_critical( FLS_NORMAL );

		/* check if the maximum number of pending requests has been reached */

		if ( ds_info->device->cyclic_pending[ CSTOP ] == MAX_CYCLIC_REQ_PENDING )
		{
      update_status( &Task_win, ds_info->device, PD_MAX_CYCLIC );

			fl_status( &Task_win, "S7_CYCL_READ_MAX_STOP", FLS_ERROR );
		}
		else
		{

			/* buffer cyclic read request and set out after acknowledgements */

			ds_info->device->cyclic[ CSTOP ][ ds_info->device->cyclic_head[ CSTOP ] ] = ds_info;

			POINTER_UP( ds_info->device->cyclic_head[ CSTOP ] );

			if ( !ds_info->device->cyclic_pending[ CSTOP ] )
			{
				if ( sapi_stop_cyclic ( &Task_win, ds_info ) != GOOD )
				{
					/*
					 * update the status tag of the device here
					 */
					update_status( &Task_win, ds_info->device, PD_STOP_CYCLIC );
				}
			}

			ds_info->device->cyclic_pending[ CSTOP ]++;
		}

    /*
     * end of the critical section
     */
    fl_leave_critical( FLS_NORMAL );
  }

  return 0;
}

/*-----------------------------------------------------------------------------
 * FUNCTION: set_board
 *
 * PURPOSE: Set the board for the depending devices
 -----------------------------------------------------------------------------*/
int set_board( void *flag, VAL value)
{

  return 0;
}


