diff options
-rw-r--r-- | drivers/iio/Kconfig | 6 | ||||
-rw-r--r-- | drivers/iio/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/buffer_cb.c | 113 | ||||
-rw-r--r-- | include/linux/iio/consumer.h | 46 |
4 files changed, 166 insertions, 0 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index fc937aca71fb..65ae734c607d 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig | |||
@@ -20,6 +20,12 @@ config IIO_BUFFER | |||
20 | 20 | ||
21 | if IIO_BUFFER | 21 | if IIO_BUFFER |
22 | 22 | ||
23 | config IIO_BUFFER_CB | ||
24 | boolean "IIO callback buffer used for push in-kernel interfaces" | ||
25 | help | ||
26 | Should be selected by any drivers that do-inkernel push | ||
27 | usage. That is, those where the data is pushed to the consumer. | ||
28 | |||
23 | config IIO_KFIFO_BUF | 29 | config IIO_KFIFO_BUF |
24 | select IIO_TRIGGER | 30 | select IIO_TRIGGER |
25 | tristate "Industrial I/O buffering based on kfifo" | 31 | tristate "Industrial I/O buffering based on kfifo" |
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 761f2b65ac52..31d76a07ec65 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_IIO) += industrialio.o | |||
6 | industrialio-y := industrialio-core.o industrialio-event.o inkern.o | 6 | industrialio-y := industrialio-core.o industrialio-event.o inkern.o |
7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o | 7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o |
8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o | 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o |
9 | industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o | ||
9 | 10 | ||
10 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o | 11 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o |
11 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o | 12 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o |
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c new file mode 100644 index 000000000000..4d40e24f3721 --- /dev/null +++ b/drivers/iio/buffer_cb.c | |||
@@ -0,0 +1,113 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/slab.h> | ||
3 | #include <linux/err.h> | ||
4 | #include <linux/export.h> | ||
5 | #include <linux/iio/buffer.h> | ||
6 | #include <linux/iio/consumer.h> | ||
7 | |||
8 | struct iio_cb_buffer { | ||
9 | struct iio_buffer buffer; | ||
10 | int (*cb)(u8 *data, void *private); | ||
11 | void *private; | ||
12 | struct iio_channel *channels; | ||
13 | }; | ||
14 | |||
15 | static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data) | ||
16 | { | ||
17 | struct iio_cb_buffer *cb_buff = container_of(buffer, | ||
18 | struct iio_cb_buffer, | ||
19 | buffer); | ||
20 | |||
21 | return cb_buff->cb(data, cb_buff->private); | ||
22 | } | ||
23 | |||
24 | static struct iio_buffer_access_funcs iio_cb_access = { | ||
25 | .store_to = &iio_buffer_cb_store_to, | ||
26 | }; | ||
27 | |||
28 | struct iio_cb_buffer *iio_channel_get_all_cb(const char *name, | ||
29 | int (*cb)(u8 *data, | ||
30 | void *private), | ||
31 | void *private) | ||
32 | { | ||
33 | int ret; | ||
34 | struct iio_cb_buffer *cb_buff; | ||
35 | struct iio_dev *indio_dev; | ||
36 | struct iio_channel *chan; | ||
37 | |||
38 | cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL); | ||
39 | if (cb_buff == NULL) { | ||
40 | ret = -ENOMEM; | ||
41 | goto error_ret; | ||
42 | } | ||
43 | |||
44 | cb_buff->private = private; | ||
45 | cb_buff->cb = cb; | ||
46 | cb_buff->buffer.access = &iio_cb_access; | ||
47 | INIT_LIST_HEAD(&cb_buff->buffer.demux_list); | ||
48 | |||
49 | cb_buff->channels = iio_channel_get_all(name); | ||
50 | if (IS_ERR(cb_buff->channels)) { | ||
51 | ret = PTR_ERR(cb_buff->channels); | ||
52 | goto error_free_cb_buff; | ||
53 | } | ||
54 | |||
55 | indio_dev = cb_buff->channels[0].indio_dev; | ||
56 | cb_buff->buffer.scan_mask | ||
57 | = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long), | ||
58 | GFP_KERNEL); | ||
59 | if (cb_buff->buffer.scan_mask == NULL) { | ||
60 | ret = -ENOMEM; | ||
61 | goto error_release_channels; | ||
62 | } | ||
63 | chan = &cb_buff->channels[0]; | ||
64 | while (chan->indio_dev) { | ||
65 | if (chan->indio_dev != indio_dev) { | ||
66 | ret = -EINVAL; | ||
67 | goto error_release_channels; | ||
68 | } | ||
69 | set_bit(chan->channel->scan_index, | ||
70 | cb_buff->buffer.scan_mask); | ||
71 | chan++; | ||
72 | } | ||
73 | |||
74 | return cb_buff; | ||
75 | |||
76 | error_release_channels: | ||
77 | iio_channel_release_all(cb_buff->channels); | ||
78 | error_free_cb_buff: | ||
79 | kfree(cb_buff); | ||
80 | error_ret: | ||
81 | return ERR_PTR(ret); | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); | ||
84 | |||
85 | int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff) | ||
86 | { | ||
87 | return iio_update_buffers(cb_buff->channels[0].indio_dev, | ||
88 | &cb_buff->buffer, | ||
89 | NULL); | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(iio_channel_start_all_cb); | ||
92 | |||
93 | void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff) | ||
94 | { | ||
95 | iio_update_buffers(cb_buff->channels[0].indio_dev, | ||
96 | NULL, | ||
97 | &cb_buff->buffer); | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); | ||
100 | |||
101 | void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff) | ||
102 | { | ||
103 | iio_channel_release_all(cb_buff->channels); | ||
104 | kfree(cb_buff); | ||
105 | } | ||
106 | EXPORT_SYMBOL_GPL(iio_channel_release_all_cb); | ||
107 | |||
108 | struct iio_channel | ||
109 | *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer) | ||
110 | { | ||
111 | return cb_buffer->channels; | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); | ||
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 57efee63a6da..126c0a9375f2 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h | |||
@@ -61,6 +61,52 @@ struct iio_channel *iio_channel_get_all(const char *name); | |||
61 | */ | 61 | */ |
62 | void iio_channel_release_all(struct iio_channel *chan); | 62 | void iio_channel_release_all(struct iio_channel *chan); |
63 | 63 | ||
64 | struct iio_cb_buffer; | ||
65 | /** | ||
66 | * iio_channel_get_all_cb() - register callback for triggered capture | ||
67 | * @name: Name of client device. | ||
68 | * @cb: Callback function. | ||
69 | * @private: Private data passed to callback. | ||
70 | * | ||
71 | * NB right now we have no ability to mux data from multiple devices. | ||
72 | * So if the channels requested come from different devices this will | ||
73 | * fail. | ||
74 | */ | ||
75 | struct iio_cb_buffer *iio_channel_get_all_cb(const char *name, | ||
76 | int (*cb)(u8 *data, | ||
77 | void *private), | ||
78 | void *private); | ||
79 | /** | ||
80 | * iio_channel_release_all_cb() - release and unregister the callback. | ||
81 | * @cb_buffer: The callback buffer that was allocated. | ||
82 | */ | ||
83 | void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buffer); | ||
84 | |||
85 | /** | ||
86 | * iio_channel_start_all_cb() - start the flow of data through callback. | ||
87 | * @cb_buff: The callback buffer we are starting. | ||
88 | */ | ||
89 | int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff); | ||
90 | |||
91 | /** | ||
92 | * iio_channel_stop_all_cb() - stop the flow of data through the callback. | ||
93 | * @cb_buff: The callback buffer we are stopping. | ||
94 | */ | ||
95 | void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff); | ||
96 | |||
97 | /** | ||
98 | * iio_channel_cb_get_channels() - get access to the underlying channels. | ||
99 | * @cb_buff: The callback buffer from whom we want the channel | ||
100 | * information. | ||
101 | * | ||
102 | * This function allows one to obtain information about the channels. | ||
103 | * Whilst this may allow direct reading if all buffers are disabled, the | ||
104 | * primary aim is to allow drivers that are consuming a channel to query | ||
105 | * things like scaling of the channel. | ||
106 | */ | ||
107 | struct iio_channel | ||
108 | *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer); | ||
109 | |||
64 | /** | 110 | /** |
65 | * iio_read_channel_raw() - read from a given channel | 111 | * iio_read_channel_raw() - read from a given channel |
66 | * @chan: The channel being queried. | 112 | * @chan: The channel being queried. |