/***************************************************************************
 *   Property rights (C) 2004-2006 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 ECOPRO_DRIVER_BUILD 1
#include "ecopro.h"

/* 
 * Deklaracje zmiennych globalnych
 */
sdrv_config sdcEcoPro;
int iEcoPro_ExtError = 0;
CComm	commEcoPro;

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

	case IOCTL_UNINIT:
		return EcoPro_DoUnInit(lpvBuff, lpiBuffSize);
		
	case IOCTL_GETCONFIGFILENAME:
		return EcoPro_DoGetConfigFileName(lpvBuff, lpiBuffSize);

	case IOCTL_AUTOCONFIGURE: 
		return EcoPro_DoAutoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_CONFIGURE: 
		return EcoPro_DoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSINFOMASK: 
		return EcoPro_DoGetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSINFOMASK:
		return EcoPro_DoSetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATESMASK:
		return EcoPro_DoGetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSTATESMASK:
		return EcoPro_DoSetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATE:
		return EcoPro_DoGetUpsState(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMSMASK:
		return EcoPro_DoGetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSPARAMSMASK:
		return EcoPro_DoSetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMS:
		return EcoPro_DoGetUpsParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMSMASK:
		return EcoPro_DoGetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMSMASK:
		return EcoPro_DoSetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMS:
		return EcoPro_DoGetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMS:
		return EcoPro_DoSetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTICMASK:
		return EcoPro_DoGetUpsCharacteristicMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTIC:
		return EcoPro_DoGetUpsCharacteristic(lpvBuff, lpiBuffSize);

	case IOCTL_GET_DRIVER_INFO:
		return EcoPro_DoGetDriverInfo(lpvBuff, lpiBuffSize);

	case IOCTL_GET_ERRORNO:
		return EcoPro_DoGetExtendedError(lpvBuff, lpiBuffSize);

	case IOCTL_TESTUPSLINK:
		return EcoPro_DoTestUpsLink(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMSCOUNT:
		return EcoPro_DoGetConfigParamsCount(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMS:
		return EcoPro_DoGetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAM:
		return EcoPro_DoGetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAMS:
		return EcoPro_DoSetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAM:
		return EcoPro_DoSetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_UPDATECONFIG:
		return EcoPro_DoUpdateConfig(lpvBuff, lpiBuffSize);

	case IOCTL_GETDRIVERMODE:
		return EcoPro_DoGetDriverMode(lpvBuff, lpiBuffSize);

	case IOCTL_SHUTDOWNUPS:
		return EcoPro_DoUpsShutdown(lpvBuff, lpiBuffSize);

	default:
		return IOCTL_ERROR_CMD_NOTSUPPORTED;
	}
}

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

	if (EcoPro_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;
	
	commEcoPro.init(sdcEcoPro.szSerialPort, 0);
	if (commEcoPro.open_simplesignalling()!=COMM_SUCCESS) {
		iEcoPro_ExtError=IOCTL_ERROR_COMM_INITFAIL;
		return IOCTL_ERROR;
	}
	
	commEcoPro.clr_line(S_DTR);
	
	iEcoPro_ExtError = 0;
	EcoPro_DoUpdateConfig(NULL, NULL);	

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoUnInit
// Description		: Deinicjalizacja drivera
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int EcoPro_DoUnInit( void *lpvBuff, int *lpiBuffSize )
{
	if (commEcoPro.close()!=COMM_SUCCESS) {
		iEcoPro_ExtError=0;
		return IOCTL_ERROR;
	}
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoGetConfigFileName
// Description		: 
int EcoPro_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 EcoPro_DoAutoConfigure( void *lpvBuff, int *lpiBuffSize )
{
	sdcEcoPro.iSerialPort=1;
	sprintf( sdcEcoPro.szSerialPort, "/dev/ttyS%d", sdcEcoPro.iSerialPort );

	return IOCTL_ERROR_SUCCESS;
}

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

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoGetUpsInfoMask
// Description		: Zwraca informacje o wypelnieniu struktury informacji o UPS-ie
int EcoPro_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	EcoPro_DoSetUpsInfoMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: EcoPro_DoGetUpsStateMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	EcoPro_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	: EcoPro_DoSetUpsStateMask
// Description		: 
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	EcoPro_DoSetUpsStateMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: EcoPro_DoGetUpsState
// Description		: Return actual UPS state
// Return type		: 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int	EcoPro_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 (commEcoPro.isInitialized()) {
		// check if communication is still active
		for (uiCnt=0; uiCnt<3; uiCnt++)
			if (commEcoPro.status_check(CTS) < 0)
				iEcoPro_ExtError = IOCTL_ERROR_COMM_LINKTERMINATED;
			else
				iEcoPro_ExtError = 0;
		if (iEcoPro_ExtError != 0)
			return IOCTL_ERROR;

		for (uiCnt=0; uiCnt<3; uiCnt++) {
			usleep(30000);
			uiUpsState[0] = commEcoPro.getStatus();
			usleep(30000);
			uiUpsState[1] = commEcoPro.getStatus();
			usleep(30000);
			uiUpsState[2] = commEcoPro.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 {
		iEcoPro_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;
	
	if ( !(( uiUpsState[0] & USB_AND_LOWBATTERY ) == USB_FLAG_LOWBATTERY) )
	{
		if (NOTSET(ulUpsState, US_POWERON))
			ulUpsState |= US_BATTERYLOW;
	}
	else
		ulUpsState &= ~(US_BATTERYLOW);

	memcpy( lpvBuff, &ulUpsState, *lpiBuffSize );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoGetUpsParamsMask
// Description		:
int	EcoPro_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	: EcoPro_DoSetUpsParamsMask
// Description		: 
int	EcoPro_DoSetUpsParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: EcoPro_DoGetUpsParams
// Description		: 
int	EcoPro_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 = EcoPro_GetAllUpsParams( sdcEcoPro.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	: EcoPro_DoGetUpsSetupParamsMask
// Description		: 
int	EcoPro_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	: EcoPro_DoSetUpsSetupParamsMask
// Description		: 
int	EcoPro_DoSetUpsSetupParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: EcoPro_DoGetUpsSetupParams
// Description		: 
int	EcoPro_DoGetUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_SUCCESS;
}

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

// Function name	: EcoPro_DoGetDriverInfo
// Description		: 
int	EcoPro_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	: EcoPro_DoGetExtendedError
// Description		: Get extended error information - return value of last error
int	EcoPro_DoGetExtendedError(void *lpvBuff, int *lpiBuffSize)
{
	return iEcoPro_ExtError;
}

// Function name	: EcoPro_DoGetUpsCharacteristicMask
// Description		: 
int	EcoPro_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	: EcoPro_DoGetUpsCharacteristic
// Description		: 
int	EcoPro_DoGetUpsCharacteristic(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoTestUpsLink
// Description		: 
int	EcoPro_DoTestUpsLink(void *lpvBuff, int *lpiBuffSize)
{
	int iCnt=0;
	
	for (iCnt=0; iCnt<3; iCnt++) {
		commEcoPro.clr_line(S_RTS);
		sleep(2);
		if (!commEcoPro.status_check(RING)) {
			commEcoPro.set_line(S_RTS);
			sleep(2);
			if (!commEcoPro.status_check(RING)) {
				commEcoPro.clr_line(S_RTS);
				if (iCnt>=2)
					return IOCTL_ERROR_COMM_LINKFAIL;
				else
					continue;
			}
			commEcoPro.clr_line(S_RTS);
			sleep(1);
			break;
		}
		else
			if (iCnt>=2)
				return IOCTL_ERROR_COMM_LINKFAIL;
			else
				continue;
	}
	return IOCTL_ERROR_SUCCESS;
}

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

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

// Function name	: EcoPro_DoGetConfigParamsCount
// Description		: 
int EcoPro_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 ) );

	iEcoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoGetConfigParams
// Description		: 
int	EcoPro_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)sdcEcoPro.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 );

	iEcoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoSetConfigParams
// Description		: 
int	EcoPro_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 */
	sdcEcoPro.iSerialPort = scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue + 1;
	sprintf(sdcEcoPro.szSerialPort, "/dev/ttyS%d", scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue + 1);

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

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

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

// Function name	: EcoPro_ReadConfig
// Description		: 
int	EcoPro_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(sdcEcoPro.szSerialPort, ((s=pCfgDev->getcfgitemvalue("commport"))=="")?"/dev/ttyS0":s);
	delete pCfgDev;
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_DoUpdateConfig
// Description		: 
int	EcoPro_DoUpdateConfig(void *lpvBuff, int *lpiBuffSize)
{
	if (EcoPro_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;
		
	iEcoPro_ExtError = 0;
	if (!commEcoPro.isInitialized())
		return IOCTL_ERROR_NOTYETINITIALIZED;
	return IOCTL_ERROR_SUCCESS;
}

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

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

// Function name	: EcoPro_GetAllUpsParams
// Description		: 
int EcoPro_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 (commEcoPro.isInitialized()) {
		uiParamsTable[IDXP_STATEFLAG] = commEcoPro.getStatus();
	} else {
		iEcoPro_ExtError = IOCTL_ERROR_NOTYETINITIALIZED;
		return IOCTL_ERROR;
	}

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

	iEcoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_GetAllUpsSetupParams
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int EcoPro_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) );

	iEcoPro_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: EcoPro_SetAllUpsSetupParams
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int EcoPro_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) );

	iEcoPro_ExtError = 0;
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

