1 /* 2 * libiio - Library for interfacing industrial I/O (IIO) devices 3 * 4 * Copyright (C) 2015 Analog Devices, Inc. 5 * Author: Paul Cercueil <paul.cercueil@analog.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * */ 18 19 using System; 20 using System.Collections.Generic; 21 using System.Linq; 22 using System.Runtime.InteropServices; 23 using System.Text; 24 using System.Threading.Tasks; 25 26 namespace iio 27 { 28 public class Version 29 { 30 public readonly uint major; 31 public readonly uint minor; 32 public readonly string git_tag; 33 Version(uint major, uint minor, string git_tag)34 internal Version(uint major, uint minor, string git_tag) 35 { 36 this.major = major; 37 this.minor = minor; 38 this.git_tag = git_tag; 39 } 40 } 41 42 /// <summary><see cref="iio.Context"/> class: 43 /// Contains the representation of an IIO context.</summary> 44 public class Context : IDisposable 45 { 46 internal IntPtr ctx; 47 48 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_create_network_context( [In()][MarshalAs(UnmanagedType.LPStr)] string hostname )49 private static extern IntPtr iio_create_network_context( 50 [In()][MarshalAs(UnmanagedType.LPStr)] string hostname 51 ); 52 53 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_create_context_from_uri( [In()][MarshalAs(UnmanagedType.LPStr)] string uri )54 private static extern IntPtr iio_create_context_from_uri( 55 [In()][MarshalAs(UnmanagedType.LPStr)] string uri 56 ); 57 58 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_create_default_context()59 private static extern IntPtr iio_create_default_context(); 60 61 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_create_local_context()62 private static extern IntPtr iio_create_local_context(); 63 64 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_destroy(IntPtr ctx)65 private static extern void iio_context_destroy(IntPtr ctx); 66 67 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_name(IntPtr ctx)68 private static extern IntPtr iio_context_get_name(IntPtr ctx); 69 70 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_description(IntPtr ctx)71 private static extern IntPtr iio_context_get_description(IntPtr ctx); 72 73 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_xml(IntPtr ctx)74 private static extern IntPtr iio_context_get_xml(IntPtr ctx); 75 76 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_library_get_version(ref uint major, ref uint minor, [Out()] StringBuilder git_tag)77 private static extern void iio_library_get_version(ref uint major, ref uint minor, [Out()] StringBuilder git_tag); 78 79 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_version(IntPtr ctx, ref uint major, ref uint minor, [Out()] StringBuilder git_tag)80 private static extern int iio_context_get_version(IntPtr ctx, ref uint major, ref uint minor, [Out()] StringBuilder git_tag); 81 82 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_devices_count(IntPtr ctx)83 private static extern uint iio_context_get_devices_count(IntPtr ctx); 84 85 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_device(IntPtr ctx, uint index)86 private static extern IntPtr iio_context_get_device(IntPtr ctx, uint index); 87 88 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 89 [return: MarshalAs(UnmanagedType.I1)] iio_device_is_trigger(IntPtr dev)90 private static extern bool iio_device_is_trigger(IntPtr dev); 91 92 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_set_timeout(IntPtr ctx, uint timeout_ms)93 private static extern int iio_context_set_timeout(IntPtr ctx, uint timeout_ms); 94 95 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_clone(IntPtr ctx)96 private static extern IntPtr iio_context_clone(IntPtr ctx); 97 98 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_attrs_count(IntPtr ctx)99 private static extern uint iio_context_get_attrs_count(IntPtr ctx); 100 101 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_get_attr(IntPtr ctx, uint index, IntPtr name_ptr, IntPtr value_ptr)102 private static extern int iio_context_get_attr(IntPtr ctx, uint index, IntPtr name_ptr, IntPtr value_ptr); 103 104 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_find_device(IntPtr ctx, [In] string name)105 private static extern IntPtr iio_context_find_device(IntPtr ctx, [In] string name); 106 107 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_context_info_get_description(IntPtr info)108 private static extern IntPtr iio_context_info_get_description(IntPtr info); 109 110 /// <summary>A XML representation of the current context.</summary> 111 public readonly string xml; 112 113 /// <summary>The name of the current context.</summary> 114 public readonly string name; 115 116 /// <summary>Retrieve a human-readable information string about the current context.</summary> 117 public readonly string description; 118 /// <summary>Retrieve a information about the version context.</summary> 119 public readonly Version library_version, backend_version; 120 121 /// <summary>A <c>List</c> of all the IIO devices present on the current context.</summary> 122 public readonly List<Device> devices; 123 124 /// <summary>A <c>Dictionary</c> of all the attributes of the current channel. (key, value) = (name, value)</summary> 125 public Dictionary<string, string> attrs { get; private set; } 126 127 /// <summary>Initializes a new instance of the <see cref="iio.Context"/> class, 128 /// using the provided URI. For compatibility with existing code, providing 129 /// an IP address or a hostname here will automatically create a network 130 /// context.</summary> 131 /// <param name="uri">URI to use for the IIO context creation</param> 132 /// <returns>an instance of the <see cref="iio.Context"/> class</returns> 133 /// <exception cref="System.Exception">The IIO context could not be created.</exception> Context(string uri)134 public Context(string uri) : this(getContextFromString(uri)) {} 135 136 /// <summary>Initializes a new instance of the <see cref="iio.Context"/> class, 137 /// using the local or the network backend of the IIO library.</summary> 138 /// <remarks>This function will create a network context if the IIOD_REMOTE 139 /// environment variable is set to the hostname where the IIOD server runs. 140 /// If set to an empty string, the server will be discovered using ZeroConf. 141 /// If the environment variable is not set, a local context will be created 142 /// instead.</remarks> 143 /// <exception cref="System.Exception">The IIO context could not be created.</exception> Context()144 public Context() : this(iio_create_default_context()) {} 145 getContextFromString(string str)146 private static IntPtr getContextFromString(string str) 147 { 148 IntPtr ptr = iio_create_context_from_uri(str); 149 if (ptr == IntPtr.Zero) 150 { 151 ptr = iio_create_network_context(str); 152 } 153 return ptr; 154 } 155 Context(IntPtr ctx)156 internal Context(IntPtr ctx) 157 { 158 this.ctx = ctx; 159 160 if (ctx == IntPtr.Zero) 161 { 162 throw new Exception("Unable to create IIO context"); 163 } 164 165 uint nb_devices = iio_context_get_devices_count(ctx); 166 167 devices = new List<Device>(); 168 for (uint i = 0; i < nb_devices; i++) 169 { 170 IntPtr ptr = iio_context_get_device(ctx, i); 171 if (iio_device_is_trigger(ptr)) 172 { 173 devices.Add(new Trigger(this, ptr)); 174 } 175 else 176 { 177 devices.Add(new Device(this, ptr)); 178 } 179 } 180 181 xml = Marshal.PtrToStringAnsi(iio_context_get_xml(ctx)); 182 name = Marshal.PtrToStringAnsi(iio_context_get_name(ctx)); 183 description = Marshal.PtrToStringAnsi(iio_context_get_description(ctx)); 184 185 uint major = 0; 186 uint minor = 0; 187 StringBuilder builder = new StringBuilder(8); 188 iio_library_get_version(ref major, ref minor, builder); 189 library_version = new Version(major, minor, builder.ToString()); 190 191 major = 0; 192 minor = 0; 193 builder.Clear(); 194 int err = iio_context_get_version(ctx, ref major, ref minor, builder); 195 if (err < 0) 196 { 197 throw new Exception("Unable to read backend version"); 198 } 199 backend_version = new Version(major, minor, builder.ToString()); 200 201 attrs = new Dictionary<string, string>(); 202 203 for (uint i = 0; i < iio_context_get_attrs_count(ctx); i++) 204 { 205 string attr_name = ""; 206 GCHandle name_handle = GCHandle.Alloc(attr_name, GCHandleType.Pinned); 207 IntPtr name_ptr = GCHandle.ToIntPtr(name_handle); 208 string attr_value = ""; 209 GCHandle value_handle = GCHandle.Alloc(attr_value, GCHandleType.Pinned); 210 IntPtr value_ptr = GCHandle.ToIntPtr(value_handle); 211 212 iio_context_get_attr(ctx, i, name_ptr, value_ptr); 213 attr_name = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(name_ptr)); 214 attr_value = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(value_ptr)); 215 216 attrs[attr_name] = attr_value; 217 } 218 } 219 ~Context()220 ~Context() 221 { 222 if (ctx != IntPtr.Zero) 223 { 224 Dispose(false); 225 } 226 } 227 228 /// <summary>Clone this instance.</summary> clone()229 public Context clone() 230 { 231 return new Context(iio_context_clone(this.ctx)); 232 } 233 234 /// <summary>Get the <see cref="iio.Device"/> object of the specified name.</summary> 235 /// <param name="name">Name or ID of the device to look for</param> 236 /// <exception cref="System.Exception">The IIO device with the specified 237 /// name or ID could not be found in the current context.</exception> get_device(string name)238 public Device get_device(string name) 239 { 240 foreach (Device each in devices) { 241 if (each.name.CompareTo(name) == 0 || 242 each.id.CompareTo(name) == 0) 243 { 244 return each; 245 } 246 } 247 248 throw new Exception("Device " + name + " not found"); 249 } 250 251 /// <summary>Set a timeout for I/O operations.</summary> 252 /// <param name="timeout">The timeout value, in milliseconds</param> 253 /// <exception cref="System.Exception">The timeout could not be applied.</exception> set_timeout(uint timeout)254 public void set_timeout(uint timeout) 255 { 256 int ret = iio_context_set_timeout(ctx, timeout); 257 if (ret < 0) 258 { 259 throw new Exception("Unable to set timeout"); 260 } 261 } 262 263 /// <summary>Releases all resource used by the <see cref="iio.Context"/> object.</summary> 264 /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="iio.Context"/>. The 265 /// <see cref="Dispose"/> method leaves the <see cref="iio.Context"/> in an unusable state. After calling 266 /// <see cref="Dispose"/>, you must release all references to the <see cref="iio.Context"/> so the garbage 267 /// collector can reclaim the memory that the <see cref="iio.Context"/> was occupying.</remarks> Dispose()268 public void Dispose() 269 { 270 Dispose(true); 271 } 272 Dispose(bool clean)273 private void Dispose(bool clean) 274 { 275 if (ctx != IntPtr.Zero) 276 { 277 if (clean) 278 { 279 GC.SuppressFinalize(this); 280 } 281 iio_context_destroy(ctx); 282 ctx = IntPtr.Zero; 283 } 284 } 285 286 /// <summary>Finds the device with the given name from the current context.</summary> 287 /// <param name="device">The name of the device.</param> 288 /// <exception cref="System.Exception">There is no device with the given name.</exception> find_device(string device)289 public Device find_device(string device) 290 { 291 IntPtr dev = iio_context_find_device(ctx, device); 292 293 if (dev == IntPtr.Zero) 294 { 295 throw new Exception("There is no device with the given name!"); 296 } 297 298 return new Device(this, dev); 299 } 300 } 301 } 302