#nullable enable
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Coptonix.LismPi26
{
    public static class Native
    {
        private const string ImportName = "usblismpi26";
        private static readonly object LibrarySync = new object();
        private static string? configuredLibraryPath;
        private static IntPtr loadedLibraryHandle;

        public const int RET_OK = 0;

        // BEGIN GENERATED LS ERROR CODES
        private static bool IsWindowsPlatform => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        public static long LS_OK => IsWindowsPlatform ? (long)0 : 0L;
        public static long LS_ERR_NO_DEVICES_ATTACHED => IsWindowsPlatform ? (long)0x20000001 : -10001L;
        public static long LS_ERR_DEVICE_INDEX_OUT_OF_RANGE => IsWindowsPlatform ? (long)0x20000002 : -10002L;
        public static long LS_ERR_SERIAL_NUM_NOT_FOUND => IsWindowsPlatform ? (long)0x20000003 : -10003L;
        public static long LS_ERR_INVALID_HANDLE => IsWindowsPlatform ? (long)6 : -10004L;
        public static long LS_ERR_DEVICE_ACTIVE => IsWindowsPlatform ? (long)0x20000011 : -10005L;
        public static long LS_ERR_CONTROL_TRANSFER => IsWindowsPlatform ? (long)0x20000015 : -10006L;
        public static long LS_ERR_TIMEOUT => IsWindowsPlatform ? (long)1460 : -10007L;
        public static long LS_ERR_DEVICE_ALREADY_OPEN => IsWindowsPlatform ? (long)0x20000013 : -10008L;
        public static long LS_ERR_NOT_IMPLEMENTED => IsWindowsPlatform ? (long)0x20000014 : -10009L;
        public static long LS_ERR_ALLOCATE_THREADPARAM_MEM => IsWindowsPlatform ? (long)0x20000004 : -10010L;
        public static long LS_ERR_PATH_INVALID_HANDLE => IsWindowsPlatform ? (long)0x20000006 : -10012L;
        public static long LS_ERR_INVALID_DATALEN => IsWindowsPlatform ? (long)0x21000001 : -10051L;
        public static long LS_ERR_I2C_NACK => IsWindowsPlatform ? (long)0x21000004 : -10052L;
        public static long LS_ERR_I2C_ERROR => IsWindowsPlatform ? (long)0x21000005 : -10053L;
        public static long LS_ERR_I2C_UNKNOWN => IsWindowsPlatform ? (long)0x21000006 : -10054L;
        public static long LS_ERR_I2C_MUX_DISABLED => IsWindowsPlatform ? (long)0x21000007 : -10055L;
        public static long LS_ERR_INVALID_PACKETLENGTH => IsWindowsPlatform ? (long)0x21000002 : -10056L;
        public static long LS_ERR_CMD_NOT_SUPPORTED => IsWindowsPlatform ? (long)0x21000003 : -10057L;
        public static long LS_ERR_PIPE_CANCELLED => IsWindowsPlatform ? (long)109 : -10058L;
        public static long LS_ERR_INVALID_TIMEOUT => IsWindowsPlatform ? (long)0x21000008 : -10059L;
        public static long LS_ERR_INVALID_THREAD_PRIORITY => IsWindowsPlatform ? (long)0x21000009 : -10060L;
        public static long LS_ERR_THREAD_PRIORITY_FAILED => IsWindowsPlatform ? (long)0x2100000A : -10061L;
        // END GENERATED LS ERROR CODES
        public const uint DEFAULT_TIMEOUT_MS = 1000;
        public const int LS_THREAD_PRIORITY_NORMAL = 0;
        public const int LS_THREAD_PRIORITY_ABOVE_NORMAL = 1;
        public const int LS_THREAD_PRIORITY_HIGH = 2;

        public const uint _512 = 512;
        public const uint _1kB = _512 * 2;
        public const uint _2kB = _1kB * 2;
        public const uint _4kB = _2kB * 2;
        public const uint _8kB = _4kB * 2;
        public const uint _16kB = _8kB * 2;
        public const uint _32kB = _16kB * 2;
        public const uint _64kB = _32kB * 2;
        public const uint _128kB = _64kB * 2;
        public const uint _256kB = _128kB * 2;
        public const uint _512kB = _256kB * 2;
        public const uint _1MB = _512kB * 2;
        public const uint _2MB = _1MB * 2;
        public const uint _4MB = _2MB * 2;
        public const uint _8MB = _4MB * 2;
        public const uint _16MB = _8MB * 2;
        public const uint _32MB = _16MB * 2;
        public const uint _64MB = _32MB * 2;
        public const uint _128MB = _64MB * 2;
        public const uint _256MB = _128MB * 2;

        public const uint _1ms = 1;
        public const uint _1s = 1000 * _1ms;

        public const byte LISM_ADDR = 0xFE;

        public const byte MODE_FREE_RUNNING = 0x00;
        public const byte MODE_EXT_RISING_EDGE_SL = 0x01;
        public const byte MODE_EXT_HIGH_LEVEL = 0x02;
        public const byte MODE_INT_SOFT_TRIGGER = 0x03;
        public const byte MODE_QUAD_ENC_TRIGGER = 0x04;
        public const byte MODE_EXT_RISING_EDGE_ML = 0x05;
        public const byte MODE_ENCODER_DIR_CW = 0x00;
        public const byte MODE_ENCODER_DIR_CCW = 0x10;
        public const byte MODE_ENCODER_CNT_DISABLE = 0x00;
        public const byte MODE_ENCODER_CNT_ENABLE = 0x20;
        public const byte IF_DCLK_400KHZ = 0x00;
        public const byte IF_DCLK_500KHZ = 0x01;
        public const byte IF_DCLK_800KHZ = 0x02;
        public const byte IF_DCLK_1MHZ = 0x03;
        public const byte IF_DCLK_2MHZ = 0x04;
        public const byte IF_DCLK_4MHZ = 0x05;
        public const byte IF_DCLK_10MHZ = 0x06;
        public const byte IF_DCLK_20MHZ = 0x07;
        public const byte IF_DCLK_POL_RISING_EDGE = 0x00;
        public const byte IF_DCLK_POL_FALLING_EDGE = 0x08;
        public const byte IF_LINE_VALID_HIGH = 0x00;
        public const byte IF_LINE_VALID_LOW = 0x10;
        public const byte IF_FRAME_VALID_HIGH = 0x00;
        public const byte IF_FRAME_VALID_LOW = 0x20;
        public const byte IF_TRIGGER_OUTPUT_HIGH = 0x00;
        public const byte IF_TRIGGER_OUTPUT_LOW = 0x40;
        public const byte ADC_VREF_1V6 = 0x00;
        public const byte ADC_VREF_2V0 = 0x01;

        static Native()
        {
            NativeLibrary.SetDllImportResolver(typeof(Native).Assembly, ResolveLibrary);
        }

        public static string DefaultLibraryName
        {
            get
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    return Environment.Is64BitProcess ? "usblismpi2664.dll" : "usblismpi2632.dll";
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                    return Environment.Is64BitProcess ? "libusblismpi2664.so" : "libusblismpi2632.so";
                throw new PlatformNotSupportedException("Only Windows and Linux are supported.");
            }
        }

        public static void SetLibraryPath(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                throw new ArgumentException("A library path is required.", nameof(path));
            lock (LibrarySync)
            {
                if (loadedLibraryHandle != IntPtr.Zero)
                    throw new InvalidOperationException("The native library is already loaded.");
                configuredLibraryPath = path;
            }
        }

        private static IntPtr ResolveLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
        {
            if (!string.Equals(libraryName, ImportName, StringComparison.Ordinal))
                return IntPtr.Zero;

            lock (LibrarySync)
            {
                if (loadedLibraryHandle != IntPtr.Zero)
                    return loadedLibraryHandle;

                string name = configuredLibraryPath ?? DefaultLibraryName;
                string[] candidates = Path.IsPathRooted(name)
                    ? new[] { name }
                    : new[]
                    {
                        Path.Combine(AppContext.BaseDirectory, name),
                        Path.Combine(Environment.CurrentDirectory, name),
                        name
                    };

                foreach (string candidate in candidates)
                {
                    if (NativeLibrary.TryLoad(candidate, assembly, searchPath, out loadedLibraryHandle))
                        return loadedLibraryHandle;
                }
                return IntPtr.Zero;
            }
        }

        private static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

        private static long NormalizeResult(int raw_result) =>
            IsWindows ? unchecked((uint)raw_result) : raw_result;

        public static string? PtrToAnsi(IntPtr value) =>
            value == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(value);

        [DllImport(ImportName, EntryPoint = "ls_initialize", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_initialize(uint pipe_size, uint packet_length, uint thread_class, int thread_priority, [MarshalAs(UnmanagedType.LPStr)] string? message_id);
        [DllImport(ImportName, EntryPoint = "ls_initialize", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern void linux_ls_initialize(int pipe_size, int packet_length);

        public static long ls_initialize(uint pipe_size, uint packet_length, uint thread_class = 0, int thread_priority = 0, string? message_id = null)
        {
            if (IsWindows)
                return NormalizeResult(win_ls_initialize(pipe_size, packet_length, thread_class, thread_priority, message_id));
            linux_ls_initialize(checked((int)pipe_size), checked((int)packet_length));
            return RET_OK;
        }

        [DllImport(ImportName, EntryPoint = "ls_libversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern ushort ls_libversion();

        [DllImport(ImportName, EntryPoint = "ls_enumdevices", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern int ls_enumdevices();

        [DllImport(ImportName, EntryPoint = "ls_getfwversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern ushort ls_getfwversion(int index);

        [DllImport(ImportName, EntryPoint = "ls_getvendorname", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern IntPtr ls_getvendorname(int index);

        [DllImport(ImportName, EntryPoint = "ls_getproductname", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern IntPtr ls_getproductname(int index);

        [DllImport(ImportName, EntryPoint = "ls_getserialnumber", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern IntPtr ls_getserialnumber(int index);

        [DllImport(ImportName, EntryPoint = "ls_devicecount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern byte ls_devicecount();

        [DllImport(ImportName, EntryPoint = "ls_currentdeviceindex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern int ls_currentdeviceindex();

        [DllImport(ImportName, EntryPoint = "ls_opendevicebyindex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_opendevicebyindex(int index);

        public static long ls_opendevicebyindex(int index) =>
            NormalizeResult(native_ls_opendevicebyindex(index));

        [DllImport(ImportName, EntryPoint = "ls_opendevicebyserial", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_opendevicebyserial([MarshalAs(UnmanagedType.LPStr)] string serial_num);

        public static long ls_opendevicebyserial([MarshalAs(UnmanagedType.LPStr)] string serial_num) =>
            NormalizeResult(native_ls_opendevicebyserial(serial_num));

        [DllImport(ImportName, EntryPoint = "ls_closedevice", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_closedevice();

        public static long ls_closedevice() =>
            NormalizeResult(native_ls_closedevice());

        [DllImport(ImportName, EntryPoint = "ls_waitforpipe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_waitforpipe(uint timeout_ms);

        public static long ls_waitforpipe(uint timeout_ms) =>
            NormalizeResult(native_ls_waitforpipe(timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_waitforpipecount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_waitforpipecount(int count, out int available, uint timeout_ms);

        public static long ls_waitforpipecount(int count, out int available, uint timeout_ms) =>
            NormalizeResult(native_ls_waitforpipecount(count, out available, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getpipe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getpipe(IntPtr buffer, uint to_read, out uint read_count);
        [DllImport(ImportName, EntryPoint = "ls_getpipe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getpipe(IntPtr buffer, uint to_read);

        public static long ls_getpipe(IntPtr buffer, uint to_read, out uint read_count)
        {
            if (IsWindows)
                return NormalizeResult(win_ls_getpipe(buffer, to_read, out read_count));

            int linux_result = linux_ls_getpipe(buffer, to_read);
            if (linux_result < 0)
            {
                read_count = 0;
                return linux_result;
            }
            read_count = checked((uint)linux_result);
            return RET_OK;
        }

        [DllImport(ImportName, EntryPoint = "ls_setpacketlength", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setpacketlength(uint packet_length);

        public static long ls_setpacketlength(uint packet_length) =>
            NormalizeResult(native_ls_setpacketlength(packet_length));

        [DllImport(ImportName, EntryPoint = "ls_seteptimeout", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_seteptimeout(uint timeout_ms);

        public static long ls_seteptimeout(uint timeout_ms) =>
            NormalizeResult(native_ls_seteptimeout(timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_geteptimeout", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern uint ls_geteptimeout();

        [DllImport(ImportName, EntryPoint = "ls_getfps", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern uint ls_getfps();

        [DllImport(ImportName, EntryPoint = "ls_geterrorstring", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern IntPtr native_ls_geterrorstring(int error_code);

        public static IntPtr ls_geterrorstring(long error_code)
        {
            int raw_error = IsWindows ? unchecked((int)(uint)error_code) : checked((int)error_code);
            return native_ls_geterrorstring(raw_error);
        }

        [DllImport(ImportName, EntryPoint = "ls_customfirmware", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_customfirmware(out uint custom_firmware);
        [DllImport(ImportName, EntryPoint = "ls_customfirmware", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_customfirmware(out uint custom_firmware, uint timeout_ms);

        public static long ls_customfirmware(out uint custom_firmware, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_customfirmware(out custom_firmware) : linux_ls_customfirmware(out custom_firmware, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setcfg1", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setcfg1(byte cfg1);
        [DllImport(ImportName, EntryPoint = "ls_setcfg1", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setcfg1(byte cfg1, uint timeout_ms);

        public static long ls_setcfg1(byte cfg1, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setcfg1(cfg1) : linux_ls_setcfg1(cfg1, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getcfg1", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getcfg1(out byte cfg1);
        [DllImport(ImportName, EntryPoint = "ls_getcfg1", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getcfg1(out byte cfg1, uint timeout_ms);

        public static long ls_getcfg1(out byte cfg1, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getcfg1(out cfg1) : linux_ls_getcfg1(out cfg1, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getpacketlength", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getpacketlength(out uint packet_length);
        [DllImport(ImportName, EntryPoint = "ls_getpacketlength", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getpacketlength(out uint packet_length, uint timeout_ms);

        public static long ls_getpacketlength(out uint packet_length, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getpacketlength(out packet_length) : linux_ls_getpacketlength(out packet_length, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setmuxchannel", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setmuxchannel(byte mux);
        [DllImport(ImportName, EntryPoint = "ls_setmuxchannel", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setmuxchannel(byte mux, uint timeout_ms);

        public static long ls_setmuxchannel(byte mux, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setmuxchannel(mux) : linux_ls_setmuxchannel(mux, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getmuxchannel", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getmuxchannel(out sbyte mux);
        [DllImport(ImportName, EntryPoint = "ls_getmuxchannel", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getmuxchannel(out sbyte mux, uint timeout_ms);

        public static long ls_getmuxchannel(out sbyte mux, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getmuxchannel(out mux) : linux_ls_getmuxchannel(out mux, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_readi2c_ext", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_readi2c_ext(byte i2c_address, IntPtr buffer, ref ushort length);
        [DllImport(ImportName, EntryPoint = "ls_readi2c_ext", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_readi2c_ext(byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms);

        public static long ls_readi2c_ext(byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_readi2c_ext(i2c_address, buffer, ref length) : linux_ls_readi2c_ext(i2c_address, buffer, ref length, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_writei2c_ext", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_writei2c_ext(byte i2c_address, IntPtr buffer, ushort length);
        [DllImport(ImportName, EntryPoint = "ls_writei2c_ext", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_writei2c_ext(byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms);

        public static long ls_writei2c_ext(byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_writei2c_ext(i2c_address, buffer, length) : linux_ls_writei2c_ext(i2c_address, buffer, length, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_readi2c", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_readi2c(byte i2c_address, IntPtr buffer, ref ushort length);
        [DllImport(ImportName, EntryPoint = "ls_readi2c", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_readi2c(byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms);

        public static long ls_readi2c(byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_readi2c(i2c_address, buffer, ref length) : linux_ls_readi2c(i2c_address, buffer, ref length, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_writei2c", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_writei2c(byte i2c_address, IntPtr buffer, ushort length);
        [DllImport(ImportName, EntryPoint = "ls_writei2c", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_writei2c(byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms);

        public static long ls_writei2c(byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_writei2c(i2c_address, buffer, length) : linux_ls_writei2c(i2c_address, buffer, length, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cread1byte", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cread1byte(byte i2c_address, byte i2c_register, out byte value);
        [DllImport(ImportName, EntryPoint = "ls_i2cread1byte", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cread1byte(byte i2c_address, byte i2c_register, out byte value, uint timeout_ms);

        public static long ls_i2cread1byte(byte i2c_address, byte i2c_register, out byte value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cread1byte(i2c_address, i2c_register, out value) : linux_ls_i2cread1byte(i2c_address, i2c_register, out value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cread2bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cread2bytes(byte i2c_address, byte i2c_register, out ushort value);
        [DllImport(ImportName, EntryPoint = "ls_i2cread2bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cread2bytes(byte i2c_address, byte i2c_register, out ushort value, uint timeout_ms);

        public static long ls_i2cread2bytes(byte i2c_address, byte i2c_register, out ushort value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cread2bytes(i2c_address, i2c_register, out value) : linux_ls_i2cread2bytes(i2c_address, i2c_register, out value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cread4bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cread4bytes(byte i2c_address, byte i2c_register, out uint value);
        [DllImport(ImportName, EntryPoint = "ls_i2cread4bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cread4bytes(byte i2c_address, byte i2c_register, out uint value, uint timeout_ms);

        public static long ls_i2cread4bytes(byte i2c_address, byte i2c_register, out uint value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cread4bytes(i2c_address, i2c_register, out value) : linux_ls_i2cread4bytes(i2c_address, i2c_register, out value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite1byte", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cwrite1byte(byte i2c_address, byte i2c_register, byte value);
        [DllImport(ImportName, EntryPoint = "ls_i2cwrite1byte", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cwrite1byte(byte i2c_address, byte i2c_register, byte value, uint timeout_ms);

        public static long ls_i2cwrite1byte(byte i2c_address, byte i2c_register, byte value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cwrite1byte(i2c_address, i2c_register, value) : linux_ls_i2cwrite1byte(i2c_address, i2c_register, value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite2bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cwrite2bytes(byte i2c_address, byte i2c_register, ushort value);
        [DllImport(ImportName, EntryPoint = "ls_i2cwrite2bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cwrite2bytes(byte i2c_address, byte i2c_register, ushort value, uint timeout_ms);

        public static long ls_i2cwrite2bytes(byte i2c_address, byte i2c_register, ushort value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cwrite2bytes(i2c_address, i2c_register, value) : linux_ls_i2cwrite2bytes(i2c_address, i2c_register, value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite4bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cwrite4bytes(byte i2c_address, byte i2c_register, uint value);
        [DllImport(ImportName, EntryPoint = "ls_i2cwrite4bytes", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cwrite4bytes(byte i2c_address, byte i2c_register, uint value, uint timeout_ms);

        public static long ls_i2cwrite4bytes(byte i2c_address, byte i2c_register, uint value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cwrite4bytes(i2c_address, i2c_register, value) : linux_ls_i2cwrite4bytes(i2c_address, i2c_register, value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_i2cwritecmd", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_i2cwritecmd(byte i2c_address, byte i2c_command);
        [DllImport(ImportName, EntryPoint = "ls_i2cwritecmd", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_i2cwritecmd(byte i2c_address, byte i2c_command, uint timeout_ms);

        public static long ls_i2cwritecmd(byte i2c_address, byte i2c_command, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_i2cwritecmd(i2c_address, i2c_command) : linux_ls_i2cwritecmd(i2c_address, i2c_command, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_hw_reset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_hw_reset(byte address);
        [DllImport(ImportName, EntryPoint = "ls_hw_reset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_hw_reset(byte address, uint timeout_ms);

        public static long ls_hw_reset(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_hw_reset(address) : linux_ls_hw_reset(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_suspend", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_suspend(byte address);
        [DllImport(ImportName, EntryPoint = "ls_suspend", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_suspend(byte address, uint timeout_ms);

        public static long ls_suspend(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_suspend(address) : linux_ls_suspend(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_resume", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_resume(byte address);
        [DllImport(ImportName, EntryPoint = "ls_resume", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_resume(byte address, uint timeout_ms);

        public static long ls_resume(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_resume(address) : linux_ls_resume(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_updateparam", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_updateparam(byte address);
        [DllImport(ImportName, EntryPoint = "ls_updateparam", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_updateparam(byte address, uint timeout_ms);

        public static long ls_updateparam(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_updateparam(address) : linux_ls_updateparam(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setstate(byte address, byte state);
        [DllImport(ImportName, EntryPoint = "ls_setstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setstate(byte address, byte state, uint timeout_ms);

        public static long ls_setstate(byte address, byte state, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setstate(address, state) : linux_ls_setstate(address, state, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setmodeconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setmodeconfig(byte address, byte mode);
        [DllImport(ImportName, EntryPoint = "ls_setmodeconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setmodeconfig(byte address, byte mode, uint timeout_ms);

        public static long ls_setmodeconfig(byte address, byte mode, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setmodeconfig(address, mode) : linux_ls_setmodeconfig(address, mode, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setifconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setifconfig(byte address, byte config);
        [DllImport(ImportName, EntryPoint = "ls_setifconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setifconfig(byte address, byte config, uint timeout_ms);

        public static long ls_setifconfig(byte address, byte config, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setifconfig(address, config) : linux_ls_setifconfig(address, config, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setstpulse", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setstpulse(byte address, uint high_value, uint low_value);
        [DllImport(ImportName, EntryPoint = "ls_setstpulse", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setstpulse(byte address, uint high_value, uint low_value, uint timeout_ms);

        public static long ls_setstpulse(byte address, uint high_value, uint low_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setstpulse(address, high_value, low_value) : linux_ls_setstpulse(address, high_value, low_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setsthigh", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setsthigh(byte address, uint high_value);
        [DllImport(ImportName, EntryPoint = "ls_setsthigh", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setsthigh(byte address, uint high_value, uint timeout_ms);

        public static long ls_setsthigh(byte address, uint high_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setsthigh(address, high_value) : linux_ls_setsthigh(address, high_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setstlow", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setstlow(byte address, uint low_value);
        [DllImport(ImportName, EntryPoint = "ls_setstlow", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setstlow(byte address, uint low_value, uint timeout_ms);

        public static long ls_setstlow(byte address, uint low_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setstlow(address, low_value) : linux_ls_setstlow(address, low_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setlinesperframe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setlinesperframe(byte address, ushort lines);
        [DllImport(ImportName, EntryPoint = "ls_setlinesperframe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setlinesperframe(byte address, ushort lines, uint timeout_ms);

        public static long ls_setlinesperframe(byte address, ushort lines, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setlinesperframe(address, lines) : linux_ls_setlinesperframe(address, lines, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setquadcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setquadcount(byte address, uint count);
        [DllImport(ImportName, EntryPoint = "ls_setquadcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setquadcount(byte address, uint count, uint timeout_ms);

        public static long ls_setquadcount(byte address, uint count, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setquadcount(address, count) : linux_ls_setquadcount(address, count, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setsofttriggertime", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setsofttriggertime(byte address, uint time_value);
        [DllImport(ImportName, EntryPoint = "ls_setsofttriggertime", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setsofttriggertime(byte address, uint time_value, uint timeout_ms);

        public static long ls_setsofttriggertime(byte address, uint time_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setsofttriggertime(address, time_value) : linux_ls_setsofttriggertime(address, time_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_settriggerdelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_settriggerdelay(byte address, uint delay_value);
        [DllImport(ImportName, EntryPoint = "ls_settriggerdelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_settriggerdelay(byte address, uint delay_value, uint timeout_ms);

        public static long ls_settriggerdelay(byte address, uint delay_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_settriggerdelay(address, delay_value) : linux_ls_settriggerdelay(address, delay_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_settriggerwidth", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_settriggerwidth(byte address, uint width_value);
        [DllImport(ImportName, EntryPoint = "ls_settriggerwidth", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_settriggerwidth(byte address, uint width_value, uint timeout_ms);

        public static long ls_settriggerwidth(byte address, uint width_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_settriggerwidth(address, width_value) : linux_ls_settriggerwidth(address, width_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setpixelcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setpixelcount(byte address, ushort pixel_count);
        [DllImport(ImportName, EntryPoint = "ls_setpixelcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setpixelcount(byte address, ushort pixel_count, uint timeout_ms);

        public static long ls_setpixelcount(byte address, ushort pixel_count, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setpixelcount(address, pixel_count) : linux_ls_setpixelcount(address, pixel_count, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setedgedelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setedgedelay(byte address, byte edge_delay);
        [DllImport(ImportName, EntryPoint = "ls_setedgedelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setedgedelay(byte address, byte edge_delay, uint timeout_ms);

        public static long ls_setedgedelay(byte address, byte edge_delay, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setedgedelay(address, edge_delay) : linux_ls_setedgedelay(address, edge_delay, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setadcvref", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setadcvref(byte address, byte vref);
        [DllImport(ImportName, EntryPoint = "ls_setadcvref", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setadcvref(byte address, byte vref, uint timeout_ms);

        public static long ls_setadcvref(byte address, byte vref, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setadcvref(address, vref) : linux_ls_setadcvref(address, vref, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setadcgain", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setadcgain(byte address, byte gain);
        [DllImport(ImportName, EntryPoint = "ls_setadcgain", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setadcgain(byte address, byte gain, uint timeout_ms);

        public static long ls_setadcgain(byte address, byte gain, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setadcgain(address, gain) : linux_ls_setadcgain(address, gain, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setadcoffset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setadcoffset(byte address, ushort offset);
        [DllImport(ImportName, EntryPoint = "ls_setadcoffset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setadcoffset(byte address, ushort offset, uint timeout_ms);

        public static long ls_setadcoffset(byte address, ushort offset, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setadcoffset(address, offset) : linux_ls_setadcoffset(address, offset, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setadcbias", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setadcbias(byte address, ushort bias);
        [DllImport(ImportName, EntryPoint = "ls_setadcbias", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setadcbias(byte address, ushort bias, uint timeout_ms);

        public static long ls_setadcbias(byte address, ushort bias, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setadcbias(address, bias) : linux_ls_setadcbias(address, bias, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_setslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_setslaveaddress(byte address, byte new_address);
        [DllImport(ImportName, EntryPoint = "ls_setslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_setslaveaddress(byte address, byte new_address, uint timeout_ms);

        public static long ls_setslaveaddress(byte address, byte new_address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_setslaveaddress(address, new_address) : linux_ls_setslaveaddress(address, new_address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_saveslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_saveslaveaddress(byte address);
        [DllImport(ImportName, EntryPoint = "ls_saveslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_saveslaveaddress(byte address, uint timeout_ms);

        public static long ls_saveslaveaddress(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_saveslaveaddress(address) : linux_ls_saveslaveaddress(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_savesettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_savesettings(byte address);
        [DllImport(ImportName, EntryPoint = "ls_savesettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_savesettings(byte address, uint timeout_ms);

        public static long ls_savesettings(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_savesettings(address) : linux_ls_savesettings(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_reloadsettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_reloadsettings(byte address);
        [DllImport(ImportName, EntryPoint = "ls_reloadsettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_reloadsettings(byte address, uint timeout_ms);

        public static long ls_reloadsettings(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_reloadsettings(address) : linux_ls_reloadsettings(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_resetsettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_resetsettings(byte address);
        [DllImport(ImportName, EntryPoint = "ls_resetsettings", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_resetsettings(byte address, uint timeout_ms);

        public static long ls_resetsettings(byte address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_resetsettings(address) : linux_ls_resetsettings(address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getmcuversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getmcuversion(byte address, out ushort version);
        [DllImport(ImportName, EntryPoint = "ls_getmcuversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getmcuversion(byte address, out ushort version, uint timeout_ms);

        public static long ls_getmcuversion(byte address, out ushort version, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getmcuversion(address, out version) : linux_ls_getmcuversion(address, out version, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getctgversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getctgversion(byte address, out ushort version);
        [DllImport(ImportName, EntryPoint = "ls_getctgversion", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getctgversion(byte address, out ushort version, uint timeout_ms);

        public static long ls_getctgversion(byte address, out ushort version, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getctgversion(address, out version) : linux_ls_getctgversion(address, out version, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getctgstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getctgstate(byte address, out byte state);
        [DllImport(ImportName, EntryPoint = "ls_getctgstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getctgstate(byte address, out byte state, uint timeout_ms);

        public static long ls_getctgstate(byte address, out byte state, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getctgstate(address, out state) : linux_ls_getctgstate(address, out state, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getstate(byte address, out byte state);
        [DllImport(ImportName, EntryPoint = "ls_getstate", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getstate(byte address, out byte state, uint timeout_ms);

        public static long ls_getstate(byte address, out byte state, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getstate(address, out state) : linux_ls_getstate(address, out state, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getmodeconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getmodeconfig(byte address, out byte mode);
        [DllImport(ImportName, EntryPoint = "ls_getmodeconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getmodeconfig(byte address, out byte mode, uint timeout_ms);

        public static long ls_getmodeconfig(byte address, out byte mode, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getmodeconfig(address, out mode) : linux_ls_getmodeconfig(address, out mode, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getifconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getifconfig(byte address, out byte config);
        [DllImport(ImportName, EntryPoint = "ls_getifconfig", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getifconfig(byte address, out byte config, uint timeout_ms);

        public static long ls_getifconfig(byte address, out byte config, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getifconfig(address, out config) : linux_ls_getifconfig(address, out config, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getstpulse", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getstpulse(byte address, out uint high_value, out uint low_value);
        [DllImport(ImportName, EntryPoint = "ls_getstpulse", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getstpulse(byte address, out uint high_value, out uint low_value, uint timeout_ms);

        public static long ls_getstpulse(byte address, out uint high_value, out uint low_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getstpulse(address, out high_value, out low_value) : linux_ls_getstpulse(address, out high_value, out low_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getsthigh", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getsthigh(byte address, out uint high_value);
        [DllImport(ImportName, EntryPoint = "ls_getsthigh", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getsthigh(byte address, out uint high_value, uint timeout_ms);

        public static long ls_getsthigh(byte address, out uint high_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getsthigh(address, out high_value) : linux_ls_getsthigh(address, out high_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getstlow", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getstlow(byte address, out uint low_value);
        [DllImport(ImportName, EntryPoint = "ls_getstlow", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getstlow(byte address, out uint low_value, uint timeout_ms);

        public static long ls_getstlow(byte address, out uint low_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getstlow(address, out low_value) : linux_ls_getstlow(address, out low_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getlinesperframe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getlinesperframe(byte address, out ushort lines);
        [DllImport(ImportName, EntryPoint = "ls_getlinesperframe", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getlinesperframe(byte address, out ushort lines, uint timeout_ms);

        public static long ls_getlinesperframe(byte address, out ushort lines, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getlinesperframe(address, out lines) : linux_ls_getlinesperframe(address, out lines, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getquadcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getquadcount(byte address, out uint count);
        [DllImport(ImportName, EntryPoint = "ls_getquadcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getquadcount(byte address, out uint count, uint timeout_ms);

        public static long ls_getquadcount(byte address, out uint count, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getquadcount(address, out count) : linux_ls_getquadcount(address, out count, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getsofttriggertime", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getsofttriggertime(byte address, out uint time_value);
        [DllImport(ImportName, EntryPoint = "ls_getsofttriggertime", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getsofttriggertime(byte address, out uint time_value, uint timeout_ms);

        public static long ls_getsofttriggertime(byte address, out uint time_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getsofttriggertime(address, out time_value) : linux_ls_getsofttriggertime(address, out time_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_gettriggerdelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_gettriggerdelay(byte address, out uint delay_value);
        [DllImport(ImportName, EntryPoint = "ls_gettriggerdelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_gettriggerdelay(byte address, out uint delay_value, uint timeout_ms);

        public static long ls_gettriggerdelay(byte address, out uint delay_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_gettriggerdelay(address, out delay_value) : linux_ls_gettriggerdelay(address, out delay_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_gettriggerwidth", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_gettriggerwidth(byte address, out uint width_value);
        [DllImport(ImportName, EntryPoint = "ls_gettriggerwidth", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_gettriggerwidth(byte address, out uint width_value, uint timeout_ms);

        public static long ls_gettriggerwidth(byte address, out uint width_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_gettriggerwidth(address, out width_value) : linux_ls_gettriggerwidth(address, out width_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getpixelcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getpixelcount(byte address, out ushort pixel_count);
        [DllImport(ImportName, EntryPoint = "ls_getpixelcount", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getpixelcount(byte address, out ushort pixel_count, uint timeout_ms);

        public static long ls_getpixelcount(byte address, out ushort pixel_count, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getpixelcount(address, out pixel_count) : linux_ls_getpixelcount(address, out pixel_count, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getedgedelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getedgedelay(byte address, out byte edge_delay);
        [DllImport(ImportName, EntryPoint = "ls_getedgedelay", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getedgedelay(byte address, out byte edge_delay, uint timeout_ms);

        public static long ls_getedgedelay(byte address, out byte edge_delay, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getedgedelay(address, out edge_delay) : linux_ls_getedgedelay(address, out edge_delay, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getadcvref", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getadcvref(byte address, out byte vref);
        [DllImport(ImportName, EntryPoint = "ls_getadcvref", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getadcvref(byte address, out byte vref, uint timeout_ms);

        public static long ls_getadcvref(byte address, out byte vref, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getadcvref(address, out vref) : linux_ls_getadcvref(address, out vref, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getadcgain", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getadcgain(byte address, out byte gain);
        [DllImport(ImportName, EntryPoint = "ls_getadcgain", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getadcgain(byte address, out byte gain, uint timeout_ms);

        public static long ls_getadcgain(byte address, out byte gain, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getadcgain(address, out gain) : linux_ls_getadcgain(address, out gain, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getadcoffset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getadcoffset(byte address, out ushort offset);
        [DllImport(ImportName, EntryPoint = "ls_getadcoffset", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getadcoffset(byte address, out ushort offset, uint timeout_ms);

        public static long ls_getadcoffset(byte address, out ushort offset, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getadcoffset(address, out offset) : linux_ls_getadcoffset(address, out offset, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getadcbias", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getadcbias(byte address, out ushort bias);
        [DllImport(ImportName, EntryPoint = "ls_getadcbias", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getadcbias(byte address, out ushort bias, uint timeout_ms);

        public static long ls_getadcbias(byte address, out ushort bias, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getadcbias(address, out bias) : linux_ls_getadcbias(address, out bias, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getslaveaddress(byte address, out byte new_address);
        [DllImport(ImportName, EntryPoint = "ls_getslaveaddress", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getslaveaddress(byte address, out byte new_address, uint timeout_ms);

        public static long ls_getslaveaddress(byte address, out byte new_address, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getslaveaddress(address, out new_address) : linux_ls_getslaveaddress(address, out new_address, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_gethw1id", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_gethw1id(byte address, out ushort hardware_id);
        [DllImport(ImportName, EntryPoint = "ls_gethw1id", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_gethw1id(byte address, out ushort hardware_id, uint timeout_ms);

        public static long ls_gethw1id(byte address, out ushort hardware_id, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_gethw1id(address, out hardware_id) : linux_ls_gethw1id(address, out hardware_id, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_gethw1version", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_gethw1version(byte address, out ushort version);
        [DllImport(ImportName, EntryPoint = "ls_gethw1version", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_gethw1version(byte address, out ushort version, uint timeout_ms);

        public static long ls_gethw1version(byte address, out ushort version, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_gethw1version(address, out version) : linux_ls_gethw1version(address, out version, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_gethw2version", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_gethw2version(byte address, out ushort version);
        [DllImport(ImportName, EntryPoint = "ls_gethw2version", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_gethw2version(byte address, out ushort version, uint timeout_ms);

        public static long ls_gethw2version(byte address, out ushort version, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_gethw2version(address, out version) : linux_ls_gethw2version(address, out version, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getgainmult", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getgainmult(byte address, out ushort multiplier);
        [DllImport(ImportName, EntryPoint = "ls_getgainmult", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getgainmult(byte address, out ushort multiplier, uint timeout_ms);

        public static long ls_getgainmult(byte address, out ushort multiplier, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getgainmult(address, out multiplier) : linux_ls_getgainmult(address, out multiplier, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getgaindiv", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getgaindiv(byte address, out ushort divisor);
        [DllImport(ImportName, EntryPoint = "ls_getgaindiv", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getgaindiv(byte address, out ushort divisor, uint timeout_ms);

        public static long ls_getgaindiv(byte address, out ushort divisor, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getgaindiv(address, out divisor) : linux_ls_getgaindiv(address, out divisor, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getinitstatus", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getinitstatus(byte address, out byte status);
        [DllImport(ImportName, EntryPoint = "ls_getinitstatus", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getinitstatus(byte address, out byte status, uint timeout_ms);

        public static long ls_getinitstatus(byte address, out byte status, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getinitstatus(address, out status) : linux_ls_getinitstatus(address, out status, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_getcomresult", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int win_ls_getcomresult(byte address, out byte result_value);
        [DllImport(ImportName, EntryPoint = "ls_getcomresult", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int linux_ls_getcomresult(byte address, out byte result_value, uint timeout_ms);

        public static long ls_getcomresult(byte address, out byte result_value, uint timeout_ms = DEFAULT_TIMEOUT_MS)
        {
            return NormalizeResult(IsWindows ? win_ls_getcomresult(address, out result_value) : linux_ls_getcomresult(address, out result_value, timeout_ms));
        }

        [DllImport(ImportName, EntryPoint = "ls_shutdown", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_shutdown();

        public static long ls_shutdown() =>
            NormalizeResult(native_ls_shutdown());

        // Handle-based API
        [DllImport(ImportName, EntryPoint = "ls_seteptimeout_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_seteptimeout_ex(IntPtr handle, uint timeout_ms);

        public static long ls_seteptimeout_ex(IntPtr handle, uint timeout_ms) =>
            NormalizeResult(native_ls_seteptimeout_ex(handle, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_geteptimeout_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_geteptimeout_ex(IntPtr handle, out uint timeout_ms);

        public static long ls_geteptimeout_ex(IntPtr handle, out uint timeout_ms) =>
            NormalizeResult(native_ls_geteptimeout_ex(handle, out timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setthreadpriority_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setthreadpriority_ex(IntPtr handle, int priority);

        public static long ls_setthreadpriority_ex(IntPtr handle, int priority) =>
            NormalizeResult(native_ls_setthreadpriority_ex(handle, priority));

        [DllImport(ImportName, EntryPoint = "ls_getthreadpriority_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getthreadpriority_ex(IntPtr handle, out int priority);

        public static long ls_getthreadpriority_ex(IntPtr handle, out int priority) =>
            NormalizeResult(native_ls_getthreadpriority_ex(handle, out priority));

        [DllImport(ImportName, EntryPoint = "ls_opendevicebyindex_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_opendevicebyindex_ex(int index, uint pipe_size, uint packet_length, out IntPtr handle);

        public static long ls_opendevicebyindex_ex(int index, uint pipe_size, uint packet_length, out IntPtr handle) =>
            NormalizeResult(native_ls_opendevicebyindex_ex(index, pipe_size, packet_length, out handle));

        [DllImport(ImportName, EntryPoint = "ls_opendevicebyserial_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_opendevicebyserial_ex([MarshalAs(UnmanagedType.LPStr)] string serial_num, uint pipe_size, uint packet_length, out IntPtr handle);

        public static long ls_opendevicebyserial_ex([MarshalAs(UnmanagedType.LPStr)] string serial_num, uint pipe_size, uint packet_length, out IntPtr handle) =>
            NormalizeResult(native_ls_opendevicebyserial_ex(serial_num, pipe_size, packet_length, out handle));

        [DllImport(ImportName, EntryPoint = "ls_closedevice_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_closedevice_ex(IntPtr handle);

        public static long ls_closedevice_ex(IntPtr handle) =>
            NormalizeResult(native_ls_closedevice_ex(handle));

        [DllImport(ImportName, EntryPoint = "ls_getpipe_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getpipe_ex(IntPtr handle, IntPtr buffer, uint to_read, out uint read_count);

        public static long ls_getpipe_ex(IntPtr handle, IntPtr buffer, uint to_read, out uint read_count) =>
            NormalizeResult(native_ls_getpipe_ex(handle, buffer, to_read, out read_count));

        [DllImport(ImportName, EntryPoint = "ls_waitforpipe_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_waitforpipe_ex(IntPtr handle, uint timeout_ms);

        public static long ls_waitforpipe_ex(IntPtr handle, uint timeout_ms) =>
            NormalizeResult(native_ls_waitforpipe_ex(handle, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_waitforpipecount_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_waitforpipecount_ex(IntPtr handle, int count, out int available, uint timeout_ms);

        public static long ls_waitforpipecount_ex(IntPtr handle, int count, out int available, uint timeout_ms) =>
            NormalizeResult(native_ls_waitforpipecount_ex(handle, count, out available, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getfps_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern uint ls_getfps_ex(IntPtr handle);

        [DllImport(ImportName, EntryPoint = "ls_getpacketlength_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getpacketlength_ex(IntPtr handle, out uint packet_length, uint timeout_ms);

        public static long ls_getpacketlength_ex(IntPtr handle, out uint packet_length, uint timeout_ms) =>
            NormalizeResult(native_ls_getpacketlength_ex(handle, out packet_length, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_customfirmware_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_customfirmware_ex(IntPtr handle, out uint custom_firmware, uint timeout_ms);

        public static long ls_customfirmware_ex(IntPtr handle, out uint custom_firmware, uint timeout_ms) =>
            NormalizeResult(native_ls_customfirmware_ex(handle, out custom_firmware, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setcfg1_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setcfg1_ex(IntPtr handle, byte cfg1, uint timeout_ms);

        public static long ls_setcfg1_ex(IntPtr handle, byte cfg1, uint timeout_ms) =>
            NormalizeResult(native_ls_setcfg1_ex(handle, cfg1, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getcfg1_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getcfg1_ex(IntPtr handle, out byte cfg1, uint timeout_ms);

        public static long ls_getcfg1_ex(IntPtr handle, out byte cfg1, uint timeout_ms) =>
            NormalizeResult(native_ls_getcfg1_ex(handle, out cfg1, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setslaveaddress_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setslaveaddress_ex(IntPtr handle, byte address, byte new_address, uint timeout_ms);

        public static long ls_setslaveaddress_ex(IntPtr handle, byte address, byte new_address, uint timeout_ms) =>
            NormalizeResult(native_ls_setslaveaddress_ex(handle, address, new_address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getslaveaddress_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getslaveaddress_ex(IntPtr handle, byte address, out byte new_address, uint timeout_ms);

        public static long ls_getslaveaddress_ex(IntPtr handle, byte address, out byte new_address, uint timeout_ms) =>
            NormalizeResult(native_ls_getslaveaddress_ex(handle, address, out new_address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_saveslaveaddress_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_saveslaveaddress_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_saveslaveaddress_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_saveslaveaddress_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setmuxchannel_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setmuxchannel_ex(IntPtr handle, byte mux, uint timeout_ms);

        public static long ls_setmuxchannel_ex(IntPtr handle, byte mux, uint timeout_ms) =>
            NormalizeResult(native_ls_setmuxchannel_ex(handle, mux, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getmuxchannel_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getmuxchannel_ex(IntPtr handle, out sbyte mux, uint timeout_ms);

        public static long ls_getmuxchannel_ex(IntPtr handle, out sbyte mux, uint timeout_ms) =>
            NormalizeResult(native_ls_getmuxchannel_ex(handle, out mux, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_readi2c_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_readi2c_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms);

        public static long ls_readi2c_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms) =>
            NormalizeResult(native_ls_readi2c_ex(handle, i2c_address, buffer, ref length, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_writei2c_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_writei2c_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms);

        public static long ls_writei2c_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms) =>
            NormalizeResult(native_ls_writei2c_ex(handle, i2c_address, buffer, length, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_readi2c_ext_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_readi2c_ext_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms);

        public static long ls_readi2c_ext_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ref ushort length, uint timeout_ms) =>
            NormalizeResult(native_ls_readi2c_ext_ex(handle, i2c_address, buffer, ref length, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_writei2c_ext_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_writei2c_ext_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms);

        public static long ls_writei2c_ext_ex(IntPtr handle, byte i2c_address, IntPtr buffer, ushort length, uint timeout_ms) =>
            NormalizeResult(native_ls_writei2c_ext_ex(handle, i2c_address, buffer, length, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cread1byte_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cread1byte_ex(IntPtr handle, byte i2c_address, byte i2c_register, out byte value, uint timeout_ms);

        public static long ls_i2cread1byte_ex(IntPtr handle, byte i2c_address, byte i2c_register, out byte value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cread1byte_ex(handle, i2c_address, i2c_register, out value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cread2bytes_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cread2bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, out ushort value, uint timeout_ms);

        public static long ls_i2cread2bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, out ushort value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cread2bytes_ex(handle, i2c_address, i2c_register, out value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cread4bytes_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cread4bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, out uint value, uint timeout_ms);

        public static long ls_i2cread4bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, out uint value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cread4bytes_ex(handle, i2c_address, i2c_register, out value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite1byte_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cwrite1byte_ex(IntPtr handle, byte i2c_address, byte i2c_register, byte value, uint timeout_ms);

        public static long ls_i2cwrite1byte_ex(IntPtr handle, byte i2c_address, byte i2c_register, byte value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cwrite1byte_ex(handle, i2c_address, i2c_register, value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite2bytes_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cwrite2bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, ushort value, uint timeout_ms);

        public static long ls_i2cwrite2bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, ushort value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cwrite2bytes_ex(handle, i2c_address, i2c_register, value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cwrite4bytes_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cwrite4bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, uint value, uint timeout_ms);

        public static long ls_i2cwrite4bytes_ex(IntPtr handle, byte i2c_address, byte i2c_register, uint value, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cwrite4bytes_ex(handle, i2c_address, i2c_register, value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_i2cwritecmd_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_i2cwritecmd_ex(IntPtr handle, byte i2c_address, byte i2c_command, uint timeout_ms);

        public static long ls_i2cwritecmd_ex(IntPtr handle, byte i2c_address, byte i2c_command, uint timeout_ms) =>
            NormalizeResult(native_ls_i2cwritecmd_ex(handle, i2c_address, i2c_command, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_hw_reset_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_hw_reset_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_hw_reset_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_hw_reset_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_resume_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_resume_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_resume_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_resume_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_suspend_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_suspend_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_suspend_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_suspend_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_updateparam_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_updateparam_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_updateparam_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_updateparam_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setstate_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setstate_ex(IntPtr handle, byte address, byte state, uint timeout_ms);

        public static long ls_setstate_ex(IntPtr handle, byte address, byte state, uint timeout_ms) =>
            NormalizeResult(native_ls_setstate_ex(handle, address, state, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setmodeconfig_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setmodeconfig_ex(IntPtr handle, byte address, byte mode, uint timeout_ms);

        public static long ls_setmodeconfig_ex(IntPtr handle, byte address, byte mode, uint timeout_ms) =>
            NormalizeResult(native_ls_setmodeconfig_ex(handle, address, mode, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setifconfig_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setifconfig_ex(IntPtr handle, byte address, byte config, uint timeout_ms);

        public static long ls_setifconfig_ex(IntPtr handle, byte address, byte config, uint timeout_ms) =>
            NormalizeResult(native_ls_setifconfig_ex(handle, address, config, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setsthigh_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setsthigh_ex(IntPtr handle, byte address, uint high_value, uint timeout_ms);

        public static long ls_setsthigh_ex(IntPtr handle, byte address, uint high_value, uint timeout_ms) =>
            NormalizeResult(native_ls_setsthigh_ex(handle, address, high_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setstlow_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setstlow_ex(IntPtr handle, byte address, uint low_value, uint timeout_ms);

        public static long ls_setstlow_ex(IntPtr handle, byte address, uint low_value, uint timeout_ms) =>
            NormalizeResult(native_ls_setstlow_ex(handle, address, low_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setstpulse_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setstpulse_ex(IntPtr handle, byte address, uint high_value, uint low_value, uint timeout_ms);

        public static long ls_setstpulse_ex(IntPtr handle, byte address, uint high_value, uint low_value, uint timeout_ms) =>
            NormalizeResult(native_ls_setstpulse_ex(handle, address, high_value, low_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setlinesperframe_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setlinesperframe_ex(IntPtr handle, byte address, ushort lines, uint timeout_ms);

        public static long ls_setlinesperframe_ex(IntPtr handle, byte address, ushort lines, uint timeout_ms) =>
            NormalizeResult(native_ls_setlinesperframe_ex(handle, address, lines, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setquadcount_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setquadcount_ex(IntPtr handle, byte address, uint count, uint timeout_ms);

        public static long ls_setquadcount_ex(IntPtr handle, byte address, uint count, uint timeout_ms) =>
            NormalizeResult(native_ls_setquadcount_ex(handle, address, count, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setsofttriggertime_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setsofttriggertime_ex(IntPtr handle, byte address, uint time_value, uint timeout_ms);

        public static long ls_setsofttriggertime_ex(IntPtr handle, byte address, uint time_value, uint timeout_ms) =>
            NormalizeResult(native_ls_setsofttriggertime_ex(handle, address, time_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_settriggerdelay_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_settriggerdelay_ex(IntPtr handle, byte address, uint delay_value, uint timeout_ms);

        public static long ls_settriggerdelay_ex(IntPtr handle, byte address, uint delay_value, uint timeout_ms) =>
            NormalizeResult(native_ls_settriggerdelay_ex(handle, address, delay_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_settriggerwidth_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_settriggerwidth_ex(IntPtr handle, byte address, uint width_value, uint timeout_ms);

        public static long ls_settriggerwidth_ex(IntPtr handle, byte address, uint width_value, uint timeout_ms) =>
            NormalizeResult(native_ls_settriggerwidth_ex(handle, address, width_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setpixelcount_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setpixelcount_ex(IntPtr handle, byte address, ushort pixel_count, uint timeout_ms);

        public static long ls_setpixelcount_ex(IntPtr handle, byte address, ushort pixel_count, uint timeout_ms) =>
            NormalizeResult(native_ls_setpixelcount_ex(handle, address, pixel_count, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setedgedelay_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setedgedelay_ex(IntPtr handle, byte address, byte edge_delay, uint timeout_ms);

        public static long ls_setedgedelay_ex(IntPtr handle, byte address, byte edge_delay, uint timeout_ms) =>
            NormalizeResult(native_ls_setedgedelay_ex(handle, address, edge_delay, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setadcvref_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setadcvref_ex(IntPtr handle, byte address, byte vref, uint timeout_ms);

        public static long ls_setadcvref_ex(IntPtr handle, byte address, byte vref, uint timeout_ms) =>
            NormalizeResult(native_ls_setadcvref_ex(handle, address, vref, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setadcgain_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setadcgain_ex(IntPtr handle, byte address, byte gain, uint timeout_ms);

        public static long ls_setadcgain_ex(IntPtr handle, byte address, byte gain, uint timeout_ms) =>
            NormalizeResult(native_ls_setadcgain_ex(handle, address, gain, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setadcoffset_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setadcoffset_ex(IntPtr handle, byte address, ushort offset, uint timeout_ms);

        public static long ls_setadcoffset_ex(IntPtr handle, byte address, ushort offset, uint timeout_ms) =>
            NormalizeResult(native_ls_setadcoffset_ex(handle, address, offset, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_setadcbias_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_setadcbias_ex(IntPtr handle, byte address, ushort bias, uint timeout_ms);

        public static long ls_setadcbias_ex(IntPtr handle, byte address, ushort bias, uint timeout_ms) =>
            NormalizeResult(native_ls_setadcbias_ex(handle, address, bias, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getctgstate_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getctgstate_ex(IntPtr handle, byte address, out byte state, uint timeout_ms);

        public static long ls_getctgstate_ex(IntPtr handle, byte address, out byte state, uint timeout_ms) =>
            NormalizeResult(native_ls_getctgstate_ex(handle, address, out state, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getstate_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getstate_ex(IntPtr handle, byte address, out byte state, uint timeout_ms);

        public static long ls_getstate_ex(IntPtr handle, byte address, out byte state, uint timeout_ms) =>
            NormalizeResult(native_ls_getstate_ex(handle, address, out state, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getmodeconfig_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getmodeconfig_ex(IntPtr handle, byte address, out byte mode, uint timeout_ms);

        public static long ls_getmodeconfig_ex(IntPtr handle, byte address, out byte mode, uint timeout_ms) =>
            NormalizeResult(native_ls_getmodeconfig_ex(handle, address, out mode, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getifconfig_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getifconfig_ex(IntPtr handle, byte address, out byte config, uint timeout_ms);

        public static long ls_getifconfig_ex(IntPtr handle, byte address, out byte config, uint timeout_ms) =>
            NormalizeResult(native_ls_getifconfig_ex(handle, address, out config, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getsthigh_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getsthigh_ex(IntPtr handle, byte address, out uint high_value, uint timeout_ms);

        public static long ls_getsthigh_ex(IntPtr handle, byte address, out uint high_value, uint timeout_ms) =>
            NormalizeResult(native_ls_getsthigh_ex(handle, address, out high_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getstlow_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getstlow_ex(IntPtr handle, byte address, out uint low_value, uint timeout_ms);

        public static long ls_getstlow_ex(IntPtr handle, byte address, out uint low_value, uint timeout_ms) =>
            NormalizeResult(native_ls_getstlow_ex(handle, address, out low_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getstpulse_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getstpulse_ex(IntPtr handle, byte address, out uint high_value, out uint low_value, uint timeout_ms);

        public static long ls_getstpulse_ex(IntPtr handle, byte address, out uint high_value, out uint low_value, uint timeout_ms) =>
            NormalizeResult(native_ls_getstpulse_ex(handle, address, out high_value, out low_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getlinesperframe_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getlinesperframe_ex(IntPtr handle, byte address, out ushort lines, uint timeout_ms);

        public static long ls_getlinesperframe_ex(IntPtr handle, byte address, out ushort lines, uint timeout_ms) =>
            NormalizeResult(native_ls_getlinesperframe_ex(handle, address, out lines, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getquadcount_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getquadcount_ex(IntPtr handle, byte address, out uint count, uint timeout_ms);

        public static long ls_getquadcount_ex(IntPtr handle, byte address, out uint count, uint timeout_ms) =>
            NormalizeResult(native_ls_getquadcount_ex(handle, address, out count, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getsofttriggertime_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getsofttriggertime_ex(IntPtr handle, byte address, out uint time_value, uint timeout_ms);

        public static long ls_getsofttriggertime_ex(IntPtr handle, byte address, out uint time_value, uint timeout_ms) =>
            NormalizeResult(native_ls_getsofttriggertime_ex(handle, address, out time_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_gettriggerdelay_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_gettriggerdelay_ex(IntPtr handle, byte address, out uint delay_value, uint timeout_ms);

        public static long ls_gettriggerdelay_ex(IntPtr handle, byte address, out uint delay_value, uint timeout_ms) =>
            NormalizeResult(native_ls_gettriggerdelay_ex(handle, address, out delay_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_gettriggerwidth_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_gettriggerwidth_ex(IntPtr handle, byte address, out uint width_value, uint timeout_ms);

        public static long ls_gettriggerwidth_ex(IntPtr handle, byte address, out uint width_value, uint timeout_ms) =>
            NormalizeResult(native_ls_gettriggerwidth_ex(handle, address, out width_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getpixelcount_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getpixelcount_ex(IntPtr handle, byte address, out ushort pixel_count, uint timeout_ms);

        public static long ls_getpixelcount_ex(IntPtr handle, byte address, out ushort pixel_count, uint timeout_ms) =>
            NormalizeResult(native_ls_getpixelcount_ex(handle, address, out pixel_count, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getedgedelay_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getedgedelay_ex(IntPtr handle, byte address, out byte edge_delay, uint timeout_ms);

        public static long ls_getedgedelay_ex(IntPtr handle, byte address, out byte edge_delay, uint timeout_ms) =>
            NormalizeResult(native_ls_getedgedelay_ex(handle, address, out edge_delay, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getadcvref_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getadcvref_ex(IntPtr handle, byte address, out byte vref, uint timeout_ms);

        public static long ls_getadcvref_ex(IntPtr handle, byte address, out byte vref, uint timeout_ms) =>
            NormalizeResult(native_ls_getadcvref_ex(handle, address, out vref, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getadcgain_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getadcgain_ex(IntPtr handle, byte address, out byte gain, uint timeout_ms);

        public static long ls_getadcgain_ex(IntPtr handle, byte address, out byte gain, uint timeout_ms) =>
            NormalizeResult(native_ls_getadcgain_ex(handle, address, out gain, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getgainmult_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getgainmult_ex(IntPtr handle, byte address, out ushort multiplier, uint timeout_ms);

        public static long ls_getgainmult_ex(IntPtr handle, byte address, out ushort multiplier, uint timeout_ms) =>
            NormalizeResult(native_ls_getgainmult_ex(handle, address, out multiplier, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getgaindiv_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getgaindiv_ex(IntPtr handle, byte address, out ushort divisor, uint timeout_ms);

        public static long ls_getgaindiv_ex(IntPtr handle, byte address, out ushort divisor, uint timeout_ms) =>
            NormalizeResult(native_ls_getgaindiv_ex(handle, address, out divisor, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getadcoffset_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getadcoffset_ex(IntPtr handle, byte address, out ushort offset, uint timeout_ms);

        public static long ls_getadcoffset_ex(IntPtr handle, byte address, out ushort offset, uint timeout_ms) =>
            NormalizeResult(native_ls_getadcoffset_ex(handle, address, out offset, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getadcbias_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getadcbias_ex(IntPtr handle, byte address, out ushort bias, uint timeout_ms);

        public static long ls_getadcbias_ex(IntPtr handle, byte address, out ushort bias, uint timeout_ms) =>
            NormalizeResult(native_ls_getadcbias_ex(handle, address, out bias, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_savesettings_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_savesettings_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_savesettings_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_savesettings_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_reloadsettings_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_reloadsettings_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_reloadsettings_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_reloadsettings_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_resetsettings_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_resetsettings_ex(IntPtr handle, byte address, uint timeout_ms);

        public static long ls_resetsettings_ex(IntPtr handle, byte address, uint timeout_ms) =>
            NormalizeResult(native_ls_resetsettings_ex(handle, address, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getinitstatus_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getinitstatus_ex(IntPtr handle, byte address, out byte status, uint timeout_ms);

        public static long ls_getinitstatus_ex(IntPtr handle, byte address, out byte status, uint timeout_ms) =>
            NormalizeResult(native_ls_getinitstatus_ex(handle, address, out status, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getcomresult_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getcomresult_ex(IntPtr handle, byte address, out byte result_value, uint timeout_ms);

        public static long ls_getcomresult_ex(IntPtr handle, byte address, out byte result_value, uint timeout_ms) =>
            NormalizeResult(native_ls_getcomresult_ex(handle, address, out result_value, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getmcuversion_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getmcuversion_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms);

        public static long ls_getmcuversion_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms) =>
            NormalizeResult(native_ls_getmcuversion_ex(handle, address, out version, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_getctgversion_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_getctgversion_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms);

        public static long ls_getctgversion_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms) =>
            NormalizeResult(native_ls_getctgversion_ex(handle, address, out version, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_gethw1id_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_gethw1id_ex(IntPtr handle, byte address, out ushort hardware_id, uint timeout_ms);

        public static long ls_gethw1id_ex(IntPtr handle, byte address, out ushort hardware_id, uint timeout_ms) =>
            NormalizeResult(native_ls_gethw1id_ex(handle, address, out hardware_id, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_gethw1version_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_gethw1version_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms);

        public static long ls_gethw1version_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms) =>
            NormalizeResult(native_ls_gethw1version_ex(handle, address, out version, timeout_ms));

        [DllImport(ImportName, EntryPoint = "ls_gethw2version_ex", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, ExactSpelling = true)]
        private static extern int native_ls_gethw2version_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms);

        public static long ls_gethw2version_ex(IntPtr handle, byte address, out ushort version, uint timeout_ms) =>
            NormalizeResult(native_ls_gethw2version_ex(handle, address, out version, timeout_ms));

        public static string? GetErrorString(long error_code)
        {
            return PtrToAnsi(ls_geterrorstring(error_code));
        }
        public static string? GetVendorName(int index) => PtrToAnsi(ls_getvendorname(index));
        public static string? GetProductName(int index) => PtrToAnsi(ls_getproductname(index));
        public static string? GetSerialNumber(int index) => PtrToAnsi(ls_getserialnumber(index));

        public static (long Error, byte[] Data) GetPipeBytes(uint number_of_bytes)
        {
            if (number_of_bytes > int.MaxValue)
                throw new ArgumentOutOfRangeException(nameof(number_of_bytes));
            IntPtr buffer = Marshal.AllocHGlobal((int)number_of_bytes);
            try
            {
                long error = ls_getpipe(buffer, number_of_bytes, out uint read_count);
                byte[] data = new byte[read_count];
                if (read_count != 0)
                    Marshal.Copy(buffer, data, 0, checked((int)read_count));
                return (error, data);
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }

        public static (long Error, uint Available) GetPipeAvailable()
        {
            long error = ls_getpipe(IntPtr.Zero, 0, out uint available);
            return (error, available);
        }

        public static (long Error, byte[] Data) GetPipeBytesEx(IntPtr handle, uint number_of_bytes)
        {
            if (number_of_bytes > int.MaxValue)
                throw new ArgumentOutOfRangeException(nameof(number_of_bytes));
            IntPtr buffer = Marshal.AllocHGlobal((int)number_of_bytes);
            try
            {
                long error = ls_getpipe_ex(handle, buffer, number_of_bytes, out uint read_count);
                byte[] data = new byte[read_count];
                if (read_count != 0)
                    Marshal.Copy(buffer, data, 0, checked((int)read_count));
                return (error, data);
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }

        public static (long Error, uint Available) GetPipeAvailableEx(IntPtr handle)
        {
            long error = ls_getpipe_ex(handle, IntPtr.Zero, 0, out uint available);
            return (error, available);
        }
    }
}
