// // HamLib.cs // // Author: // Jae Stutzman // // Copyright (c) 2016 Jae Stutzman // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Collections.Generic; using System.Runtime.InteropServices; using HamLibSharp.Utils; using HamLibSharp.x86; using HamLibSharp.x64; namespace HamLibSharp { internal enum HamLibVersion { Unknown = 0, V2 = 2, V301 = 3, Current, } public static class HamLib { internal readonly static bool bitsize64; internal readonly static bool isWindows; internal readonly static HamLibVersion hamLibVersion; public static bool Initialized { get; private set; } public readonly static SortedDictionary Rigs = new SortedDictionary (); [UnmanagedFunctionPointer (CallingConvention.Cdecl)] public delegate int RigListCallback (IntPtr rig_caps, IntPtr rig_ptr); internal const string dllName = "libhamlib-2.dll"; static HamLib () { // determine platform and bit size... if (System.Environment.Is64BitProcess) { bitsize64 = true; } if (System.Environment.OSVersion.Platform != PlatformID.MacOSX && System.Environment.OSVersion.Platform != PlatformID.Unix) { isWindows = true; } // take care of 32/64 bit native windows dll Library.LoadLibrary (dllName); hamLibVersion = PreInitLibrary (); } static HamLibVersion PreInitLibrary () { INativeRig initRig = null; IRigCapsNative initCaps = null; HamLibVersion version; SetDebugLevel (RigDebugLevel.None); // test what version of hamlib is on our system use the Dummy Rig var theRig = Rig.rig_init (1); if (!isWindows && bitsize64) { initRig = Marshal.PtrToStructure (theRig); initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.Current; } else { initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.V301; } else { initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.V2; } else { version = HamLibVersion.Unknown; } } } } else { initRig = Marshal.PtrToStructure (theRig); initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.Current; } else { initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.V301; } else { initCaps = Marshal.PtrToStructure (initRig.Caps); if (initCaps.Priv == IntPtr.Zero && initCaps.Decode_event == IntPtr.Zero) { version = HamLibVersion.V2; } else { version = HamLibVersion.Unknown; } } } } return version; } public static void Initialize () { //SetDebugLevel (RigDebugLevel.None); rig_load_all_backends (); rig_list_foreach ((rig_caps, rig_ptr) => { if (rig_caps != IntPtr.Zero) { var caps = MarshalRigCaps (rig_caps); AddRig (new RigCaps (caps)); } return 1; }, IntPtr.Zero); //SetDebugLevel (RigDebugLevel.Verbose); Initialized = true; } internal static IRigCapsNative MarshalRigCaps (IntPtr rig_caps) { IRigCapsNative caps = null; switch (hamLibVersion) { case HamLibVersion.Current: // if the platform is 64-bit, but not windows if (!isWindows && bitsize64) { caps = Marshal.PtrToStructure (rig_caps); } else { caps = Marshal.PtrToStructure (rig_caps); } break; case HamLibVersion.V301: if (!isWindows && bitsize64) { caps = Marshal.PtrToStructure (rig_caps); } else { caps = Marshal.PtrToStructure (rig_caps); } break; case HamLibVersion.V2: if (!isWindows && bitsize64) { caps = Marshal.PtrToStructure (rig_caps); } else { caps = Marshal.PtrToStructure (rig_caps); } break; default: throw new RigException ("Unknown or Incompatible HamLib library found"); } return caps; } private static void AddRig (RigCaps caps) { int index = 2; string modelName = string.Format ("{0}", caps.ModelName); while (Rigs.ContainsKey (modelName)) { modelName = string.Format ("{0}_{1}", caps.ModelName, index); index++; } Rigs.Add (modelName, caps); } [DllImport (HamLib.dllName, EntryPoint = "rig_set_debug")] public static extern void SetDebugLevel (RigDebugLevel debugLevel); [DllImport (HamLib.dllName, EntryPoint = "rig_load_all_backends")] private static extern int rig_load_all_backends (); [DllImport (HamLib.dllName, EntryPoint = "rig_list_foreach")] private static extern int rig_list_foreach (RigListCallback call, IntPtr ptr); //Note: Function introduced in version 3.1, earlier versions do not have it [DllImport (HamLib.dllName)] private static extern IntPtr rig_copyright (); public static string NativeCopyright { get { try { return Marshal.PtrToStringAnsi (rig_copyright ()); } catch (EntryPointNotFoundException) { return "Unknown"; } } } //Note: Function introduced in version 3.1, earlier versions do not have it [DllImport (HamLib.dllName)] private static extern IntPtr rig_license (); public static string NativeLicense { get { try { return Marshal.PtrToStringAnsi (rig_license ()); } catch (EntryPointNotFoundException) { return "Unknown"; } } } //Note: Function introduced in version 3.1, earlier versions do not have it [DllImport (HamLib.dllName)] private static extern IntPtr rig_version (); public static string NativeVersion { get { try { switch (hamLibVersion) { case HamLibVersion.Current: var ver = Marshal.PtrToStringAnsi (rig_version ()); return ver.Replace ("Hamlib", string.Empty).Trim (); case HamLibVersion.V301: return "3.0.1"; case HamLibVersion.V2: return "1.2 or earlier"; default: return "Unknown"; } } catch (EntryPointNotFoundException) { //Console.WriteLine (e); // Entry point not found, so it has to be 3.0.1 or earlier return "3.0.1 or earlier"; // } catch (DllNotFoundException e) { // return "Native HamLib Not Found: " + e.Message; } } } public static string ManagedCopyright { get { return Library.Copyright; } } public static string ManagedLicense { get { return Library.License; } } public static Version ManagedVersion { get { return Library.Version; } } } }