private static bool SetBitBangOutput(BitBangBits output)
 {
     if (_handleFtdi == (IntPtr)0)
     {
         return(false);
     }
     try
     {
         BitBangSendBuffer[0] = (byte)output;
         uint             bytesWritten;
         Ftd2Xx.FT_STATUS ftStatus = Ftd2Xx.FT_WriteWrapper(_handleFtdi, BitBangSendBuffer, 1, 0, out bytesWritten);
         if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
         {
             return(false);
         }
     }
     catch (Exception)
     {
         return(false);
     }
     return(true);
 }
        public static bool InterfaceSetBreak(bool enable)
        {
            if (_handleFtdi == (IntPtr)0)
            {
                return(false);
            }
#if USE_BITBANG
            if (enable)
            {
                _bitBangOutput &= ~BitBangBits.Txd;
            }
            else
            {
                _bitBangOutput |= BitBangBits.Txd;
            }
            if (_bitBangMode)
            {
                if (!SetBitBangOutput(_bitBangOutput))
                {
                    return(false);
                }
                return(true);
            }
#endif
            try
            {
                Ftd2Xx.FT_STATUS ftStatus = enable ? Ftd2Xx.FT_SetBreakOn(_handleFtdi) : Ftd2Xx.FT_SetBreakOff(_handleFtdi);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    return(false);
                }
            }
            catch (Exception)
            {
                return(false);
            }
            return(true);
        }
        public static bool InterfaceSetRts(bool rts)
        {
            if (_handleFtdi == (IntPtr)0)
            {
                return(false);
            }
#if USE_BITBANG
            if (rts)
            {
                _bitBangOutput &= ~BitBangBits.Rts;
            }
            else
            {
                _bitBangOutput |= BitBangBits.Rts;
            }
            if (_bitBangMode)
            {
                if (!SetBitBangOutput(_bitBangOutput))
                {
                    return(false);
                }
                return(true);
            }
#endif
            try
            {
                Ftd2Xx.FT_STATUS ftStatus = rts ? Ftd2Xx.FT_SetRts(_handleFtdi) : Ftd2Xx.FT_ClrRts(_handleFtdi);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    return(false);
                }
            }
            catch (Exception)
            {
                return(false);
            }
            return(true);
        }
        public static bool InterfaceConnect(string port, object parameter)
        {
            if (_handleFtdi != (IntPtr)0)
            {
                return(true);
            }
            try
            {
                Ftd2Xx.FT_STATUS ftStatus;
                if (!port.StartsWith(PortId, StringComparison.OrdinalIgnoreCase))
                {
                    InterfaceDisconnect();
                    return(false);
                }
                string portData = port.Remove(0, PortId.Length);
                if ((portData.Length > 0) && (portData[0] == ':'))
                {     // special id
                    if (portData.StartsWith(":SER=", StringComparison.OrdinalIgnoreCase))
                    { // serial number
                        string id = portData.Remove(0, 5);
                        ftStatus = Ftd2Xx.FT_OpenEx(id, Ftd2Xx.FT_OPEN_BY_SERIAL_NUMBER, out _handleFtdi);
                    }
                    else if (portData.StartsWith(":DESC=", StringComparison.OrdinalIgnoreCase))
                    {   // description
                        string id = portData.Remove(0, 6);
                        ftStatus = Ftd2Xx.FT_OpenEx(id, Ftd2Xx.FT_OPEN_BY_DESCRIPTION, out _handleFtdi);
                    }
                    else if (portData.StartsWith(":LOC=", StringComparison.OrdinalIgnoreCase))
                    {   // location
                        long loc = EdiabasNet.StringToValue(portData.Remove(0, 5));
                        ftStatus = Ftd2Xx.FT_OpenEx((IntPtr)loc, Ftd2Xx.FT_OPEN_BY_LOCATION, out _handleFtdi);
                    }
                    else
                    {
                        InterfaceDisconnect();
                        return(false);
                    }
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        InterfaceDisconnect();
                        return(false);
                    }
                }
                else
                {
                    uint usbIndex = Convert.ToUInt32(port.Remove(0, PortId.Length));

                    ftStatus = Ftd2Xx.FT_Open(usbIndex, out _handleFtdi);
                    if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                    {
                        InterfaceDisconnect();
                        return(false);
                    }
                }

#if USE_BITBANG
                _bitBangMode   = false;
                _bitBangOutput = BitBangBits.Dtr | BitBangBits.Rts | BitBangBits.Txd;
#endif
                ftStatus = Ftd2Xx.FT_SetBitMode(_handleFtdi, 0x00, Ftd2Xx.FT_BITMODE_RESET);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_SetUSBParameters(_handleFtdi, UsbBufferSizeStd, UsbBufferSizeStd);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_SetLatencyTimer(_handleFtdi, 2);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_SetBaudRate(_handleFtdi, Ftd2Xx.FT_BAUD_9600);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }
                _currentBaudRate = 9600;

                ftStatus = Ftd2Xx.FT_SetDataCharacteristics(_handleFtdi, Ftd2Xx.FT_BITS_8, Ftd2Xx.FT_STOP_BITS_1, Ftd2Xx.FT_PARITY_NONE);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }
                _currentWordLength = 8;
                _currentParity     = EdInterfaceObd.SerialParity.None;

                ftStatus = Ftd2Xx.FT_SetTimeouts(_handleFtdi, 0, WriteTimeout);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_SetFlowControl(_handleFtdi, Ftd2Xx.FT_FLOW_NONE, 0, 0);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_ClrDtr(_handleFtdi);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_ClrRts(_handleFtdi);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }

                ftStatus = Ftd2Xx.FT_Purge(_handleFtdi, Ftd2Xx.FT_PURGE_TX | Ftd2Xx.FT_PURGE_RX);
                if (ftStatus != Ftd2Xx.FT_STATUS.FT_OK)
                {
                    InterfaceDisconnect();
                    return(false);
                }
            }
            catch (Exception)
            {
                InterfaceDisconnect();
                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);
        }