]> Git Repo - linux.git/blob - drivers/input/joystick/adc-joystick.c
Linux 6.14-rc3
[linux.git] / drivers / input / joystick / adc-joystick.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Input driver for joysticks connected over ADC.
4  * Copyright (c) 2019-2020 Artur Rojek <[email protected]>
5  */
6 #include <linux/ctype.h>
7 #include <linux/input.h>
8 #include <linux/iio/iio.h>
9 #include <linux/iio/consumer.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/property.h>
13
14 #include <linux/unaligned.h>
15
16 struct adc_joystick_axis {
17         u32 code;
18         bool inverted;
19 };
20
21 struct adc_joystick {
22         struct input_dev *input;
23         struct iio_cb_buffer *buffer;
24         struct iio_channel *chans;
25         unsigned int num_chans;
26         struct adc_joystick_axis axes[] __counted_by(num_chans);
27 };
28
29 static int adc_joystick_invert(struct input_dev *dev,
30                                unsigned int axis, int val)
31 {
32         int min = input_abs_get_min(dev, axis);
33         int max = input_abs_get_max(dev, axis);
34
35         return (max + min) - val;
36 }
37
38 static void adc_joystick_poll(struct input_dev *input)
39 {
40         struct adc_joystick *joy = input_get_drvdata(input);
41         int i, val, ret;
42
43         for (i = 0; i < joy->num_chans; i++) {
44                 ret = iio_read_channel_raw(&joy->chans[i], &val);
45                 if (ret < 0)
46                         return;
47                 if (joy->axes[i].inverted)
48                         val = adc_joystick_invert(input, i, val);
49                 input_report_abs(input, joy->axes[i].code, val);
50         }
51         input_sync(input);
52 }
53
54 static int adc_joystick_handle(const void *data, void *private)
55 {
56         struct adc_joystick *joy = private;
57         enum iio_endian endianness;
58         int bytes, msb, val, idx, i;
59         const u16 *data_u16;
60         bool sign;
61
62         bytes = joy->chans[0].channel->scan_type.storagebits >> 3;
63
64         for (i = 0; i < joy->num_chans; ++i) {
65                 idx = joy->chans[i].channel->scan_index;
66                 endianness = joy->chans[i].channel->scan_type.endianness;
67                 msb = joy->chans[i].channel->scan_type.realbits - 1;
68                 sign = tolower(joy->chans[i].channel->scan_type.sign) == 's';
69
70                 switch (bytes) {
71                 case 1:
72                         val = ((const u8 *)data)[idx];
73                         break;
74                 case 2:
75                         data_u16 = (const u16 *)data + idx;
76
77                         /*
78                          * Data is aligned to the sample size by IIO core.
79                          * Call `get_unaligned_xe16` to hide type casting.
80                          */
81                         if (endianness == IIO_BE)
82                                 val = get_unaligned_be16(data_u16);
83                         else if (endianness == IIO_LE)
84                                 val = get_unaligned_le16(data_u16);
85                         else /* IIO_CPU */
86                                 val = *data_u16;
87                         break;
88                 default:
89                         return -EINVAL;
90                 }
91
92                 val >>= joy->chans[i].channel->scan_type.shift;
93                 if (sign)
94                         val = sign_extend32(val, msb);
95                 else
96                         val &= GENMASK(msb, 0);
97                 if (joy->axes[i].inverted)
98                         val = adc_joystick_invert(joy->input, i, val);
99                 input_report_abs(joy->input, joy->axes[i].code, val);
100         }
101
102         input_sync(joy->input);
103
104         return 0;
105 }
106
107 static int adc_joystick_open(struct input_dev *dev)
108 {
109         struct adc_joystick *joy = input_get_drvdata(dev);
110         struct device *devp = &dev->dev;
111         int ret;
112
113         ret = iio_channel_start_all_cb(joy->buffer);
114         if (ret)
115                 dev_err(devp, "Unable to start callback buffer: %d\n", ret);
116
117         return ret;
118 }
119
120 static void adc_joystick_close(struct input_dev *dev)
121 {
122         struct adc_joystick *joy = input_get_drvdata(dev);
123
124         iio_channel_stop_all_cb(joy->buffer);
125 }
126
127 static void adc_joystick_cleanup(void *data)
128 {
129         iio_channel_release_all_cb(data);
130 }
131
132 static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy)
133 {
134         struct adc_joystick_axis *axes = joy->axes;
135         s32 range[2], fuzz, flat;
136         unsigned int num_axes;
137         int error, i;
138
139         num_axes = device_get_child_node_count(dev);
140         if (!num_axes) {
141                 dev_err(dev, "Unable to find child nodes\n");
142                 return -EINVAL;
143         }
144
145         if (num_axes != joy->num_chans) {
146                 dev_err(dev, "Got %d child nodes for %d channels\n",
147                         num_axes, joy->num_chans);
148                 return -EINVAL;
149         }
150
151         device_for_each_child_node_scoped(dev, child) {
152                 error = fwnode_property_read_u32(child, "reg", &i);
153                 if (error) {
154                         dev_err(dev, "reg invalid or missing\n");
155                         return error;
156                 }
157
158                 if (i >= num_axes) {
159                         dev_err(dev, "No matching axis for reg %d\n", i);
160                         return -EINVAL;
161                 }
162
163                 error = fwnode_property_read_u32(child, "linux,code",
164                                                  &axes[i].code);
165                 if (error) {
166                         dev_err(dev, "linux,code invalid or missing\n");
167                         return error;
168                 }
169
170                 error = fwnode_property_read_u32_array(child, "abs-range",
171                                                        range, 2);
172                 if (error) {
173                         dev_err(dev, "abs-range invalid or missing\n");
174                         return error;
175                 }
176
177                 if (range[0] > range[1]) {
178                         dev_dbg(dev, "abs-axis %d inverted\n", i);
179                         axes[i].inverted = true;
180                         swap(range[0], range[1]);
181                 }
182
183                 if (fwnode_property_read_u32(child, "abs-fuzz", &fuzz))
184                         fuzz = 0;
185
186                 if (fwnode_property_read_u32(child, "abs-flat", &flat))
187                         flat = 0;
188
189                 input_set_abs_params(joy->input, axes[i].code,
190                                      range[0], range[1], fuzz, flat);
191         }
192
193         return 0;
194 }
195
196
197 static int adc_joystick_count_channels(struct device *dev,
198                                        const struct iio_channel *chans,
199                                        bool polled,
200                                        unsigned int *num_chans)
201 {
202         int bits;
203         int i;
204
205         /*
206          * Count how many channels we got. NULL terminated.
207          * Do not check the storage size if using polling.
208          */
209         for (i = 0; chans[i].indio_dev; i++) {
210                 if (polled)
211                         continue;
212                 bits = chans[i].channel->scan_type.storagebits;
213                 if (!bits || bits > 16) {
214                         dev_err(dev, "Unsupported channel storage size\n");
215                         return -EINVAL;
216                 }
217                 if (bits != chans[0].channel->scan_type.storagebits) {
218                         dev_err(dev, "Channels must have equal storage size\n");
219                         return -EINVAL;
220                 }
221         }
222
223         *num_chans = i;
224         return 0;
225 }
226
227 static int adc_joystick_probe(struct platform_device *pdev)
228 {
229         struct device *dev = &pdev->dev;
230         struct iio_channel *chans;
231         struct adc_joystick *joy;
232         struct input_dev *input;
233         unsigned int poll_interval = 0;
234         unsigned int num_chans;
235         int error;
236
237         chans = devm_iio_channel_get_all(dev);
238         error = PTR_ERR_OR_ZERO(chans);
239         if (error) {
240                 if (error != -EPROBE_DEFER)
241                         dev_err(dev, "Unable to get IIO channels");
242                 return error;
243         }
244
245         error = device_property_read_u32(dev, "poll-interval", &poll_interval);
246         if (error) {
247                 /* -EINVAL means the property is absent. */
248                 if (error != -EINVAL)
249                         return error;
250         } else if (poll_interval == 0) {
251                 dev_err(dev, "Unable to get poll-interval\n");
252                 return -EINVAL;
253         }
254
255         error = adc_joystick_count_channels(dev, chans, poll_interval != 0,
256                                             &num_chans);
257         if (error)
258                 return error;
259
260         joy = devm_kzalloc(dev, struct_size(joy, axes, num_chans), GFP_KERNEL);
261         if (!joy)
262                 return -ENOMEM;
263
264         joy->chans = chans;
265         joy->num_chans = num_chans;
266
267         input = devm_input_allocate_device(dev);
268         if (!input) {
269                 dev_err(dev, "Unable to allocate input device\n");
270                 return -ENOMEM;
271         }
272
273         joy->input = input;
274         input->name = pdev->name;
275         input->id.bustype = BUS_HOST;
276
277         error = adc_joystick_set_axes(dev, joy);
278         if (error)
279                 return error;
280
281         if (poll_interval != 0) {
282                 input_setup_polling(input, adc_joystick_poll);
283                 input_set_poll_interval(input, poll_interval);
284         } else {
285                 input->open = adc_joystick_open;
286                 input->close = adc_joystick_close;
287
288                 joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle,
289                                                      joy);
290                 if (IS_ERR(joy->buffer)) {
291                         dev_err(dev, "Unable to allocate callback buffer\n");
292                         return PTR_ERR(joy->buffer);
293                 }
294
295                 error = devm_add_action_or_reset(dev, adc_joystick_cleanup,
296                                                  joy->buffer);
297                 if (error)  {
298                         dev_err(dev, "Unable to add action\n");
299                         return error;
300                 }
301         }
302
303         input_set_drvdata(input, joy);
304
305         error = input_register_device(input);
306         if (error) {
307                 dev_err(dev, "Unable to register input device\n");
308                 return error;
309         }
310
311         return 0;
312 }
313
314 static const struct of_device_id adc_joystick_of_match[] = {
315         { .compatible = "adc-joystick", },
316         { }
317 };
318 MODULE_DEVICE_TABLE(of, adc_joystick_of_match);
319
320 static struct platform_driver adc_joystick_driver = {
321         .driver = {
322                 .name = "adc-joystick",
323                 .of_match_table = adc_joystick_of_match,
324         },
325         .probe = adc_joystick_probe,
326 };
327 module_platform_driver(adc_joystick_driver);
328
329 MODULE_DESCRIPTION("Input driver for joysticks connected over ADC");
330 MODULE_AUTHOR("Artur Rojek <[email protected]>");
331 MODULE_LICENSE("GPL");
This page took 0.05025 seconds and 4 git commands to generate.