/***************************************************************************
 *   Copyright (C) 2004 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 NET_DRIVER_BUILD 1
#include "net.h"

/* 
 * Helper macros
 */
#undef COMMIOFAIL
#define COMMIOFAIL( v, en )  					\
	if ( COMMFAIL( v ) ) 						\
	{											\
		iNet_ExtError = en; 					\
		return IOCTL_ERROR_COMM_LINKFAIL;		\
	}

/* 
 * Deklaracje zmiennych globalnych
 */
sdrv_config sdcNet;
int iNet_ExtError = 0;
CComm commNet;

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

	case IOCTL_UNINIT:
		return Net_DoUnInit(lpvBuff, lpiBuffSize);
		
	case IOCTL_GETCONFIGFILENAME:
		return Net_DoGetConfigFileName(lpvBuff, lpiBuffSize);

	case IOCTL_AUTOCONFIGURE: 
		return Net_DoAutoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_CONFIGURE: 
		return Net_DoConfigure(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSINFOMASK: 
		return Net_DoGetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSINFOMASK:
		return Net_DoSetUpsInfoMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATESMASK:
		return Net_DoGetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSTATESMASK:
		return Net_DoSetUpsStateMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSTATE:
		return Net_DoGetUpsState(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMSMASK:
		return Net_DoGetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSPARAMSMASK:
		return Net_DoSetUpsParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSPARAMS:
		return Net_DoGetUpsParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMSMASK:
		return Net_DoGetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMSMASK:
		return Net_DoSetUpsSetupParamsMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSSETUPPARAMS:
		return Net_DoGetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_SET_UPSSETUPPARAMS:
		return Net_DoSetUpsSetupParams(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTICMASK:
		return Net_DoGetUpsCharacteristicMask(lpvBuff, lpiBuffSize);

	case IOCTL_GET_UPSCHARACTERISTIC:
		return Net_DoGetUpsCharacteristic(lpvBuff, lpiBuffSize);

	case IOCTL_GET_DRIVER_INFO:
		return Net_DoGetDriverInfo(lpvBuff, lpiBuffSize);

	case IOCTL_GET_ERRORNO:
		return Net_DoGetExtendedError(lpvBuff, lpiBuffSize);

	case IOCTL_TESTUPSLINK:
		return Net_DoTestUpsLink(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMSCOUNT:
		return Net_DoGetConfigParamsCount(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAMS:
		return Net_DoGetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_GETCONFIGPARAM:
		return Net_DoGetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAMS:
		return Net_DoSetConfigParams(lpvBuff, lpiBuffSize);

	case IOCTL_SETCONFIGPARAM:
		return Net_DoSetConfigParam(lpvBuff, lpiBuffSize);

	case IOCTL_UPDATECONFIG:
		return Net_DoUpdateConfig(lpvBuff, lpiBuffSize);

	case IOCTL_GETDRIVERMODE:
		return Net_DoGetDriverMode(lpvBuff, lpiBuffSize);

	case IOCTL_SHUTDOWNUPS:
		return Net_DoUpsShutdown(lpvBuff, lpiBuffSize);

	default:
		return IOCTL_ERROR_CMD_NOTSUPPORTED;
	}
}

// Function name	: Net_DoInit
// Description		: Inicjalizacja drivera
int Net_DoInit( void *lpvBuff, int *lpiBuffSize )
{
	int iSize;
	iNet_ExtError = 0;

	if (Net_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;

	commNet.init(sdcNet.szSerialPort, B300);
	if (commNet.open()!=COMM_SUCCESS) {
		iNet_ExtError=IOCTL_ERROR_COMM_INITFAIL;
		return IOCTL_ERROR;
	}
	
//	iSize = PARAMS_TABLE_ITEMS;
//	Net_GetAllUpsParams(sdcNet.uiParamsTable, &iSize);
	
//	iSize = SETUP_TABLE_ITEMS;
//	Net_GetAllUpsSetupParams(sdcNet.uiSetupTable, &iSize);
	
	iNet_ExtError = 0;
	Net_DoUpdateConfig(NULL, NULL);

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoUnInit
// Description		: Deinicjalizacja drivera
int Net_DoUnInit( void *lpvBuff, int *lpiBuffSize )
{
	if (commNet.close()!=COMM_SUCCESS) {
		iNet_ExtError=0;
		return IOCTL_ERROR;
	}
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoUnInit
// Description		: 
int Net_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	: Net_DoAutoConfigure
// Description		: Self configure
int Net_DoAutoConfigure( void *lpvBuff, int *lpiBuffSize )
{
	sdcNet.iSerialPort=1;
	sprintf( sdcNet.szSerialPort, "/dev/ttyS%d", sdcNet.iSerialPort );
	
	sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME] = DEFAULT_STANDBY_TIME;
	sdcNet.uiSetupTable[SETUP_ITEM_BUZZER_EN] = 1;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_LOWER] = DEFAULT_LOWER_TT;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_AVR] = DEFAULT_AVR_TT;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_UPPER] = DEFAULT_UPPER_TT;
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoConfigure
// Description		: Configure driver to work properly with UPS and reinit
int Net_DoConfigure( void *lpvBuff, int *lpiBuffSize )
{
	sdcNet.iSerialPort=1;
	sprintf( sdcNet.szSerialPort, "/dev/ttyS%d", sdcNet.iSerialPort );
	
	sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME] = DEFAULT_STANDBY_TIME;
	sdcNet.uiSetupTable[SETUP_ITEM_BUZZER_EN] = 1;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_LOWER] = DEFAULT_LOWER_TT;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_AVR] = DEFAULT_AVR_TT;
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_UPPER] = DEFAULT_UPPER_TT;
	
	Net_DoUnInit(NULL, NULL);
	Net_DoInit(NULL, NULL);

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoGetUpsInfoMask
// Description		: Zwraca informacje o wypelnieniu struktury informacji o UPS-ie
int Net_DoGetUpsInfoMask( void *lpvBuff, int *lpiBuffSize )
{
	unsigned long ulMask = UI_CHARACTERISTICS|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	: Net_DoSetUpsInfoMask
// Description		: 
int	Net_DoSetUpsInfoMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: Net_DoGetUpsStateMask
// Description		: 
int	Net_DoGetUpsStateMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long	ulMask = US_POWERON | US_POWERFAIL | US_STANDBY | 
		US_OVERLOAD | US_AVRUP | US_BATTERYLOW;

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

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

// Function name	: Net_DoGetUpsState
// Description		: Return actual UPS state
int	Net_DoGetUpsState(void *lpvBuff, int *lpiBuffSize)
{
#undef ADJUST_BITS
#define ADJUST_BITS(src, sbit, sres, dest, dbit) \
	{ if ((src&sbit)==sres) dest|=dbit; else dest&=~(dbit); }

	unsigned long ulUpsState = 0;
	unsigned int uiUpsState = 0;
	int iRet, iSize;

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

	iSize = sizeof(uiUpsState) / sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_STATE, &uiUpsState, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS) {
		return iRet;
	}
	
	iSize = PARAMS_TABLE_ITEMS;
	iRet = Net_GetAllUpsParams(sdcNet.uiParamsTable, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// Currently supported flags are:
	// US_POWERON | US_POWERFAIL | US_STANDBY | US_OVERLOAD | US_SHORT | US_AVRUP | US_BATTERYLOW

	ADJUST_BITS( uiUpsState, USB_AND_POWERFAIL, USB_FLAG_POWERFAIL, ulUpsState, US_POWERFAIL );
	ADJUST_BITS( uiUpsState, USB_AND_POWEROK, USB_FLAG_POWEROK, ulUpsState, US_POWERON );
	ADJUST_BITS( uiUpsState, USB_AND_STANDBY, USB_FLAG_STANDBY, ulUpsState, US_STANDBY );
	ADJUST_BITS( uiUpsState, USB_AND_OVERLOAD, USB_FLAG_OVERLOAD, ulUpsState, US_OVERLOAD );
	ADJUST_BITS( uiUpsState, USB_AND_SHORT, USB_FLAG_SHORT, ulUpsState, US_SHORT );

	iSize = sizeof(uiUpsState) / sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_STATEAVR, &uiUpsState, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS) {
		return iRet;
	}
	ADJUST_BITS( uiUpsState, PAB_AND_AVRUP, PAB_FLAG_AVRUP, ulUpsState, US_AVRUP );
	
	// napiecie akumulatora dla battery low
	// jest to:
	//  - 12V dla 500
	//  - 24V dla 700-1400
	//  - 48 dla 2200-3000
	int iMul = 1;
	switch(sdcNet.uiParamsTable[IDXP_UPSTYPE]) 
	{
		case INT_UPS_MODEL1: // 500
		case INT_UPS_MODEL1_2:
			iMul = 1;
			break;
		case INT_UPS_MODEL2: // 700
		case INT_UPS_MODEL2_2:
		case INT_UPS_MODEL3: // 1000
		case INT_UPS_MODEL3_2:
		case INT_UPS_MODEL4: // 1400
		case INT_UPS_MODEL4_2:
			iMul = 2;
			break;
		case INT_UPS_MODEL5: // 2200
			iMul = 4;
			break;
	}
	unsigned int uiAkuVoltage = (unsigned int)sdcNet.uiParamsTable[IDXP_U_AKU]*iMul;
	// Battery low only if Aku i less than 10.8V but higher that 9.0V for safety
	if (uiAkuVoltage < 108 && uiAkuVoltage > 90)
		ulUpsState |= US_BATTERYLOW;
	else
		ulUpsState &= ~(US_BATTERYLOW);
		

	memcpy( lpvBuff, &ulUpsState, *lpiBuffSize );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoGetUpsParamsMask
// Description		: 
int	Net_DoGetUpsParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	__int64 iMask = UP_PST_UPPER|UP_PST_LOWER|UP_PST_AVRUP|
		UP_VLT_INPUT|UP_VLT_BATTERY|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	: Net_DoSetUpsParamsMask
// Description		: 
int	Net_DoSetUpsParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	return IOCTL_ERROR_CMD_NOTSUPPORTED;
}

