• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright (C) 2014 Analog Devices, Inc.
4# Author: Paul Cercueil <paul.cercueil@analog.com>
5#
6# This library is free software; you can redistribute it and/or
7# modify it under the terms of the GNU Lesser General Public
8# License as published by the Free Software Foundation; either
9# version 2.1 of the License, or (at your option) any later version.
10#
11# This library is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14# Lesser General Public License for more details.
15
16from ctypes import Structure, c_char_p, c_uint, c_int, c_size_t, \
17		c_ssize_t, c_char, c_void_p, c_bool, create_string_buffer, \
18		POINTER as _POINTER, CDLL as _cdll, memmove as _memmove, byref as _byref
19from os import strerror as _strerror
20from platform import system as _system
21import weakref
22
23if 'Windows' in _system():
24	from ctypes import get_last_error
25else:
26	from ctypes import get_errno
27
28def _checkNull(result, func, arguments):
29	if result:
30		return result
31	else:
32		err = get_last_error() if 'Windows' in _system() else get_errno()
33		raise OSError(err, _strerror(err))
34
35def _checkNegative(result, func, arguments):
36	if result >= 0:
37		return result
38	else:
39		raise OSError(-result, _strerror(-result))
40
41class _ScanContext(Structure):
42	pass
43class _ContextInfo(Structure):
44	pass
45class _Context(Structure):
46	pass
47class _Device(Structure):
48	pass
49class _Channel(Structure):
50	pass
51class _Buffer(Structure):
52	pass
53
54_ScanContextPtr = _POINTER(_ScanContext)
55_ContextInfoPtr = _POINTER(_ContextInfo)
56_ContextPtr = _POINTER(_Context)
57_DevicePtr = _POINTER(_Device)
58_ChannelPtr = _POINTER(_Channel)
59_BufferPtr = _POINTER(_Buffer)
60
61_lib = _cdll('libiio.dll' if 'Windows' in _system() else 'libiio.so.0',
62		use_errno = True, use_last_error = True)
63
64_get_backends_count = _lib.iio_get_backends_count
65_get_backends_count.restype = c_uint
66
67_get_backend = _lib.iio_get_backend
68_get_backend.argtypes = (c_uint, )
69_get_backend.restype = c_char_p
70_get_backend.errcheck = _checkNull
71
72_create_scan_context = _lib.iio_create_scan_context
73_create_scan_context.argtypes = (c_char_p, c_uint)
74_create_scan_context.restype = _ScanContextPtr
75_create_scan_context.errcheck = _checkNull
76
77_destroy_scan_context = _lib.iio_scan_context_destroy
78_destroy_scan_context.argtypes = (_ScanContextPtr, )
79
80_get_context_info_list = _lib.iio_scan_context_get_info_list
81_get_context_info_list.argtypes = (_ScanContextPtr, _POINTER(_POINTER(_ContextInfoPtr)))
82_get_context_info_list.restype = c_ssize_t
83_get_context_info_list.errcheck = _checkNegative
84
85_context_info_list_free = _lib.iio_context_info_list_free
86_context_info_list_free.argtypes = (_POINTER(_ContextInfoPtr), )
87
88_context_info_get_description = _lib.iio_context_info_get_description
89_context_info_get_description.argtypes = (_ContextInfoPtr, )
90_context_info_get_description.restype = c_char_p
91
92_context_info_get_uri = _lib.iio_context_info_get_uri
93_context_info_get_uri.argtypes = (_ContextInfoPtr, )
94_context_info_get_uri.restype = c_char_p
95
96_new_local = _lib.iio_create_local_context
97_new_local.restype = _ContextPtr
98_new_local.errcheck = _checkNull
99
100_new_xml = _lib.iio_create_xml_context
101_new_xml.restype = _ContextPtr
102_new_xml.argtypes = (c_char_p, )
103_new_xml.errcheck = _checkNull
104
105_new_network = _lib.iio_create_network_context
106_new_network.restype = _ContextPtr
107_new_network.argtypes = (c_char_p, )
108_new_network.errcheck = _checkNull
109
110_new_default = _lib.iio_create_default_context
111_new_default.restype = _ContextPtr
112_new_default.errcheck = _checkNull
113
114_new_uri = _lib.iio_create_context_from_uri
115_new_uri.restype = _ContextPtr
116_new_uri.errcheck = _checkNull
117
118_destroy = _lib.iio_context_destroy
119_destroy.argtypes = (_ContextPtr, )
120
121_get_name = _lib.iio_context_get_name
122_get_name.restype = c_char_p
123_get_name.argtypes = (_ContextPtr, )
124_get_name.errcheck = _checkNull
125
126_get_description = _lib.iio_context_get_description
127_get_description.restype = c_char_p
128_get_description.argtypes = (_ContextPtr, )
129
130_get_xml = _lib.iio_context_get_xml
131_get_xml.restype = c_char_p
132_get_xml.argtypes = (_ContextPtr, )
133
134_get_library_version = _lib.iio_library_get_version
135_get_library_version.argtypes = (_POINTER(c_uint), _POINTER(c_uint), c_char_p, )
136
137_get_version = _lib.iio_context_get_version
138_get_version.restype = c_int
139_get_version.argtypes = (_ContextPtr, _POINTER(c_uint), _POINTER(c_uint), c_char_p, )
140_get_version.errcheck = _checkNegative
141
142_get_attrs_count = _lib.iio_context_get_attrs_count
143_get_attrs_count.restype = c_uint
144_get_attrs_count.argtypes = (_ContextPtr, )
145
146_get_attr = _lib.iio_context_get_attr
147_get_attr.restype = c_int
148_get_attr.argtypes = (_ContextPtr, c_uint, _POINTER(c_char_p), _POINTER(c_char_p))
149_get_attr.errcheck = _checkNegative
150
151_devices_count = _lib.iio_context_get_devices_count
152_devices_count.restype = c_uint
153_devices_count.argtypes = (_ContextPtr, )
154
155_get_device = _lib.iio_context_get_device
156_get_device.restype = _DevicePtr
157_get_device.argtypes = (_ContextPtr, c_uint)
158_get_device.errcheck = _checkNull
159
160_set_timeout = _lib.iio_context_set_timeout
161_set_timeout.restype = c_int
162_set_timeout.argtypes = (_ContextPtr, c_uint, )
163_set_timeout.errcheck = _checkNegative
164
165_clone = _lib.iio_context_clone
166_clone.restype = _ContextPtr
167_clone.argtypes = (_ContextPtr, )
168_clone.errcheck = _checkNull
169
170_d_get_id = _lib.iio_device_get_id
171_d_get_id.restype = c_char_p
172_d_get_id.argtypes = (_DevicePtr, )
173_d_get_id.errcheck = _checkNull
174
175_d_get_name = _lib.iio_device_get_name
176_d_get_name.restype = c_char_p
177_d_get_name.argtypes = (_DevicePtr, )
178
179_d_attr_count = _lib.iio_device_get_attrs_count
180_d_attr_count.restype = c_uint
181_d_attr_count.argtypes = (_DevicePtr, )
182
183_d_get_attr = _lib.iio_device_get_attr
184_d_get_attr.restype = c_char_p
185_d_get_attr.argtypes = (_DevicePtr, )
186_d_get_attr.errcheck = _checkNull
187
188_d_read_attr = _lib.iio_device_attr_read
189_d_read_attr.restype = c_ssize_t
190_d_read_attr.argtypes = (_DevicePtr, c_char_p, c_char_p, c_size_t)
191_d_read_attr.errcheck = _checkNegative
192
193_d_write_attr = _lib.iio_device_attr_write
194_d_write_attr.restype = c_ssize_t
195_d_write_attr.argtypes = (_DevicePtr, c_char_p, c_char_p)
196_d_write_attr.errcheck = _checkNegative
197
198_d_debug_attr_count = _lib.iio_device_get_debug_attrs_count
199_d_debug_attr_count.restype = c_uint
200_d_debug_attr_count.argtypes = (_DevicePtr, )
201
202_d_get_debug_attr = _lib.iio_device_get_debug_attr
203_d_get_debug_attr.restype = c_char_p
204_d_get_debug_attr.argtypes = (_DevicePtr, )
205_d_get_debug_attr.errcheck = _checkNull
206
207_d_read_debug_attr = _lib.iio_device_debug_attr_read
208_d_read_debug_attr.restype = c_ssize_t
209_d_read_debug_attr.argtypes = (_DevicePtr, c_char_p, c_char_p, c_size_t)
210_d_read_debug_attr.errcheck = _checkNegative
211
212_d_write_debug_attr = _lib.iio_device_debug_attr_write
213_d_write_debug_attr.restype = c_ssize_t
214_d_write_debug_attr.argtypes = (_DevicePtr, c_char_p, c_char_p)
215_d_write_debug_attr.errcheck = _checkNegative
216
217_d_reg_write = _lib.iio_device_reg_write
218_d_reg_write.restype = c_int
219_d_reg_write.argtypes = (_DevicePtr, c_uint, c_uint)
220_d_reg_write.errcheck = _checkNegative
221
222_d_reg_read = _lib.iio_device_reg_read
223_d_reg_read.restype = c_int
224_d_reg_read.argtypes = (_DevicePtr, c_uint, _POINTER(c_uint))
225_d_reg_read.errcheck = _checkNegative
226
227_channels_count = _lib.iio_device_get_channels_count
228_channels_count.restype = c_uint
229_channels_count.argtypes = (_DevicePtr, )
230
231_get_channel = _lib.iio_device_get_channel
232_get_channel.restype = _ChannelPtr
233_get_channel.argtypes = (_DevicePtr, c_uint)
234_get_channel.errcheck = _checkNull
235
236_get_sample_size = _lib.iio_device_get_sample_size
237_get_sample_size.restype = c_int
238_get_sample_size.argtypes = (_DevicePtr, )
239_get_sample_size.errcheck = _checkNegative
240
241_d_is_trigger = _lib.iio_device_is_trigger
242_d_is_trigger.restype = c_bool
243_d_is_trigger.argtypes = (_DevicePtr, )
244
245_d_get_trigger = _lib.iio_device_get_trigger
246_d_get_trigger.restype = c_int
247_d_get_trigger.argtypes = (_DevicePtr, _DevicePtr, )
248_d_get_trigger.errcheck = _checkNegative
249
250_d_set_trigger = _lib.iio_device_set_trigger
251_d_set_trigger.restype = c_int
252_d_set_trigger.argtypes = (_DevicePtr, _DevicePtr, )
253_d_set_trigger.errcheck = _checkNegative
254
255_d_set_buffers_count = _lib.iio_device_set_kernel_buffers_count
256_d_set_buffers_count.restype = c_int
257_d_set_buffers_count.argtypes = (_DevicePtr, c_uint)
258_d_set_buffers_count.errcheck = _checkNegative
259
260_c_get_id = _lib.iio_channel_get_id
261_c_get_id.restype = c_char_p
262_c_get_id.argtypes = (_ChannelPtr, )
263_c_get_id.errcheck = _checkNull
264
265_c_get_name = _lib.iio_channel_get_name
266_c_get_name.restype = c_char_p
267_c_get_name.argtypes = (_ChannelPtr, )
268
269_c_is_output = _lib.iio_channel_is_output
270_c_is_output.restype = c_bool
271_c_is_output.argtypes = (_ChannelPtr, )
272
273_c_is_scan_element = _lib.iio_channel_is_scan_element
274_c_is_scan_element.restype = c_bool
275_c_is_scan_element.argtypes = (_ChannelPtr, )
276
277_c_attr_count = _lib.iio_channel_get_attrs_count
278_c_attr_count.restype = c_uint
279_c_attr_count.argtypes = (_ChannelPtr, )
280
281_c_get_attr = _lib.iio_channel_get_attr
282_c_get_attr.restype = c_char_p
283_c_get_attr.argtypes = (_ChannelPtr, )
284_c_get_attr.errcheck = _checkNull
285
286_c_get_filename = _lib.iio_channel_attr_get_filename
287_c_get_filename.restype = c_char_p
288_c_get_filename.argtypes = (_ChannelPtr, c_char_p, )
289_c_get_filename.errcheck = _checkNull
290
291_c_read_attr = _lib.iio_channel_attr_read
292_c_read_attr.restype = c_ssize_t
293_c_read_attr.argtypes = (_ChannelPtr, c_char_p, c_char_p, c_size_t)
294_c_read_attr.errcheck = _checkNegative
295
296_c_write_attr = _lib.iio_channel_attr_write
297_c_write_attr.restype = c_ssize_t
298_c_write_attr.argtypes = (_ChannelPtr, c_char_p, c_char_p)
299_c_write_attr.errcheck = _checkNegative
300
301_c_enable = _lib.iio_channel_enable
302_c_enable.argtypes = (_ChannelPtr, )
303
304_c_disable = _lib.iio_channel_disable
305_c_disable.argtypes = (_ChannelPtr, )
306
307_c_is_enabled = _lib.iio_channel_is_enabled
308_c_is_enabled.restype = c_bool
309_c_is_enabled.argtypes = (_ChannelPtr, )
310
311_c_read = _lib.iio_channel_read
312_c_read.restype = c_ssize_t
313_c_read.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
314
315_c_read_raw = _lib.iio_channel_read_raw
316_c_read_raw.restype = c_ssize_t
317_c_read_raw.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
318
319_c_write = _lib.iio_channel_write
320_c_write.restype = c_ssize_t
321_c_write.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
322
323_c_write_raw = _lib.iio_channel_write_raw
324_c_write_raw.restype = c_ssize_t
325_c_write_raw.argtypes = (_ChannelPtr, _BufferPtr, c_void_p, c_size_t, )
326
327_create_buffer = _lib.iio_device_create_buffer
328_create_buffer.restype = _BufferPtr
329_create_buffer.argtypes = (_DevicePtr, c_size_t, c_bool, )
330_create_buffer.errcheck = _checkNull
331
332_buffer_destroy = _lib.iio_buffer_destroy
333_buffer_destroy.argtypes = (_BufferPtr, )
334
335_buffer_refill = _lib.iio_buffer_refill
336_buffer_refill.restype = c_ssize_t
337_buffer_refill.argtypes = (_BufferPtr, )
338_buffer_refill.errcheck = _checkNegative
339
340_buffer_push_partial = _lib.iio_buffer_push_partial
341_buffer_push_partial.restype = c_ssize_t
342_buffer_push_partial.argtypes = (_BufferPtr, c_uint, )
343_buffer_push_partial.errcheck = _checkNegative
344
345_buffer_start = _lib.iio_buffer_start
346_buffer_start.restype = c_void_p
347_buffer_start.argtypes = (_BufferPtr, )
348
349_buffer_end = _lib.iio_buffer_end
350_buffer_end.restype = c_void_p
351_buffer_end.argtypes = (_BufferPtr, )
352
353def _get_lib_version():
354	major = c_uint()
355	minor = c_uint()
356	buf = create_string_buffer(8)
357	_get_library_version(_byref(major), _byref(minor), buf)
358	return (major.value, minor.value, buf.value.decode('ascii') )
359
360version = _get_lib_version()
361backends = [ _get_backend(x).decode('ascii') for x in range(0, _get_backends_count()) ]
362
363class _Attr(object):
364	def __init__(self, name, filename = None):
365		self._name = name
366		self._name_ascii = name.encode('ascii')
367		self._filename = name if filename is None else filename
368
369	def __str__(self):
370		return self._name
371
372	name = property(lambda self: self._name, None, None,
373			"The name of this attribute.\n\ttype=str")
374	filename = property(lambda self: self._filename, None, None,
375			"The filename in sysfs to which this attribute is bound.\n\ttype=str")
376	value = property(lambda self: self.__read(), lambda self, x: self.__write(x),
377			None, "Current value of this attribute.\n\ttype=str")
378
379class ChannelAttr(_Attr):
380	"""Represents an attribute of a channel."""
381
382	def __init__(self, channel, name):
383		super(ChannelAttr, self).__init__(name, _c_get_filename(channel, name.encode('ascii')).decode('ascii'))
384		self._channel = channel
385
386	def _Attr__read(self):
387		buf = create_string_buffer(1024)
388		_c_read_attr(self._channel, self._name_ascii, buf, len(buf))
389		return buf.value.decode('ascii')
390
391	def _Attr__write(self, value):
392		_c_write_attr(self._channel, self._name_ascii, value.encode('ascii'))
393
394class DeviceAttr(_Attr):
395	"""Represents an attribute of an IIO device."""
396
397	def __init__(self, device, name):
398		super(DeviceAttr, self).__init__(name)
399		self._device = device
400
401	def _Attr__read(self):
402		buf = create_string_buffer(1024)
403		_d_read_attr(self._device, self._name_ascii, buf, len(buf))
404		return buf.value.decode('ascii')
405
406	def _Attr__write(self, value):
407		_d_write_attr(self._device, self._name_ascii, value.encode('ascii'))
408
409class DeviceDebugAttr(DeviceAttr):
410	"""Represents a debug attribute of an IIO device."""
411
412	def __init__(self, device, name):
413		super(DeviceDebugAttr, self).__init__(device, name)
414
415	def _Attr__read(self):
416		buf = create_string_buffer(1024)
417		_d_read_debug_attr(self._device, self._name_ascii, buf, len(buf))
418		return buf.value.decode('ascii')
419
420	def _Attr__write(self, value):
421		_d_write_debug_attr(self._device, self._name_ascii, value.encode('ascii'))
422
423class Channel(object):
424	def __init__(self, _channel):
425		self._channel = _channel
426		self._attrs = { name : ChannelAttr(_channel, name) for name in \
427				[_c_get_attr(_channel, x).decode('ascii') for x in range(0, _c_attr_count(_channel))] }
428		self._id = _c_get_id(self._channel).decode('ascii')
429
430		name_raw = _c_get_name(self._channel)
431		self._name = name_raw.decode('ascii') if name_raw is not None else None
432		self._output = _c_is_output(self._channel)
433		self._scan_element = _c_is_scan_element(self._channel)
434
435	def read(self, buf, raw = False):
436		"""
437		Extract the samples corresponding to this channel from the given iio.Buffer object.
438
439		parameters:
440			buf: type=iio.Buffer
441				A valid instance of the iio.Buffer class
442			raw: type=bool
443				If set to True, the samples are not converted from their
444				native format to their host format
445
446		returns: type=bytearray
447			An array containing the samples for this channel
448		"""
449		array = bytearray(buf._length)
450		mytype = c_char * len(array)
451		c_array = mytype.from_buffer(array)
452		if raw:
453			length = _c_read_raw(self._channel, buf._buffer, c_array, len(array))
454		else:
455			length = _c_read(self._channel, buf._buffer, c_array, len(array))
456		return array[:length]
457
458	def write(self, buf, array, raw = False):
459		"""
460		Write the specified array of samples corresponding to this channel into the given iio.Buffer object.
461
462		parameters:
463			buf: type=iio.Buffer
464				A valid instance of the iio.Buffer class
465			array: type=bytearray
466				The array containing the samples to copy
467			raw: type=bool
468				If set to True, the samples are not converted from their
469				host format to their native format
470
471		returns: type=int
472			The number of bytes written
473		"""
474		mytype = c_char * len(array)
475		c_array = mytype.from_buffer(array)
476		if raw:
477			return _c_write_raw(self._channel, buf._buffer, c_array, len(array))
478		else:
479			return _c_write(self._channel, buf._buffer, c_array, len(array))
480
481	id = property(lambda self: self._id, None, None,
482			"An identifier of this channel.\n\tNote that it is possible that two channels have the same ID, if one is an input channel and the other is an output channel.\n\ttype=str")
483	name = property(lambda self: self._name, None, None,
484			"The name of this channel.\n\ttype=str")
485	attrs = property(lambda self: self._attrs, None, None,
486			"List of attributes for this channel.\n\ttype=dict of iio.ChannelAttr")
487	output = property(lambda self: self._output, None, None,
488			"Contains True if the channel is an output channel, False otherwise.\n\ttype=bool")
489	scan_element = property(lambda self: self._scan_element, None, None,
490			"Contains True if the channel is a scan element, False otherwise.\n\tIf a channel is a scan element, then it is possible to enable it and use it for I/O operations.\n\ttype=bool")
491	enabled = property(lambda self: _c_is_enabled(self._channel), \
492			lambda self, x: _c_enable(self._channel) if x else _c_disable(self._channel),
493			None, "Configured state of the channel\n\ttype=bool")
494
495class Buffer(object):
496	"""The class used for all I/O operations."""
497
498	def __init__(self, device, samples_count, cyclic = False):
499		"""
500		Initializes a new instance of the Buffer class.
501
502		parameters:
503			device: type=iio.Device
504				The iio.Device object that represents the device where the I/O
505				operations will be performed
506			samples_count: type=int
507				The size of the buffer, in samples
508			circular: type=bool
509				If set to True, the buffer is circular
510
511		returns: type=iio.Buffer
512			An new instance of this class
513		"""
514		try:
515			self._buffer = _create_buffer(device._device, samples_count, cyclic)
516		except:
517			self._buffer = None
518			raise
519		self._length = samples_count * device.sample_size
520		self._samples_count = samples_count
521
522		self._ctx = device.ctx()
523		# Holds a reference to the corresponding IIO Context. This ensures that
524		# every iio.Buffer object is destroyed before its corresponding IIO Context.
525
526	def __del__(self):
527		if self._buffer is not None:
528			_buffer_destroy(self._buffer)
529
530	def __len__(self):
531		"""The size of this buffer, in bytes."""
532		return self._length
533
534	def refill(self):
535		"""Fetch a new set of samples from the hardware."""
536		_buffer_refill(self._buffer)
537
538	def push(self, samples_count = None):
539		"""
540		Submit the samples contained in this buffer to the hardware.
541
542		parameters:
543			samples_count: type=int
544				The number of samples to submit, default = full buffer
545		"""
546		_buffer_push_partial(self._buffer, samples_count or self._samples_count)
547
548	def read(self):
549		"""
550		Retrieve the samples contained inside the Buffer object.
551
552		returns: type=bytearray
553			An array containing the samples
554		"""
555
556		start = _buffer_start(self._buffer)
557		end = _buffer_end(self._buffer)
558		array = bytearray(end - start)
559		mytype = c_char * len(array)
560		c_array = mytype.from_buffer(array)
561		_memmove(c_array, start, len(array))
562		return array
563
564	def write(self, array):
565		"""
566		Copy the given array of samples inside the Buffer object.
567
568		parameters:
569			array: type=bytearray
570				The array containing the samples to copy
571
572		returns: type=int
573			The number of bytes written into the buffer
574		"""
575		start = _buffer_start(self._buffer)
576		end = _buffer_end(self._buffer)
577		length = end - start
578		if length > len(array):
579			length = len(array)
580		mytype = c_char * len(array)
581		c_array = mytype.from_buffer(array)
582		_memmove(start, c_array, length)
583		return length
584
585class _DeviceOrTrigger(object):
586	def __init__(self, _device):
587		self._device = _device
588		self._attrs = { name : DeviceAttr(_device, name) for name in \
589				[_d_get_attr(_device, x).decode('ascii') for x in range(0, _d_attr_count(_device))] }
590		self._debug_attrs = { name: DeviceDebugAttr(_device, name) for name in \
591				[_d_get_debug_attr(_device, x).decode('ascii') for x in range(0, _d_debug_attr_count(_device))] }
592
593		# TODO(pcercuei): Use a dictionary for the channels.
594		chans = [ Channel(_get_channel(self._device, x))
595			for x in range(0, _channels_count(self._device)) ]
596		self._channels = sorted(chans, key=lambda c: c.id)
597		self._id = _d_get_id(self._device).decode('ascii')
598
599		name_raw = _d_get_name(self._device)
600		self._name = name_raw.decode('ascii') if name_raw is not None else None
601
602	def reg_write(self, reg, value):
603		"""
604		Set a value to one register of this device.
605
606		parameters:
607			reg: type=int
608				The register address
609			value: type=int
610				The value that will be used for this register
611		"""
612		_d_reg_write(self._device, reg, value)
613
614	def reg_read(self, reg):
615		"""
616		Read the content of a register of this device.
617
618		parameters:
619			reg: type=int
620				The register address
621
622		returns: type=int
623			The value of the register
624		"""
625		value = c_uint()
626		_d_reg_read(self._device, reg, _byref(value))
627		return value.value
628
629	def find_channel(self, name_or_id, is_output = False):
630		"""
631
632		Find a IIO channel by its name or ID.
633
634		parameters:
635			name_or_id: type=str
636				The name or ID of the channel to find
637			is_output: type=bool
638				Set to True to search for an output channel
639
640		returns: type=iio.Device or type=iio.Trigger
641			The IIO Device
642		"""
643		return next((x for x in self.channels \
644				if name_or_id == x.name or name_or_id == x.id and \
645				x.output == is_output), None)
646
647	def set_kernel_buffers_count(self, count):
648		"""
649
650		Set the number of kernel buffers to use with the specified device.
651
652		parameters:
653			count: type=int
654				The number of kernel buffers
655
656		"""
657		return _d_set_buffers_count(self._device, count)
658
659	@property
660	def sample_size(self):
661		"""
662		Current sample size of this device.
663		type: int
664
665		The sample size varies each time channels get enabled or disabled."""
666		return _get_sample_size(self._device)
667
668	id = property(lambda self: self._id, None, None,
669			"An identifier of this device, only valid in this IIO context.\n\ttype=str")
670	name = property(lambda self: self._name, None, None,
671			"The name of this device.\n\ttype=str")
672	attrs = property(lambda self: self._attrs, None, None,
673			"List of attributes for this IIO device.\n\ttype=dict of iio.DeviceAttr")
674	debug_attrs = property(lambda self: self._debug_attrs, None, None,
675			"List of debug attributes for this IIO device.\n\ttype=dict of iio.DeviceDebugAttr")
676	channels = property(lambda self: self._channels, None, None,
677			"List of channels available with this IIO device.\n\ttype=list of iio.Channel objects")
678
679class Trigger(_DeviceOrTrigger):
680	"""Contains the representation of an IIO device that can act as a trigger."""
681
682	def __init__(self, _device):
683		super(Trigger, self).__init__(_device)
684
685	def _get_rate(self):
686		return int(self._attrs['frequency'].value)
687
688	def _set_rate(self, value):
689		self._attrs['frequency'].value = str(value)
690
691	frequency = property(_get_rate, _set_rate, None,
692			"Configured frequency (in Hz) of this trigger\n\ttype=int")
693
694class Device(_DeviceOrTrigger):
695	"""Contains the representation of an IIO device."""
696
697	def __init__(self, ctx, _device):
698		super(Device, self).__init__(_device)
699		self.ctx = weakref.ref(ctx)
700
701	def _set_trigger(self, trigger):
702		_d_set_trigger(self._device, trigger._device if trigger else None)
703
704	def _get_trigger(self):
705		value = _Device()
706		_d_get_trigger(self._device, _byref(value))
707
708		for dev in self.ctx()._devices:
709			if value == dev._device:
710				return dev
711		return None
712
713	trigger = property(_get_trigger, _set_trigger, None, \
714			"Contains the configured trigger for this IIO device.\n\ttype=iio.Trigger")
715
716class Context(object):
717	"""Contains the representation of an IIO context."""
718
719	def __init__(self, _context=None):
720		"""
721		Initializes a new instance of the Context class, using the local or the network backend of the IIO library.
722
723		returns: type=iio.Context
724			An new instance of this class
725
726		This function will create a network context if the IIOD_REMOTE
727		environment variable is set to the hostname where the IIOD server runs.
728		If set to an empty string, the server will be discovered using ZeroConf.
729		If the environment variable is not set, a local context will be created instead.
730		"""
731		self._context = None
732
733		if(_context is None):
734			self._context = _new_default()
735		elif type(_context) is str or type(_context) is unicode:
736			self._context = _new_uri(_context.encode('ascii'))
737		else:
738			self._context = _context
739
740		self._attrs = {}
741		for x in range(0, _get_attrs_count(self._context)):
742			str1 = c_char_p()
743			str2 = c_char_p()
744			_get_attr(self._context, x, _byref(str1), _byref(str2))
745			self._attrs[str1.value.decode('ascii')] = str2.value.decode('ascii')
746
747		# TODO(pcercuei): Use a dictionary for the devices.
748		self._devices = [ Trigger(dev) if _d_is_trigger(dev) else Device(self, dev) for dev in \
749				[ _get_device(self._context, x) for x in range(0, _devices_count(self._context)) ]]
750		self._name = _get_name(self._context).decode('ascii')
751		self._description = _get_description(self._context).decode('ascii')
752		self._xml = _get_xml(self._context).decode('ascii')
753
754		major = c_uint()
755		minor = c_uint()
756		buf = create_string_buffer(8)
757		_get_version(self._context, _byref(major), _byref(minor), buf)
758		self._version = (major.value, minor.value, buf.value.decode('ascii') )
759
760	def __del__(self):
761		if(self._context is not None):
762			_destroy(self._context)
763
764	def set_timeout(self, timeout):
765		"""
766		Set a timeout for I/O operations.
767
768		parameters:
769			timeout: type=int
770				The timeout value, in milliseconds
771		"""
772		_set_timeout(self._context, timeout)
773
774	def clone(self):
775		"""
776		Clone this instance.
777
778		returns: type=iio.LocalContext
779			An new instance of this class
780		"""
781		return Context(_clone(self._context))
782
783	def find_device(self, name_or_id):
784		"""
785
786		Find a IIO device by its name or ID.
787
788		parameters:
789			name_or_id: type=str
790				The name or ID of the device to find
791
792		returns: type=iio.Device or type=iio.Trigger
793			The IIO Device
794		"""
795		return next((x for x in self.devices \
796				if name_or_id == x.name or name_or_id == x.id), None)
797
798	name = property(lambda self: self._name, None, None, \
799			"Name of this IIO context.\n\ttype=str")
800	description = property(lambda self: self._description, None, None, \
801			"Description of this IIO context.\n\ttype=str")
802	xml = property(lambda self: self._xml, None, None, \
803			"XML representation of the current context.\n\ttype=str")
804	version = property(lambda self: self._version, None, None, \
805			"Version of the backend.\n\ttype=(int, int, str)")
806	attrs = property(lambda self: self._attrs, None, None, \
807			"List of context-specific attributes\n\ttype=dict of str objects")
808	devices = property(lambda self: self._devices, None, None, \
809			"List of devices contained in this context.\n\ttype=list of iio.Device and iio.Trigger objects")
810
811class LocalContext(Context):
812	def __init__(self):
813		"""
814		Initializes a new instance of the Context class, using the local backend of the IIO library.
815
816		returns: type=iio.LocalContext
817			An new instance of this class
818		"""
819		ctx = _new_local()
820		super(LocalContext, self).__init__(ctx)
821
822class XMLContext(Context):
823	def __init__(self, xmlfile):
824		"""
825		Initializes a new instance of the Context class, using the XML backend of the IIO library.
826
827		parameters:
828			xmlfile: type=str
829				Filename of the XML file to build the context from
830
831		returns: type=iio.XMLContext
832			An new instance of this class
833		"""
834		ctx = _new_xml(xmlfile.encode('ascii'))
835		super(XMLContext, self).__init__(ctx)
836
837class NetworkContext(Context):
838	def __init__(self, hostname = None):
839		"""
840		Initializes a new instance of the Context class, using the network backend of the IIO library.
841
842		parameters:
843			hostname: type=str
844				Hostname, IPv4 or IPv6 address where the IIO Daemon is running
845
846		returns: type=iio.NetworkContext
847			An new instance of this class
848		"""
849		ctx = _new_network(hostname.encode('ascii') if hostname is not None else None)
850		super(NetworkContext, self).__init__(ctx)
851
852def scan_contexts():
853	d = dict()
854	ptr = _POINTER(_ContextInfoPtr)()
855
856	ctx = _create_scan_context(None, 0)
857	nb = _get_context_info_list(ctx, _byref(ptr));
858
859	for i in range(0, nb):
860		d[_context_info_get_uri(ptr[i]).decode('ascii')] = _context_info_get_description(ptr[i]).decode('ascii')
861
862	_context_info_list_free(ptr)
863	_destroy_scan_context(ctx)
864	return d
865