void RemoveListener( LPARDUINOLISTENER listener )
	{
	LOG(MAINFUNC,"Arduino::RemoveListener");
	listener_lock.Lock();
	int i=0;
	while ( (i<listeners_count) && (listeners[i].callback!=listener) )
		i++;
	if (listeners[i].callback==listener)
		{
		// remove entry so that entries after this are simply moved 1 entry lower
		while (i<listeners_count-1)
			{
			listeners[i].callback = listeners[i+1].callback;
			listeners[i].data = listeners[i+1].data;
			i++;
			}
		listeners_count--;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RemoveListener - removed successfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RemoveListener - no such listener found!");
		}
	}
int Send(const char * cmd)
	{
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - msg [%s]",cmd);
	write_lock.Lock();

	DWORD dwwritten = 0; 
	int len = strlen(cmd);

	char buf[256];
	if(len>256)
	{
		write_lock.Unlock();
		LOG(ERR,"Arduino::Send: Msg too long!");
		return -1;
	}

#ifndef USBCAN_PROTOCOL
	// surround message with {}
	sprintf_s(buf,256,"{%s}\r",cmd);
	len += 3;	// {}\r
#else
	sprintf_s(buf,256,"%s\r",cmd);
	len += 1;	// \r
#endif

	if  ( (dwwritten=blockingWrite(buf, len )) == -1)
		{
		LOG(ERR,"Arduino::SendMsg - Blocking write failed ! \n");
		write_lock.Unlock();
		return -1;
		}

	if (dwwritten != len)
		{
		write_lock.Unlock();
		LOG(ERR,"Arduino::SendMsg - Write didn't finish (%d out of %d bytes sent)\n", dwwritten,len);
		DWORD   dwErrors;
		COMSTAT comStat;
		ClearCommError(hCommPort, &dwErrors, &comStat);
		LOG(ERR,"Arduino::SendMsg - ClearCommError: Error flags: 0x%x, bytes in output queue: %d\n", dwErrors, comStat.cbOutQue);		
		return -1;
		}
	write_lock.Unlock();

#ifndef USBCAN_PROTOCOL
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-3);
	return dwwritten-3;
#else
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-1);
	return dwwritten-1;
#endif
}
bool IsConnected()
{
	init_lock.Lock();
	LOG(HELPERFUNC,"Arduino::IsConnected %d",isConnected);
	bool isconnected = isConnected;
	init_lock.Unlock();
	return isconnected;
}
int RegisterListener( LPARDUINOLISTENER listener, void *data )
	{
	LOG(MAINFUNC,"Arduino::RegisterListener");
	listener_lock.Lock();
	if (listeners_count<MAX_LISTENERS)
		{
		listeners[listeners_count].callback = listener;
		listeners[listeners_count].data = data;
		listeners_count++;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RegisterListener - added succesfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RegisterListener - too many listeners!");
		return -1;
		}
	return 0;
	}
int CloseDevice()
{
	LOG(MAINFUNC,"Arduino::CloseDevice");
	init_lock.Lock();
	CloseHandle(hCommPort);
	hCommPort=INVALID_HANDLE_VALUE;
	isConnected=0;
	CloseHandle(ghWriteCompleteEvent);
	init_lock.Unlock();
	return 0;
}
int OpenDevice( int com_port, int baud_rate, int disable_DTR )
{
	LOG(MAINFUNC,"Arduino::OpenDevice - com port %d, baud_rate %d, disable DTR %d",com_port,baud_rate,disable_DTR);
	init_lock.Lock();
	if (isConnected)
		{
		init_lock.Unlock();
		LOG(ERR,"Arduino::OpenDevice - already connected!");
		return ARDUINO_ALREADY_CONNECTED;
		}

	if (com_port==-1)
		{
		com_port = ARDUINO_DEFAULT_COM_PORT;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to comport %d",com_port);
		}
	if (baud_rate==-1)
		{
		baud_rate = ARDUINO_DEFAULT_BAUD_RATE;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to baud rate %d",baud_rate);
		}
	if (disable_DTR==-1)
		{
		disable_DTR = ARDUINO_DEFAULT_DTR_DISABLED;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to dtr disabled=%d",disable_DTR);
		}
	

	TCHAR COMx[32];
	int n = _stprintf_s(COMx, 32, _T("\\\\.\\COM%d"),com_port);
	long int err;
	BOOL fSuccess;	
	DCB dcb;

	LOG(MAINFUNC,"Arduino::OpenDevice - creating file handle for com port");
	hCommPort = CreateFile(
	COMx,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_WRITE, // 0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL
    );

	if (hCommPort == INVALID_HANDLE_VALUE) 
	{
		err=GetLastError();
		if (err==ERROR_ALREADY_EXISTS)
			{
			LOG(ERR,"Arduino::OpenDevice - Already opened by other process!");
			init_lock.Unlock();
			return ARDUINO_IN_USE;
			} 
		else
			{
			LOG(ERR,"Arduino::OpenDevice - CreateFileA failed %d!",err);
			init_lock.Unlock();
			return ARDUINO_OPEN_FAILED;
			}
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - getting comm state");
	fSuccess = GetCommState(hCommPort, &dcb);

	if (!fSuccess) 
	{
		LOG(ERR,"Arduino::OpenDevice - GetCommStateFailed %d", err=GetLastError());
		PrintError(err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		init_lock.Unlock();
		return ARDUINO_GET_COMMSTATE_FAILED;
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - setting comm state");
	dcb.BaudRate = baud_rate;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fDtrControl = (disable_DTR==1 ? DTR_CONTROL_DISABLE : DTR_CONTROL_ENABLE);	// to prevent Arduino from reseting when first sending something
		
	fSuccess = SetCommState(hCommPort, &dcb);
	if (!fSuccess) 
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - SetCommStateFailed %d", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMSTATE_FAILED;
	}


	LOG(MAINFUNC,"Arduino::OpenDevice - enable listening to comm events");
	DWORD      dwStoredFlags;
	// listen only for events regarding errors and receive buffer
	dwStoredFlags = /*EV_BREAK | EV_CTS |*/ EV_DSR | /* EV_ERR | EV_RING | EV_RLSD | */ EV_RXCHAR /* | EV_RXFLAG | EV_TXEMPTY*/ ;
	if (!SetCommMask(hCommPort, dwStoredFlags))
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - Error setting communications mask (err %d); abort!", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMMASK_FAILED;
	}

	// create event for write completed
	if ((ghWriteCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
	{
		LOG(ERR,"Arduino::OpenDevice - Create 'Write Complete Event' failed (err %d); abort!", GetLastError());
		return ARDUINO_CREATE_EVENT_FAILED;
	}


	blockingWrite("\r\r\r",3);

	isConnected=true;

#ifdef USBCAN_PROTOCOL
	Send("Z0");	// we are not interested in time stamps, we generate our own
#else
	Send(":ping");
#endif

	init_lock.Unlock();
	LOG(MAINFUNC,"Arduino::OpenDevice - port configured");
	return ARDUINO_INIT_OK;
}