public static bool InterfaceSetDtr(bool dtr)
        {
            if (_handleFtdi == (IntPtr)0)
            {
                return(false);
            }
#if USE_BITBANG
            if (dtr)
            {
                _bitBangOutput &= ~BitBangBits.Dtr;
            }
            else
            {
                _bitBangOutput |= BitBangBits.Dtr;
            }
            if (_bitBangMode)
            {
                if (!SetBitBangOutput(_bitBangOutput))
                {
                    return(false);
                }
                return(true);
            }
#endif
            try
            {
                Ftd2Xx.FT_STATUS ftStatus = dtr ? Ftd2Xx.FT_SetDtr(_handleFtdi) : Ftd2Xx.FT_ClrDtr(_handleFtdi);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    return(false);
                }
            }
            catch (Exception)
            {
                return(false);
            }
            return(true);
        }
        public static bool InterfaceSendData(byte[] sendData, int length, bool setDtr, double dtrTimeCorr)
        {
            if (_handleFtdi == (IntPtr)0)
            {
                return(false);
            }
            try
            {
                Ftd2Xx.FT_STATUS ftStatus;
                uint             bytesWritten;

#if USE_BITBANG
                if (_bitBangMode)
                {
                    int bufferSize = (_currentWordLength + 4) * _bitBangBitsPerSendByte * (length + 2);
                    if (bufferSize > BitBangSendBuffer.Length)
                    {
                        return(false);
                    }

                    int dataLen = 0;
                    for (int i = 0; i < length; i++)
                    {
                        if (i == 0)
                        {
                            if (setDtr)
                            {
                                _bitBangOutput &= ~BitBangBits.Dtr;       // DTR on
                                for (int k = 0; k < _bitBangBitsPerSendByte; k++)
                                {
                                    BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                                }
                            }
                        }
                        _bitBangOutput &= ~BitBangBits.Txd;       // Start bit
                        for (int k = 0; k < _bitBangBitsPerSendByte; k++)
                        {
                            BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                        }
                        bool parity = false;
                        for (int j = 0; j < _currentWordLength; j++)
                        {
                            bool bitSet = (sendData[i] & (1 << j)) != 0;
                            if (bitSet)
                            {
                                parity = !parity;
                            }
                            if (bitSet)
                            {
                                _bitBangOutput |= BitBangBits.Txd;
                            }
                            else
                            {
                                _bitBangOutput &= ~BitBangBits.Txd;
                            }
                            for (int k = 0; k < _bitBangBitsPerSendByte; k++)
                            {
                                BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                            }
                        }
                        switch (_currentParity)
                        {
                        case EdInterfaceObd.SerialParity.Even:
                        {
                            if (parity)
                            {
                                _bitBangOutput |= BitBangBits.Txd;
                            }
                            else
                            {
                                _bitBangOutput &= ~BitBangBits.Txd;
                            }
                            for (int k = 0; k < _bitBangBitsPerSendByte; k++)
                            {
                                BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                            }
                            break;
                        }

                        case EdInterfaceObd.SerialParity.Odd:
                        {
                            if (parity)
                            {
                                _bitBangOutput &= ~BitBangBits.Txd;
                            }
                            else
                            {
                                _bitBangOutput |= BitBangBits.Txd;
                            }
                            for (int k = 0; k < _bitBangBitsPerSendByte; k++)
                            {
                                BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                            }
                            break;
                        }
                        }
                        // 2 stop bits for time correction
                        _bitBangOutput |= BitBangBits.Txd;   // Stop bit
                        for (int k = 0; k < _bitBangBitsPerSendByte * 2; k++)
                        {
                            BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                        }
                        if ((i + 1) == length)
                        {
                            if (setDtr)
                            {
                                _bitBangOutput |= BitBangBits.Dtr;      // DTR off
                                BitBangSendBuffer[dataLen++] = (byte)_bitBangOutput;
                            }
                        }
                    }
                    _recBufLastIndex = -1;
                    ftStatus         = Ftd2Xx.FT_Purge(_handleFtdi, Ftd2Xx.FT_PURGE_RX);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
                    ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, BitBangSendBuffer, dataLen, 0, out bytesWritten);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
                    return(true);
                }
#endif
                int    bitCount = (_currentParity == EdInterfaceObd.SerialParity.None) ? (_currentWordLength + 2) : (_currentWordLength + 3);
                double byteTime = 1.0d / _currentBaudRate * 1000 * bitCount;
                if (setDtr)
                {
                    long waitTime = (long)((dtrTimeCorr + byteTime * length) * TickResolMs);
                    ftStatus = Ftd2Xx.FT_SetDtr(_handleFtdi);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
                    long startTime = Stopwatch.GetTimestamp();
#if WindowsCE
                    const int sendBlockSize = 4;
                    for (int i = 0; i < length; i += sendBlockSize)
                    {
                        int sendLength = length - i;
                        if (sendLength > sendBlockSize)
                        {
                            sendLength = sendBlockSize;
                        }
                        ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, sendData, sendLength, i, out bytesWritten);
                        if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                        {
                            return(false);
                        }
                    }
#else
                    ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, sendData, length, 0, out bytesWritten);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
#endif
                    while ((Stopwatch.GetTimestamp() - startTime) < waitTime)
                    {
                    }
                    ftStatus = Ftd2Xx.FT_ClrDtr(_handleFtdi);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
                }
                else
                {
                    long waitTime = (long)(byteTime * length);
#if WindowsCE
                    const int sendBlockSize = 4;
                    for (int i = 0; i < length; i += sendBlockSize)
                    {
                        int sendLength = length - i;
                        if (sendLength > sendBlockSize)
                        {
                            sendLength = sendBlockSize;
                        }
                        ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, sendData, sendLength, i, out bytesWritten);
                        if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                        {
                            return(false);
                        }
                    }
#else
                    ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, sendData, length, 0, out bytesWritten);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        return(false);
                    }
#endif
                    if (waitTime > 10)
                    {
                        Thread.Sleep((int)waitTime);
                    }
                }
            }
            catch (Exception)
            {
                return(false);
            }

            return(true);
        }