// Function name	: Net_DoGetUpsParams
// Description		: 
int	Net_DoGetUpsParams(void *lpvBuff, int *lpiBuffSize)
{
	int	iSize, iRet, iMul;
	unsigned int uiModel;
	supsp sup;
	struct tagModel { 
		int iId; char szName[32]; 
	} sModel[UPS_MAX_MODELS * 2] = { 
		{ INT_UPS_MODEL1, UPS_MODEL1 }, { INT_UPS_MODEL2, UPS_MODEL2 }, 
		{ INT_UPS_MODEL3, UPS_MODEL3 }, { INT_UPS_MODEL4, UPS_MODEL4 },
		{ INT_UPS_MODEL5, UPS_MODEL5 }, { INT_UPS_MODEL1_2, UPS_MODEL1 }, 
		{ INT_UPS_MODEL2_2, UPS_MODEL2 }, { INT_UPS_MODEL3_2, UPS_MODEL3 },
		{ INT_UPS_MODEL4_2, UPS_MODEL4 }, { INT_UPS_MODEL5_2, UPS_MODEL5 }
	};

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

	iSize = PARAMS_TABLE_ITEMS;
	iRet = Net_GetAllUpsParams( sdcNet.uiParamsTable, &iSize );
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// fill params mask
	sup.iMask = UP_PST_UPPER|UP_PST_LOWER|UP_PST_AVRUP|
		UP_VLT_INPUT|UP_VLT_BATTERY|UP_UID_FAMILY|UP_UID_MODEL;

	uiModel = sdcNet.uiParamsTable[IDXP_UPSTYPE];

	// by default, unknown ups type
	sprintf( sup.sz__uid_model, "%s %s", DRIVER_UPS_PREFIX, DRIVER_UPS_SUFFIX );
	sprintf( sup.sz__uid_family, "%s", DRIVER_UPS_FAMILY );
	// wybierz typ ups-a po identyfikatorze
	for ( int ii = 0; ii < UPS_MAX_MODELS * 2; ii++ )
		if ( (unsigned int)sModel[ ii ].iId == sdcNet.uiParamsTable[IDXP_UPSTYPE] )
			sprintf( sup.sz__uid_model, "%s %s %s", 
				DRIVER_UPS_PREFIX, sModel[ ii ].szName, DRIVER_UPS_SUFFIX );

	// czestotliwosc wejsciowa
	sup.ui__frq_output = 50;
	sup.ui__frq_output_div = 1;

	// napiecie sieciowe - wejsciowe
	sup.ui__vlt_input = sdcNet.uiParamsTable[IDXP_U_POWER];
	sup.ui__vlt_input_div = 1;

	// napiecie akumulatora,
	// jest to: 
	// 12V dla 500;  
	// 24V dla 700-1400; 
	// 48 dla 2200-3000;
	switch( uiModel )
	{
	default:
	case INT_UPS_MODEL1:	// 500
	case INT_UPS_MODEL1_2:
		iMul = 1;
		break;
	case INT_UPS_MODEL2:	// 700
	case INT_UPS_MODEL2_2:
	case INT_UPS_MODEL3:	// 1000
	case INT_UPS_MODEL3_2:
	case INT_UPS_MODEL4:	// 1400
	case INT_UPS_MODEL4_2:
		iMul = 2;
		break;
	case INT_UPS_MODEL5:	// 2200
		iMul = 4;
		break;
	}
	sup.ui__vlt_battery = (unsigned int)sdcNet.uiParamsTable[IDXP_U_AKU] * iMul;
	sup.ui__vlt_battery_div = 10;
	
	// 1320 = 100% pojemnosci dla pracy sieciowej w trakcie ladowania
	// 1250 = 100% pojemnoscidla pracy awaryjnej
	sup.ui__prc_batterycapacity = (unsigned int)((sup.ui__vlt_battery / iMul) * 10);
	if ( (sdcNet.uiParamsTable[IDXP_STATEFLAG] & USB_AND_POWERFAIL) == USB_FLAG_POWERFAIL )
		sup.ui__prc_batterycapacity = (sup.ui__prc_batterycapacity * 100) / 1250;
	else
		sup.ui__prc_batterycapacity = (sup.ui__prc_batterycapacity * 100) / 1320;
	if ( sup.ui__prc_batterycapacity > 100 )
		sup.ui__prc_batterycapacity = 100;
	sup.ui__prc_batterycapacity_div = 1;

	// napiecie przelaczania AVR
	sup.ui__pst_avrup = (unsigned int)sdcNet.uiParamsTable[IDXP_TH_AVRUP];
	sup.ui__pst_avrup_div = 1;
	// napiecie przelaczania - gorny prog
	sup.ui__pst_upper = (unsigned int)sdcNet.uiParamsTable[IDXP_TH_UPPER];
	sup.ui__pst_upper_div = 1;
	// napiecie przelaczania - dolny prog
	sup.ui__pst_lower = (unsigned int)sdcNet.uiParamsTable[IDXP_TH_LOWER];
	sup.ui__pst_lower_div = 1;

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

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoGetUpsSetupParamsMask
// Description		: 
int	Net_DoGetUpsSetupParamsMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long ulMask = UP_SET_PST_UPPER|UP_SET_PST_LOWER|UP_SET_PST_AVRUP|
		UP_SET_AAL_ON|UP_SET_TMR_POWERFAILTOSTANDBY;

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

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

// Function name	: Net_DoGetUpsSetupParams
// Description		: 
int	Net_DoGetUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	supssp susp;

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

	susp.ulMask = UP_SET_PST_UPPER|UP_SET_PST_LOWER|UP_SET_PST_AVRUP|
		UP_SET_AAL_ON|UP_SET_TMR_POWERFAILTOSTANDBY;

	// TODO:: reading from configuration file and/or directly from UPS
	
	susp.ui__set_pst_upper = sdcNet.uiSetupTable[SETUP_ITEM_V_TH_UPPER];
	susp.ui__set_pst_upper_div = 1;
	susp.ui__set_pst_lower = sdcNet.uiSetupTable[SETUP_ITEM_V_TH_LOWER];
	susp.ui__set_pst_lower_div = 1;
	susp.ui__set_pst_avrup = sdcNet.uiSetupTable[SETUP_ITEM_V_TH_AVR];
	susp.ui__set_pst_avrup_div = 1;
	susp.ui__set_aal_on = sdcNet.uiSetupTable[SETUP_ITEM_BUZZER_EN];
	susp.ui__set_tmr_powerfailtostandby = sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME];
	susp.ui__set_tmr_powerfailtostandby_div = 1;

	memcpy( lpvBuff, &susp, *lpiBuffSize );

	return IOCTL_ERROR_SUCCESS;
}

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

