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 /// <summary><see cref="iio.Device"/> class: 29 /// Contains the representation of an IIO device.</summary> 30 public class Device 31 { 32 private class DeviceAttr : Attr 33 { 34 internal IntPtr dev; 35 36 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len)37 private static extern int iio_device_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len); 38 39 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_attr_write(IntPtr dev, [In()] string name, [In()] string val)40 private static extern int iio_device_attr_write(IntPtr dev, [In()] string name, [In()] string val); 41 DeviceAttr(IntPtr dev, string name)42 public DeviceAttr(IntPtr dev, string name) : base(name) 43 { 44 this.dev = dev; 45 } 46 read()47 public override string read() 48 { 49 StringBuilder builder = new StringBuilder(1024); 50 int err = iio_device_attr_read(dev, name, builder, 1024); 51 if (err < 0) 52 { 53 throw new Exception("Unable to read device attribute " + err); 54 } 55 return builder.ToString(); 56 } 57 write(string str)58 public override void write(string str) 59 { 60 int err = iio_device_attr_write(dev, name, str); 61 if (err < 0) 62 { 63 throw new Exception("Unable to write device attribute " + err); 64 } 65 } 66 } 67 68 private class DeviceDebugAttr : Attr 69 { 70 private IntPtr dev; 71 72 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_debug_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len)73 private static extern int iio_device_debug_attr_read(IntPtr dev, [In()] string name, [Out()] StringBuilder val, uint len); 74 75 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_debug_attr_write(IntPtr dev, [In()] string name, [In()] string val)76 private static extern int iio_device_debug_attr_write(IntPtr dev, [In()] string name, [In()] string val); 77 DeviceDebugAttr(IntPtr dev, string name)78 public DeviceDebugAttr(IntPtr dev, string name) : base(name) 79 { 80 this.dev = dev; 81 } 82 read()83 public override string read() 84 { 85 StringBuilder builder = new StringBuilder(1024); 86 int err = iio_device_debug_attr_read(dev, name, builder, 1024); 87 if (err < 0) 88 { 89 throw new Exception("Unable to read debug attribute " + err); 90 } 91 return builder.ToString(); 92 } 93 write(string str)94 public override void write(string str) 95 { 96 int err = iio_device_debug_attr_write(dev, name, str); 97 if (err < 0) 98 { 99 throw new Exception("Unable to write debug attribute " + err); 100 } 101 } 102 } 103 104 private class DeviceBufferAttr : Attr 105 { 106 private IntPtr dev; 107 108 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_buffer_attr_read(IntPtr dev, [In] string name, [Out] StringBuilder val, uint len)109 private static extern int iio_device_buffer_attr_read(IntPtr dev, [In] string name, [Out] StringBuilder val, uint len); 110 111 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_buffer_attr_write(IntPtr dev, [In] string name, [In] string val)112 private static extern int iio_device_buffer_attr_write(IntPtr dev, [In] string name, [In] string val); 113 DeviceBufferAttr(IntPtr dev, string name)114 public DeviceBufferAttr(IntPtr dev, string name) : base(name) 115 { 116 this.dev = dev; 117 } 118 read()119 public override string read() 120 { 121 StringBuilder builder = new StringBuilder(16384); 122 int err = iio_device_buffer_attr_read(dev, name, builder, 16384); 123 if (err < 0) 124 { 125 throw new Exception("Unable to read buffer attribute " + err); 126 } 127 return builder.ToString(); 128 } 129 write(string str)130 public override void write(string str) 131 { 132 int err = iio_device_buffer_attr_write(dev, name, str); 133 if (err < 0) 134 { 135 throw new Exception("Unable to write buffer attribute " + err); 136 } 137 } 138 } 139 140 internal Context ctx; 141 142 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_id(IntPtr dev)143 private static extern IntPtr iio_device_get_id(IntPtr dev); 144 145 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_name(IntPtr dev)146 private static extern IntPtr iio_device_get_name(IntPtr dev); 147 148 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_channels_count(IntPtr dev)149 private static extern uint iio_device_get_channels_count(IntPtr dev); 150 151 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_channel(IntPtr dev, uint index)152 private static extern IntPtr iio_device_get_channel(IntPtr dev, uint index); 153 154 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_attrs_count(IntPtr dev)155 private static extern uint iio_device_get_attrs_count(IntPtr dev); 156 157 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_debug_attrs_count(IntPtr dev)158 private static extern uint iio_device_get_debug_attrs_count(IntPtr dev); 159 160 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_buffer_attrs_count(IntPtr dev)161 private static extern uint iio_device_get_buffer_attrs_count(IntPtr dev); 162 163 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_attr(IntPtr dev, uint index)164 private static extern IntPtr iio_device_get_attr(IntPtr dev, uint index); 165 166 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_debug_attr(IntPtr dev, uint index)167 private static extern IntPtr iio_device_get_debug_attr(IntPtr dev, uint index); 168 169 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_buffer_attr(IntPtr dev, uint index)170 private static extern IntPtr iio_device_get_buffer_attr(IntPtr dev, uint index); 171 172 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_trigger(IntPtr dev, IntPtr triggerptr)173 private static extern int iio_device_get_trigger(IntPtr dev, IntPtr triggerptr); 174 175 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_set_trigger(IntPtr dev, IntPtr trigger)176 private static extern int iio_device_set_trigger(IntPtr dev, IntPtr trigger); 177 178 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_sample_size(IntPtr dev)179 private static extern int iio_device_get_sample_size(IntPtr dev); 180 181 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_reg_write(IntPtr dev, uint addr, uint value)182 private static extern int iio_device_reg_write(IntPtr dev, uint addr, uint value); 183 184 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_reg_read(IntPtr dev, uint addr, ref uint value)185 private static extern int iio_device_reg_read(IntPtr dev, uint addr, ref uint value); 186 187 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_context(IntPtr dev)188 private static extern IntPtr iio_device_get_context(IntPtr dev); 189 190 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_set_kernel_buffers_count(IntPtr dev, uint nb)191 private static extern int iio_device_set_kernel_buffers_count(IntPtr dev, uint nb); 192 193 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_find_buffer_attr(IntPtr dev, [In] string name)194 private static extern IntPtr iio_device_find_buffer_attr(IntPtr dev, [In] string name); 195 196 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_find_debug_attr(IntPtr dev, [In] string name)197 private static extern IntPtr iio_device_find_debug_attr(IntPtr dev, [In] string name); 198 199 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_find_attr(IntPtr dev, [In] string name)200 private static extern IntPtr iio_device_find_attr(IntPtr dev, [In] string name); 201 202 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_find_channel(IntPtr dev, [In] string name, [In] bool output)203 private static extern IntPtr iio_device_find_channel(IntPtr dev, [In] string name, [In] bool output); 204 205 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_identify_filename(IntPtr dev, [In] string filename, out IntPtr chn_ptr, out IntPtr attr)206 private static extern int iio_device_identify_filename(IntPtr dev, [In] string filename, out IntPtr chn_ptr, out IntPtr attr); 207 208 internal IntPtr dev; 209 210 /// <summary>An identifier of this device.</summary> 211 /// <remarks>The identifier is only valid in this IIO context</remarks> 212 public readonly string id; 213 214 /// <summary>The name of this device.</summary> 215 public readonly string name; 216 217 /// <summary>A <c>list</c> of all the attributes that this device has.</summary> 218 public readonly List<Attr> attrs; 219 220 /// <summary>A <c>list</c> of all the debug attributes that this device has.</summary> 221 public readonly List<Attr> debug_attrs; 222 223 /// <summary>A <c>list</c> of all the buffer attributes that this device has.</summary> 224 public List<Attr> buffer_attrs { get; private set; } 225 226 /// <summary>A <c>list</c> of all the <see cref="iio.Channel"/> objects that this device possesses.</summary> 227 public readonly List<Channel> channels; 228 Device(Context ctx, IntPtr dev)229 internal Device(Context ctx, IntPtr dev) 230 { 231 this.ctx = ctx; 232 this.dev = dev; 233 channels = new List<Channel>(); 234 attrs = new List<Attr>(); 235 debug_attrs = new List<Attr>(); 236 buffer_attrs = new List<Attr>(); 237 238 uint nb_channels = iio_device_get_channels_count(dev); 239 uint nb_attrs = iio_device_get_attrs_count(dev); 240 uint nb_debug_attrs = iio_device_get_debug_attrs_count(dev); 241 uint nb_buffer_attrs = iio_device_get_buffer_attrs_count(dev); 242 243 for (uint i = 0; i < nb_channels; i++) 244 { 245 channels.Add(new Channel(iio_device_get_channel(dev, i))); 246 } 247 248 for (uint i = 0; i < nb_attrs; i++) 249 { 250 attrs.Add(new DeviceAttr(dev, Marshal.PtrToStringAnsi(iio_device_get_attr(dev, i)))); 251 } 252 253 for (uint i = 0; i < nb_debug_attrs; i++) 254 { 255 debug_attrs.Add(new DeviceDebugAttr(dev, Marshal.PtrToStringAnsi(iio_device_get_debug_attr(dev, i)))); 256 } 257 258 for (uint i = 0; i < nb_buffer_attrs; i++) 259 { 260 buffer_attrs.Add(new DeviceBufferAttr(dev, Marshal.PtrToStringAnsi(iio_device_get_buffer_attr(dev, i)))); 261 } 262 263 id = Marshal.PtrToStringAnsi(iio_device_get_id(dev)); 264 265 IntPtr name_ptr = iio_device_get_name(dev); 266 if (name_ptr == IntPtr.Zero) 267 { 268 name = ""; 269 } 270 else 271 { 272 name = Marshal.PtrToStringAnsi(name_ptr); 273 } 274 } 275 276 /// <summary>Get the <see cref="iio.Channel"/> object of the specified name.</summary> 277 /// <param name="name">Name or ID of the channel to look for</param> 278 /// <exception cref="System.Exception">The IIO device with the specified 279 /// name or ID could not be found in the current context.</exception> get_channel(string name)280 public Channel get_channel(string name) 281 { 282 foreach (Channel each in channels) 283 { 284 if (each.name.CompareTo(name) == 0 || 285 each.id.CompareTo(name) == 0) 286 { 287 return each; 288 } 289 } 290 291 throw new Exception("Channel " + name + " not found"); 292 } 293 294 /// <summary>Affect a trigger to this device.</summary> 295 /// <param name="trig">A valid instance of the <see cref="iio.Trigger"/> class.</param> 296 /// <exception cref="System.Exception">The trigger could not be set.</exception> set_trigger(Trigger trig)297 public void set_trigger(Trigger trig) 298 { 299 int err = iio_device_set_trigger(this.dev, trig == null ? IntPtr.Zero : trig.dev); 300 if (err < 0) 301 { 302 throw new Exception("Unable to set trigger: err=" + err); 303 } 304 } 305 306 /// <summary>Get the current trigger affected to this device.</summary> 307 /// <returns>An instance of the <see cref="iio.Trigger"/> class.</returns> 308 /// <exception cref="System.Exception">The instance could not be retrieved.</exception> get_trigger()309 public Trigger get_trigger() 310 { 311 IntPtr ptr = (IntPtr)0; 312 int err = iio_device_get_trigger(this.dev, ptr); 313 if (err < 0) 314 { 315 throw new Exception("Unable to get trigger: err=" + err); 316 } 317 318 ptr = Marshal.ReadIntPtr(ptr); 319 320 foreach (Trigger trig in ctx.devices) 321 { 322 if (trig.dev == ptr) 323 { 324 return trig; 325 } 326 } 327 328 return null; 329 } 330 331 /// <summary>Get the current sample size of the device.</summary> 332 /// <remarks>The sample size varies each time channels get enabled or disabled.</remarks> 333 /// <exception cref="System.Exception">Internal error. Please report any bug.</exception> get_sample_size()334 public uint get_sample_size() 335 { 336 int ret = iio_device_get_sample_size(dev); 337 if (ret < 0) 338 { 339 throw new Exception("Internal error. Please report any bug."); 340 } 341 return (uint) ret; 342 } 343 /// <summary>Set a value to one register of this device.</summary> 344 /// <param name="addr">The address of the register concerned.</param> 345 /// <param name="value">The value that will be used for this register.</param> 346 /// <exception cref="System.Exception">The register could not be written.</exception> reg_write(uint addr, uint value)347 public void reg_write(uint addr, uint value) 348 { 349 int err = iio_device_reg_write(dev, addr, value); 350 if (err < 0) 351 { 352 throw new Exception("Unable to write register"); 353 } 354 } 355 356 /// <summary>Read the content of a register of this device.</summary> 357 /// <param name="addr">The address of the register concerned.</param> 358 /// <exception cref="System.Exception">The register could not be read.</exception> reg_read(uint addr)359 public uint reg_read(uint addr) 360 { 361 uint value = 0; 362 int err = iio_device_reg_read(dev, addr, ref value); 363 if (err < 0) 364 { 365 throw new Exception("Unable to read register"); 366 } 367 return value; 368 } 369 370 /// <summary>Sets the number of active kernel buffers for this device.</summary> 371 /// <param name="nb">The number of kernel buffers.</param> set_kernel_buffers_count(uint nb)372 public int set_kernel_buffers_count(uint nb) 373 { 374 return iio_device_set_kernel_buffers_count(dev, nb); 375 } 376 377 /// <summary>Gets the context of the current device.</summary> 378 /// <returns>An instance of the <see cref="iio.Context"/> class.</returns> get_context()379 public Context get_context() 380 { 381 return new Context(iio_device_get_context(dev)); 382 } 383 384 /// <summary>Finds the channel with the given name from the current device.</summary> 385 /// <param name="channel">The name of the channel.</param> 386 /// <param name="output">true if you are looking for an output channel, otherwise false.</param> 387 /// <returns>An instance of the <see cref="iio.Channel"/> class.</returns> 388 /// <exception cref="System.Exception">There is no channel with the given name.</exception> find_channel(string channel, bool output)389 public Channel find_channel(string channel, bool output) 390 { 391 IntPtr chn = iio_device_find_channel(dev, channel, output); 392 393 if (chn == IntPtr.Zero) 394 { 395 throw new Exception("There is no channel with the given name!"); 396 } 397 398 return new Channel(chn); 399 } 400 401 /// <summary>Finds the attribute with the given name from the current device.</summary> 402 /// <param name="attribute">The name of the attribute.</param> 403 /// <returns>An instance of the <see cref="iio.Device.DeviceAttr"/> class.</returns> 404 /// <exception cref="System.Exception">There is no attribute with the given name.</exception> find_attribute(string attribute)405 public Attr find_attribute(string attribute) 406 { 407 IntPtr attr = iio_device_find_attr(dev, attribute); 408 409 if (attr == IntPtr.Zero) 410 { 411 throw new Exception("This device has no attribute with the given name!"); 412 } 413 414 return new DeviceAttr(dev, Marshal.PtrToStringAnsi(attr)); 415 } 416 417 /// <summary>Finds the debug attribute with the given name from the current device.</summary> 418 /// <param name="attribute">The name of the debug attribute.</param> 419 /// <returns>An instance of the <see cref="iio.Device.DeviceDebugAttr"/> class.</returns> 420 /// <exception cref="System.Exception">There is no debug attribute with the given name.</exception> find_debug_attribute(string attribute)421 public Attr find_debug_attribute(string attribute) 422 { 423 IntPtr attr = iio_device_find_debug_attr(dev, attribute); 424 425 if (attr == IntPtr.Zero) 426 { 427 throw new Exception("This device has no debug attribute with the given name!"); 428 } 429 430 return new DeviceDebugAttr(dev, Marshal.PtrToStringAnsi(attr)); 431 } 432 433 /// <summary>Finds the buffer attribute with the given name from the current device.</summary> 434 /// <param name="attribute">The name of the buffer attribute.</param> 435 /// <returns>An instance of the <see cref="iio.Device.DeviceBufferAttr"/> class.</returns> 436 /// <exception cref="System.Exception">There is no attribute with the given name.</exception> find_buffer_attribute(string attribute)437 public Attr find_buffer_attribute(string attribute) 438 { 439 IntPtr attr = iio_device_find_buffer_attr(dev, attribute); 440 441 if (attr == IntPtr.Zero) 442 { 443 throw new Exception("This device has no buffer attribute with the given name!"); 444 } 445 446 return new DeviceBufferAttr(dev, Marshal.PtrToStringAnsi(attr)); 447 } 448 449 /// <summary>Finds the channel attribute coresponding to the given filename from the current device.</summary> 450 /// <param name="filename">The name of the attribute.</param> 451 /// <param name="chn_ptr">Output variable. It will contain a pointer to the resulting <see cref="iio.Channel"/>.</param> 452 /// <param name="attr">Output variable. It will contain a pointer to the resulting <see cref="iio.ChannelAttr"/>.</param> 453 /// <returns>C errorcode if error encountered, otherwise 0.</returns> identify_filename(string filename, IntPtr chn_ptr, IntPtr attr)454 public int identify_filename(string filename, IntPtr chn_ptr, IntPtr attr) 455 { 456 return iio_device_identify_filename(dev, filename, out chn_ptr, out attr); 457 } 458 } 459 } 460