#include "Platform.h"

#ifndef UNDER_CE

#include <stdlib.h>
#include <stdio.h>
#include "USBCommunication.h"
#include "CCIDReader.h"


#define base CBaseCommunication

#define IOCTL_CCID_INT        0x80722216L
#define IOCTL_CCID_ABORT      0x80722218L
#define IOCTL_CCID_DESCRIPTOR 0x8072221CL
#define IOCTL_CCID_DRIVERVERSION 0x8072221EL




CUSBCommunication::CUSBCommunication(const char *cDeviceName,CReader *Owner)
                  :CBaseCommunication(cDeviceName,Owner)
{
	m_pSBuffer=NULL;
	m_nSBufferLen=0;
	m_hDevice=INVALID_HANDLE_VALUE;
	m_bFirstReceive=true;


	memset(&m_olTransmit,0,sizeof(m_olTransmit));
	m_olTransmit.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

	memset(&m_olReceive,0,sizeof(m_olReceive));
	m_olReceive.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
	m_pDriverInfo=(USB_DEVICE_T *)new int8_t [2048];
	m_dwWriteTimeout=5000;
}

int CUSBCommunication::Open()
{
	char *temp=new char[strlen(m_cDeviceName)+10];
	strcpy(temp,m_cDeviceName);
	strcat(temp,"\\rsct_usb");
   m_hDevice=CreateFile( temp,

						     GENERIC_READ | GENERIC_WRITE,
							  0,
							  NULL,
							  OPEN_EXISTING,
							  FILE_FLAG_OVERLAPPED,
							  (HANDLE)NULL);
	delete temp;
	if(m_hDevice!=INVALID_HANDLE_VALUE)
	{
	   StartInterruptPipe();
		return 1;
	}
	return 0;
}

void CUSBCommunication::Close(void)
{
	m_CritClose.Enter();
   _Close();
	HaltInterruptPipe();
	m_CritClose.Leave();
}

void CUSBCommunication::_Close(void)
{
	m_CritClose.Enter();
	if(m_hDevice!=INVALID_HANDLE_VALUE)
	{
		CloseHandle(m_hDevice);
		m_hDevice=INVALID_HANDLE_VALUE;
	}
	m_CritClose.Leave();
}


void CUSBCommunication::SetCommunicationString(cj_ReaderInfo *ReaderInfo)
{
	int8_t *ptr;
	ReaderInfo->PID=m_pDriverInfo->ProductId;
	ReaderInfo->PortID=atoi(m_cDeviceName+strlen(m_cDeviceName)-2);
	memcpy(ReaderInfo->CommunicationString,"USB",4);
	ptr=((int8_t *)m_pDriverInfo)+m_pDriverInfo->ProductOffs;
	memcpy(ReaderInfo->ProductString,ptr,m_pDriverInfo->ProductLength);
	ptr=((int8_t *)m_pDriverInfo)+m_pDriverInfo->ManufacturerOffs;
	memcpy(ReaderInfo->VendorString,ptr,m_pDriverInfo->ManufacturerLength);

	ReaderInfo->ContentsMask=	RSCT_READER_MASK_PID |
										RSCT_READER_MASK_VENDOR_STRING |
										RSCT_READER_MASK_PRODUCT_STRING |
										RSCT_READER_MASK_COM_TYPE |
										RSCT_READER_MASK_PORT_ID;


}



CUSBCommunication::~CUSBCommunication(void)
{
	Close();
	if(m_olTransmit.hEvent)
		CloseHandle(m_olTransmit.hEvent);
	if(m_olReceive.hEvent)
		CloseHandle(m_olReceive.hEvent);
	if(m_pSBuffer)
		delete m_pSBuffer;
	delete m_pDriverInfo;

}