// Function name	: Net_DoGetDriverInfo
// Description		: 
int	Net_DoGetDriverInfo(void *lpvBuff, int *lpiBuffSize)
{
	if (*lpiBuffSize != sizeof(sdrv_info))
		return IOCTL_ERROR_INVALIDARGUMENT;
	sprintf( (( lpsdrv_info )lpvBuff )->szName, "%s %s DRIVER", DRIVER_UPS_PREFIX, DRIVER_UPS_SUFFIX );
	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	: Net_DoGetExtendedError
// Description		: Get extended error information - return value of last error
int	Net_DoGetExtendedError(void *lpvBuff, int *lpiBuffSize)
{
	return iNet_ExtError;
}

// Function name	: Net_DoGetUpsCharacteristicMask
// Description		: 
int	Net_DoGetUpsCharacteristicMask(void *lpvBuff, int *lpiBuffSize)
{
	unsigned long ulMask = UC_PST_LOWER_MIN|UC_PST_LOWER_MAX|UC_PST_UPPER_MIN|
		UC_PST_UPPER_MAX|UC_PST_AVRUP_MIN|UC_ACCUFULLCAPVOLTAGE;

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

// Function name	: Net_DoGetUpsCharacteristic
// Description		: 
int	Net_DoGetUpsCharacteristic(void *lpvBuff, int *lpiBuffSize)
{
	supsch such;

	memset( &such, 0, sizeof(supsch) );

	such.ulMask = UC_PST_LOWER_MIN|UC_PST_LOWER_MAX|UC_PST_UPPER_MIN|
		UC_PST_UPPER_MAX|UC_PST_AVRUP_MIN|UC_ACCUFULLCAPVOLTAGE;

	such.ui__accufullcapvoltage = 265;
	such.ui__accufullcapvoltage_div = 1;
	such.ui__pst_avrup_min = 200;
	such.ui__pst_avrup_min_div = 1;
	such.ui__pst_lower_max = 195;
	such.ui__pst_lower_max_div = 1;
	such.ui__pst_lower_min = 160;
	such.ui__pst_lower_min_div = 1;
	such.ui__pst_upper_max = 290;
	such.ui__pst_upper_max_div = 1;
	such.ui__pst_upper_min = 240;
	such.ui__pst_upper_min_div = 1;

	memcpy( lpvBuff, &such, *lpiBuffSize );

	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoTestUpsLink
// Description		: 
int	Net_DoTestUpsLink(void *lpvBuff, int *lpiBuffSize)
{
	unsigned int uiInfo;
	int	iSize, iRet, iRep;

	for (iRep=0; iRep<3; iRep++) {
		// Czyszczenie ramki
		iSize = sizeof(uiInfo) / sizeof(unsigned int);
		if (Net_DoGetUPSdata(EU_CLEANFRAME, (void*)&uiInfo, &iSize) != IOCTL_ERROR_SUCCESS)
			continue;
		// Zwrot typu zasilacza
		iSize = sizeof(uiInfo) / sizeof(unsigned int);
		iRet = Net_DoGetUPSdata(EU_UPSTYPE, (void*)&uiInfo, &iSize);
		if (iRet != IOCTL_ERROR_SUCCESS)
			continue;
	}
	return iRet;
}

// Read specified table from UPS
int Net_DoGetUPSdata(eups_datatypes eType, void *lpvBuff, int *lpiBuffSize)
{
	unsigned char ucDataBuff[0xFF] = { 0 };
	unsigned int uiDataBuff[0xFF] = { 0 }, ui;
	bool bInitialized = false;
	unsigned int uiLength = 0;
	
	if (!commNet.isInitialized())
		return IOCTL_ERROR_NOTYETINITIALIZED;

	switch( eType )
	{
	// procedura czyszczaca ramke nadawczo-odbiorcza
	case EU_CLEANFRAME:
		{
			ui = 0;
			ucDataBuff[1] = 0;
			do {
				ucDataBuff[0] = 0;
				commNet.flush(1, 1);
				COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				switch( ucDataBuff[0] )
				{
				case FRAME_INITCODE:
					{
						COMMIOFAIL( commNet.send( FRAME_CODE_UPSTYPE | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
						usleep(25000);
						COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
						uiLength = 1;
						iNet_ExtError = 0;
						break;
					}

				case FRAME_BUSYCODE:
					iNet_ExtError = 0;
					break;

				default:
					// receive
					COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
					iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
					break;
				}
				usleep(350000);
				ui++;
			} while( (ui < 4) && !uiLength );

			if ( iNet_ExtError || !uiLength )
				return IOCTL_ERROR_COMM_LINKFAIL;
			break;
		}
	// procedura odczytu typu zasilacza
	case EU_UPSTYPE:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch( ucDataBuff[0] )
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_UPSTYPE | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				return IOCTL_ERROR_COMM_LINKFAIL;
			}
			break;
		}
	// procedura odczytu stanu pracy zasilacza
	case EU_STATE:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_UPSSTATE | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}
	// procedura odczytu stanu avr
	case EU_STATEAVR:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_PORTASH | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}
	// procedura odczytu rejestru sysflag
	case EU_SYSFLAG:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_SYSFLAG | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_AVRUP:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_AVRVALUE | FRAME_CTL_TOREAD | FRAME_CTL_TWOBYTES ), 
					IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				COMMIOFAIL( commNet.receive( &ucDataBuff[2] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 2;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_UPPER:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_RUPVALUE | FRAME_CTL_TOREAD | FRAME_CTL_TWOBYTES ), 
					IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				COMMIOFAIL( commNet.receive( &ucDataBuff[2] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 2;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_LOWER:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_RLOVALUE | FRAME_CTL_TOREAD | FRAME_CTL_TWOBYTES ), 
					IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				COMMIOFAIL( commNet.receive( &ucDataBuff[2] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 2;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_U_AKU:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_AKUVALUE | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_U_POWER:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_POWERVALUE | FRAME_CTL_TOREAD | FRAME_CTL_TWOBYTES), 
					IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				COMMIOFAIL( commNet.receive( &ucDataBuff[2] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 2;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_STANDBY_TIME:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_STANDBYTIME | FRAME_CTL_TOREAD ), IOCTL_ERROR_COMM_FAILTOSEND );
				usleep(25000);
				COMMIOFAIL( commNet.receive( &ucDataBuff[1] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
				uiLength = 1;
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}
	}

	if ( uiLength > (unsigned int)*lpiBuffSize )
	{
		iNet_ExtError = IOCTL_ERROR_COMM_INVALIDLENGTH;
		return IOCTL_ERROR_COMM_LINKFAIL;
	}

	for ( unsigned int ul = 1; ul <= uiLength; ul++ )
		uiDataBuff[ul-1] = (unsigned int)ucDataBuff[ul];

	// skopiuj do bufora wejsciowego nowe dane
	memcpy( lpvBuff, &uiDataBuff, *lpiBuffSize * sizeof( unsigned int ) );

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: DoSetUPSdata
// Description		: Set specified UPS parameter
// Return type		: int 
// Argument         : eups_datatypes eType
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int Net_DoSetUPSdata(eups_datatypes eType, void *lpvBuff, int *lpiBuffSize)
{
	unsigned char ucDataBuff[0xFF] = { 0 };
	unsigned int uiDataBuff[0xFF] = { 0 };
	bool bInitialized = false;
	unsigned int uiLength = 0;
	
	if (!commNet.isInitialized())
		return IOCTL_ERROR_NOTYETINITIALIZED;
	
	memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) * (*lpiBuffSize) );

	switch( eType )
	{
	// procedura zapisu rejestru sysflag
	case EU_SYSFLAG:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				{
					memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) );
					COMMIOFAIL( commNet.send( FRAME_CODE_SYSFLAG ) , IOCTL_ERROR_COMM_FAILTOSEND );
					COMMIOFAIL( commNet.send( (unsigned char)uiDataBuff[0] ), IOCTL_ERROR_COMM_FAILTOSEND );
					iNet_ExtError = 0;
					break;
				}

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_AVRUP:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				{
					COMMIOFAIL( commNet.send( FRAME_CODE_AVRVALUE | FRAME_CTL_TWOBYTES ), IOCTL_ERROR_COMM_FAILTOSEND );
					memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) * (*lpiBuffSize) );
					for (int icd = 0; icd < 2; icd++)
						COMMIOFAIL( commNet.send( (unsigned char)uiDataBuff[icd] ), IOCTL_ERROR_COMM_FAILTOSEND );
					iNet_ExtError = 0;
					break;
				}

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_UPPER:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				{
					COMMIOFAIL( commNet.send( FRAME_CODE_RUPVALUE | FRAME_CTL_TWOBYTES ), IOCTL_ERROR_COMM_FAILTOSEND );
					memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) * (*lpiBuffSize) );
					for (int icd = 0; icd < 2; icd++)
						COMMIOFAIL( commNet.send( (unsigned char)uiDataBuff[icd] ), IOCTL_ERROR_COMM_FAILTOSEND );
					iNet_ExtError = 0;
					break;
				}

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_S_LOWER:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				{
					COMMIOFAIL( commNet.send( FRAME_CODE_RLOVALUE | FRAME_CTL_TWOBYTES ), IOCTL_ERROR_COMM_FAILTOSEND );
					memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) * (*lpiBuffSize) );
					for (int icd = 0; icd < 2; icd++)
						COMMIOFAIL( commNet.send( (unsigned char)uiDataBuff[icd] ), IOCTL_ERROR_COMM_FAILTOSEND );
					iNet_ExtError = 0;
					break;
				}

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}

	case EU_STANDBY_TIME:
		{
			ucDataBuff[0] = ucDataBuff[1] = 0;
			//commNet.flush(1, 1);
			COMMIOFAIL( commNet.send( FRAME_INITCODE ), IOCTL_ERROR_COMM_FAILTOSEND );
			usleep(25000);
			COMMIOFAIL( commNet.receive( &ucDataBuff[0] ), IOCTL_ERROR_COMM_FAILTORECEIVE );
			switch(ucDataBuff[0])
			{
			case FRAME_INITCODE:
				COMMIOFAIL( commNet.send( FRAME_CODE_STANDBYTIME ), IOCTL_ERROR_COMM_FAILTOSEND );
				memcpy( &uiDataBuff, lpvBuff, sizeof( unsigned int ) );
				COMMIOFAIL( commNet.send( (unsigned char)uiDataBuff[0] ), IOCTL_ERROR_COMM_FAILTOSEND );
				iNet_ExtError = 0;
				break;

			case FRAME_BUSYCODE:
				iNet_ExtError = 0;
				break;

			default:
				iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
				break;
			}
			break;
		}
	default:
		iNet_ExtError = IOCTL_ERROR_COMM_INVALIDCODE;
		return IOCTL_ERROR;
	}

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

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

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoGetConfigParams
// Description		: 
int	Net_DoGetConfigParams(void *lpvBuff, int *lpiBuffSize)
{
	int	icnt;
	scfg_value scfgvaldef[ INT_MAX_SETUPITEMS ];
	char szStr[ MAX_PATHBUFF ];
	unsigned long ulSize;
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];

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

	memcpy( uiSetupTable, &sdcNet.uiSetupTable, sizeof(sdcNet.uiSetupTable) );

	// 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)sdcNet.iSerialPort;
	scfgvaldef[ INT_UPSCFG_SERIALCOMM ].range.lMin = 0;

	for (icnt = 0; icnt < 32; icnt++) {
		sprintf(szStr, "/dev/ttyS%d", icnt);
		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;

	// KONTROLA_PRACY:buzer
	scfgvaldef[ INT_UPSCFG_BUZZER ].eType = VT_INTLIST;
	strcpy(scfgvaldef[ INT_UPSCFG_BUZZER ].szName, TXT_CFG_SOUNDALERT);
	scfgvaldef[ INT_UPSCFG_BUZZER ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_BUZZER ].value.iValue = (int)uiSetupTable[SETUP_ITEM_BUZZER_EN];
	scfgvaldef[ INT_UPSCFG_BUZZER ].range.lMin = 0;
	scfgvaldef[ INT_UPSCFG_BUZZER ].range.lMax = 1;
	scfgvaldef[ INT_UPSCFG_BUZZER ].iListItems = 2;
	strcpy(scfgvaldef[ INT_UPSCFG_BUZZER ].list[0].szName, TXT_CFG_DISABLED);
	scfgvaldef[ INT_UPSCFG_BUZZER ].list[0].iValue = 0;
	strcpy(scfgvaldef[ INT_UPSCFG_BUZZER ].list[1].szName, TXT_CFG_ENABLED);
	scfgvaldef[ INT_UPSCFG_BUZZER ].list[1].iValue = 1;

	// V_DOLNY
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].eType = VT_INTEGER;
	strcpy(scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].szName, TXT_CFG_POWERSTATELOWER);
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].value.iValue = (int)uiSetupTable[SETUP_ITEM_V_TH_LOWER];
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].range.lMin = (long)160;
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].range.lMax = (long)200;
	scfgvaldef[ INT_UPSCFG_V_TH_LOWER ].iListItems = 0;
	// V_GORNY
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].eType = VT_INTEGER;
	strcpy(scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].szName, TXT_CFG_POWERSTATEUPPER);
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].value.iValue = (int)uiSetupTable[SETUP_ITEM_V_TH_UPPER];
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].range.lMin = (long)235;
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].range.lMax = (long)290;
	scfgvaldef[ INT_UPSCFG_V_TH_UPPER ].iListItems = 0;

	// V_AVR
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].eType = VT_INTEGER;
	strcpy(scfgvaldef[ INT_UPSCFG_V_TH_AVR ].szName, TXT_CFG_AVR);
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].value.iValue = (int)uiSetupTable[SETUP_ITEM_V_TH_AVR];
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].range.lMin = (long)165;
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].range.lMax = (long)230;
	scfgvaldef[ INT_UPSCFG_V_TH_AVR ].iListItems = 0;

	// OPOZNIENIE_STANDBY
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].eType = VT_INTEGER;
	strcpy(scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].szName, TXT_CFG_STANDBYTIMEOUT);
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].dDivider = 1;
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].value.iValue = (int)uiSetupTable[SETUP_ITEM_STANDBY_TIME];
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].range.lMin = 0;
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].range.lMax = 255;
	scfgvaldef[ INT_UPSCFG_STANDBYDELAY ].iListItems = 0;

	memcpy( lpvBuff, scfgvaldef, *lpiBuffSize );

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoSetConfigParams
// Description		: 
int	Net_DoSetConfigParams(void *lpvBuff, int *lpiBuffSize)
{
	int iSize, iRet;
	unsigned long ulSize;
	scfg_value scfgvaldef[INT_MAX_SETUPITEMS];
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];

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

	/* Port komunikacyjny */
	sdcNet.iSerialPort = scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue;
	sprintf(sdcNet.szSerialPort, "/dev/ttyS%d", scfgvaldef[ INT_UPSCFG_SERIALCOMM ].value.iValue);
	
	// BUZZER
	sdcNet.uiSetupTable[SETUP_ITEM_BUZZER_EN] = scfgvaldef[ INT_UPSCFG_BUZZER ].value.iValue;
	// IDX_V_PROG_DOLNY
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_LOWER] = (int)(scfgvaldef[INT_UPSCFG_V_TH_LOWER].value.iValue * 
		scfgvaldef[INT_UPSCFG_V_TH_LOWER].dDivider);
	// IDX_V_PROG_GORNY
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_UPPER] = (int)(scfgvaldef[INT_UPSCFG_V_TH_UPPER].value.iValue * 
		scfgvaldef[INT_UPSCFG_V_TH_UPPER].dDivider);
	// IDX_V_PROG_AVR
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_AVR] = (int)(scfgvaldef[INT_UPSCFG_V_TH_AVR].value.iValue * 
		scfgvaldef[INT_UPSCFG_V_TH_AVR].dDivider);
	// OPOZNIENIE_STANDBY
	sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME] = (int)(scfgvaldef[INT_UPSCFG_STANDBYDELAY].value.iValue *
		scfgvaldef[INT_UPSCFG_STANDBYDELAY].dDivider);

	memcpy(uiSetupTable, &sdcNet.uiSetupTable, sizeof(sdcNet.uiSetupTable));

	if (commNet.isInitialized()) {
		iSize = SETUP_TABLE_ITEMS;
		iRet = Net_SetAllUpsSetupParams(uiSetupTable, &iSize);
		if (iRet != IOCTL_ERROR_SUCCESS)
			return iRet;
	}

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

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

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

