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