11 #include "base classses.h" 12 #include "named pipes.h" 13 #include "ftdi device.h" 15 #include "misc tools.h" 19 FT_STATUS (WINAPI *lpfFT_CreateDeviceInfoList)(LPDWORD lpdwNumDevs)= NULL;
20 FT_STATUS (WINAPI *lpfFT_SetLatencyTimer)(FT_HANDLE ftHandle, UCHAR ucLatency)= NULL;
21 FT_STATUS (WINAPI *lpfFT_OpenEx)(PVOID pArg1, DWORD Flags, FT_HANDLE *pHandle)= NULL;
22 FT_STATUS (WINAPI *lpfFT_Close)(FT_HANDLE ftHandle)= NULL;
23 FT_STATUS (WINAPI *lpfFT_Read)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesReturned)= NULL;
24 FT_STATUS (WINAPI *lpfFT_Write)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten)= NULL;
25 FT_STATUS (WINAPI *lpfFT_SetBaudRate)(FT_HANDLE ftHandle, ULONG BaudRate)= NULL;
26 FT_STATUS (WINAPI *lpfFT_SetBitMode)(FT_HANDLE ftHandle, UCHAR ucMask, UCHAR ucEnable)= NULL;
27 FT_STATUS (WINAPI *lpfFT_Purge)(FT_HANDLE ftHandle, ULONG Mask)= NULL;
28 FT_STATUS (WINAPI *lpfFT_SetUSBParameters)(FT_HANDLE ftHandle, ULONG ulInTransferSize, ULONG ulOutTransferSize)= NULL;
29 FT_STATUS (WINAPI *lpfFT_CyclePort)(FT_HANDLE ftHandle)= NULL;
30 FT_STATUS (WINAPI *lpfFT_ResetPort)(FT_HANDLE ftHandle)= NULL;
31 FT_STATUS (WINAPI *lpf_FT_GetLibraryVersion)(LPDWORD lpdwVersion)= NULL;
35 CManagerFTDI::CManagerFTDI(
CComm* pcComm,
const TCHAR szPipe[],
int nChan,
int &nError) :
36 CManager(FTDI_MAN_STR, std::tstring(szPipe), nChan)
45 if (!pcComm || !szPipe)
47 nError= BAD_INPUT_PARAMS;
50 BOOL bRes= GetProcAddresses(&m_hLib, _T(
"ftd2xx.dll"), 14, &lpfFT_GetDeviceInfoList,
"FT_GetDeviceInfoList",
51 &lpfFT_CreateDeviceInfoList,
"FT_CreateDeviceInfoList",
52 &lpfFT_SetLatencyTimer,
"FT_SetLatencyTimer", &lpfFT_OpenEx,
"FT_OpenEx", &lpfFT_Close,
"FT_Close",
53 &lpfFT_Read,
"FT_Read", &lpfFT_Write,
"FT_Write", &lpfFT_SetBaudRate,
"FT_SetBaudRate", &lpfFT_SetBitMode,
"FT_SetBitMode",
54 &lpfFT_Purge,
"FT_Purge", &lpfFT_SetUSBParameters,
"FT_SetUSBParameters", &lpfFT_CyclePort,
"FT_CyclePort",
55 &lpfFT_ResetPort,
"FT_ResetPort", &lpf_FT_GetLibraryVersion,
"FT_GetLibraryVersion");
62 if ((nError= FT_ERROR(lpf_FT_GetLibraryVersion(&dwVersion), nError)) != 0)
64 if (dwVersion < MIN_FTDI_LIB_VER)
82 ((
SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
83 ((
SBaseOut*)pHead)->sBaseIn.nChan= m_nChan;
84 ((
SBaseOut*)pHead)->sBaseIn.nError= 0;
86 _tcsncpy_s(((
SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE, m_csName.c_str(), _TRUNCATE);
91 CManagerFTDI::~CManagerFTDI()
93 for (
size_t i= 0; i<m_acFTDevices.size(); ++i)
94 delete m_acFTDevices[i];
112 if (!pHead || dwSize <
sizeof(
SBaseIn) || dwSize != ((
SBaseIn*)pHead)->dwSize)
114 sBase.nError= SIZE_MISSMATCH;
115 }
else if (((
SBaseIn*)pHead)->eType == eQuery && dwSize ==
sizeof(
SBaseIn))
119 if (((
SBaseIn*)pHead)->nChan == -1)
122 sBase.nError= FT_ERROR(lpfFT_CreateDeviceInfoList(&m_dwNumDevs), sBase.nError);
126 sBase.nError= FT_ERROR(lpfFT_GetDeviceInfoList(&m_asFTChanInfo[0], &m_dwNumDevs), sBase.nError);
129 DWORD i= 0, dwInfoSize= 0;
130 std::vector<int> anDev;
131 anDev.assign(max(m_dwNumDevs, 1), -1);
133 for (; i<m_dwNumDevs; ++i)
135 m_asFTChanInfo[i].ftHandle= NULL;
136 m_asFTChanInfo[i].Flags &= ~FT_FLAGS_OPENED;
137 memset(&m_asFTChanInfo[i].Description[strlen(m_asFTChanInfo[i].Description)], 0,
138 sizeof(m_asFTChanInfo[i].Description)-strlen(m_asFTChanInfo[i].Description));
139 memset(&m_asFTChanInfo[i].SerialNumber[strlen(m_asFTChanInfo[i].SerialNumber)], 0,
140 sizeof(m_asFTChanInfo[i].SerialNumber)-strlen(m_asFTChanInfo[i].SerialNumber));
142 for (;j<m_acFTDevices.size(); ++j)
144 if (m_acFTDevices[j])
158 dwInfoSize+= m_acFTDevices[j]->GetInfo(NULL, 0);
166 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(dwInfoSize);
170 memset(pBase, 0, dwInfoSize);
171 for (; i<m_dwNumDevs; ++i)
176 pBaseO->sBaseIn.eType= eResponseEx;
177 pBaseO->sBaseIn.nChan= -1;
180 pBaseS->eType= eFTDIChan;
185 m_acFTDevices[anDev[i]]->GetInfo(pBaseO, dwInfoSize-(
int)((
char*)pBaseO-(
char*)pBase));
186 pBaseO= (
SBaseOut*)((
char*)pBaseO+m_acFTDevices[anDev[i]]->GetInfo(NULL, 0));
189 pBase->dwSize= dwInfoSize;
190 pBase->eType= eQuery;
193 sData.dwSize= dwInfoSize;
195 m_pcComm->SendData(&sData, llId);
198 sBase.nError= NO_CHAN;
201 }
else if (((
SBaseIn*)pHead)->nChan < 0 || ((
SBaseIn*)pHead)->nChan >= m_acFTDevices.size() ||
202 !m_acFTDevices[((
SBaseIn*)pHead)->nChan])
204 sBase.nError= INVALID_CHANN;
207 DWORD dwSizeInfo= m_acFTDevices[((
SBaseIn*)pHead)->nChan]->GetInfo(NULL, 0);
208 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(dwSizeInfo);
211 m_acFTDevices[((
SBaseIn*)pHead)->nChan]->GetInfo(pBase, dwSizeInfo);
212 sData.dwSize= dwSizeInfo;
214 m_pcComm->SendData(&sData, llId);
217 }
else if (dwSize ==
sizeof(
SBaseIn) && ((
SBaseIn*)pHead)->eType == eDelete)
219 sBase.eType= eDelete;
220 if (((
SBaseIn*)pHead)->nChan < 0 || ((
SBaseIn*)pHead)->nChan >= m_acFTDevices.size() ||
221 !m_acFTDevices[((
SBaseIn*)pHead)->nChan])
222 sBase.nError= INVALID_CHANN;
225 delete m_acFTDevices[((
SBaseIn*)pHead)->nChan];
226 m_acFTDevices[((
SBaseIn*)pHead)->nChan]= NULL;
227 sBase.nChan= ((
SBaseIn*)pHead)->nChan;
229 }
else if (dwSize ==
sizeof(
SBaseIn) && ((
SBaseIn*)pHead)->eType == eVersion &&
230 ((
SBaseIn*)pHead)->nChan == -1)
232 sBase.nError= FT_ERROR(lpf_FT_GetLibraryVersion(&sBase.dwInfo), sBase.nError);
233 sBase.eType= eVersion;
234 }
else if (((
SBaseIn*)pHead)->nChan >= 0 && ((
SBaseIn*)pHead)->nChan < (
int)m_dwNumDevs &&
241 LARGE_INTEGER llStart;
242 for (; i<m_acFTDevices.size() && m_acFTDevices[i]; ++i);
243 if (i == m_acFTDevices.size())
244 m_acFTDevices.push_back(NULL);
246 std::tstringstream ss;
248 std::tstringstream ss2;
250 std::tstring csPipeName= m_csPipeName+_T(
":")+ss2.str()+_T(
":")+ss.str();
255 m_asFTChanInfo[((
SBaseIn*)pHead)->nChan], csPipeName.c_str(), i, sBase.nError, llStart);
258 m_acFTDevices[i]= pcChan;
262 pBaseO->sBaseIn.dwSize=
sizeof(
SBaseOut);
263 pBaseO->sBaseIn.eType= eResponseExL;
264 pBaseO->sBaseIn.nChan= i;
265 pBaseO->sBaseIn.nError= 0;
266 pBaseO->llLargeInteger= llStart;
267 pBaseO->bActive=
true;
270 m_pcComm->SendData(&sData, llId);
275 sBase.nError= INVALID_COMMAND;
277 if (sBase.nError || bRes)
283 memcpy(sData.pHead, &sBase,
sizeof(
SBaseIn));
284 m_pcComm->SendData(&sData, llId);
293 DWORD WINAPI FTChanProc(LPVOID lpParameter)
300 const TCHAR szPipe[],
int nChan,
int &nError, LARGE_INTEGER &llStart) :
CDevice(FTDI_CHAN_STR), m_FTInfo(sFTInfo),
301 m_csPipeName(szPipe), m_hUpdate(CreateEvent(NULL,TRUE, TRUE, NULL)), m_asUpdates(m_hUpdate), m_sChanInit(sChanInit),
316 if (!pInit || !szPipe)
318 nError= BAD_INPUT_PARAMS;
323 nError= FT_ERROR(lpfFT_OpenEx((PVOID)m_FTInfo.LocId, FT_OPEN_BY_LOCATION, &m_ftHandle), nError);
327 nError= FT_ERROR(lpfFT_SetLatencyTimer(m_ftHandle, 255), nError);
331 m_hStop= CreateEvent(NULL, TRUE, FALSE, NULL);
332 m_hNext= CreateEvent(NULL, TRUE, FALSE, NULL);
333 if (!m_hStop || !m_hNext || !m_hUpdate)
335 nError= NO_SYS_RESOURCE;
338 m_ahEvents.push_back(m_hStop);
339 m_ahEvents.push_back(m_hUpdate);
340 m_ahEvents.push_back(m_hNext);
348 const DWORD dwPacket= sFTInfo.Flags&FT_FLAGS_HISPEED ? 510 : 62;
350 const DWORD dwMaxPacket= sFTInfo.Flags&FT_FLAGS_HISPEED ? FTDI_MAX_BUFF_H : FTDI_MAX_BUFF_L;
351 DWORD dwBuffSizeRead= sChanInit.dwBuffIn;
352 DWORD dwBuffSizeWrite= sChanInit.dwBuffOut;
355 while ((
char*)pBase +
sizeof(
SBase) <= (
char*)pInit + dwSize)
357 switch (pBase->eType)
359 case eFTDIMultiWriteInit:
360 if ((
char*)pBase + pBase->dwSize <= (
char*)pInit + dwSize && pBase->dwSize ==
sizeof(
SValveInit)+
sizeof(
SBase))
363 dwMaxWrite= max((psValveInit->dwBoards*8*2+2)*psValveInit->dwClkPerData, dwMaxWrite);
364 dwBuffSizeRead= max(dwBuffSizeRead, psValveInit->dwBoards*8*
sizeof(
bool));
367 if ((psValveInit->dwBoards*8*2+2)*psValveInit->dwClkPerData > dwMaxPacket)
369 nError= BUFF_TOO_SMALL;
374 nError= SIZE_MISSMATCH;
378 case eFTDIMultiReadInit:
379 if ((
char*)pBase + pBase->dwSize <= (
char*)pInit + dwSize && pBase->dwSize ==
sizeof(
SValveInit)+
sizeof(
SBase))
382 dwMaxWrite= max((psValveInit->dwBoards*8*2+2+4)*psValveInit->dwClkPerData, dwMaxWrite);
383 dwBuffSizeWrite= max(dwBuffSizeWrite, psValveInit->dwBoards*8*
sizeof(
bool));
386 if ((psValveInit->dwBoards*8*2+2+4)*psValveInit->dwClkPerData > dwMaxPacket)
388 nError= BUFF_TOO_SMALL;
393 nError= SIZE_MISSMATCH;
397 case eFTDIPinWriteInit:
398 if ((
char*)pBase + pBase->dwSize <= (
char*)pInit + dwSize && pBase->dwSize ==
sizeof(
SPinInit)+
sizeof(
SBase))
401 dwMaxWrite= max(psPinInit->
usBytesUsed, dwMaxWrite);
407 nError= BUFF_TOO_SMALL;
412 nError= SIZE_MISSMATCH;
416 case eFTDIPinReadInit:
417 if ((
char*)pBase + pBase->dwSize <= (
char*)pInit + dwSize && pBase->dwSize ==
sizeof(
SPinInit)+
sizeof(
SBase))
420 dwMaxWrite= max(psPinInit->
usBytesUsed, dwMaxWrite);
421 dwBuffSizeWrite= max(dwBuffSizeWrite, psPinInit->
usBytesUsed);
426 nError= BUFF_TOO_SMALL;
431 nError= SIZE_MISSMATCH;
436 if ((
char*)pBase + pBase->dwSize <= (
char*)pInit + dwSize && pBase->dwSize ==
sizeof(
SADCInit)+
sizeof(
SBase))
441 dwMaxWrite= max(dwMaxPacket, dwMaxWrite);
442 else if (sADCInit->
fUSBBuffToUse/100 <= 3*(
float)dwPacket/(
float)dwMaxPacket)
443 dwMaxWrite= max(max(90, 3*dwPacket), dwMaxWrite);
445 dwMaxWrite= max((DWORD)ceil(sADCInit->
fUSBBuffToUse/100*dwMaxPacket)-(DWORD)ceil(sADCInit->
fUSBBuffToUse/100*dwMaxPacket)%dwPacket, dwMaxWrite);
451 nError= SIZE_MISSMATCH;
456 nError= INVALID_DEVICE;
461 dwMaxWrite= dwPacket*(DWORD)ceil((
double)dwMaxWrite/dwPacket);
464 nError=
static_cast<CPipeServer*
>(m_pcComm)->Init(szPipe, ~0x80000000, dwBuffSizeRead+MIN_BUFF_IN,
465 dwBuffSizeWrite+MIN_BUFF_OUT,
this, NULL);
471 pBase= (
SBase*)pInit;
473 while ((
char*)pBase +
sizeof(
SBase) <= (
char*)pInit + dwSize)
475 switch (pBase->eType)
477 case eFTDIMultiWriteInit:
480 sPeriphInit.dwMinSizeW= dwPacket*(DWORD)ceil((sValveInit.dwBoards*8*2+2)*sValveInit.dwClkPerData/(double)dwPacket);
481 sPeriphInit.dwMinSizeR= sPeriphInit.dwMinSizeW;
482 sPeriphInit.nChan= (int)m_aDevices.size();
483 sPeriphInit.ucBitMode= FT_BITMODE_SYNC_BITBANG;
486 case FT_DEVICE_2232H:
487 sPeriphInit.dwMaxBaud= FTDI_BAUD_2232H;
490 sPeriphInit.dwMaxBaud= FTDI_BAUD_DEFAULT;
493 sPeriphInit.ucBitOutput= 1<<sValveInit.ucLatch|1<<sValveInit.ucClk|1<<sValveInit.ucData;
494 sPeriphInit.dwBuff= dwMaxWrite;
495 hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
496 m_ahEvents.push_back(hEvent);
497 m_aDevices.push_back(
new CMultiWPeriph(sValveInit, m_pcComm, sPeriphInit, nError, hEvent, &m_cTimer));
503 case eFTDIMultiReadInit:
506 sPeriphInit.dwMinSizeR= dwPacket*(DWORD)ceil((sValveInit.dwBoards*8*2+2+4)*sValveInit.dwClkPerData/(double)dwPacket);
507 sPeriphInit.dwMinSizeW= sPeriphInit.dwMinSizeR;
508 sPeriphInit.nChan= (int)m_aDevices.size();
509 sPeriphInit.ucBitMode= FT_BITMODE_SYNC_BITBANG;
512 case FT_DEVICE_2232H:
513 sPeriphInit.dwMaxBaud= FTDI_BAUD_2232H;
516 sPeriphInit.dwMaxBaud= FTDI_BAUD_DEFAULT;
519 sPeriphInit.ucBitOutput= 1<<sValveInit.ucLatch|1<<sValveInit.ucClk;
520 sPeriphInit.dwBuff= dwMaxWrite;
521 hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
522 m_ahEvents.push_back(hEvent);
523 m_aDevices.push_back(
new CMultiRPeriph(sValveInit, m_pcComm, sPeriphInit, nError, hEvent, &m_cTimer));
529 case eFTDIPinWriteInit:
532 sPeriphInit.dwMinSizeW= dwPacket*(DWORD)ceil(sPinInit.
usBytesUsed/(
double)dwPacket);
533 sPeriphInit.dwMinSizeR= sPeriphInit.dwMinSizeW;
534 sPeriphInit.nChan= (int)m_aDevices.size();
535 sPeriphInit.ucBitMode= FT_BITMODE_SYNC_BITBANG;
538 case FT_DEVICE_2232H:
539 sPeriphInit.dwMaxBaud= FTDI_BAUD_2232H;
542 sPeriphInit.dwMaxBaud= FTDI_BAUD_DEFAULT;
546 sPeriphInit.dwBuff= dwMaxWrite;
547 hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
548 m_ahEvents.push_back(hEvent);
549 m_aDevices.push_back(
new CPinWPeriph(sPinInit, m_pcComm, sPeriphInit, nError, hEvent, &m_cTimer));
555 case eFTDIPinReadInit:
558 sPeriphInit.dwMinSizeR= dwPacket*(DWORD)ceil(sPinInit.
usBytesUsed/(
double)dwPacket);
559 sPeriphInit.dwMinSizeW= sPeriphInit.dwMinSizeR;
560 sPeriphInit.nChan= (int)m_aDevices.size();
561 sPeriphInit.ucBitMode= FT_BITMODE_SYNC_BITBANG;
564 case FT_DEVICE_2232H:
565 sPeriphInit.dwMaxBaud= FTDI_BAUD_2232H;
568 sPeriphInit.dwMaxBaud= FTDI_BAUD_DEFAULT;
571 sPeriphInit.ucBitOutput= 0;
572 sPeriphInit.dwBuff= dwMaxWrite;
573 hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
574 m_ahEvents.push_back(hEvent);
575 m_aDevices.push_back(
new CPinRPeriph(sPinInit, m_pcComm, sPeriphInit, nError, hEvent, &m_cTimer));
584 sPeriphInit.dwBuff= dwMaxWrite;
585 sPeriphInit.dwMinSizeR= dwMaxWrite;
586 sPeriphInit.dwMinSizeW= dwMaxWrite;
587 sPeriphInit.nChan= (int)m_aDevices.size();
588 sPeriphInit.ucBitMode= FT_BITMODE_SYNC_BITBANG;
591 case FT_DEVICE_2232H:
592 sPeriphInit.dwMaxBaud= FTDI_BAUD_2232H;
595 sPeriphInit.dwMaxBaud= FTDI_BAUD_DEFAULT;
598 sPeriphInit.ucBitOutput = 1<<sADCInit.
ucClk;
599 hEvent= CreateEvent(NULL,TRUE, FALSE, NULL);
600 m_ahEvents.push_back(hEvent);
601 m_aDevices.push_back(
new CADCPeriph(sADCInit, m_pcComm, sPeriphInit, hEvent, nError, &m_cTimer));
608 nError= INVALID_DEVICE;
612 if (!m_aDevices.size())
618 if (m_ahEvents.size() > MAXIMUM_WAIT_OBJECTS)
620 nError= NO_SYS_RESOURCE;
625 unsigned char ucMode= 0xFF;
626 DWORD dwWrite= 0, dwRead= 0;
627 for (DWORD i= 0; i<m_aDevices.size(); ++i)
629 ucMode &= m_aDevices[i]->m_sInitFT.ucBitMode;
630 dwWrite= max(m_aDevices[i]->m_sInitFT.dwMinSizeW, dwWrite);
631 dwRead= max(m_aDevices[i]->m_sInitFT.dwMinSizeR, dwRead);
633 ucMode= ucMode&(~ucMode+1);
634 if (ucMode&FT_BITMODE_SYNC_BITBANG)
636 dwWrite= max(dwWrite, dwRead);
640 if (!ucMode || dwRead>dwMaxPacket || dwWrite>dwMaxPacket || !dwWrite ||
641 (dwRead && !dwWrite))
643 nError= BAD_INPUT_PARAMS;
649 m_aucTx= (
unsigned char*)m_pcMemPool->PoolAcquire(dwWrite);
652 nError= NO_SYS_RESOURCE;
655 memset(m_aucTx, 0, dwWrite);
659 m_pcMemRing =
new CMemRing(dwRead+2, 1, 100);
661 if (!m_pcMemRing->
GetFree(&nIdx))
663 nError= NO_SYS_RESOURCE;
666 for (
int i = 0; i < m_aDevices.size(); ++i)
667 m_aDevices[i]->m_pcMemRing = m_pcMemRing;
670 DWORD dwBaud = FTDI_BAUD_2232H;
671 for (DWORD i= 0; i<m_aDevices.size(); ++i)
673 dwBaud= min(m_aDevices[i]->m_sInitFT.dwMaxBaud, dwBaud);
675 m_sChanInit.dwBaud = 0;
676 if (sChanInit.dwBaud)
677 m_sChanInit.dwBaud = min(dwBaud, sChanInit.dwBaud);
678 m_sChanInit.dwBuffIn = dwBuffSizeRead + MIN_BUFF_IN;
679 m_sChanInit.dwBuffOut = dwBuffSizeWrite + MIN_BUFF_OUT;
681 m_hThread= CreateThread(NULL, 0, FTChanProc,
this, 0, NULL);
684 nError= NO_SYS_RESOURCE;
699 ((
SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
700 ((
SBaseOut*)pHead)->sBaseIn.nChan= m_nChan;
701 ((
SBaseOut*)pHead)->sBaseIn.nError= 0;
703 _tcsncpy_s(((
SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE,
m_csName.c_str(), _TRUNCATE);
704 pHead= (
char*)pHead +
sizeof(
SBaseOut);
707 ((
SBaseOut*)pHead)->sBaseIn.eType = eResponseExL;
708 ((
SBaseOut*)pHead)->sBaseIn.nChan = m_nChan;
709 ((
SBaseOut*)pHead)->sBaseIn.nError = 0;
712 pHead = (
char*)pHead +
sizeof(
SBaseOut);
715 ((
SBase*)pHead)->eType= eFTDIChan;
716 pHead= (
char*)pHead+
sizeof(
SBase);
721 ((
SBase*)pHead)->eType= eFTDIChanInit;
722 pHead= (
char*)pHead+
sizeof(
SBase);
728 CChannelFTDI::~CChannelFTDI()
730 if (m_hThread && (WAIT_OBJECT_0 != SignalObjectAndWait(m_hStop, m_hThread, 2000, FALSE)))
731 TerminateThread(m_hThread, 0);
732 if (m_pcComm) m_pcComm->
Close();
733 for(DWORD i= 0; i<m_aDevices.size(); ++i)
734 delete m_aDevices[i];
736 if (m_hStop) CloseHandle(m_hStop);
737 if (m_hNext) CloseHandle(m_hNext);
738 if (m_hUpdate) CloseHandle(m_hUpdate);
739 for (
size_t i= 3; i<m_ahEvents.size(); ++i)
741 CloseHandle(m_ahEvents[i]);
742 if (m_hThread) CloseHandle(m_hThread);
743 lpfFT_Close(m_ftHandle);
744 if (m_pcMemPool && m_aucTx) m_pcMemPool->PoolRelease(m_aucTx);
755 if (!pBase || dwSize <
sizeof(
SBaseIn) || dwSize != pBase->dwSize)
756 nError= SIZE_MISSMATCH;
757 else if (pBase->nChan >= (
int)m_aDevices.size() || (pBase->nChan < 0 && pBase->eType != eQuery))
758 nError= INVALID_CHANN;
759 else if (!(((pBase->eType == eActivate || pBase->eType == eInactivate || pBase->eType == eQuery) && dwSize ==
sizeof(
SBaseIn)) ||
760 pBase->eType == ePassOn))
761 nError= INVALID_COMMAND;
768 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(sData.dwSize);
771 pBase->dwSize=
sizeof(
SBaseIn);
772 pBase->eType= eResponse;
774 pBase->nError= nError;
779 else if (pBase->eType == ePassOn)
780 m_aDevices[pBase->nChan]->ProcessData((
char*)pHead+
sizeof(
SBaseIn), dwSize-
sizeof(
SBaseIn), llId);
781 else if (pBase->eType == eQuery)
783 if (pBase->nChan < 0)
785 sData.dwSize=
GetInfo(NULL, 0);
786 sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
787 if (sData.pHead &&
GetInfo(sData.pHead, sData.dwSize) == sData.dwSize)
792 sData.dwSize= m_aDevices[pBase->nChan]->GetInfo(NULL, 0);
793 sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
794 if (sData.pHead && m_aDevices[pBase->nChan]->GetInfo(sData.pHead, sData.dwSize) == sData.dwSize)
800 pBase= (
SBaseIn*)m_pcMemPool->PoolAcquire(sData.dwSize);
803 pBase->dwSize=
sizeof(
SBaseIn);
804 pBase->eType= ((
SBaseIn*)pHead)->eType;
805 pBase->nChan= ((
SBaseIn*)pHead)->nChan;
811 m_asUpdates.
Push(sUp);
816 DWORD CChannelFTDI::ThreadProc()
818 bool bUpdating=
false, bNotEmpty;
819 DWORD dwWrite, dwRead= 0, dwBytes, dwBaud, dwROld= 0, dwRes;
822 unsigned char ucMode= 0, ucOutput= 0, ucModeOld= 0, ucOutputOld;
823 const DWORD dwPacket= m_FTInfo.Flags&FT_FLAGS_HISPEED ? 510 : 62;
829 switch (dwRes= WaitForMultipleObjects((DWORD)m_ahEvents.size(), &m_ahEvents[0], FALSE, INFINITE))
834 case WAIT_OBJECT_0 + 1:
837 if (lpfFT_ResetPort(m_ftHandle))
838 lpfFT_CyclePort(m_ftHandle);
839 lpfFT_Close(m_ftHandle);
840 if (lpfFT_OpenEx((PVOID)m_FTInfo.LocId, FT_OPEN_BY_LOCATION, &m_ftHandle))
845 lpfFT_SetLatencyTimer(m_ftHandle, 255);
850 for (DWORD i= 0; i<m_aDevices.size(); ++i)
851 m_aDevices[i]->DoWork(NULL, 0, m_ftHandle, eRecover, 0);
858 m_aDevices[((
SBaseIn*)sUp.sData.pHead)->nChan]->DoWork(NULL, 0, m_ftHandle,
859 ((
SBaseIn*)sUp.sData.pHead)->eType == eActivate? eActivateState: eInactivateState, 0);
860 m_pcComm->
SendData(&sUp.sData, sUp.llId);
863 ResetEvent(m_hUpdate);
868 ucOutputOld= ucOutput;
875 for (DWORD i= 0; i<m_aDevices.size(); ++i)
877 EStateFTDI eType= m_aDevices[i]->GetState();
878 if (eType != eInactive)
880 dwBaud= min(m_aDevices[i]->m_sInitFT.dwMaxBaud, dwBaud);
881 dwWrite= max(m_aDevices[i]->m_sInitFT.dwMinSizeW, dwWrite);
882 dwRead= max(m_aDevices[i]->m_sInitFT.dwMinSizeR, dwRead);
884 ucMode &= m_aDevices[i]->m_sInitFT.ucBitMode;
885 ucOutput |= m_aDevices[i]->GetOutputBits();
886 bUpdating = bUpdating || eType == eActivateState || eType == eInactivateState;
888 ucMode &= (~ucMode+1);
889 if (ucMode&FT_BITMODE_SYNC_BITBANG)
891 dwWrite= max(dwWrite, dwRead);
892 dwWrite= dwPacket*(DWORD)ceil((
double)dwWrite/dwPacket);
894 if (dwRead != dwROld)
895 lpfFT_SetUSBParameters(m_ftHandle, (dwRead/dwPacket)*(dwPacket+2), 0);
897 if (ucMode!=ucModeOld || ucOutput!=ucOutputOld)
899 lpfFT_Purge(m_ftHandle, FT_PURGE_RX|FT_PURGE_TX);
900 lpfFT_SetBitMode(m_ftHandle, ucOutput, ucMode);
901 if (m_sChanInit.dwBaud)
902 dwBaud = min(m_sChanInit.dwBaud, dwBaud);
903 lpfFT_SetBaudRate(m_ftHandle, dwBaud);
909 dwRes= WAIT_OBJECT_0 + 2;
913 if (dwRes > WAIT_OBJECT_0 + 1 && dwRes < WAIT_OBJECT_0 + m_ahEvents.size())
917 for (DWORD i= 0; i<m_aDevices.size(); ++i)
918 m_aDevices[i]->DoWork(m_aucTx, dwWrite, m_ftHandle, ePreWrite, 0);
919 nError= FT_ERROR(lpfFT_Write(m_ftHandle, m_aucTx, dwWrite, &dwBytes), nError);
920 for (DWORD i= 0; i<m_aDevices.size(); ++i)
921 m_aDevices[i]->DoWork(m_aucTx, dwBytes, m_ftHandle, ePostWrite, nError);
923 if (dwRead && !nError)
925 while (!(pHead = m_pcMemRing->
GetFree(&nIdx)));
926 nError= FT_ERROR(lpfFT_Read(m_ftHandle, pHead, dwRead, &dwBytes), nError);
927 for (DWORD i= 0; i<m_aDevices.size() && !nError; ++i)
928 m_aDevices[i]->DoWork((
void *)&nIdx, dwBytes, m_ftHandle, ePostRead, nError);
940 for (DWORD i= 0; i<m_aDevices.size(); ++i)
942 EStateFTDI eType= m_aDevices[i]->GetState();
943 bUpdating = bUpdating || eType == eActivateState || eType == eInactivateState;
virtual DWORD GetInfo(void *pHead, DWORD dwSize)
DWORD GetInfo(void *pHead, DWORD dwSize)
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
virtual int SendData(const SData *pData, __int64 llId)=0
LARGE_INTEGER GetStart() const
void * GetFree(int *pnIdx)
unsigned char ucActivePins
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
CChannelFTDI(SChanInitFTDI &sChanInit, SBase *pInit, DWORD dwSize, FT_DEVICE_LIST_INFO_NODE &FTInfo, const TCHAR szPipe[], int nChan, int &nError, LARGE_INTEGER &llStart)
unsigned short usBytesUsed
const std::tstring m_csName
T Front(bool bPop, bool &bValid)