int CUSBCommunication::Write(void *Message,uint32_t len)
{
   DWORD nRet;
	DWORD last;
	if(base::Write(Message,len)==CJ_SUCCESS)
	{
   	if(len+4 > m_nSBufferLen)
	   {
			if(m_pSBuffer)
				delete m_pSBuffer;
			m_pSBuffer= new uint8_t[len+4096];
			if(m_pSBuffer==NULL)
			{
				m_nSBufferLen=0;
				return CJ_ERR_INTERNAL_BUFFER_OVERFLOW;
			}

			m_nSBufferLen=len+4096;
		}
		for(;;)
		{
			ResetEvent(m_olTransmit.hEvent);

			nRet=0;
			m_olTransmit.Internal=0;
			m_olTransmit.InternalHigh=0;
			m_olTransmit.Offset=0;
			m_olTransmit.OffsetHigh=0;
			memcpy(m_pSBuffer,"CJCC",4);
			memcpy(m_pSBuffer+4,Message,len);
			if(WriteFile(m_hDevice,m_pSBuffer,(DWORD)len+4,&nRet,&m_olTransmit)==0)
			{
			  if((last=GetLastError())!=ERROR_IO_PENDING)
			  {
				  if(last==ERROR_INVALID_HANDLE)
				  {
					  Close();
					  Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID OUT: WriteFile -- CJPP_ERR_DEVICE_LOST",0,0);
					  return CJ_ERR_DEVICE_LOST;
				  }

			  }
			  else if(WaitForSingleObject(m_olTransmit.hEvent,m_dwWriteTimeout)==WAIT_TIMEOUT)
			  {
				  if(m_dwWriteTimeout==5000)
				  {
					  Close();
					  Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID OUT: WriteFile -- CJPP_ERR_WRITE_DEVICE",0,0);
					  return CJ_ERR_CONNECT_TIMEOUT;
				  }
				  else if(WaitForSingleObject(m_olTransmit.hEvent,55000)==WAIT_TIMEOUT)
				  {
					  Close();
					  Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID OUT: WriteFile -- CJPP_ERR_WRITE_DEVICE",0,0);
					  return CJ_ERR_WRITE_DEVICE;
				  } 
				  else
					  break;
			  }    
			  else
				  break;
			}
			else
				break;
		}
   }
	m_dwWriteTimeout=30000;
	if(m_hDevice==INVALID_HANDLE_VALUE)
      return CJ_ERR_DEVICE_LOST;   
	return CJ_SUCCESS;
}

int CUSBCommunication::Read(void *Response,uint32_t *ResponseLen)
{
	DWORD		nRetBytes;
   if(m_hDevice)
	{
		nRetBytes=0;

		m_olReceive.Offset=0;
		m_olReceive.OffsetHigh=0;
		m_olReceive.Internal=0;
		m_olReceive.InternalHigh=0;
		ResetEvent(m_olReceive.hEvent);
			
		memcpy(Response,"CJCC",4);
		if(ReadFile(m_hDevice,Response,(DWORD)*ResponseLen,&nRetBytes,&m_olReceive)==0)
		{
			DWORD last;
			if((last=GetLastError())!=ERROR_IO_PENDING)
			{
			  if(last==ERROR_INVALID_HANDLE || last==ERROR_GEN_FAILURE)
			  {
				  Close();
				  Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID IN: ReadFile -- CJPP_ERR_DEVICE_LOST",0,0);
				  return CJ_ERR_DEVICE_LOST;
			  }
			  else
				  Sleep(100);
			}
			if(m_bFirstReceive)
			{
				if(WaitForSingleObject(m_olReceive.hEvent,5000)==WAIT_TIMEOUT)
				{
					Close();
					Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID IN: ReadFile -- CJPP_ERR_DEVICE_LOST -- Timeout",0,0);
					return CJ_ERR_CONNECT_TIMEOUT;
				}
				m_bFirstReceive=false;
			}

			if(!GetOverlappedResult(m_hDevice,&m_olReceive,&nRetBytes,TRUE))
			{
				last=GetLastError();
				if(last==ERROR_INVALID_HANDLE || last==ERROR_GEN_FAILURE)
				{
					Close();
					Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_ERROR,"CCID IN: ReadFile -- CJPP_ERR_DEVICE_LOST",0,0);
					return CJ_ERR_DEVICE_LOST;
				}
			}
		}
	}
	else
	   return CJ_ERR_DEVICE_LOST;
	CBaseCommunication::Read(Response,(uint32_t *)&nRetBytes);
	*ResponseLen=(int)nRetBytes;
   return CJ_SUCCESS;
}

