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 17 struct 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 25 static 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 30 static 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 36 static void iio_buffer_cb_release(struct iio_buffer *buffer) 37 { 38 struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer); 39 kfree(cb_buff->buffer.scan_mask); 40 kfree(cb_buff); 41 } 42 43 static const struct iio_buffer_access_funcs iio_cb_access = { 44 .store_to = &iio_buffer_cb_store_to, 45 .release = &iio_buffer_cb_release, 46 47 .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED, 48 }; 49 50 struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, 51 int (*cb)(const void *data, 52 void *private), 53 void *private) 54 { 55 int ret; 56 struct iio_cb_buffer *cb_buff; 57 struct iio_channel *chan; 58 59 cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL); 60 if (cb_buff == NULL) 61 return ERR_PTR(-ENOMEM); 62 63 iio_buffer_init(&cb_buff->buffer); 64 65 cb_buff->private = private; 66 cb_buff->cb = cb; 67 cb_buff->buffer.access = &iio_cb_access; 68 INIT_LIST_HEAD(&cb_buff->buffer.demux_list); 69 70 cb_buff->channels = iio_channel_get_all(dev); 71 if (IS_ERR(cb_buff->channels)) { 72 ret = PTR_ERR(cb_buff->channels); 73 goto error_free_cb_buff; 74 } 75 76 cb_buff->indio_dev = cb_buff->channels[0].indio_dev; 77 cb_buff->buffer.scan_mask 78 = kcalloc(BITS_TO_LONGS(cb_buff->indio_dev->masklength), 79 sizeof(long), 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 97 error_free_scan_mask: 98 kfree(cb_buff->buffer.scan_mask); 99 error_release_channels: 100 iio_channel_release_all(cb_buff->channels); 101 error_free_cb_buff: 102 kfree(cb_buff); 103 return ERR_PTR(ret); 104 } 105 EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); 106 107 int 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 } 116 EXPORT_SYMBOL_GPL(iio_channel_cb_set_buffer_watermark); 117 118 int 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 } 123 EXPORT_SYMBOL_GPL(iio_channel_start_all_cb); 124 125 void 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 } 129 EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); 130 131 void 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 } 136 EXPORT_SYMBOL_GPL(iio_channel_release_all_cb); 137 138 struct iio_channel 139 *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer) 140 { 141 return cb_buffer->channels; 142 } 143 EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); 144 145 struct iio_dev 146 *iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer) 147 { 148 return cb_buffer->indio_dev; 149 } 150 EXPORT_SYMBOL_GPL(iio_channel_cb_get_iio_dev); 151 152 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 153 MODULE_DESCRIPTION("Industrial I/O callback buffer"); 154 MODULE_LICENSE("GPL"); 155