/** @file dig_inputs.c

   Contains all functions to read digital inputs of the APCI-3200.

   @par CREATION
   @author Krauth Julien
   @date   06.06.05

   @par VERSION
   @verbatim
   $LastChangedRevision$
   $LastChangedDate$
   @endverbatim

   @par COMPILER
   @verbatim
   Compiler	: gcc
   Version	: gcc (GCC) 3.3.6 (Debian 1:3.3.6-5)
   kernel	: 2.4.26
   @endverbatim

   @par UPDATES
   @verbatim
   Date			:
   Author		:
   Description	:
   @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 "apci3200-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

/**
 * @note In this module, IO are indiced from 0
 */

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

/** Read 1 digital input channel.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [in]		cmd		IOCTL command. The command is <br>
 * 							CMD_APCI3200_Read1DigitalInput when using the IOCTL funktion.<br>
 * 							To call the function in kernel mode, cmd must be 0.
 * @param 			arg		Function argument. This is the digital input channel number (0 to 3).
 *
 * @retval 0		No error.
 * @retval -EFAULT	Can't get the input number / Can't return the input value.
 * @retval -EINVAL	The channel number is fals.
 */
int do_CMD_APCI3200_Read1DigitalInput(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	volatile uint32_t val = 0;
	uint8_t chan = 0;

	/* no need of locks in this code block (PRIVDATA is not used) */

	/* Gets the channel number from the user */
	if ( copy_from_user( &chan, (uint8_t __user*)arg, sizeof(uint8_t) ) )
		return -EFAULT;

	/* Legal values for channels are 0 to 3 included */
	if ( chan > 3 )
		return -EINVAL;

	/* Reads the input value from the board */
	val = inl(GET_BAR3(pdev));

	/* Shifts the input value for the decided channel */
	val = (val >> chan) & 1;

	/* Returns the modified input value to the user */
	if ( copy_to_user( (uint8_t __user *) arg , (uint32_t*) &val, sizeof(uint8_t) ) )
		return -EFAULT;

	return 0;
}
//------------------------------------------------------------------------------

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

/** Read 4 digital inputs channel.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [in]		cmd		IOCTL command. The command is <br>
 * 							CMD_APCI3200_Read4DigitalInputs when using the IOCTL funktion.<br>
 * 							To call the function in kernel mode, cmd must be 0.
 * @param 			arg		Function argument. arg can be a value from 0 up to 15.
 *
 * @retval 0		No error.
 * @retval -EFAULT	Can't return inputs value.
 */
int do_CMD_APCI3200_Read4DigitalInputs(struct pci_dev *pdev, unsigned int cmd, unsigned long arg)
{
	volatile uint32_t val = 0;

	/* no need of locks in this code block (PRIVDATA is not used) */

	/* Reads the input value from the board */
	/* Get only the 4 inputs status */
	val = inl(GET_BAR3(pdev)) & 0x1F;

	/* Returns inputs value to the user */
	if ( copy_to_user( (uint8_t __user *) arg , (uint32_t*) &val, sizeof(uint8_t) ) )
		return -EFAULT;

	return 0;
}
//------------------------------------------------------------------------------