DWORD __stdcall CUSBCommunication::_IntPipeThreadRoutine(LPVOID ptr)
{
   return ((CUSBCommunication *)ptr)->IntPipeThreadRoutine();
}


DWORD CUSBCommunication::IntPipeThreadRoutine()
{
   uint8_t buffer[270];
   OVERLAPPED over;
   DWORD nRet;
   DWORD last;


   memset(&over,0,sizeof(over));
   over.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
   while(m_InterruptPipeState!=HaltRequest && m_hDevice)
   {
      nRet=0;
      ResetEvent(over.hEvent);
      over.Offset=0;
      over.OffsetHigh=0;
      memcpy(buffer,"CJCC",4);
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_IN,"CCID INT -- Start:",0,0);
		if(!DeviceIoControl(m_hDevice,IOCTL_CCID_INT,NULL,0,buffer,270,&nRet,&over))
		{
			if((last=GetLastError())!=ERROR_IO_PENDING)
			{
			  if(last==ERROR_INVALID_HANDLE || last==ERROR_GEN_FAILURE)
			  {
				  _Close();
				  return (DWORD)CJ_ERR_DEVICE_LOST;
			  }
			  else
				  Sleep(100);
			}
			if(!GetOverlappedResult(m_hDevice,&over,&nRet,TRUE))
			{
				if(GetLastError()==ERROR_INVALID_HANDLE || last==ERROR_GEN_FAILURE)
				{
					_Close();
					return (DWORD)CJ_ERR_DEVICE_LOST;
				}
				else
					Sleep(100);
			}
		}
		if(nRet)
		{
			if(m_Reader)
		      m_Reader->DoInterruptCallback(buffer,(uint32_t)nRet);
		}
   }
   CloseHandle(over.hEvent);
   return CJ_SUCCESS;
}


int CUSBCommunication::StartInterruptPipe()
{
	DWORD ThreadId;
	m_InterruptPipeState=Running;
   m_IntPipeThread=CreateThread(NULL,0,(  DWORD (WINAPI *)( LPVOID ))_IntPipeThreadRoutine,this,0,&ThreadId);
	return 0;
}

int CUSBCommunication::HaltInterruptPipe()
{
	if(m_InterruptPipeState!=UnInit)
	{
		m_InterruptPipeState=HaltRequest;
		WaitForSingleObject(m_IntPipeThread,2000);
			Sleep(50);
		TerminateThread(m_IntPipeThread,0);
		CloseHandle(m_IntPipeThread);
		m_InterruptPipeState=UnInit;
	}
	return 0;
}

bool CUSBCommunication::SetupDeviceInfo()
{
	DWORD nRet;
	DWORD last;
	OVERLAPPED over;
	over.hEvent = CreateEvent(NULL, false, false, NULL);

	if (!DeviceIoControl(m_hDevice, IOCTL_CCID_DESCRIPTOR, m_pDriverInfo, 2048, m_pDriverInfo, 2048, &nRet, &over))
	{
		if ((last = GetLastError()) != ERROR_IO_PENDING)
		{
			m_Owner->DebugLeveled(DEBUG_MASK_COMMUNICATION_ERROR, "Unknown SYS - driver: request error");
			Close();
			CloseHandle(over.hEvent);
			return false;
		}
		Sleep(500);
		if (!GetOverlappedResult(m_hDevice, &over, &nRet, FALSE))
		{
			m_Owner->DebugLeveled(DEBUG_MASK_COMMUNICATION_ERROR, "Unknown SYS - driver: timeout");
			Close();
			CloseHandle(over.hEvent);
			return false;
		}
	}
	CloseHandle(over.hEvent);

	if (nRet<sizeof(USB_DEVICE_T))
	{
		m_Owner->DebugLeveled(DEBUG_MASK_COMMUNICATION_ERROR, "Unknown SYS - driver: struct error");
		Close();
		return false;
	}

	return true;
}


