moel@87: /*
moel@87:  
moel@344:   This Source Code Form is subject to the terms of the Mozilla Public
moel@344:   License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344:   file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@87:  
moel@384:   Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344: 	
moel@87: */
moel@87: 
moel@87: using System;
moel@87: using System.Runtime.InteropServices;
moel@87: 
moel@87: namespace OpenHardwareMonitor.Hardware.TBalancer {
moel@87: 
moel@165:   internal enum FT_DEVICE : uint {
moel@186:     FT_DEVICE_232BM,
moel@186:     FT_DEVICE_232AM,
moel@87:     FT_DEVICE_100AX,
moel@87:     FT_DEVICE_UNKNOWN,
moel@186:     FT_DEVICE_2232C,
moel@87:     FT_DEVICE_232R,
moel@87:     FT_DEVICE_2232H,
moel@87:     FT_DEVICE_4232H
moel@87:   }
moel@87: 
moel@165:   internal enum FT_STATUS {
moel@87:     FT_OK,
moel@87:     FT_INVALID_HANDLE,
moel@87:     FT_DEVICE_NOT_FOUND,
moel@87:     FT_DEVICE_NOT_OPENED,
moel@87:     FT_IO_ERROR,
moel@87:     FT_INSUFFICIENT_RESOURCES,
moel@87:     FT_INVALID_PARAMETER,
moel@87:     FT_INVALID_BAUD_RATE,
moel@87:     FT_DEVICE_NOT_OPENED_FOR_ERASE,
moel@87:     FT_DEVICE_NOT_OPENED_FOR_WRITE,
moel@87:     FT_FAILED_TO_WRITE_DEVICE,
moel@87:     FT_EEPROM_READ_FAILED,
moel@87:     FT_EEPROM_WRITE_FAILED,
moel@87:     FT_EEPROM_ERASE_FAILED,
moel@87:     FT_EEPROM_NOT_PRESENT,
moel@87:     FT_EEPROM_NOT_PROGRAMMED,
moel@87:     FT_INVALID_ARGS,
moel@87:     FT_OTHER_ERROR
moel@87:   }
moel@87: 
moel@165:   internal enum FT_FLOW_CONTROL : ushort {
moel@87:     FT_FLOW_DTR_DSR = 512,
moel@87:     FT_FLOW_NONE = 0,
moel@87:     FT_FLOW_RTS_CTS = 256,
moel@87:     FT_FLOW_XON_XOFF = 1024,
moel@87:   }
moel@87: 
moel@165:   internal enum FT_PURGE : uint {
moel@87:     FT_PURGE_RX = 1,
moel@87:     FT_PURGE_TX = 2,
moel@87:     FT_PURGE_ALL = 3,
moel@87:   }
moel@87: 
moel@87:   [StructLayout(LayoutKind.Sequential)]
moel@165:   internal struct FT_HANDLE {
moel@195:     private readonly uint handle;
moel@87:   }
moel@87: 
moel@87:   [StructLayout(LayoutKind.Sequential)]
moel@165:   internal struct FT_DEVICE_INFO_NODE {    
moel@87:     public uint Flags;
moel@87:     public FT_DEVICE Type; 
moel@87:     public uint ID; 
moel@87:     public uint LocId; 
moel@87:     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
moel@87:     public string SerialNumber; 
moel@87:     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
moel@87:     public string Description;
moel@87:     public FT_HANDLE Handle;
moel@87:   }
moel@87: 
moel@165:   internal class FTD2XX {
moel@87: 
moel@87:     public delegate FT_STATUS FT_CreateDeviceInfoListDelegate(
moel@87:       out uint numDevices);
moel@87:     public delegate FT_STATUS FT_GetDeviceInfoListDelegate(
moel@87:       [Out] FT_DEVICE_INFO_NODE[] deviceInfoNodes, ref uint length);
moel@87:     public delegate FT_STATUS FT_OpenDelegate(int device, out FT_HANDLE handle);
moel@87:     public delegate FT_STATUS FT_CloseDelegate(FT_HANDLE handle);
moel@87:     public delegate FT_STATUS FT_SetBaudRateDelegate(FT_HANDLE handle,
moel@87:       uint baudRate);
moel@87:     public delegate FT_STATUS FT_SetDataCharacteristicsDelegate(
moel@87:       FT_HANDLE handle, byte wordLength, byte stopBits, byte parity);
moel@87:     public delegate FT_STATUS FT_SetFlowControlDelegate(FT_HANDLE handle,
moel@87:       FT_FLOW_CONTROL flowControl, byte xon, byte xoff);
moel@87:     public delegate FT_STATUS FT_SetTimeoutsDelegate(FT_HANDLE handle,
moel@87:       uint readTimeout, uint writeTimeout);
moel@87:     public delegate FT_STATUS FT_WriteDelegate(FT_HANDLE handle, byte[] buffer,
moel@87:       uint bytesToWrite, out uint bytesWritten);
moel@87:     public delegate FT_STATUS FT_PurgeDelegate(FT_HANDLE handle, FT_PURGE mask);
moel@87:     public delegate FT_STATUS FT_GetStatusDelegate(FT_HANDLE handle,
moel@87:       out uint amountInRxQueue, out uint amountInTxQueue, out uint eventStatus);
moel@87:     public delegate FT_STATUS FT_ReadDelegate(FT_HANDLE handle, 
moel@87:       [Out] byte[] buffer, uint bytesToRead, out uint bytesReturned);
moel@384:     public delegate FT_STATUS FT_ReadByteDelegate(FT_HANDLE handle,
moel@384:       out byte buffer, uint bytesToRead, out uint bytesReturned);
moel@87: 
moel@167:     public static readonly FT_CreateDeviceInfoListDelegate 
moel@167:       FT_CreateDeviceInfoList = CreateDelegate<
moel@167:       FT_CreateDeviceInfoListDelegate>("FT_CreateDeviceInfoList");
moel@167:     public static readonly FT_GetDeviceInfoListDelegate 
moel@167:       FT_GetDeviceInfoList = CreateDelegate<
moel@167:       FT_GetDeviceInfoListDelegate>("FT_GetDeviceInfoList");
moel@167:     public static readonly FT_OpenDelegate 
moel@167:       FT_Open = CreateDelegate<
moel@167:       FT_OpenDelegate>("FT_Open");
moel@167:     public static readonly FT_CloseDelegate 
moel@167:       FT_Close = CreateDelegate<
moel@167:       FT_CloseDelegate>("FT_Close");
moel@167:     public static readonly FT_SetBaudRateDelegate 
moel@167:       FT_SetBaudRate = CreateDelegate<
moel@167:       FT_SetBaudRateDelegate>("FT_SetBaudRate");
moel@167:     public static readonly FT_SetDataCharacteristicsDelegate 
moel@167:       FT_SetDataCharacteristics = CreateDelegate<
moel@167:       FT_SetDataCharacteristicsDelegate>("FT_SetDataCharacteristics");
moel@167:     public static readonly FT_SetFlowControlDelegate 
moel@167:       FT_SetFlowControl = CreateDelegate<
moel@167:       FT_SetFlowControlDelegate>("FT_SetFlowControl");
moel@167:     public static readonly FT_SetTimeoutsDelegate 
moel@167:       FT_SetTimeouts = CreateDelegate<
moel@167:       FT_SetTimeoutsDelegate>("FT_SetTimeouts");
moel@167:     public static readonly FT_WriteDelegate 
moel@167:       FT_Write = CreateDelegate<
moel@167:       FT_WriteDelegate>("FT_Write");
moel@167:     public static readonly FT_PurgeDelegate 
moel@167:       FT_Purge = CreateDelegate<
moel@167:       FT_PurgeDelegate>("FT_Purge");
moel@167:     public static readonly FT_GetStatusDelegate 
moel@167:       FT_GetStatus = CreateDelegate<
moel@167:       FT_GetStatusDelegate>("FT_GetStatus");
moel@167:     public static readonly FT_ReadDelegate 
moel@167:       FT_Read = CreateDelegate<
moel@167:       FT_ReadDelegate>("FT_Read");
moel@384:     public static readonly FT_ReadByteDelegate
moel@384:       FT_ReadByte = CreateDelegate<
moel@384:       FT_ReadByteDelegate>("FT_Read");
moel@167: 
moel@167:     private FTD2XX() { }
moel@87: 
moel@87:     public static FT_STATUS Write(FT_HANDLE handle, byte[] buffer) {
moel@87:       uint bytesWritten;
moel@87:       FT_STATUS status = FT_Write(handle, buffer, (uint)buffer.Length, 
moel@87:         out bytesWritten);
moel@87:       if (bytesWritten != buffer.Length)
moel@87:         return FT_STATUS.FT_FAILED_TO_WRITE_DEVICE;
moel@87:       else
moel@87:         return status;
moel@87:     }
moel@87: 
moel@87:     public static int BytesToRead(FT_HANDLE handle) {
moel@87:       uint amountInRxQueue;
moel@87:       uint amountInTxQueue;
moel@87:       uint eventStatus;
moel@87:       if (FT_GetStatus(handle, out amountInRxQueue, out amountInTxQueue,
moel@87:         out eventStatus) == FT_STATUS.FT_OK) {
moel@87:         return (int)amountInRxQueue;
moel@87:       } else {
moel@87:         return 0;
moel@87:       }
moel@87:     }
moel@87: 
moel@87:     public static byte ReadByte(FT_HANDLE handle) {
moel@384:       byte buffer;
moel@87:       uint bytesReturned;
moel@384:       FT_STATUS status = FT_ReadByte(handle, out buffer, 1, out bytesReturned);
moel@87:       if (status != FT_STATUS.FT_OK || bytesReturned != 1)
moel@167:         throw new InvalidOperationException();
moel@384:       return buffer;
moel@384:     }
moel@384: 
moel@384:     public static void Read(FT_HANDLE handle, byte[] buffer) {
moel@384:       uint bytesReturned;
moel@384:       FT_STATUS status = 
moel@384:         FT_Read(handle, buffer, (uint)buffer.Length, out bytesReturned);
moel@384:       if (status != FT_STATUS.FT_OK || bytesReturned != buffer.Length)
moel@384:         throw new InvalidOperationException();
moel@87:     }
moel@87: 
moel@167:     private static string GetDllName() {
moel@195:       int p = (int)Environment.OSVersion.Platform;
moel@167:       if ((p == 4) || (p == 128))
moel@167:         return "libftd2xx.so";
moel@167:       else
moel@167:         return "ftd2xx.dll";
moel@167:     }
moel@87: 
moel@167:     private static T CreateDelegate<T>(string entryPoint)
moel@87:       where T : class {
moel@167:       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
moel@87:       attribute.CallingConvention = CallingConvention.StdCall;
moel@87:       attribute.PreserveSig = true;
moel@87:       attribute.EntryPoint = entryPoint;
moel@167:       T newDelegate;
moel@87:       PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
moel@167:       return newDelegate;
moel@87:     }
moel@87:   }
moel@87: }