/***************************************************************************
 *   Copyright (C) 2005 by EVER Sp. z o.o.                                 *
 *                                                                         *
 *   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.             *
 ***************************************************************************/
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#include "ccomm.h"
#include "conf.h"
#include "common.h"

#define DUOPRO_DRIVER_BUILD 1
#include "duopro.h"

/* 
 * Deklaracje zmiennych globalnych
 */
sdrv_config sdcDuoPro;
int iDuoPro_ExtError = 0;
CComm	commDuoPro;

int duopro_ioctl(long lCommand, void *lpvBuff, int *lpiBuffSize)
{
	switch(lCommand)
	{
	case IOCTL_INIT: 
		return DuoPro_DoInit(lpvBuff, lpiBuffSize);

	case IOCTL_UNINIT:
		return DuoPro_DoUnInit(lpvBuff, lpiBuffSize);
		
	case IOCTL_GETCONFIGFILENAME:
		return DuoPro_DoGetConfigFileName(lpvBuff, lpiBuffSize);

	case IOCTL_AUTOCONFIGURE: 
		return DuoPro_DoAutoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_CONFIGURE: 
		return DuoPro_DoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSINFOMASK: 
		return DuoPro_DoGetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSINFOMASK:
		return DuoPro_DoSetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATESMASK:
		return DuoPro_DoGetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSTATESMASK:
		return DuoPro_DoSetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATE:
		return DuoPro_DoGetUpsState(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMSMASK:
		return DuoPro_DoGetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSPARAMSMASK:
		return DuoPro_DoSetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMS:
		return DuoPro_DoGetUpsParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMSMASK:
		return DuoPro_DoGetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMSMASK:
		return DuoPro_DoSetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMS:
		return DuoPro_DoGetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMS:
		return DuoPro_DoSetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTICMASK:
		return DuoPro_DoGetUpsCharacteristicMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTIC:
		return DuoPro_DoGetUpsCharacteristic(lpvBuff, lpiBuffSize);

	case IOCTL_GET_DRIVER_INFO:
		return DuoPro_DoGetDriverInfo(lpvBuff, lpiBuffSize);

	case IOCTL_GET_ERRORNO:
		return DuoPro_DoGetExtendedError(lpvBuff, lpiBuffSize);

	case IOCTL_TESTUPSLINK:
		return DuoPro_DoTestUpsLink(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMSCOUNT:
		return DuoPro_DoGetConfigParamsCount(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMS:
		return DuoPro_DoGetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAM:
		return DuoPro_DoGetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAMS:
		return DuoPro_DoSetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAM:
		return DuoPro_DoSetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_UPDATECONFIG:
		return DuoPro_DoUpdateConfig(lpvBuff, lpiBuffSize);

	case IOCTL_GETDRIVERMODE:
		return DuoPro_DoGetDriverMode(lpvBuff, lpiBuffSize);

	case IOCTL_SHUTDOWNUPS:
		return DuoPro_DoUpsShutdown(lpvBuff, lpiBuffSize);

	default:
		return IOCTL_ERROR_CMD_NOTSUPPORTED;
	}
}

// Function name	: DuoPro_DoInit
// Description		: Inicjalizacja drivera
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_DoInit( void *lpvBuff, int *lpiBuffSize )
{
	iDuoPro_ExtError = 0;

	if (DuoPro_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;
	
	commDuoPro.init(sdcDuoPro.szSerialPort, 0);
	if (commDuoPro.open_simplesignalling()!=COMM_SUCCESS) {
		iDuoPro_ExtError=IOCTL_ERROR_COMM_INITFAIL;
		return IOCTL_ERROR;
	}
	
	commDuoPro.clr_line(S_DTR);
	commDuoPro.set_line(S_RTS);
	
	iDuoPro_ExtError = 0;
	DuoPro_DoUpdateConfig(NULL, NULL);	

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoUnInit
// Description		: Deinicjalizacja drivera
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_DoUnInit( void *lpvBuff, int *lpiBuffSize )
{
	commDuoPro.clr_line(S_DTR);
	commDuoPro.clr_line(S_RTS);
	if (commDuoPro.close()!=COMM_SUCCESS) {
		iDuoPro_ExtError=0;
		return IOCTL_ERROR;
	}
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DoUnInit
// Description		: 
int DuoPro_DoGetConfigFileName( void *lpvBuff, int *lpiBuffSize )
{
	if (lpvBuff != NULL) {
		if ( *lpiBuffSize >= strlen(DRIVER_CONFIG_FILE) )
			strcpy((char *)lpvBuff, DRIVER_CONFIG_FILE );
		else
			return IOCTL_ERROR_INVALIDARGUMENT;
	} else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DoAutoConfigure
// Description		: Self configure
int DuoPro_DoAutoConfigure( void *lpvBuff, int *lpiBuffSize )
{
	sdcDuoPro.iSerialPort=1;
	sprintf( sdcDuoPro.szSerialPort, "/dev/ttyS%d", sdcDuoPro.iSerialPort );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DoConfigure
// Description		: Configure driver to work properly with UPS
int DuoPro_DoConfigure( void *lpvBuff, int *lpiBuffSize )
{
	sdcDuoPro.iSerialPort=1;
	sprintf( sdcDuoPro.szSerialPort, "/dev/ttyS%d", sdcDuoPro.iSerialPort );
	
	DuoPro_DoUnInit(NULL, NULL);
	DuoPro_DoInit(NULL, NULL);

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetUpsInfoMask
// Description		: Zwraca informacje o wypelnieniu struktury informacji o UPS-ie
int DuoPro_DoGetUpsInfoMask( void *lpvBuff, int *lpiBuffSize )
{
	unsigned long ulMask = UI_PARAMETERS | UI_SETUP_PARAMETERS | UI_UPS_STATE;

	if ( *lpiBuffSize == sizeof( unsigned long ) )
		memcpy( lpvBuff, &ulMask, sizeof( unsigned long ) );
	else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DoSetUpsInfoMask
// Description		: 
int	DuoPro_DoSetUpsInfoMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetUpsStateMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsStateMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long	ulMask = US_POWERON | US_POWERFAIL | US_BATTERYLOW;

	if ( *lpiBuffSize == sizeof( unsigned long ) )
		memcpy( lpvBuff, &ulMask, sizeof( unsigned long ) );
	else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetUpsStateMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoSetUpsStateMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetUpsState
// Description		: Return actual UPS state
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsState(void *lpvBuff, int *lpiBuffSize)
{
#undef NOTSET
#define NOTSET(src, bit) (((src & bit)==bit)?0:1)

	unsigned long ulUpsState = 0;
	unsigned int uiUpsState[3] = { 0 };
	unsigned int uiCnt = 0;

	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < sizeof(ulUpsState))
			return IOCTL_ERROR_INVALIDARGUMENT;

	if (commDuoPro.isInitialized()) {
		// check if communication is still active
		//for (uiCnt=0; uiCnt<3; uiCnt++)
		//	if (commDuoPro.status_check(CTS) < 0)
		//		iDuoPro_ExtError = IOCTL_ERROR_COMM_LINKTERMINATED;
		//	else
				iDuoPro_ExtError = 0;
		//if (iDuoPro_ExtError != 0)
		//	return IOCTL_ERROR;

		for (uiCnt=0; uiCnt<3; uiCnt++) {
			usleep(30000);
			uiUpsState[0] = commDuoPro.getStatus();
			usleep(30000);
			uiUpsState[1] = commDuoPro.getStatus();
			usleep(30000);
			uiUpsState[2] = commDuoPro.getStatus();
			if (uiUpsState[0]==uiUpsState[1])
				uiUpsState[2]=uiUpsState[0]=uiUpsState[1];
			else if (uiUpsState[0]==uiUpsState[2])
				uiUpsState[0]=uiUpsState[1]=uiUpsState[2];
			else if (uiUpsState[1]==uiUpsState[2])
				uiUpsState[0]=uiUpsState[1]=uiUpsState[2];
			else
				continue;
			break;
		}
	} else {
		iDuoPro_ExtError = IOCTL_ERROR_NOTYETINITIALIZED;
		return IOCTL_ERROR;
	}
	
	// Only these flags are supported by now and forever
	// US_POWERON | US_POWERFAIL | US_BATTERYLOW

	// bits conversion to the pscore standard
	if ((uiUpsState[0] & USB_AND_POWERFAIL) == USB_FLAG_POWERFAIL)
		ulUpsState |= US_POWERFAIL;
	else
		ulUpsState &= ~(US_POWERFAIL);

	ulUpsState &= ~(US_POWERON);
	if (NOTSET(ulUpsState, US_POWERFAIL))
		ulUpsState |= US_POWERON;
	
	ulUpsState &= ~(US_BATTERYLOW);
	if ((uiUpsState[0] & USB_AND_LOWBATTERY) == USB_FLAG_LOWBATTERY) {
		if (NOTSET(ulUpsState, US_POWERON))
			ulUpsState |= US_BATTERYLOW;
	}

	memcpy( lpvBuff, &ulUpsState, *lpiBuffSize );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetUpsParamsMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	__int64 iMask = UP_UID_FAMILY | UP_UID_MODEL;

	if ( *lpiBuffSize == sizeof( __int64 ) )
		memcpy( lpvBuff, &iMask, sizeof( __int64 ) );
	else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetUpsParamsMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoSetUpsParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetUpsParams
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsParams(void *lpvBuff, int *lpiBuffSize)
{
	int iSize, iRet;
	supsp sup;

	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < sizeof( supsp ))
			return IOCTL_ERROR_INVALIDARGUMENT;

	iSize = PARAMS_TABLE_ITEMS;
	iRet = DuoPro_GetAllUpsParams( sdcDuoPro.uiParamsTable, &iSize );
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// fill params mask
	sup.iMask = UP_UID_FAMILY | UP_UID_MODEL;

	sprintf( sup.sz__uid_model, "%s %s", DRIVER_UPS_PREFIX, DRIVER_UPS_SUFFIX );
	sprintf( sup.sz__uid_family, "%s", DRIVER_UPS_FAMILY );

	memcpy( lpvBuff, &sup, sizeof(supsp) );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetUpsSetupParamsMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsSetupParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long ulMask = 0;

	if ( *lpiBuffSize == sizeof( unsigned long ) )
		memcpy( lpvBuff, &ulMask, sizeof( unsigned long ) );
	else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetUpsSetupParamsMask
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoSetUpsSetupParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetUpsSetupParams
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetUpsSetupParams
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoSetUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetDriverInfo
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetDriverInfo(void *lpvBuff, int *lpiBuffSize)
{
	if (*lpiBuffSize != sizeof(sdrv_info))
		return IOCTL_ERROR_INVALIDARGUMENT;
	sprintf( (( lpsdrv_info )lpvBuff )->szName, "%s DRIVER", DRIVER_UPS_PREFIX );
	sprintf( (( lpsdrv_info )lpvBuff )->szFamily, "%s", DRIVER_UPS_FAMILY );
	((lpsdrv_info)lpvBuff)->eLink = ul_serial;
	((lpsdrv_info)lpvBuff)->uiVersionMajor = DRIVER_VERSION_MAJOR;
	((lpsdrv_info)lpvBuff)->uiVersionMinor = DRIVER_VERSION_MINOR;
	strcpy(((lpsdrv_info)lpvBuff)->szCfgFileName, DRIVER_CONFIG_FILE);
	strcpy(((lpsdrv_info)lpvBuff)->szBmpFileName, DRIVER_BITMAP_FILE);

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetExtendedError
// Description		: Get extended error information - return value of last error
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetExtendedError(void *lpvBuff, int *lpiBuffSize)
{
	return iDuoPro_ExtError;
}

// Function name	: DuoPro_DoGetUpsCharacteristicMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsCharacteristicMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long ulMask=0;

	if ( *lpiBuffSize == sizeof( unsigned long ) )
		memcpy( lpvBuff, &ulMask, sizeof( unsigned long ) );
	else
		return IOCTL_ERROR_INVALIDARGUMENT;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetUpsCharacteristic
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetUpsCharacteristic(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoTestUpsLink
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoTestUpsLink(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetUPSStructures
// Description		: Return specified structure from UPS
// Return type		: int 
// Argument         : eups_structs eType
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_DoGetUPSStructures(eups_structs eType, void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoSetUPSStructures
// Description		: 
// Return type		: int 
// Argument         : eups_structs eType
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
// Argument         : int *lpiBuffErrPos
int DuoPro_DoSetUPSStructures(eups_structs eType, void *lpvBuff, int *lpiBuffSize, int *lpiBuffErrPos )
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoGetConfigParamsCount
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_DoGetConfigParamsCount(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long ulCount = INT_MAX_SETUPITEMS;

	if ( lpiBuffSize != NULL )
		if ( *lpiBuffSize < sizeof( unsigned long ) )
			return IOCTL_ERROR_INVALIDARGUMENT;

	memcpy( lpvBuff, &ulCount, sizeof( ulCount ) );

	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetConfigParams
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetConfigParams(void *lpvBuff, int *lpiBuffSize)
{
	int icnt;
	scfg_value scfgvaldef[ INT_MAX_SETUPITEMS ];
	char szStr[ MAX_PATHBUFF ];
	unsigned long ulSize;

	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < sizeof( scfgvaldef ))
			return IOCTL_ERROR_INVALIDARGUMENT;

	/* Port komunikacyjny */
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].eType = VT_INTLIST;
	strcpy(scfgvaldef[ INT_UPSCFG_SERIALCOMM ].szName, TXT_CFG_COMMUNICATIONPORT);
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue = (int)sdcDuoPro.iSerialPort-1;
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].range.lMin = 0;
	for (icnt = 0; icnt < 32; icnt++)
	{
		sprintf(szStr, "/dev/ttyS%d", icnt+1);
		strcpy(scfgvaldef[ INT_UPSCFG_SERIALCOMM ].list[icnt].szName, szStr);
		scfgvaldef[ INT_UPSCFG_SERIALCOMM ].list[icnt].iValue = atoi((const char *)(szStr + 3) ) - 1;
		memset(szStr, 0, sizeof(szStr));
	}
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].range.lMax = icnt-1;
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].iListItems = icnt;

	memcpy( lpvBuff, scfgvaldef, *lpiBuffSize );

	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetConfigParams
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoSetConfigParams(void *lpvBuff, int *lpiBuffSize)
{
	int iSize, iRet;
	unsigned long ulSize;
	scfg_value scfgvaldef[ INT_MAX_SETUPITEMS ];

	if ( *lpiBuffSize != (sizeof(scfg_value) * INT_MAX_SETUPITEMS) )
		return IOCTL_ERROR_INVALIDARGUMENT;
	else
		memcpy( &scfgvaldef, lpvBuff, *lpiBuffSize );

	/* Port komunikacyjny */
	sdcDuoPro.iSerialPort = scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue + 1;
	sprintf(sdcDuoPro.szSerialPort, "/dev/ttyS%d", scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue + 1);

	/* TODO - self file configuration update */	
	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetConfigParam
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetConfigParam(void *lpvBuff, int *lpiBuffSize)
{
	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoSetConfigParam
// Description		: 
int	DuoPro_DoSetConfigParam(void *lpvBuff, int *lpiBuffSize)
{
	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_ReadConfig
// Description		: 
int	DuoPro_ReadConfig()
{
	char *fp;
	fp = get_config_filepath(DRIVER_CONFIG_FILE);
	if (fp==NULL) {
		return IOCTL_ERROR;
	}
	CConf *pCfgDev = new CConf;
	if (pCfgDev->init(fp)!=CONF_SUCCESS) {
		free(fp);
		delete pCfgDev;
		return IOCTL_ERROR_CONFIG_READFAIL;
	} else {
		free(fp);
		pCfgDev->parse_config();
	}
	
	char szBuf[128] = "", *s;
	strcpy(sdcDuoPro.szSerialPort, ((s=pCfgDev->getcfgitemvalue("commport"))=="")?"/dev/ttyS0":s);
	delete pCfgDev;
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoUpdateConfig
// Description		: 
int	DuoPro_DoUpdateConfig(void *lpvBuff, int *lpiBuffSize)
{
	if (DuoPro_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;
		
	iDuoPro_ExtError = 0;
	if (!commDuoPro.isInitialized())
		return IOCTL_ERROR_NOTYETINITIALIZED;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_DoGetDriverMode
// Description		: 
// Return type		: int
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	DuoPro_DoGetDriverMode(void *lpvBuff, int *lpiBuffSize)
{
	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: DuoPro_DoUpsShutdown
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_DoUpsShutdown(void *lpvBuff, int *lpiBuffSize)
{
	if (commDuoPro.isInitialized()) {
		commDuoPro.set_line(S_DTR);
		sleep(5);
		commDuoPro.clr_line(S_DTR);
	} else {
		iDuoPro_ExtError = IOCTL_ERROR_NOTYETINITIALIZED;
		return IOCTL_ERROR;
	}
	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_GetAllUpsParams
// Description		: 
int DuoPro_GetAllUpsParams(void *lpvBuff, int *lpiBuffSize)
{
	/* parameters table */
	unsigned int uiParamsTable[PARAMS_TABLE_ITEMS];
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < PARAMS_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

	if (commDuoPro.isInitialized()) {
		uiParamsTable[IDXP_STATEFLAG] = commDuoPro.getStatus();
	} else {
		iDuoPro_ExtError = IOCTL_ERROR_NOTYETINITIALIZED;
		return IOCTL_ERROR;
	}

	memcpy( lpvBuff, uiParamsTable, PARAMS_TABLE_ITEMS * sizeof(unsigned int) );

	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_GetAllUpsSetupParams
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_GetAllUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	/* tablica parametrow */
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < SETUP_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

	memcpy( lpvBuff, uiSetupTable, SETUP_TABLE_ITEMS * sizeof(unsigned int) );

	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DuoPro_SetAllUpsSetupParams
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int DuoPro_SetAllUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	/* tablica parametrow */
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < SETUP_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

	memcpy( &uiSetupTable, lpvBuff, sizeof(unsigned int) * (*lpiBuffSize) );

	iDuoPro_ExtError = 0;
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

