157 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* The industrial I/O callback buffer3 */4 5#include <linux/kernel.h>6#include <linux/module.h>7#include <linux/slab.h>8#include <linux/err.h>9#include <linux/export.h>10#include <linux/iio/iio.h>11#include <linux/iio/buffer_impl.h>12#include <linux/iio/consumer.h>13 14struct iio_cb_buffer {15 struct iio_buffer buffer;16 int (*cb)(const void *data, void *private);17 void *private;18 struct iio_channel *channels;19 struct iio_dev *indio_dev;20};21 22static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer)23{24 return container_of(buffer, struct iio_cb_buffer, buffer);25}26 27static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)28{29 struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);30 return cb_buff->cb(data, cb_buff->private);31}32 33static void iio_buffer_cb_release(struct iio_buffer *buffer)34{35 struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);36 37 bitmap_free(cb_buff->buffer.scan_mask);38 kfree(cb_buff);39}40 41static const struct iio_buffer_access_funcs iio_cb_access = {42 .store_to = &iio_buffer_cb_store_to,43 .release = &iio_buffer_cb_release,44 45 .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED,46};47 48struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,49 int (*cb)(const void *data,50 void *private),51 void *private)52{53 int ret;54 struct iio_cb_buffer *cb_buff;55 struct iio_channel *chan;56 57 if (!cb) {58 dev_err(dev, "Invalid arguments: A callback must be provided!\n");59 return ERR_PTR(-EINVAL);60 }61 62 cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);63 if (cb_buff == NULL)64 return ERR_PTR(-ENOMEM);65 66 iio_buffer_init(&cb_buff->buffer);67 68 cb_buff->private = private;69 cb_buff->cb = cb;70 cb_buff->buffer.access = &iio_cb_access;71 INIT_LIST_HEAD(&cb_buff->buffer.demux_list);72 73 cb_buff->channels = iio_channel_get_all(dev);74 if (IS_ERR(cb_buff->channels)) {75 ret = PTR_ERR(cb_buff->channels);76 goto error_free_cb_buff;77 }78 79 cb_buff->indio_dev = cb_buff->channels[0].indio_dev;80 cb_buff->buffer.scan_mask = bitmap_zalloc(iio_get_masklength(cb_buff->indio_dev),81 GFP_KERNEL);82 if (cb_buff->buffer.scan_mask == NULL) {83 ret = -ENOMEM;84 goto error_release_channels;85 }86 chan = &cb_buff->channels[0];87 while (chan->indio_dev) {88 if (chan->indio_dev != cb_buff->indio_dev) {89 ret = -EINVAL;90 goto error_free_scan_mask;91 }92 set_bit(chan->channel->scan_index,93 cb_buff->buffer.scan_mask);94 chan++;95 }96 97 return cb_buff;98 99error_free_scan_mask:100 bitmap_free(cb_buff->buffer.scan_mask);101error_release_channels:102 iio_channel_release_all(cb_buff->channels);103error_free_cb_buff:104 kfree(cb_buff);105 return ERR_PTR(ret);106}107EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);108 109int iio_channel_cb_set_buffer_watermark(struct iio_cb_buffer *cb_buff,110 size_t watermark)111{112 if (!watermark)113 return -EINVAL;114 cb_buff->buffer.watermark = watermark;115 116 return 0;117}118EXPORT_SYMBOL_GPL(iio_channel_cb_set_buffer_watermark);119 120int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff)121{122 return iio_update_buffers(cb_buff->indio_dev, &cb_buff->buffer,123 NULL);124}125EXPORT_SYMBOL_GPL(iio_channel_start_all_cb);126 127void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff)128{129 iio_update_buffers(cb_buff->indio_dev, NULL, &cb_buff->buffer);130}131EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);132 133void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)134{135 iio_channel_release_all(cb_buff->channels);136 iio_buffer_put(&cb_buff->buffer);137}138EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);139 140struct iio_channel141*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer)142{143 return cb_buffer->channels;144}145EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels);146 147struct iio_dev148*iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer)149{150 return cb_buffer->indio_dev;151}152EXPORT_SYMBOL_GPL(iio_channel_cb_get_iio_dev);153 154MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");155MODULE_DESCRIPTION("Industrial I/O callback buffer");156MODULE_LICENSE("GPL");157