/*
** FTD2XX_NET.cs
**
** Copyright © 2009-2012 Future Technology Devices International Limited
**
** C# Source file for .NET wrapper of the Windows FTD2XX.dll API calls.
** Main module
**
** Author: FTDI
** Project: CDM Windows Driver Package
** Module: FTD2XX_NET Managed Wrapper
** Requires: 
** Comments:
**
** History:
**  1.0.0	-	Initial version
**  1.0.12	-	Included support for the FT232H device.
**  1.0.14	-	Included Support for the X-Series of devices.
**
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using System.IO;

namespace FTD2XX_NET
{
    /// <summary>
    /// Class wrapper for ftd2xx.DLL
    /// </summary>
    public class FTDI
    {
        #region CONSTRUCTOR_DESTRUCTOR
        // constructor
        /// <summary>
        /// Constructor for the FTDI class.
        /// </summary>
        public FTDI()
        {
        }
        #endregion

        #region DELEGATES
        // Definitions for ftd2xx functions
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_CreateDeviceInfoList")]
        private static extern FT_STATUS FT_CreateDeviceInfoList(ref UInt32 numdevs);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetDeviceInfoDetail")]
        private static extern FT_STATUS FT_GetDeviceInfoDetail(UInt32 index, ref UInt32 flags, ref FT_DEVICE chiptype, ref UInt32 id, ref UInt32 locid, byte[] serialnumber, byte[] description, ref IntPtr ftHandle);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Open")]
        private static extern FT_STATUS FT_Open(UInt32 index, ref IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_OpenEx")]
        private static extern FT_STATUS FT_OpenEx(string devstring, UInt32 dwFlags, ref IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_OpenExLoc")]
        private static extern FT_STATUS FT_OpenExLoc(UInt32 devloc, UInt32 dwFlags, ref IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Close")]
        private static extern FT_STATUS FT_Close(IntPtr ftHandle);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Read")]
        private static extern FT_STATUS FT_Read(IntPtr ftHandle, byte[] lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesReturned);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Write")]
        private static extern FT_STATUS FT_Write(IntPtr ftHandle, byte[] lpBuffer, UInt32 dwBytesToWrite, ref UInt32 lpdwBytesWritten);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetQueueStatus")]
        private static extern FT_STATUS FT_GetQueueStatus(IntPtr ftHandle, ref UInt32 lpdwAmountInRxQueue);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetModemStatus")]
        private static extern FT_STATUS FT_GetModemStatus(IntPtr ftHandle, ref UInt32 lpdwModemStatus);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetStatus")]
        private static extern FT_STATUS FT_GetStatus(IntPtr ftHandle, ref UInt32 lpdwAmountInRxQueue, ref UInt32 lpdwAmountInTxQueue, ref UInt32 lpdwEventStatus);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetBaudRate")]
        private static extern FT_STATUS FT_SetBaudRate(IntPtr ftHandle, UInt32 dwBaudRate);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetDataCharacteristics")]
        private static extern FT_STATUS FT_SetDataCharacteristics(IntPtr ftHandle, byte uWordLength, byte uStopBits, byte uParity);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetFlowControl")]
        private static extern FT_STATUS FT_SetFlowControl(IntPtr ftHandle, UInt16 usFlowControl, byte uXon, byte uXoff);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetDtr")]
        private static extern FT_STATUS FT_SetDtr(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_ClrDtr")]
        private static extern FT_STATUS FT_ClrDtr(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetRts")]
        private static extern FT_STATUS FT_SetRts(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_ClrRts")]
        private static extern FT_STATUS FT_ClrRts(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_ResetDevice")]
        private static extern FT_STATUS FT_ResetDevice(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_ResetPort")]
        private static extern FT_STATUS FT_ResetPort(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_CyclePort")]
        private static extern FT_STATUS FT_CyclePort(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Rescan")]
        private static extern FT_STATUS FT_Rescan();
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Reload")]
        private static extern FT_STATUS FT_Reload(UInt16 wVID, UInt16 wPID);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_Purge")]
        private static extern FT_STATUS FT_Purge(IntPtr ftHandle, UInt32 dwMask);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetTimeouts")]
        private static extern FT_STATUS FT_SetTimeouts(IntPtr ftHandle, UInt32 dwReadTimeout, UInt32 dwWriteTimeout);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetBreakOn")]
        private static extern FT_STATUS FT_SetBreakOn(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetBreakOff")]
        private static extern FT_STATUS FT_SetBreakOff(IntPtr ftHandle);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetDeviceInfo")]
        private static extern FT_STATUS FT_GetDeviceInfo(IntPtr ftHandle, ref FT_DEVICE pftType, ref UInt32 lpdwID, byte[] pcSerialNumber, byte[] pcDescription, IntPtr pvDummy);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetResetPipeRetryCount")]
        private static extern FT_STATUS FT_SetResetPipeRetryCount(IntPtr ftHandle, UInt32 dwCount);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_StopInTask")]
        private static extern FT_STATUS FT_StopInTask(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_RestartInTask")]
        private static extern FT_STATUS FT_RestartInTask(IntPtr ftHandle);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetDriverVersion")]
        private static extern FT_STATUS FT_GetDriverVersion(IntPtr ftHandle, ref UInt32 lpdwDriverVersion);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetLibraryVersion")]
        private static extern FT_STATUS FT_GetLibraryVersion(ref UInt32 lpdwLibraryVersion);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetDeadmanTimeout")]
        private static extern FT_STATUS FT_SetDeadmanTimeout(IntPtr ftHandle, UInt32 dwDeadmanTimeout);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetChars")]
        private static extern FT_STATUS FT_SetChars(IntPtr ftHandle, byte uEventCh, byte uEventChEn, byte uErrorCh, byte uErrorChEn);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetEventNotification")]
        private static extern FT_STATUS FT_SetEventNotification(IntPtr ftHandle, UInt32 dwEventMask, SafeHandle hEvent);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetComPortNumber")]
        private static extern FT_STATUS FT_GetComPortNumber(IntPtr ftHandle, ref Int32 dwComPortNumber);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetLatencyTimer")]
        private static extern FT_STATUS FT_SetLatencyTimer(IntPtr ftHandle, byte ucLatency);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetLatencyTimer")]
        private static extern FT_STATUS FT_GetLatencyTimer(IntPtr ftHandle, ref byte ucLatency);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetBitMode")]
        private static extern FT_STATUS FT_SetBitMode(IntPtr ftHandle, byte ucMask, byte ucMode);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_GetBitMode")]
        private static extern FT_STATUS FT_GetBitMode(IntPtr ftHandle, ref byte ucMode);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_SetUSBParameters")]
        private static extern FT_STATUS FT_SetUSBParameters(IntPtr ftHandle, UInt32 dwInTransferSize, UInt32 dwOutTransferSize);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_ReadEE")]
        private static extern FT_STATUS FT_ReadEE(IntPtr ftHandle, UInt32 dwWordOffset, ref UInt16 lpwValue);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_WriteEE")]
        private static extern FT_STATUS FT_WriteEE(IntPtr ftHandle, UInt32 dwWordOffset, UInt16 wValue);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EraseEE")]
        private static extern FT_STATUS FT_EraseEE(IntPtr ftHandle);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EE_UASize")]
        private static extern FT_STATUS FT_EE_UASize(IntPtr ftHandle, ref UInt32 dwSize);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EE_UARead")]
        private static extern FT_STATUS FT_EE_UARead(IntPtr ftHandle, byte[] pucData, Int32 dwDataLen, ref UInt32 lpdwDataRead);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EE_UAWrite")]
        private static extern FT_STATUS FT_EE_UAWrite(IntPtr ftHandle, byte[] pucData, Int32 dwDataLen);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EE_Read")]
        private static extern FT_STATUS FT_EE_Read(IntPtr ftHandle, FT_PROGRAM_DATA pData);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EE_Program")]
        private static extern FT_STATUS FT_EE_Program(IntPtr ftHandle, FT_PROGRAM_DATA pData);

        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EEPROM_Read")]
        private static extern FT_STATUS FT_EEPROM_Read(IntPtr ftHandle, IntPtr eepromData, UInt32 eepromDataSize, byte[] manufacturer, byte[] manufacturerID, byte[] description, byte[] serialnumber);
        [System.Runtime.InteropServices.DllImportAttribute("ftd2xx", EntryPoint = "FT_EEPROM_Program")]
        private static extern FT_STATUS FT_EEPROM_Program(IntPtr ftHandle, IntPtr eepromData, UInt32 eepromDataSize, byte[] manufacturer, byte[] manufacturerID, byte[] description, byte[] serialnumber);
        #endregion

        #region CONSTANT_VALUES
        // Constants for FT_STATUS
        /// <summary>
        /// Status values for FTDI devices.
        /// </summary>
        public enum FT_STATUS
        {
            /// <summary>
            /// Status OK
            /// </summary>
            FT_OK = 0,
            /// <summary>
            /// The device handle is invalid
            /// </summary>
            FT_INVALID_HANDLE,
            /// <summary>
            /// Device not found
            /// </summary>
            FT_DEVICE_NOT_FOUND,
            /// <summary>
            /// Device is not open
            /// </summary>
            FT_DEVICE_NOT_OPENED,
            /// <summary>
            /// IO error
            /// </summary>
            FT_IO_ERROR,
            /// <summary>
            /// Insufficient resources
            /// </summary>
            FT_INSUFFICIENT_RESOURCES,
            /// <summary>
            /// A parameter was invalid
            /// </summary>
            FT_INVALID_PARAMETER,
            /// <summary>
            /// The requested baud rate is invalid
            /// </summary>
            FT_INVALID_BAUD_RATE,
            /// <summary>
            /// Device not opened for erase
            /// </summary>
            FT_DEVICE_NOT_OPENED_FOR_ERASE,
            /// <summary>
            /// Device not poened for write
            /// </summary>
            FT_DEVICE_NOT_OPENED_FOR_WRITE,
            /// <summary>
            /// Failed to write to device
            /// </summary>
            FT_FAILED_TO_WRITE_DEVICE,
            /// <summary>
            /// Failed to read the device EEPROM
            /// </summary>
            FT_EEPROM_READ_FAILED,
            /// <summary>
            /// Failed to write the device EEPROM
            /// </summary>
            FT_EEPROM_WRITE_FAILED,
            /// <summary>
            /// Failed to erase the device EEPROM
            /// </summary>
            FT_EEPROM_ERASE_FAILED,
            /// <summary>
            /// An EEPROM is not fitted to the device
            /// </summary>
            FT_EEPROM_NOT_PRESENT,
            /// <summary>
            /// Device EEPROM is blank
            /// </summary>
            FT_EEPROM_NOT_PROGRAMMED,
            /// <summary>
            /// Invalid arguments
            /// </summary>
            FT_INVALID_ARGS,
            /// <summary>
            /// An other error has occurred
            /// </summary>
            FT_OTHER_ERROR
        };

        // Constants for other error states internal to this class library
        /// <summary>
        /// Error states not supported by ftd2xx DLL.
        /// </summary>
        private enum FT_ERROR
        {
            FT_NO_ERROR = 0,
            FT_INCORRECT_DEVICE,
            FT_INVALID_BITMODE,
            FT_BUFFER_SIZE
        };

        // Flags for FT_OpenEx
        private const UInt32 FT_OPEN_BY_SERIAL_NUMBER = 0x00000001;
        private const UInt32 FT_OPEN_BY_DESCRIPTION = 0x00000002;
        private const UInt32 FT_OPEN_BY_LOCATION = 0x00000004;

        // Word Lengths
        /// <summary>
        /// Permitted data bits for FTDI devices
        /// </summary>
        public class FT_DATA_BITS
        {
            /// <summary>
            /// 8 data bits
            /// </summary>
            public const byte FT_BITS_8 = 0x08;
            /// <summary>
            /// 7 data bits
            /// </summary>
            public const byte FT_BITS_7 = 0x07;
        }

        // Stop Bits
        /// <summary>
        /// Permitted stop bits for FTDI devices
        /// </summary>
        public class FT_STOP_BITS
        {
            /// <summary>
            /// 1 stop bit
            /// </summary>
            public const byte FT_STOP_BITS_1 = 0x00;
            /// <summary>
            /// 2 stop bits
            /// </summary>
            public const byte FT_STOP_BITS_2 = 0x02;
        }

        // Parity
        /// <summary>
        /// Permitted parity values for FTDI devices
        /// </summary>
        public class FT_PARITY
        {
            /// <summary>
            /// No parity
            /// </summary>
            public const byte FT_PARITY_NONE = 0x00;
            /// <summary>
            /// Odd parity
            /// </summary>
            public const byte FT_PARITY_ODD = 0x01;
            /// <summary>
            /// Even parity
            /// </summary>
            public const byte FT_PARITY_EVEN = 0x02;
            /// <summary>
            /// Mark parity
            /// </summary>
            public const byte FT_PARITY_MARK = 0x03;
            /// <summary>
            /// Space parity
            /// </summary>
            public const byte FT_PARITY_SPACE = 0x04;
        }

        // Flow Control
        /// <summary>
        /// Permitted flow control values for FTDI devices
        /// </summary>
        public class FT_FLOW_CONTROL
        {
            /// <summary>
            /// No flow control
            /// </summary>
            public const UInt16 FT_FLOW_NONE = 0x0000;
            /// <summary>
            /// RTS/CTS flow control
            /// </summary>
            public const UInt16 FT_FLOW_RTS_CTS = 0x0100;
            /// <summary>
            /// DTR/DSR flow control
            /// </summary>
            public const UInt16 FT_FLOW_DTR_DSR = 0x0200;
            /// <summary>
            /// Xon/Xoff flow control
            /// </summary>
            public const UInt16 FT_FLOW_XON_XOFF = 0x0400;
        }

        // Purge Rx and Tx buffers
        /// <summary>
        /// Purge buffer constant definitions
        /// </summary>
        public class FT_PURGE
        {
            /// <summary>
            /// Purge Rx buffer
            /// </summary>
            public const byte FT_PURGE_RX = 0x01;
            /// <summary>
            /// Purge Tx buffer
            /// </summary>
            public const byte FT_PURGE_TX = 0x02;
        }

        // Modem Status bits
        /// <summary>
        /// Modem status bit definitions
        /// </summary>
        public class FT_MODEM_STATUS
        {
            /// <summary>
            /// Clear To Send (CTS) modem status
            /// </summary>
            public const byte FT_CTS = 0x10;
            /// <summary>
            /// Data Set Ready (DSR) modem status
            /// </summary>
            public const byte FT_DSR = 0x20;
            /// <summary>
            /// Ring Indicator (RI) modem status
            /// </summary>
            public const byte FT_RI = 0x40;
            /// <summary>
            /// Data Carrier Detect (DCD) modem status
            /// </summary>
            public const byte FT_DCD = 0x80;
        }

        // Line Status bits
        /// <summary>
        /// Line status bit definitions
        /// </summary>
        public class FT_LINE_STATUS
        {
            /// <summary>
            /// Overrun Error (OE) line status
            /// </summary>
            public const byte FT_OE = 0x02;
            /// <summary>
            /// Parity Error (PE) line status
            /// </summary>
            public const byte FT_PE = 0x04;
            /// <summary>
            /// Framing Error (FE) line status
            /// </summary>
            public const byte FT_FE = 0x08;
            /// <summary>
            /// Break Interrupt (BI) line status
            /// </summary>
            public const byte FT_BI = 0x10;
        }

        // Events
        /// <summary>
        /// FTDI device event types that can be monitored
        /// </summary>
        public class FT_EVENTS
        {
            /// <summary>
            /// Event on receive character
            /// </summary>
            public const UInt32 FT_EVENT_RXCHAR = 0x00000001;
            /// <summary>
            /// Event on modem status change
            /// </summary>
            public const UInt32 FT_EVENT_MODEM_STATUS = 0x00000002;
            /// <summary>
            /// Event on line status change
            /// </summary>
            public const UInt32 FT_EVENT_LINE_STATUS = 0x00000004;
        }

        // Bit modes
        /// <summary>
        /// Permitted bit mode values for FTDI devices.  For use with SetBitMode
        /// </summary>
        public class FT_BIT_MODES
        {
            /// <summary>
            /// Reset bit mode
            /// </summary>
            public const byte FT_BIT_MODE_RESET = 0x00;
            /// <summary>
            /// Asynchronous bit-bang mode
            /// </summary>
            public const byte FT_BIT_MODE_ASYNC_BITBANG = 0x01;
            /// <summary>
            /// MPSSE bit mode - only available on FT2232, FT2232H, FT4232H and FT232H
            /// </summary>
            public const byte FT_BIT_MODE_MPSSE = 0x02;
            /// <summary>
            /// Synchronous bit-bang mode
            /// </summary>
            public const byte FT_BIT_MODE_SYNC_BITBANG = 0x04;
            /// <summary>
            /// MCU host bus emulation mode - only available on FT2232, FT2232H, FT4232H and FT232H
            /// </summary>
            public const byte FT_BIT_MODE_MCU_HOST = 0x08;
            /// <summary>
            /// Fast opto-isolated serial mode - only available on FT2232, FT2232H, FT4232H and FT232H
            /// </summary>
            public const byte FT_BIT_MODE_FAST_SERIAL = 0x10;
            /// <summary>
            /// CBUS bit-bang mode - only available on FT232R and FT232H
            /// </summary>
            public const byte FT_BIT_MODE_CBUS_BITBANG = 0x20;
            /// <summary>
            /// Single channel synchronous 245 FIFO mode - only available on FT2232H channel A and FT232H
            /// </summary>
            public const byte FT_BIT_MODE_SYNC_FIFO = 0x40;
        }

        // FT232R CBUS Options
        /// <summary>
        /// Available functions for the FT232R CBUS pins.  Controlled by FT232R EEPROM settings
        /// </summary>
        public class FT_CBUS_OPTIONS
        {
            /// <summary>
            /// FT232R CBUS EEPROM options - Tx Data Enable
            /// </summary>
            public const byte FT_CBUS_TXDEN = 0x00;
            /// <summary>
            /// FT232R CBUS EEPROM options - Power On
            /// </summary>
            public const byte FT_CBUS_PWRON = 0x01;
            /// <summary>
            /// FT232R CBUS EEPROM options - Rx LED
            /// </summary>
            public const byte FT_CBUS_RXLED = 0x02;
            /// <summary>
            /// FT232R CBUS EEPROM options - Tx LED
            /// </summary>
            public const byte FT_CBUS_TXLED = 0x03;
            /// <summary>
            /// FT232R CBUS EEPROM options - Tx and Rx LED
            /// </summary>
            public const byte FT_CBUS_TXRXLED = 0x04;
            /// <summary>
            /// FT232R CBUS EEPROM options - Sleep
            /// </summary>
            public const byte FT_CBUS_SLEEP = 0x05;
            /// <summary>
            /// FT232R CBUS EEPROM options - 48MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK48 = 0x06;
            /// <summary>
            /// FT232R CBUS EEPROM options - 24MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK24 = 0x07;
            /// <summary>
            /// FT232R CBUS EEPROM options - 12MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK12 = 0x08;
            /// <summary>
            /// FT232R CBUS EEPROM options - 6MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK6 = 0x09;
            /// <summary>
            /// FT232R CBUS EEPROM options - IO mode
            /// </summary>
            public const byte FT_CBUS_IOMODE = 0x0A;
            /// <summary>
            /// FT232R CBUS EEPROM options - Bit-bang write strobe
            /// </summary>
            public const byte FT_CBUS_BITBANG_WR = 0x0B;
            /// <summary>
            /// FT232R CBUS EEPROM options - Bit-bang read strobe
            /// </summary>
            public const byte FT_CBUS_BITBANG_RD = 0x0C;
        }

        // FT232H CBUS Options
        /// <summary>
        /// Available functions for the FT232H CBUS pins.  Controlled by FT232H EEPROM settings
        /// </summary>
        public class FT_232H_CBUS_OPTIONS
        {
            /// <summary>
            /// FT232H CBUS EEPROM options - Tristate
            /// </summary>
            public const byte FT_CBUS_TRISTATE = 0x00;
            /// <summary>
            /// FT232H CBUS EEPROM options - Rx LED
            /// </summary>
            public const byte FT_CBUS_RXLED = 0x01;
            /// <summary>
            /// FT232H CBUS EEPROM options - Tx LED
            /// </summary>
            public const byte FT_CBUS_TXLED = 0x02;
            /// <summary>
            /// FT232H CBUS EEPROM options - Tx and Rx LED
            /// </summary>
            public const byte FT_CBUS_TXRXLED = 0x03;
            /// <summary>
            /// FT232H CBUS EEPROM options - Power Enable
            /// </summary>
            public const byte FT_CBUS_PWREN = 0x04;
            /// <summary>
            /// FT232H CBUS EEPROM options - Sleep
            /// </summary>
            public const byte FT_CBUS_SLEEP = 0x05;
            /// <summary>
            /// FT232H CBUS EEPROM options - Drive pin to logic 0
            /// </summary>
            public const byte FT_CBUS_DRIVE_0 = 0x06;
            /// <summary>
            /// FT232H CBUS EEPROM options - Drive pin to logic 1
            /// </summary>
            public const byte FT_CBUS_DRIVE_1 = 0x07;
            /// <summary>
            /// FT232H CBUS EEPROM options - IO Mode
            /// </summary>
            public const byte FT_CBUS_IOMODE = 0x08;
            /// <summary>
            /// FT232H CBUS EEPROM options - Tx Data Enable
            /// </summary>
            public const byte FT_CBUS_TXDEN = 0x09;
            /// <summary>
            /// FT232H CBUS EEPROM options - 30MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK30 = 0x0A;
            /// <summary>
            /// FT232H CBUS EEPROM options - 15MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK15 = 0x0B;/// <summary>
            /// FT232H CBUS EEPROM options - 7.5MHz clock
            /// </summary>
            public const byte FT_CBUS_CLK7_5 = 0x0C;
        }

        /// <summary>
        /// Available functions for the X-Series CBUS pins.  Controlled by X-Series EEPROM settings
        /// </summary>
        public class FT_XSERIES_CBUS_OPTIONS
        {
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Tristate
            /// </summary>
            public const byte FT_CBUS_TRISTATE = 0x00;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - RxLED#
            /// </summary>
            public const byte FT_CBUS_RXLED = 0x01;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - TxLED#
            /// </summary>
            public const byte FT_CBUS_TXLED = 0x02;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - TxRxLED
            /// </summary>
            public const byte FT_CBUS_TXRXLED = 0x03;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - PwrEn#
            /// </summary>
            public const byte FT_CBUS_PWREN = 0x04;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Sleep#
            /// </summary>
            public const byte FT_CBUS_SLEEP = 0x05;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Drive_0
            /// </summary>
            public const byte FT_CBUS_Drive_0 = 0x06;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Drive_1
            /// </summary>
            public const byte FT_CBUS_Drive_1 = 0x07;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - GPIO
            /// </summary>
            public const byte FT_CBUS_GPIO = 0x08;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - TxdEn
            /// </summary>
            public const byte FT_CBUS_TXDEN = 0x09;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Clk24MHz
            /// </summary>
            public const byte FT_CBUS_CLK24MHz = 0x0A;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Clk12MHz
            /// </summary>
            public const byte FT_CBUS_CLK12MHz = 0x0B;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Clk6MHz
            /// </summary>
            public const byte FT_CBUS_CLK6MHz = 0x0C;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - BCD_Charger
            /// </summary>
            public const byte FT_CBUS_BCD_Charger = 0x0D;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - BCD_Charger#
            /// </summary>
            public const byte FT_CBUS_BCD_Charger_N = 0x0E;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - I2C_TXE#
            /// </summary>
            public const byte FT_CBUS_I2C_TXE = 0x0F;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - I2C_RXF#
            /// </summary>
            public const byte FT_CBUS_I2C_RXF = 0x10;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - VBUS_Sense
            /// </summary>
            public const byte FT_CBUS_VBUS_Sense = 0x11;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - BitBang_WR#
            /// </summary>
            public const byte FT_CBUS_BitBang_WR = 0x12;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - BitBang_RD#
            /// </summary>
            public const byte FT_CBUS_BitBang_RD = 0x13;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Time_Stampe
            /// </summary>
            public const byte FT_CBUS_Time_Stamp = 0x14;
            /// <summary>
            /// FT X-Series CBUS EEPROM options - Keep_Awake#
            /// </summary>
            public const byte FT_CBUS_Keep_Awake = 0x15;
        }

        // Flag values for FT_GetDeviceInfoDetail and FT_GetDeviceInfo
        /// <summary>
        /// Flags that provide information on the FTDI device state
        /// </summary>
        public class FT_FLAGS
        {
            /// <summary>
            /// Indicates that the device is open
            /// </summary>
            public const UInt32 FT_FLAGS_OPENED = 0x00000001;
            /// <summary>
            /// Indicates that the device is enumerated as a hi-speed USB device
            /// </summary>
            public const UInt32 FT_FLAGS_HISPEED = 0x00000002;
        }

        // Valid drive current values for FT2232H, FT4232H and FT232H devices
        /// <summary>
        /// Valid values for drive current options on FT2232H, FT4232H and FT232H devices.
        /// </summary>
        public class FT_DRIVE_CURRENT
        {
            /// <summary>
            /// 4mA drive current
            /// </summary>
            public const byte FT_DRIVE_CURRENT_4MA = 4;
            /// <summary>
            /// 8mA drive current
            /// </summary>
            public const byte FT_DRIVE_CURRENT_8MA = 8;
            /// <summary>
            /// 12mA drive current
            /// </summary>
            public const byte FT_DRIVE_CURRENT_12MA = 12;
            /// <summary>
            /// 16mA drive current
            /// </summary>
            public const byte FT_DRIVE_CURRENT_16MA = 16;
        }

        // Device type identifiers for FT_GetDeviceInfoDetail and FT_GetDeviceInfo
        /// <summary>
        /// List of FTDI device types
        /// </summary>
        public enum FT_DEVICE
        {
            /// <summary>
            /// FT232B or FT245B device
            /// </summary>
            FT_DEVICE_BM = 0,
            /// <summary>
            /// FT8U232AM or FT8U245AM device
            /// </summary>
            FT_DEVICE_AM,
            /// <summary>
            /// FT8U100AX device
            /// </summary>
            FT_DEVICE_100AX,
            /// <summary>
            /// Unknown device
            /// </summary>
            FT_DEVICE_UNKNOWN,
            /// <summary>
            /// FT2232 device
            /// </summary>
            FT_DEVICE_2232,
            /// <summary>
            /// FT232R or FT245R device
            /// </summary>
            FT_DEVICE_232R,
            /// <summary>
            /// FT2232H device
            /// </summary>
            FT_DEVICE_2232H,
            /// <summary>
            /// FT4232H device
            /// </summary>
            FT_DEVICE_4232H,
            /// <summary>
            /// FT232H device
            /// </summary>
            FT_DEVICE_232H,
            /// <summary>
            /// FT232X device
            /// </summary>
            FT_DEVICE_X_SERIES
        };
        #endregion

        #region DEFAULT_VALUES
        private const UInt32 FT_DEFAULT_BAUD_RATE = 9600;
        private const UInt32 FT_DEFAULT_DEADMAN_TIMEOUT = 5000;
        private const Int32 FT_COM_PORT_NOT_ASSIGNED = -1;
        private const UInt32 FT_DEFAULT_IN_TRANSFER_SIZE = 0x1000;
        private const UInt32 FT_DEFAULT_OUT_TRANSFER_SIZE = 0x1000;
        private const byte FT_DEFAULT_LATENCY = 16;
        private const UInt32 FT_DEFAULT_DEVICE_ID = 0x04036001;
        #endregion

        #region VARIABLES
        // Create private variables for the device within the class
        private IntPtr ftHandle = IntPtr.Zero;
        #endregion

        #region TYPEDEFS
        /// <summary>
        /// Type that holds device information for GetDeviceInformation method.
        /// Used with FT_GetDeviceInfo and FT_GetDeviceInfoDetail in ftd2xx.DLL
        /// </summary>
        public class FT_DEVICE_INFO_NODE
        {
            /// <summary>
            /// Indicates device state.  Can be any combination of the following: FT_FLAGS_OPENED, FT_FLAGS_HISPEED
            /// </summary>
            public UInt32 Flags;
            /// <summary>
            /// Indicates the device type.  Can be one of the following: FT_DEVICE_232R, FT_DEVICE_2232C, FT_DEVICE_BM, FT_DEVICE_AM, FT_DEVICE_100AX or FT_DEVICE_UNKNOWN
            /// </summary>
            public FT_DEVICE Type;
            /// <summary>
            /// The Vendor ID and Product ID of the device
            /// </summary>
            public UInt32 ID;
            /// <summary>
            /// The physical location identifier of the device
            /// </summary>
            public UInt32 LocId;
            /// <summary>
            /// The device serial number
            /// </summary>
            public string SerialNumber;
            /// <summary>
            /// The device description
            /// </summary>
            public string Description;
            /// <summary>
            /// The device handle.  This value is not used externally and is provided for information only.
            /// If the device is not open, this value is 0.
            /// </summary>
            public IntPtr ftHandle;
        }
        #endregion

        #region EEPROM_STRUCTURES
        // Internal structure for reading and writing EEPROM contents
        // NOTE:  NEED Pack=1 for byte alignment!  Without this, data is garbage
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        private class FT_PROGRAM_DATA
        {
            public UInt32 Signature1;
            public UInt32 Signature2;
            public UInt32 Version;
            public UInt16 VendorID;
            public UInt16 ProductID;

            public IntPtr Manufacturer;
            public IntPtr ManufacturerID;
            public IntPtr Description;
            public IntPtr SerialNumber;

            public UInt16 MaxPower;
            public UInt16 PnP;
            public UInt16 SelfPowered;
            public UInt16 RemoteWakeup;
            // FT232B extensions
            public byte Rev4;
            public byte IsoIn;
            public byte IsoOut;
            public byte PullDownEnable;
            public byte SerNumEnable;
            public byte USBVersionEnable;
            public UInt16 USBVersion;
            // FT2232D extensions
            public byte Rev5;
            public byte IsoInA;
            public byte IsoInB;
            public byte IsoOutA;
            public byte IsoOutB;
            public byte PullDownEnable5;
            public byte SerNumEnable5;
            public byte USBVersionEnable5;
            public UInt16 USBVersion5;
            public byte AIsHighCurrent;
            public byte BIsHighCurrent;
            public byte IFAIsFifo;
            public byte IFAIsFifoTar;
            public byte IFAIsFastSer;
            public byte AIsVCP;
            public byte IFBIsFifo;
            public byte IFBIsFifoTar;
            public byte IFBIsFastSer;
            public byte BIsVCP;
            // FT232R extensions
            public byte UseExtOsc;
            public byte HighDriveIOs;
            public byte EndpointSize;
            public byte PullDownEnableR;
            public byte SerNumEnableR;
            public byte InvertTXD;			// non-zero if invert TXD
            public byte InvertRXD;			// non-zero if invert RXD
            public byte InvertRTS;			// non-zero if invert RTS
            public byte InvertCTS;			// non-zero if invert CTS
            public byte InvertDTR;			// non-zero if invert DTR
            public byte InvertDSR;			// non-zero if invert DSR
            public byte InvertDCD;			// non-zero if invert DCD
            public byte InvertRI;			// non-zero if invert RI
            public byte Cbus0;				// Cbus Mux control - Ignored for FT245R
            public byte Cbus1;				// Cbus Mux control - Ignored for FT245R
            public byte Cbus2;				// Cbus Mux control - Ignored for FT245R
            public byte Cbus3;				// Cbus Mux control - Ignored for FT245R
            public byte Cbus4;				// Cbus Mux control - Ignored for FT245R
            public byte RIsD2XX;			// Default to loading VCP
            // FT2232H extensions
            public byte PullDownEnable7;
            public byte SerNumEnable7;
            public byte ALSlowSlew;			// non-zero if AL pins have slow slew
            public byte ALSchmittInput;		// non-zero if AL pins are Schmitt input
            public byte ALDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte AHSlowSlew;			// non-zero if AH pins have slow slew
            public byte AHSchmittInput;		// non-zero if AH pins are Schmitt input
            public byte AHDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte BLSlowSlew;			// non-zero if BL pins have slow slew
            public byte BLSchmittInput;		// non-zero if BL pins are Schmitt input
            public byte BLDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte BHSlowSlew;			// non-zero if BH pins have slow slew
            public byte BHSchmittInput;		// non-zero if BH pins are Schmitt input
            public byte BHDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte IFAIsFifo7;			// non-zero if interface is 245 FIFO
            public byte IFAIsFifoTar7;		// non-zero if interface is 245 FIFO CPU target
            public byte IFAIsFastSer7;		// non-zero if interface is Fast serial
            public byte AIsVCP7;			// non-zero if interface is to use VCP drivers
            public byte IFBIsFifo7;			// non-zero if interface is 245 FIFO
            public byte IFBIsFifoTar7;		// non-zero if interface is 245 FIFO CPU target
            public byte IFBIsFastSer7;		// non-zero if interface is Fast serial
            public byte BIsVCP7;			// non-zero if interface is to use VCP drivers
            public byte PowerSaveEnable;    // non-zero if using BCBUS7 to save power for self-powered designs
            // FT4232H extensions
            public byte PullDownEnable8;
            public byte SerNumEnable8;
            public byte ASlowSlew;			// non-zero if AL pins have slow slew
            public byte ASchmittInput;		// non-zero if AL pins are Schmitt input
            public byte ADriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte BSlowSlew;			// non-zero if AH pins have slow slew
            public byte BSchmittInput;		// non-zero if AH pins are Schmitt input
            public byte BDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte CSlowSlew;			// non-zero if BL pins have slow slew
            public byte CSchmittInput;		// non-zero if BL pins are Schmitt input
            public byte CDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte DSlowSlew;			// non-zero if BH pins have slow slew
            public byte DSchmittInput;		// non-zero if BH pins are Schmitt input
            public byte DDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte ARIIsTXDEN;
            public byte BRIIsTXDEN;
            public byte CRIIsTXDEN;
            public byte DRIIsTXDEN;
            public byte AIsVCP8;			// non-zero if interface is to use VCP drivers
            public byte BIsVCP8;			// non-zero if interface is to use VCP drivers
            public byte CIsVCP8;			// non-zero if interface is to use VCP drivers
            public byte DIsVCP8;			// non-zero if interface is to use VCP drivers
            // FT232H extensions
            public byte PullDownEnableH;	// non-zero if pull down enabled
            public byte SerNumEnableH;		// non-zero if serial number to be used
            public byte ACSlowSlewH;		// non-zero if AC pins have slow slew
            public byte ACSchmittInputH;	// non-zero if AC pins are Schmitt input
            public byte ACDriveCurrentH;	// valid values are 4mA, 8mA, 12mA, 16mA
            public byte ADSlowSlewH;		// non-zero if AD pins have slow slew
            public byte ADSchmittInputH;	// non-zero if AD pins are Schmitt input
            public byte ADDriveCurrentH;	// valid values are 4mA, 8mA, 12mA, 16mA
            public byte Cbus0H;				// Cbus Mux control
            public byte Cbus1H;				// Cbus Mux control
            public byte Cbus2H;				// Cbus Mux control
            public byte Cbus3H;				// Cbus Mux control
            public byte Cbus4H;				// Cbus Mux control
            public byte Cbus5H;				// Cbus Mux control
            public byte Cbus6H;				// Cbus Mux control
            public byte Cbus7H;				// Cbus Mux control
            public byte Cbus8H;				// Cbus Mux control
            public byte Cbus9H;				// Cbus Mux control
            public byte IsFifoH;			// non-zero if interface is 245 FIFO
            public byte IsFifoTarH;			// non-zero if interface is 245 FIFO CPU target
            public byte IsFastSerH;			// non-zero if interface is Fast serial
            public byte IsFT1248H;			// non-zero if interface is FT1248
            public byte FT1248CpolH;		// FT1248 clock polarity
            public byte FT1248LsbH;			// FT1248 data is LSB (1) or MSB (0)
            public byte FT1248FlowControlH;	// FT1248 flow control enable
            public byte IsVCPH;				// non-zero if interface is to use VCP drivers
            public byte PowerSaveEnableH;	// non-zero if using ACBUS7 to save power for self-powered designs
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct FT_EEPROM_HEADER
        {
            public UInt32 deviceType;		// FTxxxx device type to be programmed
            // Device descriptor options
            public UInt16 VendorId;				// 0x0403
            public UInt16 ProductId;				// 0x6001
            public byte SerNumEnable;			// non-zero if serial number to be used
            // Config descriptor options
            public UInt16 MaxPower;				// 0 < MaxPower <= 500
            public byte SelfPowered;			// 0 = bus powered, 1 = self powered
            public byte RemoteWakeup;			// 0 = not capable, 1 = capable
            // Hardware options
            public byte PullDownEnable;		// non-zero if pull down in suspend enabled
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct FT_XSERIES_DATA
        {
            public FT_EEPROM_HEADER common;

            public byte ACSlowSlew;			// non-zero if AC bus pins have slow slew
            public byte ACSchmittInput;		// non-zero if AC bus pins are Schmitt input
            public byte ACDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            public byte ADSlowSlew;			// non-zero if AD bus pins have slow slew
            public byte ADSchmittInput;		// non-zero if AD bus pins are Schmitt input
            public byte ADDriveCurrent;		// valid values are 4mA, 8mA, 12mA, 16mA
            // CBUS options
            public byte Cbus0;				// Cbus Mux control
            public byte Cbus1;				// Cbus Mux control
            public byte Cbus2;				// Cbus Mux control
            public byte Cbus3;				// Cbus Mux control
            public byte Cbus4;				// Cbus Mux control
            public byte Cbus5;				// Cbus Mux control
            public byte Cbus6;				// Cbus Mux control
            // UART signal options
            public byte InvertTXD;			// non-zero if invert TXD
            public byte InvertRXD;			// non-zero if invert RXD
            public byte InvertRTS;			// non-zero if invert RTS
            public byte InvertCTS;			// non-zero if invert CTS
            public byte InvertDTR;			// non-zero if invert DTR
            public byte InvertDSR;			// non-zero if invert DSR
            public byte InvertDCD;			// non-zero if invert DCD
            public byte InvertRI;				// non-zero if invert RI
            // Battery Charge Detect options
            public byte BCDEnable;			// Enable Battery Charger Detection
            public byte BCDForceCbusPWREN;	// asserts the power enable signal on CBUS when charging port detected
            public byte BCDDisableSleep;		// forces the device never to go into sleep mode
            // I2C options
            public UInt16 I2CSlaveAddress;		// I2C slave device address
            public UInt32 I2CDeviceId;			// I2C device ID
            public byte I2CDisableSchmitt;	// Disable I2C Schmitt trigger
            // FT1248 options
            public byte FT1248Cpol;			// FT1248 clock polarity - clock idle high (1) or clock idle low (0)
            public byte FT1248Lsb;			// FT1248 data is LSB (1) or MSB (0)
            public byte FT1248FlowControl;	// FT1248 flow control enable
            // Hardware options
            public byte RS485EchoSuppress;	// 
            public byte PowerSaveEnable;		// 
            // Driver option
            public byte DriverType;			// 
        }

        // Base class for EEPROM structures - these elements are common to all devices
        /// <summary>
        /// Common EEPROM elements for all devices.  Inherited to specific device type EEPROMs.
        /// </summary>
        public class FT_EEPROM_DATA
        {
            //private const UInt32 Signature1     = 0x00000000;
            //private const UInt32 Signature2     = 0xFFFFFFFF;
            //private const UInt32 Version        = 0x00000002;
            /// <summary>
            /// Vendor ID as supplied by the USB Implementers Forum
            /// </summary>
            public UInt16 VendorID = 0x0403;
            /// <summary>
            /// Product ID
            /// </summary>
            public UInt16 ProductID = 0x6001;
            /// <summary>
            /// Manufacturer name string
            /// </summary>
            public string Manufacturer = "FTDI";
            /// <summary>
            /// Manufacturer name abbreviation to be used as a prefix for automatically generated serial numbers
            /// </summary>
            public string ManufacturerID = "FT";
            /// <summary>
            /// Device description string
            /// </summary>
            public string Description = "USB-Serial Converter";
            /// <summary>
            /// Device serial number string
            /// </summary>
            public string SerialNumber = "";
            /// <summary>
            /// Maximum power the device needs
            /// </summary>
            public UInt16 MaxPower = 0x0090;
            //private bool PnP                    = true;
            /// <summary>
            /// Indicates if the device has its own power supply (self-powered) or gets power from the USB port (bus-powered)
            /// </summary>
            public bool SelfPowered = false;
            /// <summary>
            /// Determines if the device can wake the host PC from suspend by toggling the RI line
            /// </summary>
            public bool RemoteWakeup = false;
        }

        // EEPROM class for FT232B and FT245B
        /// <summary>
        /// EEPROM structure specific to FT232B and FT245B devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT232B_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            //private bool Rev4                   = true;
            //private bool IsoIn                  = false;
            //private bool IsoOut                 = false;
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if the USB version number is enabled
            /// </summary>
            public bool USBVersionEnable = true;
            /// <summary>
            /// The USB version number.  Should be either 0x0110 (USB 1.1) or 0x0200 (USB 2.0)
            /// </summary>
            public UInt16 USBVersion = 0x0200;
        }

        // EEPROM class for FT2232C, FT2232L and FT2232D
        /// <summary>
        /// EEPROM structure specific to FT2232 devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT2232_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            //private bool Rev5                   = true;
            //private bool IsoInA                 = false;
            //private bool IsoInB                 = false;
            //private bool IsoOutA                = false;
            //private bool IsoOutB                = false;
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if the USB version number is enabled
            /// </summary>
            public bool USBVersionEnable = true;
            /// <summary>
            /// The USB version number.  Should be either 0x0110 (USB 1.1) or 0x0200 (USB 2.0)
            /// </summary>
            public UInt16 USBVersion = 0x0200;
            /// <summary>
            /// Enables high current IOs on channel A
            /// </summary>
            public bool AIsHighCurrent = false;
            /// <summary>
            /// Enables high current IOs on channel B
            /// </summary>
            public bool BIsHighCurrent = false;
            /// <summary>
            /// Determines if channel A is in FIFO mode
            /// </summary>
            public bool IFAIsFifo = false;
            /// <summary>
            /// Determines if channel A is in FIFO target mode
            /// </summary>
            public bool IFAIsFifoTar = false;
            /// <summary>
            /// Determines if channel A is in fast serial mode
            /// </summary>
            public bool IFAIsFastSer = false;
            /// <summary>
            /// Determines if channel A loads the VCP driver
            /// </summary>
            public bool AIsVCP = true;
            /// <summary>
            /// Determines if channel B is in FIFO mode
            /// </summary>
            public bool IFBIsFifo = false;
            /// <summary>
            /// Determines if channel B is in FIFO target mode
            /// </summary>
            public bool IFBIsFifoTar = false;
            /// <summary>
            /// Determines if channel B is in fast serial mode
            /// </summary>
            public bool IFBIsFastSer = false;
            /// <summary>
            /// Determines if channel B loads the VCP driver
            /// </summary>
            public bool BIsVCP = true;
        }

        // EEPROM class for FT232R and FT245R
        /// <summary>
        /// EEPROM structure specific to FT232R and FT245R devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT232R_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            /// <summary>
            /// Disables the FT232R internal clock source.  
            /// If the device has external oscillator enabled it must have an external oscillator fitted to function
            /// </summary>
            public bool UseExtOsc = false;
            /// <summary>
            /// Enables high current IOs
            /// </summary>
            public bool HighDriveIOs = false;
            /// <summary>
            /// Sets the endpoint size.  This should always be set to 64
            /// </summary>
            public byte EndpointSize = 64;
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Inverts the sense of the TXD line
            /// </summary>
            public bool InvertTXD = false;
            /// <summary>
            /// Inverts the sense of the RXD line
            /// </summary>
            public bool InvertRXD = false;
            /// <summary>
            /// Inverts the sense of the RTS line
            /// </summary>
            public bool InvertRTS = false;
            /// <summary>
            /// Inverts the sense of the CTS line
            /// </summary>
            public bool InvertCTS = false;
            /// <summary>
            /// Inverts the sense of the DTR line
            /// </summary>
            public bool InvertDTR = false;
            /// <summary>
            /// Inverts the sense of the DSR line
            /// </summary>
            public bool InvertDSR = false;
            /// <summary>
            /// Inverts the sense of the DCD line
            /// </summary>
            public bool InvertDCD = false;
            /// <summary>
            /// Inverts the sense of the RI line
            /// </summary>
            public bool InvertRI = false;
            /// <summary>
            /// Sets the function of the CBUS0 pin for FT232R devices.
            /// Valid values are FT_CBUS_TXDEN, FT_CBUS_PWRON , FT_CBUS_RXLED, FT_CBUS_TXLED, 
            /// FT_CBUS_TXRXLED, FT_CBUS_SLEEP, FT_CBUS_CLK48, FT_CBUS_CLK24, FT_CBUS_CLK12, 
            /// FT_CBUS_CLK6, FT_CBUS_IOMODE, FT_CBUS_BITBANG_WR, FT_CBUS_BITBANG_RD
            /// </summary>
            public byte Cbus0 = FT_CBUS_OPTIONS.FT_CBUS_SLEEP;
            /// <summary>
            /// Sets the function of the CBUS1 pin for FT232R devices.
            /// Valid values are FT_CBUS_TXDEN, FT_CBUS_PWRON , FT_CBUS_RXLED, FT_CBUS_TXLED, 
            /// FT_CBUS_TXRXLED, FT_CBUS_SLEEP, FT_CBUS_CLK48, FT_CBUS_CLK24, FT_CBUS_CLK12, 
            /// FT_CBUS_CLK6, FT_CBUS_IOMODE, FT_CBUS_BITBANG_WR, FT_CBUS_BITBANG_RD
            /// </summary>
            public byte Cbus1 = FT_CBUS_OPTIONS.FT_CBUS_SLEEP;
            /// <summary>
            /// Sets the function of the CBUS2 pin for FT232R devices.
            /// Valid values are FT_CBUS_TXDEN, FT_CBUS_PWRON , FT_CBUS_RXLED, FT_CBUS_TXLED, 
            /// FT_CBUS_TXRXLED, FT_CBUS_SLEEP, FT_CBUS_CLK48, FT_CBUS_CLK24, FT_CBUS_CLK12, 
            /// FT_CBUS_CLK6, FT_CBUS_IOMODE, FT_CBUS_BITBANG_WR, FT_CBUS_BITBANG_RD
            /// </summary>
            public byte Cbus2 = FT_CBUS_OPTIONS.FT_CBUS_SLEEP;
            /// <summary>
            /// Sets the function of the CBUS3 pin for FT232R devices.
            /// Valid values are FT_CBUS_TXDEN, FT_CBUS_PWRON , FT_CBUS_RXLED, FT_CBUS_TXLED, 
            /// FT_CBUS_TXRXLED, FT_CBUS_SLEEP, FT_CBUS_CLK48, FT_CBUS_CLK24, FT_CBUS_CLK12, 
            /// FT_CBUS_CLK6, FT_CBUS_IOMODE, FT_CBUS_BITBANG_WR, FT_CBUS_BITBANG_RD
            /// </summary>
            public byte Cbus3 = FT_CBUS_OPTIONS.FT_CBUS_SLEEP;
            /// <summary>
            /// Sets the function of the CBUS4 pin for FT232R devices.
            /// Valid values are FT_CBUS_TXDEN, FT_CBUS_PWRON , FT_CBUS_RXLED, FT_CBUS_TXLED, 
            /// FT_CBUS_TXRXLED, FT_CBUS_SLEEP, FT_CBUS_CLK48, FT_CBUS_CLK24, FT_CBUS_CLK12, 
            /// FT_CBUS_CLK6
            /// </summary>
            public byte Cbus4 = FT_CBUS_OPTIONS.FT_CBUS_SLEEP;
            /// <summary>
            /// Determines if the VCP driver is loaded
            /// </summary>
            public bool RIsD2XX = false;
        }

        // EEPROM class for FT2232H
        /// <summary>
        /// EEPROM structure specific to FT2232H devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT2232H_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if AL pins have a slow slew rate
            /// </summary>
            public bool ALSlowSlew = false;
            /// <summary>
            /// Determines if the AL pins have a Schmitt input
            /// </summary>
            public bool ALSchmittInput = false;
            /// <summary>
            /// Determines the AL pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ALDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if AH pins have a slow slew rate
            /// </summary>
            public bool AHSlowSlew = false;
            /// <summary>
            /// Determines if the AH pins have a Schmitt input
            /// </summary>
            public bool AHSchmittInput = false;
            /// <summary>
            /// Determines the AH pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte AHDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if BL pins have a slow slew rate
            /// </summary>
            public bool BLSlowSlew = false;
            /// <summary>
            /// Determines if the BL pins have a Schmitt input
            /// </summary>
            public bool BLSchmittInput = false;
            /// <summary>
            /// Determines the BL pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte BLDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if BH pins have a slow slew rate
            /// </summary>
            public bool BHSlowSlew = false;
            /// <summary>
            /// Determines if the BH pins have a Schmitt input
            /// </summary>
            public bool BHSchmittInput = false;
            /// <summary>
            /// Determines the BH pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte BHDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if channel A is in FIFO mode
            /// </summary>
            public bool IFAIsFifo = false;
            /// <summary>
            /// Determines if channel A is in FIFO target mode
            /// </summary>
            public bool IFAIsFifoTar = false;
            /// <summary>
            /// Determines if channel A is in fast serial mode
            /// </summary>
            public bool IFAIsFastSer = false;
            /// <summary>
            /// Determines if channel A loads the VCP driver
            /// </summary>
            public bool AIsVCP = true;
            /// <summary>
            /// Determines if channel B is in FIFO mode
            /// </summary>
            public bool IFBIsFifo = false;
            /// <summary>
            /// Determines if channel B is in FIFO target mode
            /// </summary>
            public bool IFBIsFifoTar = false;
            /// <summary>
            /// Determines if channel B is in fast serial mode
            /// </summary>
            public bool IFBIsFastSer = false;
            /// <summary>
            /// Determines if channel B loads the VCP driver
            /// </summary>
            public bool BIsVCP = true;
            /// <summary>
            /// For self-powered designs, keeps the FT2232H in low power state until BCBUS7 is high
            /// </summary>
            public bool PowerSaveEnable = false;
        }

        // EEPROM class for FT4232H
        /// <summary>
        /// EEPROM structure specific to FT4232H devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT4232H_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if A pins have a slow slew rate
            /// </summary>
            public bool ASlowSlew = false;
            /// <summary>
            /// Determines if the A pins have a Schmitt input
            /// </summary>
            public bool ASchmittInput = false;
            /// <summary>
            /// Determines the A pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ADriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if B pins have a slow slew rate
            /// </summary>
            public bool BSlowSlew = false;
            /// <summary>
            /// Determines if the B pins have a Schmitt input
            /// </summary>
            public bool BSchmittInput = false;
            /// <summary>
            /// Determines the B pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte BDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if C pins have a slow slew rate
            /// </summary>
            public bool CSlowSlew = false;
            /// <summary>
            /// Determines if the C pins have a Schmitt input
            /// </summary>
            public bool CSchmittInput = false;
            /// <summary>
            /// Determines the C pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte CDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if D pins have a slow slew rate
            /// </summary>
            public bool DSlowSlew = false;
            /// <summary>
            /// Determines if the D pins have a Schmitt input
            /// </summary>
            public bool DSchmittInput = false;
            /// <summary>
            /// Determines the D pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte DDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// RI of port A acts as RS485 transmit enable (TXDEN)
            /// </summary>
            public bool ARIIsTXDEN = false;
            /// <summary>
            /// RI of port B acts as RS485 transmit enable (TXDEN)
            /// </summary>
            public bool BRIIsTXDEN = false;
            /// <summary>
            /// RI of port C acts as RS485 transmit enable (TXDEN)
            /// </summary>
            public bool CRIIsTXDEN = false;
            /// <summary>
            /// RI of port D acts as RS485 transmit enable (TXDEN)
            /// </summary>
            public bool DRIIsTXDEN = false;
            /// <summary>
            /// Determines if channel A loads the VCP driver
            /// </summary>
            public bool AIsVCP = true;
            /// <summary>
            /// Determines if channel B loads the VCP driver
            /// </summary>
            public bool BIsVCP = true;
            /// <summary>
            /// Determines if channel C loads the VCP driver
            /// </summary>
            public bool CIsVCP = true;
            /// <summary>
            /// Determines if channel D loads the VCP driver
            /// </summary>
            public bool DIsVCP = true;
        }
        // EEPROM class for FT232H
        /// <summary>
        /// EEPROM structure specific to FT232H devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT232H_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if AC pins have a slow slew rate
            /// </summary>
            public bool ACSlowSlew = false;
            /// <summary>
            /// Determines if the AC pins have a Schmitt input
            /// </summary>
            public bool ACSchmittInput = false;
            /// <summary>
            /// Determines the AC pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ACDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Determines if AD pins have a slow slew rate
            /// </summary>
            public bool ADSlowSlew = false;
            /// <summary>
            /// Determines if the AD pins have a Schmitt input
            /// </summary>
            public bool ADSchmittInput = false;
            /// <summary>
            /// Determines the AD pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ADDriveCurrent = FT_DRIVE_CURRENT.FT_DRIVE_CURRENT_4MA;
            /// <summary>
            /// Sets the function of the CBUS0 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN, FT_CBUS_CLK30,
            /// FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus0 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS1 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN, FT_CBUS_CLK30,
            /// FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus1 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS2 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN
            /// </summary>
            public byte Cbus2 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS3 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN
            /// </summary>
            public byte Cbus3 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS4 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN
            /// </summary>
            public byte Cbus4 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS5 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_IOMODE,
            /// FT_CBUS_TXDEN, FT_CBUS_CLK30, FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus5 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS6 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_IOMODE,
            /// FT_CBUS_TXDEN, FT_CBUS_CLK30, FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus6 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS7 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE
            /// </summary>
            public byte Cbus7 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS8 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_IOMODE,
            /// FT_CBUS_TXDEN, FT_CBUS_CLK30, FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus8 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Sets the function of the CBUS9 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_IOMODE,
            /// FT_CBUS_TXDEN, FT_CBUS_CLK30, FT_CBUS_CLK15, FT_CBUS_CLK7_5
            /// </summary>
            public byte Cbus9 = FT_232H_CBUS_OPTIONS.FT_CBUS_TRISTATE;
            /// <summary>
            /// Determines if the device is in FIFO mode
            /// </summary>
            public bool IsFifo = false;
            /// <summary>
            /// Determines if the device is in FIFO target mode
            /// </summary>
            public bool IsFifoTar = false;
            /// <summary>
            /// Determines if the device is in fast serial mode
            /// </summary>
            public bool IsFastSer = false;
            /// <summary>
            /// Determines if the device is in FT1248 mode
            /// </summary>
            public bool IsFT1248 = false;
            /// <summary>
            /// Determines FT1248 mode clock polarity
            /// </summary>
            public bool FT1248Cpol = false;
            /// <summary>
            /// Determines if data is ent MSB (0) or LSB (1) in FT1248 mode
            /// </summary>
            public bool FT1248Lsb = false;
            /// <summary>
            /// Determines if FT1248 mode uses flow control
            /// </summary>
            public bool FT1248FlowControl = false;
            /// <summary>
            /// Determines if the VCP driver is loaded
            /// </summary>
            public bool IsVCP = true;
            /// <summary>
            /// For self-powered designs, keeps the FT232H in low power state until ACBUS7 is high
            /// </summary>
            public bool PowerSaveEnable = false;
        }

        /// <summary>
        /// EEPROM structure specific to X-Series devices.
        /// Inherits from FT_EEPROM_DATA.
        /// </summary>
        public class FT_XSERIES_EEPROM_STRUCTURE : FT_EEPROM_DATA
        {
            /// <summary>
            /// Determines if IOs are pulled down when the device is in suspend
            /// </summary>
            public bool PullDownEnable = false;
            /// <summary>
            /// Determines if the serial number is enabled
            /// </summary>
            public bool SerNumEnable = true;
            /// <summary>
            /// Determines if the USB version number is enabled
            /// </summary>
            public bool USBVersionEnable = true;
            /// <summary>
            /// The USB version number: 0x0200 (USB 2.0)
            /// </summary>
            public UInt16 USBVersion = 0x0200;
            /// <summary>
            /// Determines if AC pins have a slow slew rate
            /// </summary>
            public byte ACSlowSlew;
            /// <summary>
            /// Determines if the AC pins have a Schmitt input
            /// </summary>
            public byte ACSchmittInput;
            /// <summary>
            /// Determines the AC pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ACDriveCurrent;
            /// <summary>
            /// Determines if AD pins have a slow slew rate
            /// </summary>
            public byte ADSlowSlew;
            /// <summary>
            /// Determines if AD pins have a schmitt input
            /// </summary>
            public byte ADSchmittInput;
            /// <summary>
            /// Determines the AD pins drive current in mA.  Valid values are FT_DRIVE_CURRENT_4MA, FT_DRIVE_CURRENT_8MA, FT_DRIVE_CURRENT_12MA or FT_DRIVE_CURRENT_16MA
            /// </summary>
            public byte ADDriveCurrent;
            /// <summary>
            /// Sets the function of the CBUS0 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_GPIO, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus0;
            /// <summary>
            /// Sets the function of the CBUS1 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_GPIO, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus1;
            /// <summary>
            /// Sets the function of the CBUS2 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_GPIO, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus2;
            /// <summary>
            /// Sets the function of the CBUS3 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_GPIO, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus3;
            /// <summary>
            /// Sets the function of the CBUS4 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus4;
            /// <summary>
            /// Sets the function of the CBUS5 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus5;
            /// <summary>
            /// Sets the function of the CBUS6 pin for FT232H devices.
            /// Valid values are FT_CBUS_TRISTATE, FT_CBUS_RXLED, FT_CBUS_TXLED, FT_CBUS_TXRXLED,
            /// FT_CBUS_PWREN, FT_CBUS_SLEEP, FT_CBUS_DRIVE_0, FT_CBUS_DRIVE_1, FT_CBUS_TXDEN, FT_CBUS_CLK24,
            /// FT_CBUS_CLK12, FT_CBUS_CLK6, FT_CBUS_BCD_CHARGER, FT_CBUS_BCD_CHARGER_N, FT_CBUS_VBUS_SENSE, FT_CBUS_BITBANG_WR,
            /// FT_CBUS_BITBANG_RD, FT_CBUS_TIME_STAMP, FT_CBUS_KEEP_AWAKE
            /// </summary>
            public byte Cbus6;
            /// <summary>
            /// Inverts the sense of the TXD line
            /// </summary>
            public byte InvertTXD;
            /// <summary>
            /// Inverts the sense of the RXD line
            /// </summary>
            public byte InvertRXD;
            /// <summary>
            /// Inverts the sense of the RTS line
            /// </summary>
            public byte InvertRTS;
            /// <summary>
            /// Inverts the sense of the CTS line
            /// </summary>
            public byte InvertCTS;
            /// <summary>
            /// Inverts the sense of the DTR line
            /// </summary>
            public byte InvertDTR;
            /// <summary>
            /// Inverts the sense of the DSR line
            /// </summary>
            public byte InvertDSR;
            /// <summary>
            /// Inverts the sense of the DCD line
            /// </summary>
            public byte InvertDCD;
            /// <summary>
            /// Inverts the sense of the RI line
            /// </summary>
            public byte InvertRI;
            /// <summary>
            /// Determines whether the Battery Charge Detection option is enabled.
            /// </summary>
            public byte BCDEnable;
            /// <summary>
            /// Asserts the power enable signal on CBUS when charging port detected.
            /// </summary>
            public byte BCDForceCbusPWREN;
            /// <summary>
            /// Forces the device never to go into sleep mode.
            /// </summary>
            public byte BCDDisableSleep;
            /// <summary>
            /// I2C slave device address.
            /// </summary>
            public ushort I2CSlaveAddress;
            /// <summary>
            /// I2C device ID
            /// </summary>
            public UInt32 I2CDeviceId;
            /// <summary>
            /// Disable I2C Schmitt trigger.
            /// </summary>
            public byte I2CDisableSchmitt;
            /// <summary>
            /// FT1248 clock polarity - clock idle high (1) or clock idle low (0)
            /// </summary>
            public byte FT1248Cpol;
            /// <summary>
            /// FT1248 data is LSB (1) or MSB (0)
            /// </summary>
            public byte FT1248Lsb;
            /// <summary>
            /// FT1248 flow control enable.
            /// </summary>
            public byte FT1248FlowControl;
            /// <summary>
            /// Enable RS485 Echo Suppression
            /// </summary>
            public byte RS485EchoSuppress;
            /// <summary>
            /// Enable Power Save mode.
            /// </summary>
            public byte PowerSaveEnable;
            /// <summary>
            /// Determines whether the VCP driver is loaded.
            /// </summary>
            public byte IsVCP;
        }

        #endregion

        #region EXCEPTION_HANDLING
        /// <summary>
        /// Exceptions thrown by errors within the FTDI class.
        /// </summary>
        [global::System.Serializable]
        public class FT_EXCEPTION : Exception
        {
            /// <summary>
            /// 
            /// </summary>
            public FT_EXCEPTION() { }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="message"></param>
            public FT_EXCEPTION(string message) : base(message) { }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="message"></param>
            /// <param name="inner"></param>
            public FT_EXCEPTION(string message, Exception inner) : base(message, inner) { }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="info"></param>
            /// <param name="context"></param>
            protected FT_EXCEPTION(
            System.Runtime.Serialization.SerializationInfo info,
            System.Runtime.Serialization.StreamingContext context)
                : base(info, context) { }
        }
        #endregion
#if false
        #region FUNCTION_IMPORTS_ftd2xx.DLL
		// Handle to our DLL - used with GetProcAddress to load all of our functions
		IntPtr hftd2xxDLL = IntPtr.Zero;
		// Declare pointers to each of the functions we are going to use in FT2DXX.DLL
		// These are assigned in our constructor and freed in our destructor.
		IntPtr pFT_CreateDeviceInfoList = IntPtr.Zero;
		IntPtr pFT_GetDeviceInfoDetail = IntPtr.Zero;
		IntPtr pFT_Open = IntPtr.Zero;
		IntPtr pFT_OpenEx = IntPtr.Zero;
		IntPtr pFT_Close = IntPtr.Zero;
		IntPtr pFT_Read = IntPtr.Zero;
		IntPtr pFT_Write = IntPtr.Zero;
		IntPtr pFT_GetQueueStatus = IntPtr.Zero;
		IntPtr pFT_GetModemStatus = IntPtr.Zero;
		IntPtr pFT_GetStatus = IntPtr.Zero;
		IntPtr pFT_SetBaudRate = IntPtr.Zero;
		IntPtr pFT_SetDataCharacteristics = IntPtr.Zero;
		IntPtr pFT_SetFlowControl = IntPtr.Zero;
		IntPtr pFT_SetDtr = IntPtr.Zero;
		IntPtr pFT_ClrDtr = IntPtr.Zero;
		IntPtr pFT_SetRts = IntPtr.Zero;
		IntPtr pFT_ClrRts = IntPtr.Zero;
		IntPtr pFT_ResetDevice = IntPtr.Zero;
		IntPtr pFT_ResetPort = IntPtr.Zero;
		IntPtr pFT_CyclePort = IntPtr.Zero;
		IntPtr pFT_Rescan = IntPtr.Zero;
		IntPtr pFT_Reload = IntPtr.Zero;
		IntPtr pFT_Purge = IntPtr.Zero;
		IntPtr pFT_SetTimeouts = IntPtr.Zero;
		IntPtr pFT_SetBreakOn = IntPtr.Zero;
		IntPtr pFT_SetBreakOff = IntPtr.Zero;
		IntPtr pFT_GetDeviceInfo = IntPtr.Zero;
		IntPtr pFT_SetResetPipeRetryCount = IntPtr.Zero;
		IntPtr pFT_StopInTask = IntPtr.Zero;
		IntPtr pFT_RestartInTask = IntPtr.Zero;
		IntPtr pFT_GetDriverVersion = IntPtr.Zero;
		IntPtr pFT_GetLibraryVersion = IntPtr.Zero;
		IntPtr pFT_SetDeadmanTimeout = IntPtr.Zero;
		IntPtr pFT_SetChars = IntPtr.Zero;
		IntPtr pFT_SetEventNotification = IntPtr.Zero;
		IntPtr pFT_GetComPortNumber = IntPtr.Zero;
		IntPtr pFT_SetLatencyTimer = IntPtr.Zero;
		IntPtr pFT_GetLatencyTimer = IntPtr.Zero;
		IntPtr pFT_SetBitMode = IntPtr.Zero;
		IntPtr pFT_GetBitMode = IntPtr.Zero;
		IntPtr pFT_SetUSBParameters = IntPtr.Zero;
		IntPtr pFT_ReadEE = IntPtr.Zero;
		IntPtr pFT_WriteEE = IntPtr.Zero;
		IntPtr pFT_EraseEE = IntPtr.Zero;
		IntPtr pFT_EE_UASize = IntPtr.Zero;
		IntPtr pFT_EE_UARead = IntPtr.Zero;
		IntPtr pFT_EE_UAWrite = IntPtr.Zero;
		IntPtr pFT_EE_Read = IntPtr.Zero;
		IntPtr pFT_EE_Program = IntPtr.Zero;
		IntPtr pFT_EEPROM_Read = IntPtr.Zero;
		IntPtr pFT_EEPROM_Program = IntPtr.Zero;
        #endregion
#endif
        #region METHOD_DEFINITIONS
        //**************************************************************************
        // GetNumberOfDevices
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the number of FTDI devices available.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_CreateDeviceInfoList in ftd2xx.DLL</returns>
        /// <param name="devcount">The number of FTDI devices available.</param>
        public FT_STATUS GetNumberOfDevices(ref UInt32 devcount)
        {

                // Call FT_CreateDeviceInfoList
            FT_STATUS ftStatus = FT_CreateDeviceInfoList(ref devcount);

            return ftStatus;

        }



        //LET this be the example function
        //**************************************************************************
        // GetDeviceList
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets information on all of the FTDI devices available.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDeviceInfoDetail in ftd2xx.DLL</returns>
        /// <param name="devicelist">An array of type FT_DEVICE_INFO_NODE to contain the device information for all available devices.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the supplied buffer is not large enough to contain the device info list.</exception>
        public FT_STATUS GetDeviceList(FT_DEVICE_INFO_NODE[] devicelist)
        {
            UInt32 devcount = 0;

            // Call FT_CreateDeviceInfoList
            FT_STATUS ftStatus = FT_CreateDeviceInfoList(ref devcount);

            // Allocate the required storage for our list
			byte[] sernum = new byte[16];
			byte[] desc = new byte[64];

            if (devcount > 0)
            {
                // Check the size of the buffer passed in is big enough
                if (devicelist.Length < devcount)
                {
                    // Buffer not big enough
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_BUFFER_SIZE;
                    // Throw exception
                    ErrorHandler(ftStatus, ftErrorCondition);
                }

                // Instantiate the array elements as FT_DEVICE_INFO_NODE
                for (UInt32 i = 0; i < devcount; i++)
                {
                    devicelist[i] = new FT_DEVICE_INFO_NODE();
                    // Call FT_GetDeviceInfoDetail
                    ftStatus = FT_GetDeviceInfoDetail(i, ref devicelist[i].Flags, ref devicelist[i].Type, ref devicelist[i].ID, ref devicelist[i].LocId, sernum, desc, ref devicelist[i].ftHandle);

                    devicelist[i].SerialNumber = Encoding.ASCII.GetString(sernum);
                    devicelist[i].SerialNumber = devicelist[i].SerialNumber.Substring(0, devicelist[i].SerialNumber.IndexOf("\0"));

                    devicelist[i].Description = Encoding.ASCII.GetString(desc);
                    devicelist[i].Description = devicelist[i].Description.Substring(0, devicelist[i].Description.IndexOf("\0"));
                }
            }

            return ftStatus;
        }


        //**************************************************************************
        // OpenByIndex
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Opens the FTDI device with the specified index.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_Open in ftd2xx.DLL</returns>
        /// <param name="index">Index of the device to open.
        /// Note that this cannot be guaranteed to open a specific device.</param>
        /// <remarks>Initialises the device to 8 data bits, 1 stop bit, no parity, no flow control and 9600 Baud.</remarks>
        public FT_STATUS OpenByIndex(UInt32 index)
        {
            // Call FT_Open
            FT_STATUS ftStatus = FT_Open(index, ref ftHandle);

            // Appears that the handle value can be non-NULL on a fail, so set it explicitly
            if (ftStatus != FT_STATUS.FT_OK)
                ftHandle = IntPtr.Zero;

            if (ftHandle != IntPtr.Zero)
            {
                // Initialise port data characteristics
                byte WordLength = FT_DATA_BITS.FT_BITS_8;
                byte StopBits = FT_STOP_BITS.FT_STOP_BITS_1;
                byte Parity = FT_PARITY.FT_PARITY_NONE;
                ftStatus = FT_SetDataCharacteristics(ftHandle, WordLength, StopBits, Parity);
                // Initialise to no flow control
                UInt16 FlowControl = FT_FLOW_CONTROL.FT_FLOW_NONE;
                byte Xon = 0x11;
                byte Xoff = 0x13;
                ftStatus = FT_SetFlowControl(ftHandle, FlowControl, Xon, Xoff);
                // Initialise Baud rate
                UInt32 BaudRate = 9600;
                ftStatus = FT_SetBaudRate(ftHandle, BaudRate);
            }
            return ftStatus;
        }


        //**************************************************************************
        // OpenBySerialNumber
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Opens the FTDI device with the specified serial number.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_OpenEx in ftd2xx.DLL</returns>
        /// <param name="serialnumber">Serial number of the device to open.</param>
        /// <remarks>Initialises the device to 8 data bits, 1 stop bit, no parity, no flow control and 9600 Baud.</remarks>
        public FT_STATUS OpenBySerialNumber(string serialnumber)
        {

            // Call FT_OpenEx
            FT_STATUS ftStatus = FT_OpenEx(serialnumber, FT_OPEN_BY_SERIAL_NUMBER, ref ftHandle);

            // Appears that the handle value can be non-NULL on a fail, so set it explicitly
            if (ftStatus != FT_STATUS.FT_OK)
                ftHandle = IntPtr.Zero;

            if (ftHandle != IntPtr.Zero)
            {
                // Initialise port data characteristics
                byte WordLength = FT_DATA_BITS.FT_BITS_8;
                byte StopBits = FT_STOP_BITS.FT_STOP_BITS_1;
                byte Parity = FT_PARITY.FT_PARITY_NONE;
                ftStatus = FT_SetDataCharacteristics(ftHandle, WordLength, StopBits, Parity);
                // Initialise to no flow control
                UInt16 FlowControl = FT_FLOW_CONTROL.FT_FLOW_NONE;
                byte Xon = 0x11;
                byte Xoff = 0x13;
                ftStatus = FT_SetFlowControl(ftHandle, FlowControl, Xon, Xoff);
                // Initialise Baud rate
                UInt32 BaudRate = 9600;
                ftStatus = FT_SetBaudRate(ftHandle, BaudRate);
            }
            return ftStatus;
        }


        //**************************************************************************
        // OpenByDescription
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Opens the FTDI device with the specified description.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_OpenEx in ftd2xx.DLL</returns>
        /// <param name="description">Description of the device to open.</param>
        /// <remarks>Initialises the device to 8 data bits, 1 stop bit, no parity, no flow control and 9600 Baud.</remarks>
        public FT_STATUS OpenByDescription(string description)
        {
            // Call FT_OpenEx
            FT_STATUS ftStatus = FT_OpenEx(description, FT_OPEN_BY_DESCRIPTION, ref ftHandle);

            // Appears that the handle value can be non-NULL on a fail, so set it explicitly
            if (ftStatus != FT_STATUS.FT_OK)
                ftHandle = IntPtr.Zero;

            if (ftHandle != IntPtr.Zero)
            {
                // Initialise port data characteristics
                byte WordLength = FT_DATA_BITS.FT_BITS_8;
                byte StopBits = FT_STOP_BITS.FT_STOP_BITS_1;
                byte Parity = FT_PARITY.FT_PARITY_NONE;
                ftStatus = FT_SetDataCharacteristics(ftHandle, WordLength, StopBits, Parity);
                // Initialise to no flow control
                UInt16 FlowControl = FT_FLOW_CONTROL.FT_FLOW_NONE;
                byte Xon = 0x11;
                byte Xoff = 0x13;
                ftStatus = FT_SetFlowControl(ftHandle, FlowControl, Xon, Xoff);
                // Initialise Baud rate
                UInt32 BaudRate = 9600;
                ftStatus = FT_SetBaudRate(ftHandle, BaudRate);
            }
            return ftStatus;
        }


        //**************************************************************************
        // OpenByLocation
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Opens the FTDI device at the specified physical location.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_OpenEx in ftd2xx.DLL</returns>
        /// <param name="location">Location of the device to open.</param>
        /// <remarks>Initialises the device to 8 data bits, 1 stop bit, no parity, no flow control and 9600 Baud.</remarks>
        public FT_STATUS OpenByLocation(UInt32 location)
        {

            // Call FT_OpenEx
            FT_STATUS ftStatus = FT_OpenExLoc(location, FT_OPEN_BY_LOCATION, ref ftHandle);

            // Appears that the handle value can be non-NULL on a fail, so set it explicitly
            if (ftStatus != FT_STATUS.FT_OK)
                ftHandle = IntPtr.Zero;

            if (ftHandle != IntPtr.Zero)
            {
                // Initialise port data characteristics
                byte WordLength = FT_DATA_BITS.FT_BITS_8;
                byte StopBits = FT_STOP_BITS.FT_STOP_BITS_1;
                byte Parity = FT_PARITY.FT_PARITY_NONE;
                ftStatus = FT_SetDataCharacteristics(ftHandle, WordLength, StopBits, Parity);
                // Initialise to no flow control
                UInt16 FlowControl = FT_FLOW_CONTROL.FT_FLOW_NONE;
                byte Xon = 0x11;
                byte Xoff = 0x13;
                ftStatus = FT_SetFlowControl(ftHandle, FlowControl, Xon, Xoff);
                // Initialise Baud rate
                UInt32 BaudRate = 9600;
                ftStatus = FT_SetBaudRate(ftHandle, BaudRate);
            }
            return ftStatus;
        }


        //**************************************************************************
        // Close
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Closes the handle to an open FTDI device.  
        /// </summary>
        /// <returns>FT_STATUS value from FT_Close in ftd2xx.DLL</returns>
        public FT_STATUS Close()
        {

            // Call FT_Close
            FT_STATUS ftStatus = FT_Close(ftHandle);

            if (ftStatus == FT_STATUS.FT_OK)
            {
                ftHandle = IntPtr.Zero;
            }
            return ftStatus;
        }


        //**************************************************************************
        // Read
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Read data from an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Read in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">An array of bytes which will be populated with the data read from the device.</param>
        /// <param name="numBytesToRead">The number of bytes requested from the device.</param>
        /// <param name="numBytesRead">The number of bytes actually read.</param>
        public FT_STATUS Read(byte[] dataBuffer, UInt32 numBytesToRead, ref UInt32 numBytesRead)
        {

            // If the buffer is not big enough to receive the amount of data requested, adjust the number of bytes to read
            if (dataBuffer.Length < numBytesToRead)
            {
                numBytesToRead = (uint)dataBuffer.Length;
            }

            // Call FT_Read
            FT_STATUS ftStatus = FT_Read(ftHandle, dataBuffer, numBytesToRead, ref numBytesRead);

            return ftStatus;
        }

        // Intellisense comments
        /// <summary>
        /// Read data from an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Read in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">A string containing the data read</param>
        /// <param name="numBytesToRead">The number of bytes requested from the device.</param>
        /// <param name="numBytesRead">The number of bytes actually read.</param>
        public FT_STATUS Read(out string dataBuffer, UInt32 numBytesToRead, ref UInt32 numBytesRead)
        {
            byte[] byteDataBuffer = new byte[(int)numBytesToRead];
            // Call FT_Read
            FT_STATUS ftStatus = FT_Read(ftHandle, byteDataBuffer, numBytesToRead, ref numBytesRead);

            dataBuffer = byteDataBuffer.ToString();
            // Trim buffer to actual bytes read
            dataBuffer = dataBuffer.Substring(0, (int)numBytesRead);


            return ftStatus;
        }

        //**************************************************************************
        // Write
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Write data to an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Write in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">An array of bytes which contains the data to be written to the device.</param>
        /// <param name="numBytesToWrite">The number of bytes to be written to the device.</param>
        /// <param name="numBytesWritten">The number of bytes actually written to the device.</param>
        public FT_STATUS Write(byte[] dataBuffer, Int32 numBytesToWrite, ref UInt32 numBytesWritten)
        {
            // Call FT_Write
            FT_STATUS ftStatus = FT_Write(ftHandle, dataBuffer, (UInt32)numBytesToWrite, ref numBytesWritten);
            return ftStatus;
        }

        // Intellisense comments
        /// <summary>
        /// Write data to an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Write in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">An array of bytes which contains the data to be written to the device.</param>
        /// <param name="numBytesToWrite">The number of bytes to be written to the device.</param>
        /// <param name="numBytesWritten">The number of bytes actually written to the device.</param>
        public FT_STATUS Write(byte[] dataBuffer, UInt32 numBytesToWrite, ref UInt32 numBytesWritten)
        {
            // Call FT_Write
            FT_STATUS ftStatus = FT_Write(ftHandle, dataBuffer, numBytesToWrite, ref numBytesWritten);

            return ftStatus;
        }

        // Intellisense comments
        /// <summary>
        /// Write data to an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Write in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">A  string which contains the data to be written to the device.</param>
        /// <param name="numBytesToWrite">The number of bytes to be written to the device.</param>
        /// <param name="numBytesWritten">The number of bytes actually written to the device.</param>
        public FT_STATUS Write(string dataBuffer, Int32 numBytesToWrite, ref UInt32 numBytesWritten)
        {
			byte[] byteDataBuffer = Encoding.ASCII.GetBytes(dataBuffer);
            // Call FT_Write
            FT_STATUS ftStatus = FT_Write(ftHandle, byteDataBuffer, (UInt32)numBytesToWrite, ref numBytesWritten);

            return ftStatus;
        }

        // Intellisense comments
        /// <summary>
        /// Write data to an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Write in ftd2xx.DLL</returns>
        /// <param name="dataBuffer">A  string which contains the data to be written to the device.</param>
        /// <param name="numBytesToWrite">The number of bytes to be written to the device.</param>
        /// <param name="numBytesWritten">The number of bytes actually written to the device.</param>
        public FT_STATUS Write(string dataBuffer, UInt32 numBytesToWrite, ref UInt32 numBytesWritten)
        {
			byte[] byteDataBuffer = Encoding.ASCII.GetBytes(dataBuffer);
            // Call FT_Write
            FT_STATUS ftStatus = FT_Write(ftHandle, byteDataBuffer, numBytesToWrite, ref numBytesWritten);

            return ftStatus;
        }

        //**************************************************************************
        // ResetDevice
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reset an open FTDI device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_ResetDevice in ftd2xx.DLL</returns>
        public FT_STATUS ResetDevice()
        {
            // Call FT_ResetDevice
            FT_STATUS ftStatus = FT_ResetDevice(ftHandle);

            return ftStatus;
        }

        //**************************************************************************
        // Purge
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Purge data from the devices transmit and/or receive buffers.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Purge in ftd2xx.DLL</returns>
        /// <param name="purgemask">Specifies which buffer(s) to be purged.  Valid values are any combination of the following flags: FT_PURGE_RX, FT_PURGE_TX</param>
        public FT_STATUS Purge(UInt32 purgemask)
        {
            // Call FT_Purge
            FT_STATUS ftStatus = FT_Purge(ftHandle, purgemask);

            return ftStatus;
        }

        //**************************************************************************
        // SetEventNotification
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Register for event notification.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetEventNotification in ftd2xx.DLL</returns>
        /// <remarks>After setting event notification, the event can be caught by executing the WaitOne() method of the EventWaitHandle.  If multiple event types are being monitored, the event that fired can be determined from the GetEventType method.</remarks>
        /// <param name="eventmask">The type of events to signal.  Can be any combination of the following: FT_EVENT_RXCHAR, FT_EVENT_MODEM_STATUS, FT_EVENT_LINE_STATUS</param>
        /// <param name="eventhandle">Handle to the event that will receive the notification</param>
        public FT_STATUS SetEventNotification(UInt32 eventmask, EventWaitHandle eventhandle)
        {
            // Call FT_SetSetEventNotification
            FT_STATUS ftStatus = FT_SetEventNotification(ftHandle, eventmask, eventhandle.SafeWaitHandle);

            return ftStatus;
        }

        //**************************************************************************
        // StopInTask
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Stops the driver issuing USB in requests.
        /// </summary>
        /// <returns>FT_STATUS value from FT_StopInTask in ftd2xx.DLL</returns>
        public FT_STATUS StopInTask()
        {
            // Call FT_StopInTask
            FT_STATUS ftStatus = FT_StopInTask(ftHandle);
            return ftStatus;
        }

        //**************************************************************************
        // RestartInTask
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Resumes the driver issuing USB in requests.
        /// </summary>
        /// <returns>FT_STATUS value from FT_RestartInTask in ftd2xx.DLL</returns>
        public FT_STATUS RestartInTask()
        {
            // Call FT_RestartInTask
            FT_STATUS ftStatus = FT_RestartInTask(ftHandle);
            return ftStatus;
        }

        //**************************************************************************
        // ResetPort
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Resets the device port.
        /// </summary>
        /// <returns>FT_STATUS value from FT_ResetPort in ftd2xx.DLL</returns>
        public FT_STATUS ResetPort()
        {
            // Call FT_ResetPort
           	FT_STATUS ftStatus = FT_ResetPort(ftHandle);

            return ftStatus;
        }

        //**************************************************************************
        // CyclePort
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Causes the device to be re-enumerated on the USB bus.  This is equivalent to unplugging and replugging the device.
        /// Also calls FT_Close if FT_CyclePort is successful, so no need to call this separately in the application.
        /// </summary>
        /// <returns>FT_STATUS value from FT_CyclePort in ftd2xx.DLL</returns>
        public FT_STATUS CyclePort()
        {
            // Call FT_CyclePort
            FT_STATUS ftStatus = FT_CyclePort(ftHandle);
            if (ftStatus == FT_STATUS.FT_OK)
            {
                // If successful, call FT_Close
                ftStatus = FT_Close(ftHandle);
                if (ftStatus == FT_STATUS.FT_OK)
                {
                    ftHandle = IntPtr.Zero;
                }
            }

            return ftStatus;
        }

        //**************************************************************************
        // Rescan
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Causes the system to check for USB hardware changes.  This is equivalent to clicking on the "Scan for hardware changes" button in the Device Manager.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Rescan in ftd2xx.DLL</returns>
        public FT_STATUS Rescan()
        {
            // Call FT_Rescan
            FT_STATUS ftStatus = FT_Rescan();

            return ftStatus;
        }

        //**************************************************************************
        // Reload
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Forces a reload of the driver for devices with a specific VID and PID combination.
        /// </summary>
        /// <returns>FT_STATUS value from FT_Reload in ftd2xx.DLL</returns>
        /// <remarks>If the VID and PID parameters are 0, the drivers for USB root hubs will be reloaded, causing all USB devices connected to reload their drivers</remarks>
        /// <param name="VendorID">Vendor ID of the devices to have the driver reloaded</param>
        /// <param name="ProductID">Product ID of the devices to have the driver reloaded</param>
        public FT_STATUS Reload(UInt16 VendorID, UInt16 ProductID)
        {
            // Call FT_Reload
            FT_STATUS ftStatus = FT_Reload(VendorID, ProductID);

            return ftStatus;
        }

        //**************************************************************************
        // SetBitMode
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Puts the device in a mode other than the default UART or FIFO mode.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetBitMode in ftd2xx.DLL</returns>
        /// <param name="Mask">Sets up which bits are inputs and which are outputs.  A bit value of 0 sets the corresponding pin to an input, a bit value of 1 sets the corresponding pin to an output.
        /// In the case of CBUS Bit Bang, the upper nibble of this value controls which pins are inputs and outputs, while the lower nibble controls which of the outputs are high and low.</param>
        /// <param name="BitMode"> For FT232H devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_MPSSE, FT_BIT_MODE_SYNC_BITBANG, FT_BIT_MODE_CBUS_BITBANG, FT_BIT_MODE_MCU_HOST, FT_BIT_MODE_FAST_SERIAL, FT_BIT_MODE_SYNC_FIFO.
        /// For FT2232H devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_MPSSE, FT_BIT_MODE_SYNC_BITBANG, FT_BIT_MODE_MCU_HOST, FT_BIT_MODE_FAST_SERIAL, FT_BIT_MODE_SYNC_FIFO.
        /// For FT4232H devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_MPSSE, FT_BIT_MODE_SYNC_BITBANG.
        /// For FT232R devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_SYNC_BITBANG, FT_BIT_MODE_CBUS_BITBANG.
        /// For FT245R devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_SYNC_BITBANG.
        /// For FT2232 devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG, FT_BIT_MODE_MPSSE, FT_BIT_MODE_SYNC_BITBANG, FT_BIT_MODE_MCU_HOST, FT_BIT_MODE_FAST_SERIAL.
        /// For FT232B and FT245B devices, valid values are FT_BIT_MODE_RESET, FT_BIT_MODE_ASYNC_BITBANG.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not support the requested bit mode.</exception>
        public FT_STATUS SetBitMode(byte Mask, byte BitMode)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
			
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Set Bit Mode does not apply to FT8U232AM, FT8U245AM or FT8U100AX devices
            GetDeviceType(ref DeviceType);
            if (DeviceType == FT_DEVICE.FT_DEVICE_AM)
            {
                // Throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }
            else if (DeviceType == FT_DEVICE.FT_DEVICE_100AX)
            {
                // Throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_BM) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                if ((BitMode & (FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG)) == 0)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_2232) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                if ((BitMode & (FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_MPSSE | FT_BIT_MODES.FT_BIT_MODE_SYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_MCU_HOST | FT_BIT_MODES.FT_BIT_MODE_FAST_SERIAL)) == 0)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
                if ((BitMode == FT_BIT_MODES.FT_BIT_MODE_MPSSE) & (InterfaceIdentifier != "A"))
                {
                    // MPSSE mode is only available on channel A
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_232R) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                if ((BitMode & (FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_SYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_CBUS_BITBANG)) == 0)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_2232H) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                if ((BitMode & (FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_MPSSE | FT_BIT_MODES.FT_BIT_MODE_SYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_MCU_HOST | FT_BIT_MODES.FT_BIT_MODE_FAST_SERIAL | FT_BIT_MODES.FT_BIT_MODE_SYNC_FIFO)) == 0)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
                if (((BitMode == FT_BIT_MODES.FT_BIT_MODE_MCU_HOST) | (BitMode == FT_BIT_MODES.FT_BIT_MODE_SYNC_FIFO)) & (InterfaceIdentifier != "A"))
                {
                    // MCU Host Emulation and Single channel synchronous 245 FIFO mode is only available on channel A
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_4232H) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                if ((BitMode & (FT_BIT_MODES.FT_BIT_MODE_ASYNC_BITBANG | FT_BIT_MODES.FT_BIT_MODE_MPSSE | FT_BIT_MODES.FT_BIT_MODE_SYNC_BITBANG)) == 0)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
                if ((BitMode == FT_BIT_MODES.FT_BIT_MODE_MPSSE) & ((InterfaceIdentifier != "A") & (InterfaceIdentifier != "B")))
                {
                    // MPSSE mode is only available on channel A and B
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }
            else if ((DeviceType == FT_DEVICE.FT_DEVICE_232H) && (BitMode != FT_BIT_MODES.FT_BIT_MODE_RESET))
            {
                // FT232H supports all current bit modes!
                if (BitMode > FT_BIT_MODES.FT_BIT_MODE_SYNC_FIFO)
                {
                    // Throw an exception
                    FT_ERROR ftErrorCondition = FT_ERROR.FT_INVALID_BITMODE;
                    ErrorHandler(ftStatus, ftErrorCondition);
                }
            }

            // Requested bit mode is supported
            // Note FT_BIT_MODES.FT_BIT_MODE_RESET falls through to here - no bits set so cannot check for AND
            // Call FT_SetBitMode
            ftStatus = FT_SetBitMode(ftHandle, Mask, BitMode);

            return ftStatus;
        }

        //**************************************************************************
        // GetPinStates
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the instantaneous state of the device IO pins.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetBitMode in ftd2xx.DLL</returns>
        /// <param name="BitMode">A bitmap value containing the instantaneous state of the device IO pins</param>
        public FT_STATUS GetPinStates(ref byte BitMode)
        {
            // Call FT_GetBitMode
             FT_STATUS ftStatus = FT_GetBitMode(ftHandle, ref BitMode);

            return ftStatus;
        }

        //**************************************************************************
        // ReadEEPROMLocation
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads an individual word value from a specified location in the device's EEPROM.
        /// </summary>
        /// <returns>FT_STATUS value from FT_ReadEE in ftd2xx.DLL</returns>
        /// <param name="Address">The EEPROM location to read data from</param>
        /// <param name="EEValue">The WORD value read from the EEPROM location specified in the Address paramter</param>
        public FT_STATUS ReadEEPROMLocation(UInt32 Address, ref UInt16 EEValue)
        {
            // Call FT_ReadEE
             FT_STATUS ftStatus = FT_ReadEE(ftHandle, Address, ref EEValue);

            return ftStatus;
        }

        //**************************************************************************
        // WriteEEPROMLocation
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes an individual word value to a specified location in the device's EEPROM.
        /// </summary>
        /// <returns>FT_STATUS value from FT_WriteEE in ftd2xx.DLL</returns>
        /// <param name="Address">The EEPROM location to read data from</param>
        /// <param name="EEValue">The WORD value to write to the EEPROM location specified by the Address parameter</param>
        public FT_STATUS WriteEEPROMLocation(UInt32 Address, UInt16 EEValue)
        {
            // Call FT_WriteEE
             FT_STATUS ftStatus = FT_WriteEE(ftHandle, Address, EEValue);

            return ftStatus;
        }

        //**************************************************************************
        // EraseEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Erases the device EEPROM.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EraseEE in ftd2xx.DLL</returns>
        /// <exception cref="FT_EXCEPTION">Thrown when attempting to erase the EEPROM of a device with an internal EEPROM such as an FT232R or FT245R.</exception>
        public FT_STATUS EraseEEPROM()
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
			
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is not an FT232R or FT245R that we are trying to erase
            GetDeviceType(ref DeviceType);
            if (DeviceType == FT_DEVICE.FT_DEVICE_232R)
            {
                // If it is a device with an internal EEPROM, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Call FT_EraseEE
            ftStatus = FT_EraseEE(ftHandle);

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT232BEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT232B or FT245B device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Read in ftd2xx DLL</returns>
        /// <param name="ee232b">An FT232B_EEPROM_STRUCTURE which contains only the relevant information for an FT232B and FT245B device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT232BEEPROM(FT232B_EEPROM_STRUCTURE ee232b)
        {
			FT_STATUS  ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
			
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232B or FT245B that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_BM)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee232b.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee232b.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee232b.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee232b.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee232b.VendorID = eedata.VendorID;
            ee232b.ProductID = eedata.ProductID;
            ee232b.MaxPower = eedata.MaxPower;
            ee232b.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee232b.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // B specific fields
            ee232b.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnable);
            ee232b.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnable);
            ee232b.USBVersionEnable = Convert.ToBoolean(eedata.USBVersionEnable);
            ee232b.USBVersion = eedata.USBVersion;

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT2232EEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT2232 device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Read in ftd2xx DLL</returns>
        /// <param name="ee2232">An FT2232_EEPROM_STRUCTURE which contains only the relevant information for an FT2232 device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT2232EEPROM(FT2232_EEPROM_STRUCTURE ee2232)
        {
			FT_STATUS  ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
			
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT2232 that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_2232)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee2232.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee2232.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee2232.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee2232.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee2232.VendorID = eedata.VendorID;
            ee2232.ProductID = eedata.ProductID;
            ee2232.MaxPower = eedata.MaxPower;
            ee2232.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee2232.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // 2232 specific fields
            ee2232.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnable5);
            ee2232.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnable5);
            ee2232.USBVersionEnable = Convert.ToBoolean(eedata.USBVersionEnable5);
            ee2232.USBVersion = eedata.USBVersion5;
            ee2232.AIsHighCurrent = Convert.ToBoolean(eedata.AIsHighCurrent);
            ee2232.BIsHighCurrent = Convert.ToBoolean(eedata.BIsHighCurrent);
            ee2232.IFAIsFifo = Convert.ToBoolean(eedata.IFAIsFifo);
            ee2232.IFAIsFifoTar = Convert.ToBoolean(eedata.IFAIsFifoTar);
            ee2232.IFAIsFastSer = Convert.ToBoolean(eedata.IFAIsFastSer);
            ee2232.AIsVCP = Convert.ToBoolean(eedata.AIsVCP);
            ee2232.IFBIsFifo = Convert.ToBoolean(eedata.IFBIsFifo);
            ee2232.IFBIsFifoTar = Convert.ToBoolean(eedata.IFBIsFifoTar);
            ee2232.IFBIsFastSer = Convert.ToBoolean(eedata.IFBIsFastSer);
            ee2232.BIsVCP = Convert.ToBoolean(eedata.BIsVCP);

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT232REEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT232R or FT245R device.
        /// Calls FT_EE_Read in ftd2xx DLL
        /// </summary>
        /// <returns>An FT232R_EEPROM_STRUCTURE which contains only the relevant information for an FT232R and FT245R device.</returns>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT232REEPROM(FT232R_EEPROM_STRUCTURE ee232r)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232R or FT245R that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_232R)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee232r.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee232r.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee232r.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee232r.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee232r.VendorID = eedata.VendorID;
            ee232r.ProductID = eedata.ProductID;
            ee232r.MaxPower = eedata.MaxPower;
            ee232r.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee232r.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // 232R specific fields
            ee232r.UseExtOsc = Convert.ToBoolean(eedata.UseExtOsc);
            ee232r.HighDriveIOs = Convert.ToBoolean(eedata.HighDriveIOs);
            ee232r.EndpointSize = eedata.EndpointSize;
            ee232r.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnableR);
            ee232r.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnableR);
            ee232r.InvertTXD = Convert.ToBoolean(eedata.InvertTXD);
            ee232r.InvertRXD = Convert.ToBoolean(eedata.InvertRXD);
            ee232r.InvertRTS = Convert.ToBoolean(eedata.InvertRTS);
            ee232r.InvertCTS = Convert.ToBoolean(eedata.InvertCTS);
            ee232r.InvertDTR = Convert.ToBoolean(eedata.InvertDTR);
            ee232r.InvertDSR = Convert.ToBoolean(eedata.InvertDSR);
            ee232r.InvertDCD = Convert.ToBoolean(eedata.InvertDCD);
            ee232r.InvertRI = Convert.ToBoolean(eedata.InvertRI);
            ee232r.Cbus0 = eedata.Cbus0;
            ee232r.Cbus1 = eedata.Cbus1;
            ee232r.Cbus2 = eedata.Cbus2;
            ee232r.Cbus3 = eedata.Cbus3;
            ee232r.Cbus4 = eedata.Cbus4;
            ee232r.RIsD2XX = Convert.ToBoolean(eedata.RIsD2XX);

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT2232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT2232H device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Read in ftd2xx DLL</returns>
        /// <param name="ee2232h">An FT2232H_EEPROM_STRUCTURE which contains only the relevant information for an FT2232H device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT2232HEEPROM(FT2232H_EEPROM_STRUCTURE ee2232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT2232H that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_2232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 3;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee2232h.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee2232h.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee2232h.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee2232h.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee2232h.VendorID = eedata.VendorID;
            ee2232h.ProductID = eedata.ProductID;
            ee2232h.MaxPower = eedata.MaxPower;
            ee2232h.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee2232h.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // 2232H specific fields
            ee2232h.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnable7);
            ee2232h.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnable7);
            ee2232h.ALSlowSlew = Convert.ToBoolean(eedata.ALSlowSlew);
            ee2232h.ALSchmittInput = Convert.ToBoolean(eedata.ALSchmittInput);
            ee2232h.ALDriveCurrent = eedata.ALDriveCurrent;
            ee2232h.AHSlowSlew = Convert.ToBoolean(eedata.AHSlowSlew);
            ee2232h.AHSchmittInput = Convert.ToBoolean(eedata.AHSchmittInput);
            ee2232h.AHDriveCurrent = eedata.AHDriveCurrent;
            ee2232h.BLSlowSlew = Convert.ToBoolean(eedata.BLSlowSlew);
            ee2232h.BLSchmittInput = Convert.ToBoolean(eedata.BLSchmittInput);
            ee2232h.BLDriveCurrent = eedata.BLDriveCurrent;
            ee2232h.BHSlowSlew = Convert.ToBoolean(eedata.BHSlowSlew);
            ee2232h.BHSchmittInput = Convert.ToBoolean(eedata.BHSchmittInput);
            ee2232h.BHDriveCurrent = eedata.BHDriveCurrent;
            ee2232h.IFAIsFifo = Convert.ToBoolean(eedata.IFAIsFifo7);
            ee2232h.IFAIsFifoTar = Convert.ToBoolean(eedata.IFAIsFifoTar7);
            ee2232h.IFAIsFastSer = Convert.ToBoolean(eedata.IFAIsFastSer7);
            ee2232h.AIsVCP = Convert.ToBoolean(eedata.AIsVCP7);
            ee2232h.IFBIsFifo = Convert.ToBoolean(eedata.IFBIsFifo7);
            ee2232h.IFBIsFifoTar = Convert.ToBoolean(eedata.IFBIsFifoTar7);
            ee2232h.IFBIsFastSer = Convert.ToBoolean(eedata.IFBIsFastSer7);
            ee2232h.BIsVCP = Convert.ToBoolean(eedata.BIsVCP7);
            ee2232h.PowerSaveEnable = Convert.ToBoolean(eedata.PowerSaveEnable);

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT4232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT4232H device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Read in ftd2xx DLL</returns>
        /// <param name="ee4232h">An FT4232H_EEPROM_STRUCTURE which contains only the relevant information for an FT4232H device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT4232HEEPROM(FT4232H_EEPROM_STRUCTURE ee4232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT4232H that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_4232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 4;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee4232h.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee4232h.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee4232h.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee4232h.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee4232h.VendorID = eedata.VendorID;
            ee4232h.ProductID = eedata.ProductID;
            ee4232h.MaxPower = eedata.MaxPower;
            ee4232h.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee4232h.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // 4232H specific fields
            ee4232h.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnable8);
            ee4232h.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnable8);
            ee4232h.ASlowSlew = Convert.ToBoolean(eedata.ASlowSlew);
            ee4232h.ASchmittInput = Convert.ToBoolean(eedata.ASchmittInput);
            ee4232h.ADriveCurrent = eedata.ADriveCurrent;
            ee4232h.BSlowSlew = Convert.ToBoolean(eedata.BSlowSlew);
            ee4232h.BSchmittInput = Convert.ToBoolean(eedata.BSchmittInput);
            ee4232h.BDriveCurrent = eedata.BDriveCurrent;
            ee4232h.CSlowSlew = Convert.ToBoolean(eedata.CSlowSlew);
            ee4232h.CSchmittInput = Convert.ToBoolean(eedata.CSchmittInput);
            ee4232h.CDriveCurrent = eedata.CDriveCurrent;
            ee4232h.DSlowSlew = Convert.ToBoolean(eedata.DSlowSlew);
            ee4232h.DSchmittInput = Convert.ToBoolean(eedata.DSchmittInput);
            ee4232h.DDriveCurrent = eedata.DDriveCurrent;
            ee4232h.ARIIsTXDEN = Convert.ToBoolean(eedata.ARIIsTXDEN);
            ee4232h.BRIIsTXDEN = Convert.ToBoolean(eedata.BRIIsTXDEN);
            ee4232h.CRIIsTXDEN = Convert.ToBoolean(eedata.CRIIsTXDEN);
            ee4232h.DRIIsTXDEN = Convert.ToBoolean(eedata.DRIIsTXDEN);
            ee4232h.AIsVCP = Convert.ToBoolean(eedata.AIsVCP8);
            ee4232h.BIsVCP = Convert.ToBoolean(eedata.BIsVCP8);
            ee4232h.CIsVCP = Convert.ToBoolean(eedata.CIsVCP8);
            ee4232h.DIsVCP = Convert.ToBoolean(eedata.DIsVCP8);

            return ftStatus;
        }

        //**************************************************************************
        // ReadFT232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an FT232H device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Read in ftd2xx DLL</returns>
        /// <param name="ee232h">An FT232H_EEPROM_STRUCTURE which contains only the relevant information for an FT232H device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadFT232HEEPROM(FT232H_EEPROM_STRUCTURE ee232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232H that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 5;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Call FT_EE_Read
            ftStatus = FT_EE_Read(ftHandle, eedata);

            // Retrieve string values
            ee232h.Manufacturer = Marshal.PtrToStringAnsi(eedata.Manufacturer);
            ee232h.ManufacturerID = Marshal.PtrToStringAnsi(eedata.ManufacturerID);
            ee232h.Description = Marshal.PtrToStringAnsi(eedata.Description);
            ee232h.SerialNumber = Marshal.PtrToStringAnsi(eedata.SerialNumber);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            ee232h.VendorID = eedata.VendorID;
            ee232h.ProductID = eedata.ProductID;
            ee232h.MaxPower = eedata.MaxPower;
            ee232h.SelfPowered = Convert.ToBoolean(eedata.SelfPowered);
            ee232h.RemoteWakeup = Convert.ToBoolean(eedata.RemoteWakeup);
            // 232H specific fields
            ee232h.PullDownEnable = Convert.ToBoolean(eedata.PullDownEnableH);
            ee232h.SerNumEnable = Convert.ToBoolean(eedata.SerNumEnableH);
            ee232h.ACSlowSlew = Convert.ToBoolean(eedata.ACSlowSlewH);
            ee232h.ACSchmittInput = Convert.ToBoolean(eedata.ACSchmittInputH);
            ee232h.ACDriveCurrent = eedata.ACDriveCurrentH;
            ee232h.ADSlowSlew = Convert.ToBoolean(eedata.ADSlowSlewH);
            ee232h.ADSchmittInput = Convert.ToBoolean(eedata.ADSchmittInputH);
            ee232h.ADDriveCurrent = eedata.ADDriveCurrentH;
            ee232h.Cbus0 = eedata.Cbus0H;
            ee232h.Cbus1 = eedata.Cbus1H;
            ee232h.Cbus2 = eedata.Cbus2H;
            ee232h.Cbus3 = eedata.Cbus3H;
            ee232h.Cbus4 = eedata.Cbus4H;
            ee232h.Cbus5 = eedata.Cbus5H;
            ee232h.Cbus6 = eedata.Cbus6H;
            ee232h.Cbus7 = eedata.Cbus7H;
            ee232h.Cbus8 = eedata.Cbus8H;
            ee232h.Cbus9 = eedata.Cbus9H;
            ee232h.IsFifo = Convert.ToBoolean(eedata.IsFifoH);
            ee232h.IsFifoTar = Convert.ToBoolean(eedata.IsFifoTarH);
            ee232h.IsFastSer = Convert.ToBoolean(eedata.IsFastSerH);
            ee232h.IsFT1248 = Convert.ToBoolean(eedata.IsFT1248H);
            ee232h.FT1248Cpol = Convert.ToBoolean(eedata.FT1248CpolH);
            ee232h.FT1248Lsb = Convert.ToBoolean(eedata.FT1248LsbH);
            ee232h.FT1248FlowControl = Convert.ToBoolean(eedata.FT1248FlowControlH);
            ee232h.IsVCP = Convert.ToBoolean(eedata.IsVCPH);
            ee232h.PowerSaveEnable = Convert.ToBoolean(eedata.PowerSaveEnableH);

            return ftStatus;
        }

        //**************************************************************************
        // ReadXSeriesEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads the EEPROM contents of an X-Series device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EEPROM_Read in ftd2xx DLL</returns>
        /// <param name="eeX">An FT_XSERIES_EEPROM_STRUCTURE which contains only the relevant information for an X-Series device.</param>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS ReadXSeriesEEPROM(FT_XSERIES_EEPROM_STRUCTURE eeX)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232H that we are trying to read
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_X_SERIES)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            FT_XSERIES_DATA eeData = new FT_XSERIES_DATA();
            FT_EEPROM_HEADER eeHeader = new FT_EEPROM_HEADER();

            byte[] manufacturer = new byte[32];
            byte[] manufacturerID = new byte[16];
            byte[] description = new byte[64];
            byte[] serialNumber = new byte[16];

            eeHeader.deviceType = (uint)FT_DEVICE.FT_DEVICE_X_SERIES;
            eeData.common = eeHeader;

            // Calculate the size of our data structure...
            int size = Marshal.SizeOf(eeData);

            // Allocate space for our pointer...
            IntPtr eeDataMarshal = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(eeData, eeDataMarshal, false);

            // Call FT_EEPROM_Read
            ftStatus = FT_EEPROM_Read(ftHandle, eeDataMarshal, (uint)size, manufacturer, manufacturerID, description, serialNumber);

            if (ftStatus == FT_STATUS.FT_OK)
            {
                // Get the data back from the pointer...
                eeData = (FT_XSERIES_DATA)Marshal.PtrToStructure(eeDataMarshal, typeof(FT_XSERIES_DATA));

                // Retrieve string values
                System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
                eeX.Manufacturer = enc.GetString(manufacturer);
                eeX.ManufacturerID = enc.GetString(manufacturerID);
                eeX.Description = enc.GetString(description);
                eeX.SerialNumber = enc.GetString(serialNumber);
                // Map non-string elements to structure to be returned
                // Standard elements
                eeX.VendorID = eeData.common.VendorId;
                eeX.ProductID = eeData.common.ProductId;
                eeX.MaxPower = eeData.common.MaxPower;
                eeX.SelfPowered = Convert.ToBoolean(eeData.common.SelfPowered);
                eeX.RemoteWakeup = Convert.ToBoolean(eeData.common.RemoteWakeup);
                eeX.SerNumEnable = Convert.ToBoolean(eeData.common.SerNumEnable);
                eeX.PullDownEnable = Convert.ToBoolean(eeData.common.PullDownEnable);
                // X-Series specific fields
                // CBUS
                eeX.Cbus0 = eeData.Cbus0;
                eeX.Cbus1 = eeData.Cbus1;
                eeX.Cbus2 = eeData.Cbus2;
                eeX.Cbus3 = eeData.Cbus3;
                eeX.Cbus4 = eeData.Cbus4;
                eeX.Cbus5 = eeData.Cbus5;
                eeX.Cbus6 = eeData.Cbus6;
                // Drive Options
                eeX.ACDriveCurrent = eeData.ACDriveCurrent;
                eeX.ACSchmittInput = eeData.ACSchmittInput;
                eeX.ACSlowSlew = eeData.ACSlowSlew;
                eeX.ADDriveCurrent = eeData.ADDriveCurrent;
                eeX.ADSchmittInput = eeData.ADSchmittInput;
                eeX.ADSlowSlew = eeData.ADSlowSlew;
                // BCD
                eeX.BCDDisableSleep = eeData.BCDDisableSleep;
                eeX.BCDEnable = eeData.BCDEnable;
                eeX.BCDForceCbusPWREN = eeData.BCDForceCbusPWREN;
                // FT1248
                eeX.FT1248Cpol = eeData.FT1248Cpol;
                eeX.FT1248FlowControl = eeData.FT1248FlowControl;
                eeX.FT1248Lsb = eeData.FT1248Lsb;
                // I2C
                eeX.I2CDeviceId = eeData.I2CDeviceId;
                eeX.I2CDisableSchmitt = eeData.I2CDisableSchmitt;
                eeX.I2CSlaveAddress = eeData.I2CSlaveAddress;
                // RS232 Signals
                eeX.InvertCTS = eeData.InvertCTS;
                eeX.InvertDCD = eeData.InvertDCD;
                eeX.InvertDSR = eeData.InvertDSR;
                eeX.InvertDTR = eeData.InvertDTR;
                eeX.InvertRI = eeData.InvertRI;
                eeX.InvertRTS = eeData.InvertRTS;
                eeX.InvertRXD = eeData.InvertRXD;
                eeX.InvertTXD = eeData.InvertTXD;
                // Hardware Options
                eeX.PowerSaveEnable = eeData.PowerSaveEnable;
                eeX.RS485EchoSuppress = eeData.RS485EchoSuppress;
                // Driver Option
                eeX.IsVCP = eeData.DriverType;
            }

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT232BEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT232B or FT245B device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee232b">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT232BEEPROM(FT232B_EEPROM_STRUCTURE ee232b)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232B or FT245B that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_BM)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee232b.VendorID == 0x0000) | (ee232b.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee232b.Manufacturer.Length > 32)
                ee232b.Manufacturer = ee232b.Manufacturer.Substring(0, 32);
            if (ee232b.ManufacturerID.Length > 16)
                ee232b.ManufacturerID = ee232b.ManufacturerID.Substring(0, 16);
            if (ee232b.Description.Length > 64)
                ee232b.Description = ee232b.Description.Substring(0, 64);
            if (ee232b.SerialNumber.Length > 16)
                ee232b.SerialNumber = ee232b.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee232b.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee232b.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee232b.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee232b.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee232b.VendorID;
            eedata.ProductID = ee232b.ProductID;
            eedata.MaxPower = ee232b.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee232b.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee232b.RemoteWakeup);
            // B specific fields
            eedata.Rev4 = Convert.ToByte(true);
            eedata.PullDownEnable = Convert.ToByte(ee232b.PullDownEnable);
            eedata.SerNumEnable = Convert.ToByte(ee232b.SerNumEnable);
            eedata.USBVersionEnable = Convert.ToByte(ee232b.USBVersionEnable);
            eedata.USBVersion = ee232b.USBVersion;

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT2232EEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT2232 device.
        /// Calls FT_EE_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee2232">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT2232EEPROM(FT2232_EEPROM_STRUCTURE ee2232)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT2232 that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_2232)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee2232.VendorID == 0x0000) | (ee2232.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee2232.Manufacturer.Length > 32)
                ee2232.Manufacturer = ee2232.Manufacturer.Substring(0, 32);
            if (ee2232.ManufacturerID.Length > 16)
                ee2232.ManufacturerID = ee2232.ManufacturerID.Substring(0, 16);
            if (ee2232.Description.Length > 64)
                ee2232.Description = ee2232.Description.Substring(0, 64);
            if (ee2232.SerialNumber.Length > 16)
                ee2232.SerialNumber = ee2232.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee2232.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee2232.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee2232.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee2232.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee2232.VendorID;
            eedata.ProductID = ee2232.ProductID;
            eedata.MaxPower = ee2232.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee2232.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee2232.RemoteWakeup);
            // 2232 specific fields
            eedata.Rev5 = Convert.ToByte(true);
            eedata.PullDownEnable5 = Convert.ToByte(ee2232.PullDownEnable);
            eedata.SerNumEnable5 = Convert.ToByte(ee2232.SerNumEnable);
            eedata.USBVersionEnable5 = Convert.ToByte(ee2232.USBVersionEnable);
            eedata.USBVersion5 = ee2232.USBVersion;
            eedata.AIsHighCurrent = Convert.ToByte(ee2232.AIsHighCurrent);
            eedata.BIsHighCurrent = Convert.ToByte(ee2232.BIsHighCurrent);
            eedata.IFAIsFifo = Convert.ToByte(ee2232.IFAIsFifo);
            eedata.IFAIsFifoTar = Convert.ToByte(ee2232.IFAIsFifoTar);
            eedata.IFAIsFastSer = Convert.ToByte(ee2232.IFAIsFastSer);
            eedata.AIsVCP = Convert.ToByte(ee2232.AIsVCP);
            eedata.IFBIsFifo = Convert.ToByte(ee2232.IFBIsFifo);
            eedata.IFBIsFifoTar = Convert.ToByte(ee2232.IFBIsFifoTar);
            eedata.IFBIsFastSer = Convert.ToByte(ee2232.IFBIsFastSer);
            eedata.BIsVCP = Convert.ToByte(ee2232.BIsVCP);

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT232REEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT232R or FT245R device.
        /// Calls FT_EE_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee232r">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT232REEPROM(FT232R_EEPROM_STRUCTURE ee232r)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232R or FT245R that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_232R)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee232r.VendorID == 0x0000) | (ee232r.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 2;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee232r.Manufacturer.Length > 32)
                ee232r.Manufacturer = ee232r.Manufacturer.Substring(0, 32);
            if (ee232r.ManufacturerID.Length > 16)
                ee232r.ManufacturerID = ee232r.ManufacturerID.Substring(0, 16);
            if (ee232r.Description.Length > 64)
                ee232r.Description = ee232r.Description.Substring(0, 64);
            if (ee232r.SerialNumber.Length > 16)
                ee232r.SerialNumber = ee232r.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee232r.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee232r.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee232r.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee232r.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee232r.VendorID;
            eedata.ProductID = ee232r.ProductID;
            eedata.MaxPower = ee232r.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee232r.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee232r.RemoteWakeup);
            // 232R specific fields
            eedata.PullDownEnableR = Convert.ToByte(ee232r.PullDownEnable);
            eedata.SerNumEnableR = Convert.ToByte(ee232r.SerNumEnable);
            eedata.UseExtOsc = Convert.ToByte(ee232r.UseExtOsc);
            eedata.HighDriveIOs = Convert.ToByte(ee232r.HighDriveIOs);
            // Override any endpoint size the user has selected and force 64 bytes
            // Some users have been known to wreck devices by setting 0 here...
            eedata.EndpointSize = 64;
            eedata.PullDownEnableR = Convert.ToByte(ee232r.PullDownEnable);
            eedata.SerNumEnableR = Convert.ToByte(ee232r.SerNumEnable);
            eedata.InvertTXD = Convert.ToByte(ee232r.InvertTXD);
            eedata.InvertRXD = Convert.ToByte(ee232r.InvertRXD);
            eedata.InvertRTS = Convert.ToByte(ee232r.InvertRTS);
            eedata.InvertCTS = Convert.ToByte(ee232r.InvertCTS);
            eedata.InvertDTR = Convert.ToByte(ee232r.InvertDTR);
            eedata.InvertDSR = Convert.ToByte(ee232r.InvertDSR);
            eedata.InvertDCD = Convert.ToByte(ee232r.InvertDCD);
            eedata.InvertRI = Convert.ToByte(ee232r.InvertRI);
            eedata.Cbus0 = ee232r.Cbus0;
            eedata.Cbus1 = ee232r.Cbus1;
            eedata.Cbus2 = ee232r.Cbus2;
            eedata.Cbus3 = ee232r.Cbus3;
            eedata.Cbus4 = ee232r.Cbus4;
            eedata.RIsD2XX = Convert.ToByte(ee232r.RIsD2XX);

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT2232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT2232H device.
        /// Calls FT_EE_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee2232h">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT2232HEEPROM(FT2232H_EEPROM_STRUCTURE ee2232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT2232H that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_2232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee2232h.VendorID == 0x0000) | (ee2232h.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 3;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee2232h.Manufacturer.Length > 32)
                ee2232h.Manufacturer = ee2232h.Manufacturer.Substring(0, 32);
            if (ee2232h.ManufacturerID.Length > 16)
                ee2232h.ManufacturerID = ee2232h.ManufacturerID.Substring(0, 16);
            if (ee2232h.Description.Length > 64)
                ee2232h.Description = ee2232h.Description.Substring(0, 64);
            if (ee2232h.SerialNumber.Length > 16)
                ee2232h.SerialNumber = ee2232h.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee2232h.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee2232h.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee2232h.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee2232h.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee2232h.VendorID;
            eedata.ProductID = ee2232h.ProductID;
            eedata.MaxPower = ee2232h.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee2232h.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee2232h.RemoteWakeup);
            // 2232H specific fields
            eedata.PullDownEnable7 = Convert.ToByte(ee2232h.PullDownEnable);
            eedata.SerNumEnable7 = Convert.ToByte(ee2232h.SerNumEnable);
            eedata.ALSlowSlew = Convert.ToByte(ee2232h.ALSlowSlew);
            eedata.ALSchmittInput = Convert.ToByte(ee2232h.ALSchmittInput);
            eedata.ALDriveCurrent = ee2232h.ALDriveCurrent;
            eedata.AHSlowSlew = Convert.ToByte(ee2232h.AHSlowSlew);
            eedata.AHSchmittInput = Convert.ToByte(ee2232h.AHSchmittInput);
            eedata.AHDriveCurrent = ee2232h.AHDriveCurrent;
            eedata.BLSlowSlew = Convert.ToByte(ee2232h.BLSlowSlew);
            eedata.BLSchmittInput = Convert.ToByte(ee2232h.BLSchmittInput);
            eedata.BLDriveCurrent = ee2232h.BLDriveCurrent;
            eedata.BHSlowSlew = Convert.ToByte(ee2232h.BHSlowSlew);
            eedata.BHSchmittInput = Convert.ToByte(ee2232h.BHSchmittInput);
            eedata.BHDriveCurrent = ee2232h.BHDriveCurrent;
            eedata.IFAIsFifo7 = Convert.ToByte(ee2232h.IFAIsFifo);
            eedata.IFAIsFifoTar7 = Convert.ToByte(ee2232h.IFAIsFifoTar);
            eedata.IFAIsFastSer7 = Convert.ToByte(ee2232h.IFAIsFastSer);
            eedata.AIsVCP7 = Convert.ToByte(ee2232h.AIsVCP);
            eedata.IFBIsFifo7 = Convert.ToByte(ee2232h.IFBIsFifo);
            eedata.IFBIsFifoTar7 = Convert.ToByte(ee2232h.IFBIsFifoTar);
            eedata.IFBIsFastSer7 = Convert.ToByte(ee2232h.IFBIsFastSer);
            eedata.BIsVCP7 = Convert.ToByte(ee2232h.BIsVCP);
            eedata.PowerSaveEnable = Convert.ToByte(ee2232h.PowerSaveEnable);

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT4232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT4232H device.
        /// Calls FT_EE_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee4232h">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT4232HEEPROM(FT4232H_EEPROM_STRUCTURE ee4232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT4232H that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_4232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee4232h.VendorID == 0x0000) | (ee4232h.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 4;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee4232h.Manufacturer.Length > 32)
                ee4232h.Manufacturer = ee4232h.Manufacturer.Substring(0, 32);
            if (ee4232h.ManufacturerID.Length > 16)
                ee4232h.ManufacturerID = ee4232h.ManufacturerID.Substring(0, 16);
            if (ee4232h.Description.Length > 64)
                ee4232h.Description = ee4232h.Description.Substring(0, 64);
            if (ee4232h.SerialNumber.Length > 16)
                ee4232h.SerialNumber = ee4232h.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee4232h.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee4232h.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee4232h.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee4232h.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee4232h.VendorID;
            eedata.ProductID = ee4232h.ProductID;
            eedata.MaxPower = ee4232h.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee4232h.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee4232h.RemoteWakeup);
            // 4232H specific fields
            eedata.PullDownEnable8 = Convert.ToByte(ee4232h.PullDownEnable);
            eedata.SerNumEnable8 = Convert.ToByte(ee4232h.SerNumEnable);
            eedata.ASlowSlew = Convert.ToByte(ee4232h.ASlowSlew);
            eedata.ASchmittInput = Convert.ToByte(ee4232h.ASchmittInput);
            eedata.ADriveCurrent = ee4232h.ADriveCurrent;
            eedata.BSlowSlew = Convert.ToByte(ee4232h.BSlowSlew);
            eedata.BSchmittInput = Convert.ToByte(ee4232h.BSchmittInput);
            eedata.BDriveCurrent = ee4232h.BDriveCurrent;
            eedata.CSlowSlew = Convert.ToByte(ee4232h.CSlowSlew);
            eedata.CSchmittInput = Convert.ToByte(ee4232h.CSchmittInput);
            eedata.CDriveCurrent = ee4232h.CDriveCurrent;
            eedata.DSlowSlew = Convert.ToByte(ee4232h.DSlowSlew);
            eedata.DSchmittInput = Convert.ToByte(ee4232h.DSchmittInput);
            eedata.DDriveCurrent = ee4232h.DDriveCurrent;
            eedata.ARIIsTXDEN = Convert.ToByte(ee4232h.ARIIsTXDEN);
            eedata.BRIIsTXDEN = Convert.ToByte(ee4232h.BRIIsTXDEN);
            eedata.CRIIsTXDEN = Convert.ToByte(ee4232h.CRIIsTXDEN);
            eedata.DRIIsTXDEN = Convert.ToByte(ee4232h.DRIIsTXDEN);
            eedata.AIsVCP8 = Convert.ToByte(ee4232h.AIsVCP);
            eedata.BIsVCP8 = Convert.ToByte(ee4232h.BIsVCP);
            eedata.CIsVCP8 = Convert.ToByte(ee4232h.CIsVCP);
            eedata.DIsVCP8 = Convert.ToByte(ee4232h.DIsVCP);

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteFT232HEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an FT232H device.
        /// Calls FT_EE_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_Program in ftd2xx DLL</returns>
        /// <param name="ee232h">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteFT232HEEPROM(FT232H_EEPROM_STRUCTURE ee232h)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232H that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_232H)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((ee232h.VendorID == 0x0000) | (ee232h.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_PROGRAM_DATA eedata = new FT_PROGRAM_DATA();

            // Set up structure headers
            eedata.Signature1 = 0x00000000;
            eedata.Signature2 = 0xFFFFFFFF;
            eedata.Version = 5;

            // Allocate space from unmanaged heap
            eedata.Manufacturer = Marshal.AllocHGlobal(32);
            eedata.ManufacturerID = Marshal.AllocHGlobal(16);
            eedata.Description = Marshal.AllocHGlobal(64);
            eedata.SerialNumber = Marshal.AllocHGlobal(16);

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (ee232h.Manufacturer.Length > 32)
                ee232h.Manufacturer = ee232h.Manufacturer.Substring(0, 32);
            if (ee232h.ManufacturerID.Length > 16)
                ee232h.ManufacturerID = ee232h.ManufacturerID.Substring(0, 16);
            if (ee232h.Description.Length > 64)
                ee232h.Description = ee232h.Description.Substring(0, 64);
            if (ee232h.SerialNumber.Length > 16)
                ee232h.SerialNumber = ee232h.SerialNumber.Substring(0, 16);

            // Set string values
            eedata.Manufacturer = Marshal.StringToHGlobalAnsi(ee232h.Manufacturer);
            eedata.ManufacturerID = Marshal.StringToHGlobalAnsi(ee232h.ManufacturerID);
            eedata.Description = Marshal.StringToHGlobalAnsi(ee232h.Description);
            eedata.SerialNumber = Marshal.StringToHGlobalAnsi(ee232h.SerialNumber);

            // Map non-string elements to structure
            // Standard elements
            eedata.VendorID = ee232h.VendorID;
            eedata.ProductID = ee232h.ProductID;
            eedata.MaxPower = ee232h.MaxPower;
            eedata.SelfPowered = Convert.ToUInt16(ee232h.SelfPowered);
            eedata.RemoteWakeup = Convert.ToUInt16(ee232h.RemoteWakeup);
            // 232H specific fields
            eedata.PullDownEnableH = Convert.ToByte(ee232h.PullDownEnable);
            eedata.SerNumEnableH = Convert.ToByte(ee232h.SerNumEnable);
            eedata.ACSlowSlewH = Convert.ToByte(ee232h.ACSlowSlew);
            eedata.ACSchmittInputH = Convert.ToByte(ee232h.ACSchmittInput);
            eedata.ACDriveCurrentH = Convert.ToByte(ee232h.ACDriveCurrent);
            eedata.ADSlowSlewH = Convert.ToByte(ee232h.ADSlowSlew);
            eedata.ADSchmittInputH = Convert.ToByte(ee232h.ADSchmittInput);
            eedata.ADDriveCurrentH = Convert.ToByte(ee232h.ADDriveCurrent);
            eedata.Cbus0H = Convert.ToByte(ee232h.Cbus0);
            eedata.Cbus1H = Convert.ToByte(ee232h.Cbus1);
            eedata.Cbus2H = Convert.ToByte(ee232h.Cbus2);
            eedata.Cbus3H = Convert.ToByte(ee232h.Cbus3);
            eedata.Cbus4H = Convert.ToByte(ee232h.Cbus4);
            eedata.Cbus5H = Convert.ToByte(ee232h.Cbus5);
            eedata.Cbus6H = Convert.ToByte(ee232h.Cbus6);
            eedata.Cbus7H = Convert.ToByte(ee232h.Cbus7);
            eedata.Cbus8H = Convert.ToByte(ee232h.Cbus8);
            eedata.Cbus9H = Convert.ToByte(ee232h.Cbus9);
            eedata.IsFifoH = Convert.ToByte(ee232h.IsFifo);
            eedata.IsFifoTarH = Convert.ToByte(ee232h.IsFifoTar);
            eedata.IsFastSerH = Convert.ToByte(ee232h.IsFastSer);
            eedata.IsFT1248H = Convert.ToByte(ee232h.IsFT1248);
            eedata.FT1248CpolH = Convert.ToByte(ee232h.FT1248Cpol);
            eedata.FT1248LsbH = Convert.ToByte(ee232h.FT1248Lsb);
            eedata.FT1248FlowControlH = Convert.ToByte(ee232h.FT1248FlowControl);
            eedata.IsVCPH = Convert.ToByte(ee232h.IsVCP);
            eedata.PowerSaveEnableH = Convert.ToByte(ee232h.PowerSaveEnable);

            // Call FT_EE_Program
            ftStatus = FT_EE_Program(ftHandle, eedata);

            // Free unmanaged buffers
            Marshal.FreeHGlobal(eedata.Manufacturer);
            Marshal.FreeHGlobal(eedata.ManufacturerID);
            Marshal.FreeHGlobal(eedata.Description);
            Marshal.FreeHGlobal(eedata.SerialNumber);

            return ftStatus;
        }

        //**************************************************************************
        // WriteXSeriesEEPROM
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes the specified values to the EEPROM of an X-Series device.
        /// Calls FT_EEPROM_Program in ftd2xx DLL
        /// </summary>
        /// <returns>FT_STATUS value from FT_EEPROM_Program in ftd2xx DLL</returns>
        /// <param name="eeX">The EEPROM settings to be written to the device</param>
        /// <remarks>If the strings are too long, they will be truncated to their maximum permitted lengths</remarks>
        /// <exception cref="FT_EXCEPTION">Thrown when the current device does not match the type required by this method.</exception>
        public FT_STATUS WriteXSeriesEEPROM(FT_XSERIES_EEPROM_STRUCTURE eeX)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Check that it is an FT232H that we are trying to write
            GetDeviceType(ref DeviceType);
            if (DeviceType != FT_DEVICE.FT_DEVICE_X_SERIES)
            {
                // If it is not, throw an exception
                FT_ERROR ftErrorCondition = FT_ERROR.FT_INCORRECT_DEVICE;
                ErrorHandler(ftStatus, ftErrorCondition);
            }

            // Check for VID and PID of 0x0000
            if ((eeX.VendorID == 0x0000) | (eeX.ProductID == 0x0000))
            {
                // Do not allow users to program the device with VID or PID of 0x0000
                return FT_STATUS.FT_INVALID_PARAMETER;
            }

            FT_XSERIES_DATA eeData = new FT_XSERIES_DATA();

            // String manipulation...
            // Allocate space from unmanaged heap
            byte[] manufacturer = new byte[32];
            byte[] manufacturerID = new byte[16];
            byte[] description = new byte[64];
            byte[] serialNumber = new byte[16];

            // Check lengths of strings to make sure that they are within our limits
            // If not, trim them to make them our maximum length
            if (eeX.Manufacturer.Length > 32)
                eeX.Manufacturer = eeX.Manufacturer.Substring(0, 32);
            if (eeX.ManufacturerID.Length > 16)
                eeX.ManufacturerID = eeX.ManufacturerID.Substring(0, 16);
            if (eeX.Description.Length > 64)
                eeX.Description = eeX.Description.Substring(0, 64);
            if (eeX.SerialNumber.Length > 16)
                eeX.SerialNumber = eeX.SerialNumber.Substring(0, 16);

            // Set string values
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            manufacturer = encoding.GetBytes(eeX.Manufacturer);
            manufacturerID = encoding.GetBytes(eeX.ManufacturerID);
            description = encoding.GetBytes(eeX.Description);
            serialNumber = encoding.GetBytes(eeX.SerialNumber);

            // Map non-string elements to structure to be returned
            // Standard elements
            eeData.common.deviceType = (uint)FT_DEVICE.FT_DEVICE_X_SERIES;
            eeData.common.VendorId = eeX.VendorID;
            eeData.common.ProductId = eeX.ProductID;
            eeData.common.MaxPower = eeX.MaxPower;
            eeData.common.SelfPowered = Convert.ToByte(eeX.SelfPowered);
            eeData.common.RemoteWakeup = Convert.ToByte(eeX.RemoteWakeup);
            eeData.common.SerNumEnable = Convert.ToByte(eeX.SerNumEnable);
            eeData.common.PullDownEnable = Convert.ToByte(eeX.PullDownEnable);
            // X-Series specific fields
            // CBUS
            eeData.Cbus0 = eeX.Cbus0;
            eeData.Cbus1 = eeX.Cbus1;
            eeData.Cbus2 = eeX.Cbus2;
            eeData.Cbus3 = eeX.Cbus3;
            eeData.Cbus4 = eeX.Cbus4;
            eeData.Cbus5 = eeX.Cbus5;
            eeData.Cbus6 = eeX.Cbus6;
            // Drive Options
            eeData.ACDriveCurrent = eeX.ACDriveCurrent;
            eeData.ACSchmittInput = eeX.ACSchmittInput;
            eeData.ACSlowSlew = eeX.ACSlowSlew;
            eeData.ADDriveCurrent = eeX.ADDriveCurrent;
            eeData.ADSchmittInput = eeX.ADSchmittInput;
            eeData.ADSlowSlew = eeX.ADSlowSlew;
            // BCD
            eeData.BCDDisableSleep = eeX.BCDDisableSleep;
            eeData.BCDEnable = eeX.BCDEnable;
            eeData.BCDForceCbusPWREN = eeX.BCDForceCbusPWREN;
            // FT1248
            eeData.FT1248Cpol = eeX.FT1248Cpol;
            eeData.FT1248FlowControl = eeX.FT1248FlowControl;
            eeData.FT1248Lsb = eeX.FT1248Lsb;
            // I2C
            eeData.I2CDeviceId = eeX.I2CDeviceId;
            eeData.I2CDisableSchmitt = eeX.I2CDisableSchmitt;
            eeData.I2CSlaveAddress = eeX.I2CSlaveAddress;
            // RS232 Signals
            eeData.InvertCTS = eeX.InvertCTS;
            eeData.InvertDCD = eeX.InvertDCD;
            eeData.InvertDSR = eeX.InvertDSR;
            eeData.InvertDTR = eeX.InvertDTR;
            eeData.InvertRI = eeX.InvertRI;
            eeData.InvertRTS = eeX.InvertRTS;
            eeData.InvertRXD = eeX.InvertRXD;
            eeData.InvertTXD = eeX.InvertTXD;
            // Hardware Options
            eeData.PowerSaveEnable = eeX.PowerSaveEnable;
            eeData.RS485EchoSuppress = eeX.RS485EchoSuppress;
            // Driver Option
            eeData.DriverType = eeX.IsVCP;

            // Check the size of the structure...
            int size = Marshal.SizeOf(eeData);
            // Allocate space for our pointer...
            IntPtr eeDataMarshal = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(eeData, eeDataMarshal, false);

            ftStatus = FT_EEPROM_Program(ftHandle, eeDataMarshal, (uint)size, manufacturer, manufacturerID, description, serialNumber);


            return FT_STATUS.FT_DEVICE_NOT_FOUND;
        }

        //**************************************************************************
        // EEReadUserArea
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Reads data from the user area of the device EEPROM.
        /// </summary>
        /// <returns>FT_STATUS from FT_UARead in ftd2xx.DLL</returns>
        /// <param name="UserAreaDataBuffer">An array of bytes which will be populated with the data read from the device EEPROM user area.</param>
        /// <param name="numBytesRead">The number of bytes actually read from the EEPROM user area.</param>
        public FT_STATUS EEReadUserArea(byte[] UserAreaDataBuffer, ref UInt32 numBytesRead)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            UInt32 UASize = 0;
            // Get size of user area to allocate an array of the correct size.
            // The application must also get the UA size for its copy
            ftStatus = FT_EE_UASize(ftHandle, ref UASize);

            // Make sure we have enough storage for the whole user area
            if (UserAreaDataBuffer.Length >= UASize)
            {
                // Call FT_EE_UARead
                ftStatus = FT_EE_UARead(ftHandle, UserAreaDataBuffer, UserAreaDataBuffer.Length, ref numBytesRead);
            }

            return ftStatus;
        }

        //**************************************************************************
        // EEWriteUserArea
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Writes data to the user area of the device EEPROM.
        /// </summary>
        /// <returns>FT_STATUS value from FT_UAWrite in ftd2xx.DLL</returns>
        /// <param name="UserAreaDataBuffer">An array of bytes which will be written to the device EEPROM user area.</param>
        public FT_STATUS EEWriteUserArea(byte[] UserAreaDataBuffer)
        {

            UInt32 UASize = 0;
            // Get size of user area to allocate an array of the correct size.
            // The application must also get the UA size for its copy
            FT_STATUS ftStatus = FT_EE_UASize(ftHandle, ref UASize);

            // Make sure we have enough storage for all the data in the EEPROM
            if (UserAreaDataBuffer.Length <= UASize)
            {
                // Call FT_EE_UAWrite
                ftStatus = FT_EE_UAWrite(ftHandle, UserAreaDataBuffer, UserAreaDataBuffer.Length);
            }

            return ftStatus;
        }

        //**************************************************************************
        // GetDeviceType
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the chip type of the current device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDeviceInfo in ftd2xx.DLL</returns>
        /// <param name="DeviceType">The FTDI chip type of the current device.</param>
        public FT_STATUS GetDeviceType(ref FT_DEVICE DeviceType)
        {

            UInt32 DeviceID = 0;
            byte[] sernum = new byte[16];
            byte[] desc = new byte[64];

            DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;

                // Call FT_GetDeviceInfo
               FT_STATUS ftStatus = FT_GetDeviceInfo(ftHandle, ref DeviceType, ref DeviceID, sernum, desc, IntPtr.Zero);
      
            return ftStatus;
        }

        //**************************************************************************
        // GetDeviceID
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the Vendor ID and Product ID of the current device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDeviceInfo in ftd2xx.DLL</returns>
        /// <param name="DeviceID">The device ID (Vendor ID and Product ID) of the current device.</param>
        public FT_STATUS GetDeviceID(ref UInt32 DeviceID)
        {

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            byte[] sernum = new byte[16];
            byte[] desc = new byte[64];

                // Call FT_GetDeviceInfo
                FT_STATUS ftStatus = FT_GetDeviceInfo(ftHandle, ref DeviceType, ref DeviceID, sernum, desc, IntPtr.Zero);
            return ftStatus;
        }

        //**************************************************************************
        // GetDescription
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the description of the current device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDeviceInfo in ftd2xx.DLL</returns>
        /// <param name="Description">The description of the current device.</param>
        public FT_STATUS GetDescription(out string Description)
        {

            UInt32 DeviceID = 0;
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            byte[] sernum = new byte[16];
            byte[] desc = new byte[64];

                // Call FT_GetDeviceInfo
                FT_STATUS ftStatus = FT_GetDeviceInfo(ftHandle, ref DeviceType, ref DeviceID, sernum, desc, IntPtr.Zero);
                Description = Encoding.ASCII.GetString(desc);
                Description = Description.Substring(0, Description.IndexOf("\0"));

            return ftStatus;
        }

        //**************************************************************************
        // GetSerialNumber
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the serial number of the current device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDeviceInfo in ftd2xx.DLL</returns>
        /// <param name="SerialNumber">The serial number of the current device.</param>
        public FT_STATUS GetSerialNumber(out string SerialNumber)
        {

            UInt32 DeviceID = 0;
            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            byte[] sernum = new byte[16];
            byte[] desc = new byte[64];
 
                // Call FT_GetDeviceInfo
                FT_STATUS ftStatus = FT_GetDeviceInfo(ftHandle, ref DeviceType, ref DeviceID, sernum, desc, IntPtr.Zero);
                SerialNumber = Encoding.ASCII.GetString(sernum);
                SerialNumber = SerialNumber.Substring(0, SerialNumber.IndexOf("\0"));
 
            return ftStatus;
        }

        //**************************************************************************
        // GetRxBytesAvailable
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the number of bytes available in the receive buffer.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetQueueStatus in ftd2xx.DLL</returns>
        /// <param name="RxQueue">The number of bytes available to be read.</param>
        public FT_STATUS GetRxBytesAvailable(ref UInt32 RxQueue)
        {
                // Call FT_GetQueueStatus
                FT_STATUS ftStatus = FT_GetQueueStatus(ftHandle, ref RxQueue);
 
            return ftStatus;
        }

        //**************************************************************************
        // GetTxBytesWaiting
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the number of bytes waiting in the transmit buffer.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetStatus in ftd2xx.DLL</returns>
        /// <param name="TxQueue">The number of bytes waiting to be sent.</param>
        public FT_STATUS GetTxBytesWaiting(ref UInt32 TxQueue)
        {

            UInt32 RxQueue = 0;
            UInt32 EventStatus = 0;

                // Call FT_GetStatus
                FT_STATUS ftStatus = FT_GetStatus(ftHandle, ref RxQueue, ref TxQueue, ref EventStatus);

            return ftStatus;
        }

        //**************************************************************************
        // GetEventType
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the event type after an event has fired.  Can be used to distinguish which event has been triggered when waiting on multiple event types.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetStatus in ftd2xx.DLL</returns>
        /// <param name="EventType">The type of event that has occurred.</param>
        public FT_STATUS GetEventType(ref UInt32 EventType)
        {

            UInt32 RxQueue = 0;
            UInt32 TxQueue = 0;

                // Call FT_GetStatus
			FT_STATUS ftStatus = FT_GetStatus(ftHandle, ref RxQueue, ref TxQueue, ref EventType);
  
            return ftStatus;
        }

        //**************************************************************************
        // GetModemStatus
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the current modem status.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetModemStatus in ftd2xx.DLL</returns>
        /// <param name="ModemStatus">A bit map representaion of the current modem status.</param>
        public FT_STATUS GetModemStatus(ref byte ModemStatus)
        {

            UInt32 ModemLineStatus = 0;

                // Call FT_GetModemStatus
FT_STATUS ftStatus = FT_GetModemStatus(ftHandle, ref ModemLineStatus);

            ModemStatus = Convert.ToByte(ModemLineStatus & 0x000000FF);

            return ftStatus;
        }

        //**************************************************************************
        // GetLineStatus
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the current line status.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetModemStatus in ftd2xx.DLL</returns>
        /// <param name="LineStatus">A bit map representaion of the current line status.</param>
        public FT_STATUS GetLineStatus(ref byte LineStatus)
        {
            UInt32 ModemLineStatus = 0;
               // Call FT_GetModemStatus
               FT_STATUS ftStatus = FT_GetModemStatus(ftHandle, ref ModemLineStatus);
            LineStatus = Convert.ToByte((ModemLineStatus >> 8) & 0x000000FF);

            return ftStatus;
        }

        //**************************************************************************
        // SetBaudRate
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the current Baud rate.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetBaudRate in ftd2xx.DLL</returns>
        /// <param name="BaudRate">The desired Baud rate for the device.</param>
        public FT_STATUS SetBaudRate(UInt32 BaudRate)
        {

            // Call FT_SetBaudRate
            FT_STATUS ftStatus = FT_SetBaudRate(ftHandle, BaudRate);

            return ftStatus;
        }

        //**************************************************************************
        // SetDataCharacteristics
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the data bits, stop bits and parity for the device.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetDataCharacteristics in ftd2xx.DLL</returns>
        /// <param name="DataBits">The number of data bits for UART data.  Valid values are FT_DATA_BITS.FT_DATA_7 or FT_DATA_BITS.FT_BITS_8</param>
        /// <param name="StopBits">The number of stop bits for UART data.  Valid values are FT_STOP_BITS.FT_STOP_BITS_1 or FT_STOP_BITS.FT_STOP_BITS_2</param>
        /// <param name="Parity">The parity of the UART data.  Valid values are FT_PARITY.FT_PARITY_NONE, FT_PARITY.FT_PARITY_ODD, FT_PARITY.FT_PARITY_EVEN, FT_PARITY.FT_PARITY_MARK or FT_PARITY.FT_PARITY_SPACE</param>
        public FT_STATUS SetDataCharacteristics(byte DataBits, byte StopBits, byte Parity)
        {

            // Call FT_SetDataCharacteristics
            FT_STATUS ftStatus = FT_SetDataCharacteristics(ftHandle, DataBits, StopBits, Parity);

            return ftStatus;
        }

        //**************************************************************************
        // SetFlowControl
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the flow control type.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetFlowControl in ftd2xx.DLL</returns>
        /// <param name="FlowControl">The type of flow control for the UART.  Valid values are FT_FLOW_CONTROL.FT_FLOW_NONE, FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, FT_FLOW_CONTROL.FT_FLOW_DTR_DSR or FT_FLOW_CONTROL.FT_FLOW_XON_XOFF</param>
        /// <param name="Xon">The Xon character for Xon/Xoff flow control.  Ignored if not using Xon/XOff flow control.</param>
        /// <param name="Xoff">The Xoff character for Xon/Xoff flow control.  Ignored if not using Xon/XOff flow control.</param>
        public FT_STATUS SetFlowControl(UInt16 FlowControl, byte Xon, byte Xoff)
        {

            // Call FT_SetFlowControl
            FT_STATUS ftStatus = FT_SetFlowControl(ftHandle, FlowControl, Xon, Xoff);

            return ftStatus;
        }

        //**************************************************************************
        // SetRTS
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Asserts or de-asserts the Request To Send (RTS) line.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetRts or FT_ClrRts in ftd2xx.DLL</returns>
        /// <param name="Enable">If true, asserts RTS.  If false, de-asserts RTS</param>
        public FT_STATUS SetRTS(bool Enable)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
            if (Enable)
            {
                // Call FT_SetRts
                ftStatus = FT_SetRts(ftHandle);
            }
            else
            {
                // Call FT_ClrRts
                ftStatus = FT_ClrRts(ftHandle);
            }

            return ftStatus;
        }

        //**************************************************************************
        // SetDTR
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Asserts or de-asserts the Data Terminal Ready (DTR) line.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetDtr or FT_ClrDtr in ftd2xx.DLL</returns>
        /// <param name="Enable">If true, asserts DTR.  If false, de-asserts DTR.</param>
        public FT_STATUS SetDTR(bool Enable)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            if (Enable)
            {
                // Call FT_SetDtr
                ftStatus = FT_SetDtr(ftHandle);
            }
            else
            {
                // Call FT_ClrDtr
                ftStatus = FT_ClrDtr(ftHandle);
            }

            return ftStatus;
        }

        //**************************************************************************
        // SetTimeouts
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the read and write timeout values.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetTimeouts in ftd2xx.DLL</returns>
        /// <param name="ReadTimeout">Read timeout value in ms.  A value of 0 indicates an infinite timeout.</param>
        /// <param name="WriteTimeout">Write timeout value in ms.  A value of 0 indicates an infinite timeout.</param>
        public FT_STATUS SetTimeouts(UInt32 ReadTimeout, UInt32 WriteTimeout)
        {

            // Call FT_SetTimeouts
            FT_STATUS ftStatus = FT_SetTimeouts(ftHandle, ReadTimeout, WriteTimeout);

            return ftStatus;
        }

        //**************************************************************************
        // SetBreak
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets or clears the break state.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetBreakOn or FT_SetBreakOff in ftd2xx.DLL</returns>
        /// <param name="Enable">If true, sets break on.  If false, sets break off.</param>
        public FT_STATUS SetBreak(bool Enable)
        {
			FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;

            if (Enable)
            {
                // Call FT_SetBreakOn
                ftStatus = FT_SetBreakOn(ftHandle);
            }
            else
            {
                // Call FT_SetBreakOff
                ftStatus = FT_SetBreakOff(ftHandle);
            }

            return ftStatus;
        }

        //**************************************************************************
        // SetResetPipeRetryCount
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets or sets the reset pipe retry count.  Default value is 50.
        /// </summary>
        /// <returns>FT_STATUS vlaue from FT_SetResetPipeRetryCount in ftd2xx.DLL</returns>
        /// <param name="ResetPipeRetryCount">The reset pipe retry count.  
        /// Electrically noisy environments may benefit from a larger value.</param>
        public FT_STATUS SetResetPipeRetryCount(UInt32 ResetPipeRetryCount)
        {

            // Call FT_SetResetPipeRetryCount
            FT_STATUS ftStatus = FT_SetResetPipeRetryCount(ftHandle, ResetPipeRetryCount);

            return ftStatus;
        }

        //**************************************************************************
        // GetDriverVersion
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the current FTDIBUS.SYS driver version number.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetDriverVersion in ftd2xx.DLL</returns>
        /// <param name="DriverVersion">The current driver version number.</param>
        public FT_STATUS GetDriverVersion(ref UInt32 DriverVersion)
        {
            // Call FT_GetDriverVersion
            FT_STATUS ftStatus = FT_GetDriverVersion(ftHandle, ref DriverVersion);

            return ftStatus;
        }

        //**************************************************************************
        // GetLibraryVersion
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the current ftd2xx.DLL driver version number.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetLibraryVersion in ftd2xx.DLL</returns>
        /// <param name="LibraryVersion">The current library version.</param>
        public FT_STATUS GetLibraryVersion(ref UInt32 LibraryVersion)
        {
            // Call FT_GetLibraryVersion
            FT_STATUS ftStatus = FT_GetLibraryVersion(ref LibraryVersion);

            return ftStatus;
        }

        //**************************************************************************
        // SetDeadmanTimeout
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the USB deadman timeout value.  Default is 5000ms.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetDeadmanTimeout in ftd2xx.DLL</returns>
        /// <param name="DeadmanTimeout">The deadman timeout value in ms.  Default is 5000ms.</param>
        public FT_STATUS SetDeadmanTimeout(UInt32 DeadmanTimeout)
        {

            // Call FT_SetDeadmanTimeout
            FT_STATUS ftStatus = FT_SetDeadmanTimeout(ftHandle, DeadmanTimeout);

            return ftStatus;
        }

        //**************************************************************************
        // SetLatency
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the value of the latency timer.  Default value is 16ms.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetLatencyTimer in ftd2xx.DLL</returns>
        /// <param name="Latency">The latency timer value in ms.
        /// Valid values are 2ms - 255ms for FT232BM, FT245BM and FT2232 devices.
        /// Valid values are 0ms - 255ms for other devices.</param>
        public FT_STATUS SetLatency(byte Latency)
        {

            FT_DEVICE DeviceType = FT_DEVICE.FT_DEVICE_UNKNOWN;
            // Set Bit Mode does not apply to FT8U232AM, FT8U245AM or FT8U100AX devices
            GetDeviceType(ref DeviceType);
            if ((DeviceType == FT_DEVICE.FT_DEVICE_BM) || (DeviceType == FT_DEVICE.FT_DEVICE_2232))
            {
                // Do not allow latency of 1ms or 0ms for older devices
                // since this can cause problems/lock up due to buffering mechanism
                if (Latency < 2)
                    Latency = 2;
            }

            // Call FT_SetLatencyTimer
            FT_STATUS ftStatus = FT_SetLatencyTimer(ftHandle, Latency);

            return ftStatus;
        }

        //**************************************************************************
        // GetLatency
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the value of the latency timer.  Default value is 16ms.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetLatencyTimer in ftd2xx.DLL</returns>
        /// <param name="Latency">The latency timer value in ms.</param>
        public FT_STATUS GetLatency(ref byte Latency)
        {
            // Call FT_GetLatencyTimer
            FT_STATUS ftStatus = FT_GetLatencyTimer(ftHandle, ref Latency);

            return ftStatus;
        }

        //**************************************************************************
        // SetUSBTransferSizes
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets the USB IN and OUT transfer sizes.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetUSBParameters in ftd2xx.DLL</returns>
        /// <param name="InTransferSize">The USB IN transfer size in bytes.</param>
        public FT_STATUS InTransferSize(UInt32 InTransferSize)
        // Only support IN transfer sizes at the moment
        //public UInt32 InTransferSize(UInt32 InTransferSize, UInt32 OutTransferSize)
        {
            UInt32 OutTransferSize = InTransferSize;

				// Call FT_SetUSBParameters
                FT_STATUS ftStatus = FT_SetUSBParameters(ftHandle, InTransferSize, OutTransferSize);

            return ftStatus;
        }

        //**************************************************************************
        // SetCharacters
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Sets an event character, an error character and enables or disables them.
        /// </summary>
        /// <returns>FT_STATUS value from FT_SetChars in ftd2xx.DLL</returns>
        /// <param name="EventChar">A character that will be tigger an IN to the host when this character is received.</param>
        /// <param name="EventCharEnable">Determines if the EventChar is enabled or disabled.</param>
        /// <param name="ErrorChar">A character that will be inserted into the data stream to indicate that an error has occurred.</param>
        /// <param name="ErrorCharEnable">Determines if the ErrorChar is enabled or disabled.</param>
        public FT_STATUS SetCharacters(byte EventChar, bool EventCharEnable, byte ErrorChar, bool ErrorCharEnable)
        {
            return FT_SetChars(ftHandle, EventChar, Convert.ToByte(EventCharEnable), ErrorChar, Convert.ToByte(ErrorCharEnable));
        }

        //**************************************************************************
        // GetEEUserAreaSize
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the size of the EEPROM user area.
        /// </summary>
        /// <returns>FT_STATUS value from FT_EE_UASize in ftd2xx.DLL</returns>
        /// <param name="UASize">The EEPROM user area size in bytes.</param>
        public FT_STATUS EEUserAreaSize(ref UInt32 UASize)
        {

            FT_STATUS ftStatus = FT_EE_UASize(ftHandle, ref UASize);

            return ftStatus;
        }

        //**************************************************************************
        // GetCOMPort
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the corresponding COM port number for the current device.  If no COM port is exposed, an empty string is returned.
        /// </summary>
        /// <returns>FT_STATUS value from FT_GetComPortNumber in ftd2xx.DLL</returns>
        /// <param name="ComPortName">The COM port name corresponding to the current device.  If no COM port is installed, an empty string is passed back.</param>
        public FT_STATUS GetCOMPort(out string ComPortName)
        {
            // As ComPortName is an OUT paremeter, has to be assigned before returning
            ComPortName = string.Empty;
			
			int ComPortNumber = -1;
			
            // Call FT_GetComPortNumber
            FT_STATUS ftStatus = FT_GetComPortNumber(ftHandle, ref ComPortNumber);

            if (ComPortNumber == -1)
            {
                // If no COM port installed, return an empty string
                ComPortName = string.Empty;
            }
            else
            {
                // If installed, return full COM string
                // This can then be passed to an instance of the SerialPort class to assign the port number.
                ComPortName = "COM" + ComPortNumber.ToString();
            }

            return ftStatus;
        }
        #endregion

        #region PROPERTY_DEFINITIONS
        //**************************************************************************
        // IsOpen
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the open status of the device.
        /// </summary>
        public bool IsOpen
        {
            get
            {
                if (ftHandle == IntPtr.Zero)
                    return false;
                else
                    return true;
            }
        }

        //**************************************************************************
        // InterfaceIdentifier
        //**************************************************************************
        // Intellisense comments
        /// <summary>
        /// Gets the interface identifier.
        /// </summary>
        private string InterfaceIdentifier
        {
            get
            {
                string Identifier;
                Identifier = String.Empty;
                if (IsOpen)
                {
                    FT_DEVICE deviceType = FT_DEVICE.FT_DEVICE_BM;
                    GetDeviceType(ref deviceType);
                    if ((deviceType == FT_DEVICE.FT_DEVICE_2232) | (deviceType == FT_DEVICE.FT_DEVICE_2232H) | (deviceType == FT_DEVICE.FT_DEVICE_4232H))
                    {
                        string Description;
                        GetDescription(out Description);
                        Identifier = Description.Substring((Description.Length - 1));
                        return Identifier;
                    }
                }
                return Identifier;
            }
        }
        #endregion

        #region HELPER_METHODS
        //**************************************************************************
        // ErrorHandler
        //**************************************************************************
        /// <summary>
        /// Method to check ftStatus and ftErrorCondition values for error conditions and throw exceptions accordingly.
        /// </summary>
        private void ErrorHandler(FT_STATUS ftStatus, FT_ERROR ftErrorCondition)
        {
            if (ftStatus != FT_STATUS.FT_OK)
            {
                // Check FT_STATUS values returned from ftd2xx DLL calls
                switch (ftStatus)
                {
                    case FT_STATUS.FT_DEVICE_NOT_FOUND:
                        {
                            throw new FT_EXCEPTION("FTDI device not found.");
                        }
                    case FT_STATUS.FT_DEVICE_NOT_OPENED:
                        {
                            throw new FT_EXCEPTION("FTDI device not opened.");
                        }
                    case FT_STATUS.FT_DEVICE_NOT_OPENED_FOR_ERASE:
                        {
                            throw new FT_EXCEPTION("FTDI device not opened for erase.");
                        }
                    case FT_STATUS.FT_DEVICE_NOT_OPENED_FOR_WRITE:
                        {
                            throw new FT_EXCEPTION("FTDI device not opened for write.");
                        }
                    case FT_STATUS.FT_EEPROM_ERASE_FAILED:
                        {
                            throw new FT_EXCEPTION("Failed to erase FTDI device EEPROM.");
                        }
                    case FT_STATUS.FT_EEPROM_NOT_PRESENT:
                        {
                            throw new FT_EXCEPTION("No EEPROM fitted to FTDI device.");
                        }
                    case FT_STATUS.FT_EEPROM_NOT_PROGRAMMED:
                        {
                            throw new FT_EXCEPTION("FTDI device EEPROM not programmed.");
                        }
                    case FT_STATUS.FT_EEPROM_READ_FAILED:
                        {
                            throw new FT_EXCEPTION("Failed to read FTDI device EEPROM.");
                        }
                    case FT_STATUS.FT_EEPROM_WRITE_FAILED:
                        {
                            throw new FT_EXCEPTION("Failed to write FTDI device EEPROM.");
                        }
                    case FT_STATUS.FT_FAILED_TO_WRITE_DEVICE:
                        {
                            throw new FT_EXCEPTION("Failed to write to FTDI device.");
                        }
                    case FT_STATUS.FT_INSUFFICIENT_RESOURCES:
                        {
                            throw new FT_EXCEPTION("Insufficient resources.");
                        }
                    case FT_STATUS.FT_INVALID_ARGS:
                        {
                            throw new FT_EXCEPTION("Invalid arguments for ftd2xx function call.");
                        }
                    case FT_STATUS.FT_INVALID_BAUD_RATE:
                        {
                            throw new FT_EXCEPTION("Invalid Baud rate for FTDI device.");
                        }
                    case FT_STATUS.FT_INVALID_HANDLE:
                        {
                            throw new FT_EXCEPTION("Invalid handle for FTDI device.");
                        }
                    case FT_STATUS.FT_INVALID_PARAMETER:
                        {
                            throw new FT_EXCEPTION("Invalid parameter for ftd2xx function call.");
                        }
                    case FT_STATUS.FT_IO_ERROR:
                        {
                            throw new FT_EXCEPTION("FTDI device IO error.");
                        }
                    case FT_STATUS.FT_OTHER_ERROR:
                        {
                            throw new FT_EXCEPTION("An unexpected error has occurred when trying to communicate with the FTDI device.");
                        }
                    default:
                        break;
                }
            }
            if (ftErrorCondition != FT_ERROR.FT_NO_ERROR)
            {
                // Check for other error conditions not handled by ftd2xx DLL
                switch (ftErrorCondition)
                {
                    case FT_ERROR.FT_INCORRECT_DEVICE:
                        {
                            throw new FT_EXCEPTION("The current device type does not match the EEPROM structure.");
                        }
                    case FT_ERROR.FT_INVALID_BITMODE:
                        {
                            throw new FT_EXCEPTION("The requested bit mode is not valid for the current device.");
                        }
                    case FT_ERROR.FT_BUFFER_SIZE:
                        {
                            throw new FT_EXCEPTION("The supplied buffer is not big enough.");
                        }

                    default:
                        break;
                }

            }

            return;
        }
        #endregion
    }
}