// Function name	: Net_ReadConfig
// Description		: 
int	Net_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;
	// serial port
	strcpy(sdcNet.szSerialPort, ((s=pCfgDev->getcfgitemvalue("commport"))=="")?"/dev/ttyS0":s);
	// BUZZER
	sdcNet.uiSetupTable[SETUP_ITEM_BUZZER_EN]=(bool)atoi(((s=pCfgDev->getcfgitemvalue("audible_alarm"))=="")?"1":s);
	// IDX_V_PROG_DOLNY
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_LOWER]=(unsigned int)atoi(
		((s=pCfgDev->getcfgitemvalue("lower_transfer_treshold"))=="")?"185":s);
	// IDX_V_PROG_GORNY
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_UPPER]=(unsigned int)atoi(
		((s=pCfgDev->getcfgitemvalue("upper_transfer_treshold"))=="")?"270":s);
	// IDX_V_PROG_AVR
	sdcNet.uiSetupTable[SETUP_ITEM_V_TH_AVR]=(unsigned int)atoi(
		((s=pCfgDev->getcfgitemvalue("avr_transfer_treshold"))=="")?"200":s);
	// OPOZNIENIE_STANDBY
	sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME]=(unsigned int)strtoul(
		((s=pCfgDev->getcfgitemvalue("powerfail_to_standby_timeout"))=="")?"90":s, NULL, 10);

	
	delete pCfgDev;
	
	return IOCTL_ERROR_SUCCESS;
}

