/** @file dig_io.c
 
   Contains digital I/O ioctl functions.
 
   @par CREATION  
   @author Krauth Julien
   @date   03.04.2007
   
   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim   
   
   @par LICENCE
   @verbatim
   Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
        
        ADDI-DATA GmbH 
        Dieselstrasse 3 
        D-77833 Ottersweier 
        Tel: +19(0)7223/9493-0 
        Fax: +49(0)7223/9493-92 
        http://www.addi-data-com 
        info@addi-data.com 
        
   This program is free software; you can redistribute it and/or modify it under 
   the terms of the GNU General Public License as published by the Free Software 
   Foundation; either version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, 
   but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
   or FITNESS FOR A PARTICULAR PURPOSE. 
   See the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with 
   this program; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

   You shoud also find the complete GPL in the COPYING file 
   accompanying this source code.
   @endverbatim   
 */ 

#include "apci2200-private.h"

/**@def EXPORT_NO_SYMBOLS
 * Function in this file are not exported.
 */
EXPORT_NO_SYMBOLS;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
#define __user 
#endif

//------------------------------------------------------------------------------	

/** Read 8 digital input.
 *
 * @param [in] pdev                       : The device to initialize.
 * @param [out] arg (b_DigitalInputValue) : Digital input channel status <br>
 *                                             0 : Channle is not active <br>
 *                                             1 : Channle is active    
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval -EFAULT : Fail to retrieve user data.             
 */
int do_CMD_APCI2200_Read8DigitalInput (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret = 0;											
	uint8_t b_Tmp = 0;
	
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Read8DigitalInput (pdev, &b_Tmp);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}									
	if (ret)
		return (ret);		
		
	if ( copy_to_user( (uint8_t __user *)arg , &b_Tmp, sizeof(b_Tmp) ) )
		return -EFAULT;													
												
	return (ret);
}																

//------------------------------------------------------------------------------

/** Activates the digital output memory. 
 * 
 * After having called up this function, the output you have previously
 * activated with the function "i_APCI2200_SetXDigitalOutputOn" are not reset.
 * You can reset them with the function "i_APCI2200_SetXDigitalOutputOff".                  
 *
 * @param [in] pdev                  : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Output memory is already set on.
 */
int do_CMD_APCI2200_SetDigitalOutputMemoryOn (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret = 0;											
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_SetDigitalOutputMemoryOn (pdev);								
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}								
	return (ret);
}

//------------------------------------------------------------------------------

/** Deactivates the digital output memory.
 *
 * @param [in] pdev                  : The device to initialize.
  * 
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Output memory is already set off.
 */
int do_CMD_APCI2200_SetDigitalOutputMemoryOff (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret = 0;											
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_SetDigitalOutputMemoryOff (pdev);								
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}								
	return (ret);
}

//------------------------------------------------------------------------------

/** Set 1 digital output on. 
 * 
 * Setting an output means setting an ouput high.                                         
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] arg (b_DigitalOutput) : Selection from digital output (0 to 15). 
 * 
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Wrong digital output (0 to 15). 
 */
int do_CMD_APCI2200_Set1DigitalOutputOn (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret;
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Set1DigitalOutputOn (pdev, arg);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	
	return ret;
}	

//------------------------------------------------------------------------------

/** Set 1 digital output off. 
 * 
 * Setting an output means setting an ouput low.                                         
 *
 * @param [in] pdev                  : The device to initialize.
 * @param [in] arg (b_DigitalOutput) : Selection from digital output (0 to 15). 
 * 
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Digital output memory is not activated.
 * @retval 3: Wrong digital output (0 to 15). 
 */
int do_CMD_APCI2200_Set1DigitalOutputOff (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret;
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Set1DigitalOutputOff (pdev, arg);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	
	return ret;
}	

//------------------------------------------------------------------------------

/** Set 8 digital output on.                                        
 *
 * @param [in] pdev                 : The device to initialize.
 * @param [in] arg[0] (b_Port)      : The port to set (0: Port 1, 1: Port 2).
 * @param [in] arg[1] (b_PortValue) : Port value (0 to 0xFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The port parameter of the board is wrong (has to be 0: Port 1, 1: Port 2).
 * @retval -EFAULT : Fail to retrieve user data. 
 */
int do_CMD_APCI2200_Set8DigitalOutputOn (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{										
	uint8_t b_ArgArray[2];
	int ret;

	if ( copy_from_user( b_ArgArray, (uint8_t __user *)arg, sizeof(b_ArgArray) ) )
		return -EFAULT;									

	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{		
			ret = i_APCI2200_Set8DigitalOutputOn (pdev, b_ArgArray[0], b_ArgArray[1]);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	
	return ret;
}	

//------------------------------------------------------------------------------

/** Set 8 digital output off.                                        
 *
 * @param [in] pdev                 : The device to initialize.
 * @param [in] arg[0] (b_Port)      : The port to set (0: Port 1, 1: Port 2).
 * @param [in] arg[1] (b_PortValue) : Port value (0 to 0xFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The port parameter of the board is wrong (has to be 0: Port 1, 1: Port 2).
 * @retval 3: Digital output memory is not activated.
 */
int do_CMD_APCI2200_Set8DigitalOutputOff (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{										
	uint8_t b_ArgArray[2];
	int ret;
    			        
	if ( copy_from_user( b_ArgArray, (uint8_t __user *)arg, sizeof(b_ArgArray) ) )
		return -EFAULT;									
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Set8DigitalOutputOff (pdev, b_ArgArray[0], b_ArgArray[1]);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	
	return ret;
}	

//------------------------------------------------------------------------------

/** Set 16 digital output on.                                       
 *
 * @param [in] pdev                       : The device to initialize.
 * @param [in] arg (w_DigitalOutputValue) : Port value (0 to 0xFFFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int do_CMD_APCI2200_Set16DigitalOutputOn (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret;
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Set16DigitalOutputOn (pdev, (uint16_t) arg);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	
	return ret;
}	

//------------------------------------------------------------------------------

/** Set 16 digital output off.                                       
 *
 * @param [in] pdev                       : The device to initialize.
 * @param [in] arg (w_DigitalOutputValue) : Port value (0 to 0xFFFF).
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Digital output memory is not activated.
 */
int do_CMD_APCI2200_Set16DigitalOutputOff (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret;
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = (i_APCI2200_Set16DigitalOutputOff (pdev, (uint16_t) arg));
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
	return ret;
}	

//------------------------------------------------------------------------------

/** Read 16 digital output             
 *
 * @param [in] pdev                        : The device to initialize.
 *
 * @param [out] arg (w_DigitalOutputValue) : Digital output port status.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wro
 * @retval -EFAULT : Fail to export user data. 
 */
int do_CMD_APCI2200_Read16DigitalOutput (struct pci_dev *pdev, unsigned int cmd, unsigned long arg)   
{
	int ret;											
	uint16_t w_Tmp = 0;
	{
		unsigned long irqstate;
		if (APCI2200_LOCK(pdev,&irqstate))
 			return -ERESTARTSYS;
		{
			ret = i_APCI2200_Read16DigitalOutput (pdev, &w_Tmp);
		}
		APCI2200_UNLOCK(pdev,irqstate);
	}
											
	if (ret != 0)
		return (ret);		
		
	if ( copy_to_user( (uint16_t __user *)arg , &w_Tmp, sizeof(w_Tmp) ) )
		return -EFAULT;													
											
	return (ret);
}	

//------------------------------------------------------------------------------




