

// A wrapper of the IO methods described in the FTDI's D2XX Programmer's Guide. Version 1.1, 03-Mar-2022.
// Copyright (C) 2022 by Benev Science & Technology Ltd. All rights reserved.



using System;
using System.Text;
using System.Runtime.InteropServices;


namespace GTR
{
    // FT_STATUS enumeration.
    public enum FT_STATUS : uint
    {
        FT_OK = 0,
        FT_INVALID_HANDLE,
        FT_DEVICE_NOT_FOUND,
        FT_DEVICE_NOT_OPENED,
        FT_IO_ERROR,
        FT_INSUFFICIENT_RESOURCES,
        FT_INVALID_PARAMETER,
        FT_INVALID_BAUD_RATE,
        FT_DEVICE_NOT_OPENED_FOR_ERASE,
        FT_DEVICE_NOT_OPENED_FOR_WRITE,
        FT_FAILED_TO_WRITE_DEVICE,
        FT_EEPROM_READ_FAILED,
        FT_EEPROM_WRITE_FAILED,
        FT_EEPROM_ERASE_FAILED,
        FT_EEPROM_NOT_PRESENT,
        FT_EEPROM_NOT_PROGRAMMED,
        FT_INVALID_ARGS,
        FT_NOT_SUPPORTED,
        FT_OTHER_ERROR
    }


    // FT_DEVICE_LIST_INFO_NODE struct.
    [StructLayout(LayoutKind.Sequential)]
    public struct FT_DEVICE_LIST_INFO_NODE
    {
        public uint Flags;
        public uint Type;
        public uint ID;
        public uint LocId;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string SerialNumber;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string Description;
        public IntPtr ftHandle;
    }


    // FTDI class.
    public class FTDI
    {
        // Flags.
        public const uint FT_LIST_NUMBER_ONLY = 0x80000000u;
        public const uint FT_LIST_BY_INDEX = 0x40000000u;
        public const uint FT_LIST_ALL = 0x20000000u;

        public const uint FT_OPEN_BY_SERIAL_NUMBER = 1u;
        public const uint FT_OPEN_BY_DESCRIPTION = 2u;
        public const uint FT_OPEN_BY_LOCATION = 4u;

        // Word Lengths.
        public const byte FT_BITS_8 = (byte)8;
        public const byte FT_BITS_7 = (byte)7;

        // Stop Bits.
        public const byte FT_STOP_BITS_1 = (byte)0;
        public const byte FT_STOP_BITS_2 = (byte)2;

        // Parity.
        public const byte FT_PARITY_NONE = (byte)0;
        public const byte FT_PARITY_ODD = (byte)1;
        public const byte FT_PARITY_EVEN = (byte)2;
        public const byte FT_PARITY_MARK = (byte)3;
        public const byte FT_PARITY_SPACE = (byte)4;

        // Flow Control.
        public const ushort FT_FLOW_NONE = (ushort)0x0000;
        public const ushort FT_FLOW_RTS_CTS = (ushort)0x0100;
        public const ushort FT_FLOW_DTR_DSR = (ushort)0x0200;
        public const ushort FT_FLOW_XON_XOFF = (ushort)0x0400;

        // Purge rx and tx buffers.
        public const uint FT_PURGE_RX = 1;
        public const uint FT_PURGE_TX = 2;


        // Classic Interface Methods.
        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_CreateDeviceInfoList(ref uint lpdwNumDevs);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetDeviceInfoList([In, Out]FT_DEVICE_LIST_INFO_NODE[] pDest,
                                                            ref uint lpdwNumDevs);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_ListDevices(ref uint pvArg1,
                                                        uint pvArg2,
                                                        uint dwFlags);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Open(int iDevice,
                                                ref IntPtr ftHandle);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Close(IntPtr ftHandle);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Read(IntPtr ftHandle,
                                                [In, Out] byte[] lpBuffer,
                                                uint dwBytesToRead,
                                                ref uint lpdwBytesReturned);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Write(IntPtr ftHandle,
                                                [In, Out] byte[] lpBuffer,
                                                uint dwBytesToWrite,
                                                ref uint lpdwBytesWritten);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetBaudRate(IntPtr ftHandle,
                                                        uint dwBaudRate);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetDivisor(IntPtr ftHandle,
                                                        ushort usDivisor);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetDataCharacteristics(IntPtr ftHandle,
                                                                    byte uWordLength,
                                                                    byte uStopBits,
                                                                    byte uParity);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetTimeouts(IntPtr ftHandle,
                                                        uint dwReadTimeout,
                                                        uint dwWriteTimeout);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetFlowControl(IntPtr ftHandle,
                                                            ushort usFlowControl,
                                                            byte uXon,
                                                            byte uXoff);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetDeviceInfo(IntPtr ftHandle,
                                                        ref uint pftType,
                                                        ref uint lpdwID,
                                                        StringBuilder pcSerialNumber,
                                                        StringBuilder pcDescription,
                                                        int pvDummy);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetDriverVersion(IntPtr ftHandle,
                                                            ref uint lpdwDriverVersion);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetLibraryVersion(ref uint lpdwDLLVersion);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Purge(IntPtr ftHandle,
                                                uint dwMask);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_ResetDevice(IntPtr ftHandle);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_ResetPort(IntPtr ftHandle);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_CyclePort(IntPtr ftHandle);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Rescan();

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_Reload(ushort wVID,
                                                 ushort wPID);


        // Extended API Functions.
        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetLatencyTimer(IntPtr ftHandle,
                                                            byte ucTimer);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetLatencyTimer(IntPtr ftHandle,
                                                            ref byte pucTimer);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetBitMode(IntPtr ftHandle,
                                                        byte ucMask,
                                                        byte ucMode);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_GetBitMode(IntPtr ftHandle,
                                                        ref byte pucMode);

        [DllImport("FTD2XX.dll")]
        public static extern FT_STATUS FT_SetUSBParameters(IntPtr ftHandle,
                                                            uint dwInTransferSize,
                                                            uint dwOutTransferSize);
    }
}