Blame view

kernel/linux-imx6_3.14.28/drivers/iio/buffer_cb.c 3.08 KB
6b13f685e   김민수   BSP 최초 추가
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
  #include <linux/kernel.h>
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/export.h>
  #include <linux/iio/buffer.h>
  #include <linux/iio/consumer.h>
  
  struct iio_cb_buffer {
  	struct iio_buffer buffer;
  	int (*cb)(const void *data, void *private);
  	void *private;
  	struct iio_channel *channels;
  };
  
  static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer)
  {
  	return container_of(buffer, struct iio_cb_buffer, buffer);
  }
  
  static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
  {
  	struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
  	return cb_buff->cb(data, cb_buff->private);
  }
  
  static void iio_buffer_cb_release(struct iio_buffer *buffer)
  {
  	struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
  	kfree(cb_buff->buffer.scan_mask);
  	kfree(cb_buff);
  }
  
  static const struct iio_buffer_access_funcs iio_cb_access = {
  	.store_to = &iio_buffer_cb_store_to,
  	.release = &iio_buffer_cb_release,
  };
  
  struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
  					     int (*cb)(const void *data,
  						       void *private),
  					     void *private)
  {
  	int ret;
  	struct iio_cb_buffer *cb_buff;
  	struct iio_dev *indio_dev;
  	struct iio_channel *chan;
  
  	cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);
  	if (cb_buff == NULL) {
  		ret = -ENOMEM;
  		goto error_ret;
  	}
  
  	iio_buffer_init(&cb_buff->buffer);
  
  	cb_buff->private = private;
  	cb_buff->cb = cb;
  	cb_buff->buffer.access = &iio_cb_access;
  	INIT_LIST_HEAD(&cb_buff->buffer.demux_list);
  
  	cb_buff->channels = iio_channel_get_all(dev);
  	if (IS_ERR(cb_buff->channels)) {
  		ret = PTR_ERR(cb_buff->channels);
  		goto error_free_cb_buff;
  	}
  
  	indio_dev = cb_buff->channels[0].indio_dev;
  	cb_buff->buffer.scan_mask
  		= kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long),
  			  GFP_KERNEL);
  	if (cb_buff->buffer.scan_mask == NULL) {
  		ret = -ENOMEM;
  		goto error_release_channels;
  	}
  	chan = &cb_buff->channels[0];
  	while (chan->indio_dev) {
  		if (chan->indio_dev != indio_dev) {
  			ret = -EINVAL;
  			goto error_free_scan_mask;
  		}
  		set_bit(chan->channel->scan_index,
  			cb_buff->buffer.scan_mask);
  		chan++;
  	}
  
  	return cb_buff;
  
  error_free_scan_mask:
  	kfree(cb_buff->buffer.scan_mask);
  error_release_channels:
  	iio_channel_release_all(cb_buff->channels);
  error_free_cb_buff:
  	kfree(cb_buff);
  error_ret:
  	return ERR_PTR(ret);
  }
  EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);
  
  int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff)
  {
  	return iio_update_buffers(cb_buff->channels[0].indio_dev,
  				  &cb_buff->buffer,
  				  NULL);
  }
  EXPORT_SYMBOL_GPL(iio_channel_start_all_cb);
  
  void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff)
  {
  	iio_update_buffers(cb_buff->channels[0].indio_dev,
  			   NULL,
  			   &cb_buff->buffer);
  }
  EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);
  
  void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
  {
  	iio_channel_release_all(cb_buff->channels);
  	iio_buffer_put(&cb_buff->buffer);
  }
  EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);
  
  struct iio_channel
  *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer)
  {
  	return cb_buffer->channels;
  }
  EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels);