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.IO; 22 using System.Linq; 23 using System.Runtime.InteropServices; 24 using System.Text; 25 using System.Threading.Tasks; 26 27 namespace iio 28 { 29 /// <summary><see cref="iio.Channel"/> class: 30 /// Contains the representation of an input or output channel.</summary> 31 public class Channel 32 { 33 private class ChannelAttr : Attr 34 { 35 private IntPtr chn; 36 37 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_read(IntPtr chn, [In()] string name, [Out()] StringBuilder val, uint len)38 private static extern int iio_channel_attr_read(IntPtr chn, [In()] string name, [Out()] StringBuilder val, uint len); 39 40 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_write(IntPtr chn, [In()] string name, string val)41 private static extern int iio_channel_attr_write(IntPtr chn, [In()] string name, string val); 42 43 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_get_filename(IntPtr chn, [In()] string attr)44 private static extern IntPtr iio_channel_attr_get_filename(IntPtr chn, [In()] string attr); 45 ChannelAttr(IntPtr chn, string name)46 public ChannelAttr(IntPtr chn, string name) : base(name, Marshal.PtrToStringAnsi(iio_channel_attr_get_filename(chn, name))) 47 { 48 this.chn = chn; 49 } 50 read()51 public override string read() 52 { 53 StringBuilder builder = new StringBuilder(1024); 54 int err = iio_channel_attr_read(chn, name, builder, (uint) builder.Capacity); 55 if (err < 0) 56 throw new Exception("Unable to read channel attribute " + err); 57 return builder.ToString(); 58 } 59 write(string str)60 public override void write(string str) 61 { 62 int err = iio_channel_attr_write(chn, name, str); 63 if (err < 0) 64 throw new Exception("Unable to write channel attribute " + err); 65 } 66 } 67 68 69 private IntPtr chn; 70 private uint sample_size; 71 72 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_id(IntPtr chn)73 private static extern IntPtr iio_channel_get_id(IntPtr chn); 74 75 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_name(IntPtr chn)76 private static extern IntPtr iio_channel_get_name(IntPtr chn); 77 78 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_attrs_count(IntPtr chn)79 private static extern uint iio_channel_get_attrs_count(IntPtr chn); 80 81 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_attr(IntPtr chn, uint index)82 private static extern IntPtr iio_channel_get_attr(IntPtr chn, uint index); 83 84 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 85 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_output(IntPtr chn)86 private static extern bool iio_channel_is_output(IntPtr chn); 87 88 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 89 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_scan_element(IntPtr chn)90 private static extern bool iio_channel_is_scan_element(IntPtr chn); 91 92 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_enable(IntPtr chn)93 private static extern void iio_channel_enable(IntPtr chn); 94 95 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_disable(IntPtr chn)96 private static extern void iio_channel_disable(IntPtr chn); 97 98 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 99 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_enabled(IntPtr chn)100 private static extern bool iio_channel_is_enabled(IntPtr chn); 101 102 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len)103 private static extern uint iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len); 104 105 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len)106 private static extern uint iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len); 107 108 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len)109 private static extern uint iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len); 110 111 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len)112 private static extern uint iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len); 113 114 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_data_format(IntPtr chn)115 private static extern IntPtr iio_channel_get_data_format(IntPtr chn); 116 117 /// <summary>The name of this channel.</summary> 118 public readonly string name; 119 120 /// <summary>An identifier of this channel.</summary> 121 /// <remarks>It is possible that two channels have the same ID, 122 /// if one is an input channel and the other is an output channel.</remarks> 123 public readonly string id; 124 125 /// <summary>Contains <c>true</c> if the channel is an output channel, 126 /// <c>false</c> otherwise.</summary> 127 public readonly bool output; 128 129 /// <summary>Contains <c>true</c> if the channel is a scan element, 130 /// <c>false</c> otherwise.</summary> 131 /// <remarks>If a channel is a scan element, then it is possible to enable it 132 /// and use it for I/O operations.</remarks> 133 public readonly bool scan_element; 134 135 /// <summary>A <c>list</c> of all the attributes that this channel has.</summary> 136 public readonly List<Attr> attrs; 137 Channel(IntPtr chn)138 internal Channel(IntPtr chn) 139 { 140 this.chn = chn; 141 attrs = new List<Attr>(); 142 sample_size = (uint)Marshal.ReadInt32(iio_channel_get_data_format(this.chn)) / 8; 143 uint nb_attrs = iio_channel_get_attrs_count(chn); 144 145 for (uint i = 0; i < nb_attrs; i++) 146 attrs.Add(new ChannelAttr(this.chn, Marshal.PtrToStringAnsi(iio_channel_get_attr(chn, i)))); 147 148 IntPtr name_ptr = iio_channel_get_name(this.chn); 149 if (name_ptr == IntPtr.Zero) 150 name = ""; 151 else 152 name = Marshal.PtrToStringAnsi(name_ptr); 153 154 id = Marshal.PtrToStringAnsi(iio_channel_get_id(this.chn)); 155 output = iio_channel_is_output(this.chn); 156 scan_element = iio_channel_is_scan_element(this.chn); 157 } 158 159 /// <summary>Enable the current channel, so that it can be used for I/O operations.</summary> enable()160 public void enable() 161 { 162 iio_channel_enable(this.chn); 163 } 164 165 /// <summary>Disable the current channel.</summary> disable()166 public void disable() 167 { 168 iio_channel_disable(this.chn); 169 } 170 171 /// <summary>Returns whether or not the channel has been enabled.</summary> is_enabled()172 public bool is_enabled() 173 { 174 return iio_channel_is_enabled(this.chn); 175 } 176 177 /// <summary>Extract the samples corresponding to this channel from the 178 /// given <see cref="iio.IOBuffer"/> object.</summary> 179 /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param> 180 /// <param name="raw">If set to <c>true</c>, the samples are not converted from their 181 /// hardware format to their host format.</param> 182 /// <returns>A <c>byte</c> array containing the extracted samples.</returns> 183 /// <exception cref="System.Exception">The samples could not be read.</exception> read(IOBuffer buffer, bool raw = false)184 public byte[] read(IOBuffer buffer, bool raw = false) 185 { 186 if (!is_enabled()) 187 throw new Exception("Channel must be enabled before the IOBuffer is instantiated"); 188 if (this.output) 189 throw new Exception("Unable to read from output channel"); 190 191 byte[] array = new byte[(int) (buffer.samples_count * sample_size)]; 192 MemoryStream stream = new MemoryStream(array, true); 193 GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); 194 IntPtr addr = handle.AddrOfPinnedObject(); 195 uint count; 196 197 if (raw) 198 count = iio_channel_read_raw(this.chn, buffer.buf, addr, buffer.samples_count * sample_size); 199 else 200 count = iio_channel_read(this.chn, buffer.buf, addr, buffer.samples_count * sample_size); 201 handle.Free(); 202 stream.SetLength((long) count); 203 return stream.ToArray(); 204 205 } 206 207 /// <summary> 208 /// Write the specified array of samples corresponding to this channel into the 209 /// given <see cref="iio.IOBuffer"/> object.</summary> 210 /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param> 211 /// <param name="array">A <c>byte</c> array containing the samples to write.</param> 212 /// <param name="raw">If set to <c>true</c>, the samples are not converted from their 213 /// host format to their native format.</param> 214 /// <returns>The number of bytes written.</returns> 215 /// <exception cref="System.Exception">The samples could not be written.</exception> write(IOBuffer buffer, byte[] array, bool raw = false)216 public uint write(IOBuffer buffer, byte[] array, bool raw = false) 217 { 218 if (!is_enabled()) 219 throw new Exception("Channel must be enabled before the IOBuffer is instantiated"); 220 if (!this.output) 221 throw new Exception("Unable to write to an input channel"); 222 223 GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); 224 IntPtr addr = handle.AddrOfPinnedObject(); 225 uint count; 226 227 if (raw) 228 count = iio_channel_write_raw(this.chn, buffer.buf, addr, (uint) array.Length); 229 else 230 count = iio_channel_write(this.chn, buffer.buf, addr, (uint) array.Length); 231 handle.Free(); 232 233 return count; 234 } 235 } 236 } 237