forked from analogdevicesinc/libiio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
events.c
144 lines (114 loc) · 3.2 KB
/
events.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libiio - Library for interfacing industrial I/O (IIO) devices
*
* Copyright (C) 2023 Analog Devices, Inc.
* Author: Paul Cercueil <[email protected]>
*/
#include "iio-private.h"
#include <ctype.h>
#include <errno.h>
#include <iio/iio-debug.h>
struct iio_event_stream_pdata;
struct iio_event_stream {
const struct iio_device *dev;
struct iio_event_stream_pdata *pdata;
};
/* Corresponds to IIO_EVENT_CODE_EXTRACT_CHAN() and
* IIO_EVENT_CODE_EXTRACT_CHAN2() macros of <linux/iio/events.h> */
static inline int16_t
iio_event_get_channel_id(const struct iio_event *event, unsigned int channel)
{
return (int16_t)(event->id >> (channel << 4));
}
/* Corresponds to IIO_EVENT_CODE_EXTRACT_DIFF() of <linux/iio/events.h> */
static inline bool
iio_event_is_differential(const struct iio_event *event)
{
return event->id & BIT(55);
}
/* Corresponds to IIO_EVENT_CODE_EXTRACT_MODIFIER() of <linux/iio/events.h> */
static inline enum iio_modifier
iio_event_get_modifier(const struct iio_event *event)
{
return (enum iio_modifier)((event->id >> 40) & 0xff);
}
/* Corresponds to IIO_EVENT_CODE_EXTRACT_CHAN_TYPE() of <linux/iio/events.h> */
static inline enum iio_chan_type
iio_event_get_chan_type(const struct iio_event *event)
{
return (enum iio_chan_type)((event->id >> 32) & 0xff);
}
const struct iio_channel *
iio_event_get_channel(const struct iio_event *event,
const struct iio_device *dev, bool diff)
{
const struct iio_channel *chn = NULL;
const char *ptr;
unsigned int i;
int16_t chid;
if (diff && !iio_event_is_differential(event))
return NULL;
chid = iio_event_get_channel_id(event, diff);
if (chid < 0)
return NULL;
if ((unsigned int)chid >= dev->nb_channels) {
dev_warn(dev, "Unexpected IIO event channel ID\n");
return NULL;
}
for (i = 0; i < dev->nb_channels; i++) {
chn = dev->channels[i];
if (chn->type != iio_event_get_chan_type(event)
|| chn->modifier != iio_event_get_modifier(event)) {
continue;
}
for (ptr = chn->id; *ptr && isalpha((unsigned char)*ptr); )
ptr++;
if (!*ptr && chid <= 0)
break;
if ((uint16_t)chid == strtoul(ptr, NULL, 10))
break;
}
if (chn) {
chn_dbg(chn, "Found channel %s for event\n",
iio_channel_get_id(chn));
} else {
dev_dbg(dev, "Unable to find channel for event\n");
}
return chn;
}
struct iio_event_stream *
iio_device_create_event_stream(const struct iio_device *dev)
{
struct iio_event_stream *stream;
int err;
if (!dev->ctx->ops->open_ev)
return iio_ptr(-ENOSYS);
stream = zalloc(sizeof(*stream));
if (!stream)
return iio_ptr(-ENOMEM);
stream->dev = dev;
stream->pdata = dev->ctx->ops->open_ev(dev);
err = iio_err(stream->pdata);
if (err) {
free(stream);
return iio_ptr(err);
}
return stream;
}
void iio_event_stream_destroy(struct iio_event_stream *stream)
{
if (stream->dev->ctx->ops->close_ev)
stream->dev->ctx->ops->close_ev(stream->pdata);
free(stream);
}
int iio_event_stream_read(struct iio_event_stream *stream,
struct iio_event *out_event,
bool nonblock)
{
if (!stream->dev->ctx->ops->read_ev)
return -ENOSYS;
if (!out_event)
return -EINVAL;
return stream->dev->ctx->ops->read_ev(stream->pdata, out_event, nonblock);
}