]> Git Repo - J-linux.git/blob - drivers/input/ff-core.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / input / ff-core.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Force feedback support for Linux input subsystem
4  *
5  *  Copyright (c) 2006 Anssi Hannula <[email protected]>
6  *  Copyright (c) 2006 Dmitry Torokhov <[email protected]>
7  */
8
9 /* #define DEBUG */
10
11 #include <linux/input.h>
12 #include <linux/limits.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/overflow.h>
16 #include <linux/sched.h>
17 #include <linux/slab.h>
18
19 /*
20  * Check that the effect_id is a valid effect and whether the user
21  * is the owner
22  */
23 static int check_effect_access(struct ff_device *ff, int effect_id,
24                                 struct file *file)
25 {
26         if (effect_id < 0 || effect_id >= ff->max_effects ||
27             !ff->effect_owners[effect_id])
28                 return -EINVAL;
29
30         if (file && ff->effect_owners[effect_id] != file)
31                 return -EACCES;
32
33         return 0;
34 }
35
36 /*
37  * Checks whether 2 effects can be combined together
38  */
39 static inline int check_effects_compatible(struct ff_effect *e1,
40                                            struct ff_effect *e2)
41 {
42         return e1->type == e2->type &&
43                (e1->type != FF_PERIODIC ||
44                 e1->u.periodic.waveform == e2->u.periodic.waveform);
45 }
46
47 /*
48  * Convert an effect into compatible one
49  */
50 static int compat_effect(struct ff_device *ff, struct ff_effect *effect)
51 {
52         int magnitude;
53
54         switch (effect->type) {
55         case FF_RUMBLE:
56                 if (!test_bit(FF_PERIODIC, ff->ffbit))
57                         return -EINVAL;
58
59                 /*
60                  * calculate magnitude of sine wave as average of rumble's
61                  * 2/3 of strong magnitude and 1/3 of weak magnitude
62                  */
63                 magnitude = effect->u.rumble.strong_magnitude / 3 +
64                             effect->u.rumble.weak_magnitude / 6;
65
66                 effect->type = FF_PERIODIC;
67                 effect->u.periodic.waveform = FF_SINE;
68                 effect->u.periodic.period = 50;
69                 effect->u.periodic.magnitude = magnitude;
70                 effect->u.periodic.offset = 0;
71                 effect->u.periodic.phase = 0;
72                 effect->u.periodic.envelope.attack_length = 0;
73                 effect->u.periodic.envelope.attack_level = 0;
74                 effect->u.periodic.envelope.fade_length = 0;
75                 effect->u.periodic.envelope.fade_level = 0;
76
77                 return 0;
78
79         default:
80                 /* Let driver handle conversion */
81                 return 0;
82         }
83 }
84
85 /**
86  * input_ff_upload() - upload effect into force-feedback device
87  * @dev: input device
88  * @effect: effect to be uploaded
89  * @file: owner of the effect
90  */
91 int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
92                     struct file *file)
93 {
94         struct ff_device *ff = dev->ff;
95         struct ff_effect *old;
96         int ret = 0;
97         int id;
98
99         if (!test_bit(EV_FF, dev->evbit))
100                 return -ENOSYS;
101
102         if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
103             !test_bit(effect->type, dev->ffbit)) {
104                 dev_dbg(&dev->dev, "invalid or not supported effect type in upload\n");
105                 return -EINVAL;
106         }
107
108         if (effect->type == FF_PERIODIC &&
109             (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
110              effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
111              !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
112                 dev_dbg(&dev->dev, "invalid or not supported wave form in upload\n");
113                 return -EINVAL;
114         }
115
116         if (!test_bit(effect->type, ff->ffbit)) {
117                 ret = compat_effect(ff, effect);
118                 if (ret)
119                         return ret;
120         }
121
122         mutex_lock(&ff->mutex);
123
124         if (effect->id == -1) {
125                 for (id = 0; id < ff->max_effects; id++)
126                         if (!ff->effect_owners[id])
127                                 break;
128
129                 if (id >= ff->max_effects) {
130                         ret = -ENOSPC;
131                         goto out;
132                 }
133
134                 effect->id = id;
135                 old = NULL;
136
137         } else {
138                 id = effect->id;
139
140                 ret = check_effect_access(ff, id, file);
141                 if (ret)
142                         goto out;
143
144                 old = &ff->effects[id];
145
146                 if (!check_effects_compatible(effect, old)) {
147                         ret = -EINVAL;
148                         goto out;
149                 }
150         }
151
152         ret = ff->upload(dev, effect, old);
153         if (ret)
154                 goto out;
155
156         spin_lock_irq(&dev->event_lock);
157         ff->effects[id] = *effect;
158         ff->effect_owners[id] = file;
159         spin_unlock_irq(&dev->event_lock);
160
161  out:
162         mutex_unlock(&ff->mutex);
163         return ret;
164 }
165 EXPORT_SYMBOL_GPL(input_ff_upload);
166
167 /*
168  * Erases the effect if the requester is also the effect owner. The mutex
169  * should already be locked before calling this function.
170  */
171 static int erase_effect(struct input_dev *dev, int effect_id,
172                         struct file *file)
173 {
174         struct ff_device *ff = dev->ff;
175         int error;
176
177         error = check_effect_access(ff, effect_id, file);
178         if (error)
179                 return error;
180
181         spin_lock_irq(&dev->event_lock);
182         ff->playback(dev, effect_id, 0);
183         ff->effect_owners[effect_id] = NULL;
184         spin_unlock_irq(&dev->event_lock);
185
186         if (ff->erase) {
187                 error = ff->erase(dev, effect_id);
188                 if (error) {
189                         spin_lock_irq(&dev->event_lock);
190                         ff->effect_owners[effect_id] = file;
191                         spin_unlock_irq(&dev->event_lock);
192
193                         return error;
194                 }
195         }
196
197         return 0;
198 }
199
200 /**
201  * input_ff_erase - erase a force-feedback effect from device
202  * @dev: input device to erase effect from
203  * @effect_id: id of the effect to be erased
204  * @file: purported owner of the request
205  *
206  * This function erases a force-feedback effect from specified device.
207  * The effect will only be erased if it was uploaded through the same
208  * file handle that is requesting erase.
209  */
210 int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
211 {
212         struct ff_device *ff = dev->ff;
213         int ret;
214
215         if (!test_bit(EV_FF, dev->evbit))
216                 return -ENOSYS;
217
218         mutex_lock(&ff->mutex);
219         ret = erase_effect(dev, effect_id, file);
220         mutex_unlock(&ff->mutex);
221
222         return ret;
223 }
224 EXPORT_SYMBOL_GPL(input_ff_erase);
225
226 /*
227  * input_ff_flush - erase all effects owned by a file handle
228  * @dev: input device to erase effect from
229  * @file: purported owner of the effects
230  *
231  * This function erases all force-feedback effects associated with
232  * the given owner from specified device. Note that @file may be %NULL,
233  * in which case all effects will be erased.
234  */
235 int input_ff_flush(struct input_dev *dev, struct file *file)
236 {
237         struct ff_device *ff = dev->ff;
238         int i;
239
240         dev_dbg(&dev->dev, "flushing now\n");
241
242         mutex_lock(&ff->mutex);
243
244         for (i = 0; i < ff->max_effects; i++)
245                 erase_effect(dev, i, file);
246
247         mutex_unlock(&ff->mutex);
248
249         return 0;
250 }
251 EXPORT_SYMBOL_GPL(input_ff_flush);
252
253 /**
254  * input_ff_event() - generic handler for force-feedback events
255  * @dev: input device to send the effect to
256  * @type: event type (anything but EV_FF is ignored)
257  * @code: event code
258  * @value: event value
259  */
260 int input_ff_event(struct input_dev *dev, unsigned int type,
261                    unsigned int code, int value)
262 {
263         struct ff_device *ff = dev->ff;
264
265         if (type != EV_FF)
266                 return 0;
267
268         switch (code) {
269         case FF_GAIN:
270                 if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
271                         break;
272
273                 ff->set_gain(dev, value);
274                 break;
275
276         case FF_AUTOCENTER:
277                 if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
278                         break;
279
280                 ff->set_autocenter(dev, value);
281                 break;
282
283         default:
284                 if (check_effect_access(ff, code, NULL) == 0)
285                         ff->playback(dev, code, value);
286                 break;
287         }
288
289         return 0;
290 }
291 EXPORT_SYMBOL_GPL(input_ff_event);
292
293 /**
294  * input_ff_create() - create force-feedback device
295  * @dev: input device supporting force-feedback
296  * @max_effects: maximum number of effects supported by the device
297  *
298  * This function allocates all necessary memory for a force feedback
299  * portion of an input device and installs all default handlers.
300  * @dev->ffbit should be already set up before calling this function.
301  * Once ff device is created you need to setup its upload, erase,
302  * playback and other handlers before registering input device
303  */
304 int input_ff_create(struct input_dev *dev, unsigned int max_effects)
305 {
306         struct ff_device *ff;
307         size_t ff_dev_size;
308         int i;
309
310         if (!max_effects) {
311                 dev_err(&dev->dev, "cannot allocate device without any effects\n");
312                 return -EINVAL;
313         }
314
315         if (max_effects > FF_MAX_EFFECTS) {
316                 dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n");
317                 return -EINVAL;
318         }
319
320         ff_dev_size = struct_size(ff, effect_owners, max_effects);
321         if (ff_dev_size == SIZE_MAX) /* overflow */
322                 return -EINVAL;
323
324         ff = kzalloc(ff_dev_size, GFP_KERNEL);
325         if (!ff)
326                 return -ENOMEM;
327
328         ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
329                               GFP_KERNEL);
330         if (!ff->effects) {
331                 kfree(ff);
332                 return -ENOMEM;
333         }
334
335         ff->max_effects = max_effects;
336         mutex_init(&ff->mutex);
337
338         dev->ff = ff;
339         dev->flush = input_ff_flush;
340         dev->event = input_ff_event;
341         __set_bit(EV_FF, dev->evbit);
342
343         /* Copy "true" bits into ff device bitmap */
344         for_each_set_bit(i, dev->ffbit, FF_CNT)
345                 __set_bit(i, ff->ffbit);
346
347         /* we can emulate RUMBLE with periodic effects */
348         if (test_bit(FF_PERIODIC, ff->ffbit))
349                 __set_bit(FF_RUMBLE, dev->ffbit);
350
351         return 0;
352 }
353 EXPORT_SYMBOL_GPL(input_ff_create);
354
355 /**
356  * input_ff_destroy() - frees force feedback portion of input device
357  * @dev: input device supporting force feedback
358  *
359  * This function is only needed in error path as input core will
360  * automatically free force feedback structures when device is
361  * destroyed.
362  */
363 void input_ff_destroy(struct input_dev *dev)
364 {
365         struct ff_device *ff = dev->ff;
366
367         __clear_bit(EV_FF, dev->evbit);
368         if (ff) {
369                 if (ff->destroy)
370                         ff->destroy(ff);
371                 kfree(ff->private);
372                 kfree(ff->effects);
373                 kfree(ff);
374                 dev->ff = NULL;
375         }
376 }
377 EXPORT_SYMBOL_GPL(input_ff_destroy);
This page took 0.046954 seconds and 4 git commands to generate.