// Function name	: Net_DoUpdateConfig
// Description		: 
int	Net_DoUpdateConfig(void *lpvBuff, int *lpiBuffSize)
{
	iNet_ExtError = 0;
	
	if (Net_ReadConfig() != IOCTL_ERROR_SUCCESS)
		return IOCTL_ERROR_CONFIG_READFAIL;
	
	int iSize = SETUP_TABLE_ITEMS;
	return Net_SetAllUpsSetupParams(sdcNet.uiSetupTable, &iSize);
}

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

// Function name	: Net_DoUpsShutdown
// Description		: 
// Return type		: int 
// Argument         : void *lpvBuff
// Argument         : int *lpiBuffSize
int Net_DoUpsShutdown(void *lpvBuff, int *lpiBuffSize)
{
	unsigned int uiData[2];
	int iSize, iRet;
	
	// standby timeout
	uiData[0] = (unsigned int)(((float)sdcNet.uiSetupTable[SETUP_ITEM_STANDBY_TIME]+0.5f) / 1.28f);
	iSize = 1;
	iRet = Net_DoSetUPSdata(EU_STANDBY_TIME, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_SYSFLAG, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiData[0] &= SFB_AND_STANDBY;
	uiData[0] |= SFB_OR_STANDBY;
	iSize = 1;
	iRet = Net_DoSetUPSdata(EU_SYSFLAG, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

int Net_GetAllUpsParams(void *lpvBuff, int *lpiBuffSize)
{
	int	iSize, iRet;
	unsigned int uiData[2];
	/* tablica parametrow */
	unsigned int uiParamsTable[PARAMS_TABLE_ITEMS];
	float fDiv = 0.0f;
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < PARAMS_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_UPSTYPE, &uiParamsTable[IDXP_UPSTYPE], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	if (uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL1_2 ||
		uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL2_2 ||
		uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL3_2 ||
		uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL4_2)
		fDiv = 3.52f;
	else
		fDiv = 3.72f;
	// napiecie sieciowe - wejsciowe
	iSize = sizeof(uiData)/sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_U_POWER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiParamsTable[IDXP_U_POWER] = (unsigned int)((float)(uiData[0] + (uiData[1] << 8)) / fDiv);
	
	// napiecie akumulatora
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_U_AKU, &uiParamsTable[IDXP_U_AKU], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiParamsTable[IDXP_U_AKU] = (unsigned int)((uiParamsTable[IDXP_U_AKU] * 150) / 255);
	
	// status pracy zasilacza do obliczenia pojemnosci
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_STATE, &uiParamsTable[IDXP_STATEFLAG], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// rejestr sysflag
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_SYSFLAG, &uiParamsTable[IDXP_SYSFLAG], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// status avr
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_STATEAVR, &uiParamsTable[IDXP_STATEAVR], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// napiecie przelaczania AVR
	iSize = 2;
	iRet = Net_DoGetUPSdata(EU_S_AVRUP, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiParamsTable[IDXP_TH_AVRUP] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);
	
	// napiecie przelaczania - gorny prog
	iSize = 2;
	iRet = Net_DoGetUPSdata(EU_S_UPPER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiParamsTable[IDXP_TH_UPPER] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);

	// napiecie przelaczania - dolny prog
	iSize = 2;
	iRet = Net_DoGetUPSdata(EU_S_LOWER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiParamsTable[IDXP_TH_LOWER] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);
 
	memcpy( lpvBuff, uiParamsTable, PARAMS_TABLE_ITEMS * sizeof(unsigned int) );

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

int Net_GetAllUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	int	iSize, iRet;
	unsigned int uiData[2];
	/* tablica parametrow */
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];
	float fDiv = 0.0f;
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < SETUP_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

	if (sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL1_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL2_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL3_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL4_2)
		fDiv = 3.52f;
	else
		fDiv = 3.72f;
	
	// napiecie przelaczania AVR
	iSize = sizeof(uiData)/sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_S_AVRUP, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiSetupTable[SETUP_ITEM_V_TH_AVR] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);

	// napiecie przelaczania - gorny prog
	iSize = sizeof(uiData)/sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_S_UPPER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiSetupTable[SETUP_ITEM_V_TH_UPPER] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);

	// napiecie przelaczania - dolny prog
	iSize = sizeof(uiData) / sizeof(unsigned int);
	iRet = Net_DoGetUPSdata(EU_S_LOWER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiSetupTable[SETUP_ITEM_V_TH_LOWER] = (unsigned int)(((float)(uiData[0] + (uiData[1]<<8)) + 0.5f) / fDiv);

	// status pracy zasilacza do obliczenia pojemnosci
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_SYSFLAG, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	uiSetupTable[SETUP_ITEM_BUZZER_EN] = ((uiData[0] & SFB_OR_SOUND)==SFB_OR_SOUND)?0:1;

	// opoznienie standby
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_STANDBY_TIME, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiSetupTable[SETUP_ITEM_STANDBY_TIME] = (unsigned int)(((float)(uiData[0])*1.28)+0.5f);

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

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}

int Net_SetAllUpsSetupParams(void *lpvBuff, int *lpiBuffSize)
{
	int	iSize, iRet;
	unsigned int uiData[2];
	/* tablica parametrow */
	unsigned int uiSetupTable[SETUP_TABLE_ITEMS];
	float fDiv = 3.72;
	
	if (lpiBuffSize != NULL)
		if (*lpiBuffSize < SETUP_TABLE_ITEMS)
			return IOCTL_ERROR_INVALIDARGUMENT;

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

	if (sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL1_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL2_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL3_2 ||
		sdcNet.uiParamsTable[IDXP_UPSTYPE] == INT_UPS_MODEL4_2)
		fDiv = 3.52f;
	else
		fDiv = 3.72f;

	// napiecie przelaczania AVR
	uiSetupTable[SETUP_ITEM_V_TH_AVR] = (unsigned int)(((float)uiSetupTable[SETUP_ITEM_V_TH_AVR]*fDiv)+0.5f);
	uiData[0] = uiSetupTable[SETUP_ITEM_V_TH_AVR] & 0xFF;
	uiData[1] = (uiSetupTable[SETUP_ITEM_V_TH_AVR] >> 8) & 0xFF;
	iSize = 2;
	iRet = Net_DoSetUPSdata(EU_S_AVRUP, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	// napiecie przelaczania - gorny prog
	uiSetupTable[SETUP_ITEM_V_TH_UPPER] = (unsigned int)(((float)uiSetupTable[SETUP_ITEM_V_TH_UPPER]*fDiv)+0.5f);
	uiData[0] = uiSetupTable[SETUP_ITEM_V_TH_UPPER] & 0xFF;
	uiData[1] = (uiSetupTable[SETUP_ITEM_V_TH_UPPER] >> 8) & 0xFF;
	iSize = 2;
	iRet = Net_DoSetUPSdata(EU_S_UPPER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	// napiecie przelaczania - dolny prog
	uiSetupTable[SETUP_ITEM_V_TH_LOWER] = (unsigned int)(((float)uiSetupTable[SETUP_ITEM_V_TH_LOWER]*fDiv)+0.5f);
	uiData[0] = uiSetupTable[SETUP_ITEM_V_TH_LOWER] & 0xFF;
	uiData[1] = (uiSetupTable[SETUP_ITEM_V_TH_LOWER] >> 8) & 0xFF;
	iSize = 2;
	iRet = Net_DoSetUPSdata(EU_S_LOWER, &uiData, &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// status pracy zasilacza do ustawienia dzwieku
	iSize = 1;
	iRet = Net_DoGetUPSdata(EU_SYSFLAG, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;
	uiData[0] &= SFB_AND_SOUND;
	if ( !uiSetupTable[SETUP_ITEM_BUZZER_EN] )
		uiData[0] |= SFB_OR_SOUND;
	iSize = 1;
	iRet = Net_DoSetUPSdata(EU_SYSFLAG, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

	// opoznienie standby
	uiData[0] = (unsigned int)(((float)uiSetupTable[SETUP_ITEM_STANDBY_TIME]+0.5f) / 1.28f);
	iSize = 1;
	iRet = Net_DoSetUPSdata(EU_STANDBY_TIME, &uiData[0], &iSize);
	if (iRet != IOCTL_ERROR_SUCCESS)
		return iRet;

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

	iNet_ExtError = 0;
	return IOCTL_ERROR_SUCCESS;
}