CBaseReader *CUSBCommunication::BuildReaderObject()
{
	int8_t *ptr;


	if (!SetupDeviceInfo())
		return NULL;


	ptr = ((int8_t *)m_pDriverInfo) + m_pDriverInfo->ProductOffs;


	if (m_pDriverInfo->VendorId != 0x0c4b)
	{
		m_Owner->DebugLeveled(DEBUG_MASK_COMMUNICATION_ERROR, "Unknown device vendor");
		Close();
		return NULL;
	}

	switch(m_pDriverInfo->ProductId)
	{
	case 0x0300:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
	    m_pDriverInfo->ProductLength=20;
		ptr[19]='\0';
		m_Reader = new CPPAReader(m_Owner,this);
		return m_Reader;
	case 0x0400:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if(m_pDriverInfo->ProductLength>=19 && memcmp(ptr,"cyberJack e-com(a)",18)==0)
		{
			m_pDriverInfo->ProductLength=19;
			ptr[18]='\0';
			m_Reader = new CECAReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=25 && memcmp(ptr,"cyberJack e-com plus DUO",24)==0)
		{
			m_pDriverInfo->ProductLength=25;
			ptr[24]='\0';
			m_Reader = new CECBReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=25 && memcmp(ptr,"cyberJack e-com plus BIO",24)==0)
		{
			m_pDriverInfo->ProductLength=25;
			ptr[24]='\0';
			m_Reader = new CECBReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=26 && memcmp(ptr,"cyberJack e-com plus RFID",25)==0)
		{
			m_pDriverInfo->ProductLength=26;
			ptr[25]='\0';
			m_Reader = new CECRReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=21 && memcmp(ptr,"cyberJack e-com plus",20)==0)
		{
			m_pDriverInfo->ProductLength=21;
			ptr[20]='\0';
			m_Reader = new CECPReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=18 && memcmp(ptr,"cyberJack Secoder",17)==0)
		{
			m_pDriverInfo->ProductLength=18;
			ptr[17]='\0';
			m_Reader = new CSECReader(m_Owner,this);
		}
		else
			break;
		return m_Reader;
	case 0x0401:
		if(m_pDriverInfo->ProductLength>=19 && memcmp(ptr,"cyberJack e-com(f)",18)==0)
		{
			m_pDriverInfo->ProductLength=19;
			ptr[18]='\0';
			m_Reader = new CECFReader(m_Owner,this);
		}
		else if(m_pDriverInfo->ProductLength>=20 && memcmp(ptr,"cyberJack e-com BIO",19)==0)
		{
			m_pDriverInfo->ProductLength=20;
			ptr[19]='\0';
			m_Reader = new CEFBReader(m_Owner,this);
		}
		else
			break;
		return m_Reader;
	case 0x0500:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if (m_pDriverInfo->ProductLength >= 29 && memcmp(ptr, "cyberJack RFID standard HUN1", 28) == 0)
		{
			m_pDriverInfo->ProductLength = 28;
			ptr[27] = '\0';
			m_Reader = new CRS2Reader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 28 && memcmp(ptr, "cyberJack RFID standard HUN", 27) == 0)
		{
			m_pDriverInfo->ProductLength = 28;
			ptr[27] = '\0';
			m_Reader = new CSHUReader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 25 && memcmp(ptr, "cyberJack RFID standard1", 24) == 0)
		{
			m_pDriverInfo->ProductLength = 24;
			ptr[23] = '\0';
			m_Reader = new CRS1Reader(m_Owner, this);
		}
		else if(m_pDriverInfo->ProductLength>=24 && memcmp(ptr,"cyberJack RFID standard",23)==0)
		{
			m_pDriverInfo->ProductLength=24;
			ptr[23]='\0';
			m_Reader = new CRFSReader(m_Owner,this);
		}
		else
			break;
		return m_Reader;
	case 0x0501:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if (m_pDriverInfo->ProductLength >= 28 && memcmp(ptr, "cyberJack RFID komfort HUN1", 27) == 0)
		{
			m_pDriverInfo->ProductLength = 27;
			ptr[26] = '\0';
			m_Reader = new CRK2Reader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 27 && memcmp(ptr, "cyberJack RFID komfort HUN", 26) == 0)
		{
			m_pDriverInfo->ProductLength = 27;
			ptr[26] = '\0';
			m_Reader = new CKHUReader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 24 && memcmp(ptr, "cyberJack RFID komfort1", 23) == 0)
		{                                                          
			m_pDriverInfo->ProductLength = 23;
			ptr[22] = '\0';
			m_Reader = new CRK1Reader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 23 && memcmp(ptr, "cyberJack RFID komfort", 22) == 0)
		{
			m_pDriverInfo->ProductLength = 23;
			ptr[22] = '\0';
			m_Reader = new CRFKReader(m_Owner, this);
		}
		else
			break;
		return m_Reader;
	case 0x0502:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if(m_pDriverInfo->ProductLength>=18 && memcmp(ptr,"cyberJack compact",17)==0)
		{
			m_pDriverInfo->ProductLength=18;
			ptr[17]='\0';
			m_Reader = new CCPTReader(m_Owner,this);
		}
		else
			break;
		return m_Reader;
	case 0x0503:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if(m_pDriverInfo->ProductLength>=25 && memcmp(ptr,"cyberJack RFID universal",24)==0)
		{
			m_pDriverInfo->ProductLength=25;
			ptr[24]='\0';
			m_Reader = new CRFUReader(m_Owner,this);
		}
		else
			break;
		return m_Reader;
	case 0x0504:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		m_Reader = new CCGOReader(m_Owner,this);
		return m_Reader;

	case 0x0505:
		if (m_pDriverInfo->ProductLength >= 19 && memcmp(ptr, "cyberJack wave POL", 18) == 0)
		{
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
			m_Reader = new CWAPLReader(m_Owner, this);
			return m_Reader;
		}
		else
		{
			if (m_pDriverInfo->ProductLength >= 19 && (memcmp(ptr, "cyberJack wave PKO", 18) == 0 || 
				memcmp(ptr, "cyberJack wave PeKaO", 20) == 0))
			{
				Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
				m_Reader = new CWAPKReader(m_Owner, this);
				return m_Reader;
			}
			else
			{
				if (m_pDriverInfo->ProductLength >= 17 && memcmp(ptr, "cyberJack POS WIC", 18) == 0 )
				{
					Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
					m_Reader = new CWICReader(m_Owner, this);
					return m_Reader;
				}
				else
				{
					Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CWAVReader(m_Owner,this);
		return m_Reader;
				}
			}
		}

	case 0x0506:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		m_Reader = new CRFCReader(m_Owner,this);
		return m_Reader;
	case 0x0507:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CRFSoliReader(m_Owner,this);
		return m_Reader;
	case 0x0525:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CBDRReader(m_Owner, this);
		return m_Reader;
	case 0x0527:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CSISReader(m_Owner, this);
		return m_Reader;
	case 0x0535:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CWAHReader(m_Owner, this);
		return m_Reader;
	case 0x0580:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CONEReader(m_Owner, this);
		return m_Reader;
	case 0x0485:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		if (m_pDriverInfo->ProductLength >= 14 && memcmp(ptr, "cyberJack MKT", 13) == 0)
		{
			m_pDriverInfo->ProductLength = 14;
			ptr[13] = '\0';
			m_Reader = new CMKTReader(m_Owner, this);
			return m_Reader;
		}
		else
		{
			m_Reader = new CSYOReader(m_Owner, this);
			return m_Reader;
		}
	case 0x0412:
		Debug.Out(m_cDeviceName,DEBUG_MASK_COMMUNICATION_INFO,"Reader INFO - Productstring:",ptr,m_pDriverInfo->ProductLength);
		m_Reader = new CTLSReader(m_Owner,this);
		return m_Reader;
	case 0x2000:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CSLOReader(m_Owner, this);
		return m_Reader;
	case 0x2002:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		if ((m_pDriverInfo->ProductLength >= 26 && memcmp(ptr, "cyberJack RFID komfort PKO", 26) == 0) ||
			(m_pDriverInfo->ProductLength >= 28 && memcmp(ptr, "cyberJack RFID komfort PeKaO", 28) == 0))
		{
			m_Reader = new CKPKReader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 25 && memcmp(ptr, "cyberJack RFID komfort PL", 25) == 0)
		{
		m_Reader = new CKPLReader(m_Owner, this);
		}
		else if ((m_pDriverInfo->ProductLength >= 27 && memcmp(ptr, "cyberJack RFID komfort PKO1", 27) == 0) ||
			(m_pDriverInfo->ProductLength >= 29 && memcmp(ptr, "cyberJack RFID komfort PeKaO1", 29) == 0))
		{
			m_pDriverInfo->ProductLength -= 1;
			ptr[m_pDriverInfo->ProductLength - 1] = '\0';
			m_Reader = new CRK4Reader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 26 && memcmp(ptr, "cyberJack RFID komfort PL1", 26) == 0)
		{
			m_pDriverInfo->ProductLength -= 1;
			ptr[m_pDriverInfo->ProductLength - 1] = '\0';
			m_Reader = new CRK3Reader(m_Owner, this);
		}
		else
		{
			break;
		}
		return m_Reader;
	case 0x2003:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CRTCReader(m_Owner, this);
		return m_Reader;
	case 0x2004:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		if (m_pDriverInfo->ProductLength >= 29 && memcmp(ptr, "cyberJack RFID standard POL1", 28) == 0)
		{
			m_pDriverInfo->ProductLength = 28;
			ptr[27] = '\0';
			m_Reader = new CRS3Reader(m_Owner, this);
		}
		else
		{
			m_Reader = new CSPLReader(m_Owner, this);
		}
		return m_Reader;

	case 0x2005:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		if (m_pDriverInfo->ProductLength >= 23 && memcmp(ptr, "cyberJack RFID citycard", 23) == 0)
		{
			m_Reader = new CCYCReader(m_Owner, this);
		}
		else if (m_pDriverInfo->ProductLength >= 24 && memcmp(ptr, "cyberJack RFID citycard1", 24) == 0)
		{
			m_pDriverInfo->ProductLength = 23;
			ptr[24] = '\0';
			m_Reader = new CRK6Reader(m_Owner, this);
		}
		return m_Reader;

	case 0x2006:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CONEReader(m_Owner, this);
		return m_Reader;

	case 0x2007:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CRKFReader(m_Owner, this);
		return m_Reader;
	case 0x2008:
		Debug.Out(m_cDeviceName, DEBUG_MASK_COMMUNICATION_INFO, "Reader INFO - Productstring:", ptr, m_pDriverInfo->ProductLength);
		m_Reader = new CRSEReader(m_Owner, this);
		return m_Reader;

	default:;
	}
	m_Owner->DebugLeveled(DEBUG_MASK_COMMUNICATION_ERROR,"Unknown device product");
	return NULL;
}

bool CUSBCommunication::IsConnected()
{
	return (m_hDevice!=INVALID_HANDLE_VALUE);
}

#endif // #ifdef UNDER_CE
