File Index
Files and directories
Sign in
FILE

ff-core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/input/ff-core.c 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 <anssi.hannula@gmail.com>
  6 *  Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
  7 */
  8
  9/* #define DEBUG */
 10
 11#include <linux/export.h>
 12#include <linux/input.h>
 13#include <linux/limits.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 */
 23static 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 */
 39static 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 */
 50static 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 */
 91int 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 error;
 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		error = compat_effect(ff, effect);
118		if (error)
119			return error;
120	}
121
122	guard(mutex)(&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			return -ENOSPC;
131
132		effect->id = id;
133		old = NULL;
134
135	} else {
136		id = effect->id;
137
138		error = check_effect_access(ff, id, file);
139		if (error)
140			return error;
141
142		old = &ff->effects[id];
143
144		if (!check_effects_compatible(effect, old))
145			return -EINVAL;
146	}
147
148	error = ff->upload(dev, effect, old);
149	if (error)
150		return error;
151
152	scoped_guard(spinlock_irq, &dev->event_lock) {
153		ff->effects[id] = *effect;
154		ff->effect_owners[id] = file;
155	}
156
157	return 0;
158}
159EXPORT_SYMBOL_GPL(input_ff_upload);
160
161/*
162 * Erases the effect if the requester is also the effect owner. The mutex
163 * should already be locked before calling this function.
164 */
165static int erase_effect(struct input_dev *dev, int effect_id,
166			struct file *file)
167{
168	struct ff_device *ff = dev->ff;
169	int error;
170
171	error = check_effect_access(ff, effect_id, file);
172	if (error)
173		return error;
174
175	scoped_guard(spinlock_irq, &dev->event_lock) {
176		ff->playback(dev, effect_id, 0);
177		ff->effect_owners[effect_id] = NULL;
178	}
179
180	if (ff->erase) {
181		error = ff->erase(dev, effect_id);
182		if (error) {
183			scoped_guard(spinlock_irq, &dev->event_lock)
184				ff->effect_owners[effect_id] = file;
185
186			return error;
187		}
188	}
189
190	return 0;
191}
192
193/**
194 * input_ff_erase - erase a force-feedback effect from device
195 * @dev: input device to erase effect from
196 * @effect_id: id of the effect to be erased
197 * @file: purported owner of the request
198 *
199 * This function erases a force-feedback effect from specified device.
200 * The effect will only be erased if it was uploaded through the same
201 * file handle that is requesting erase.
202 */
203int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
204{
205	struct ff_device *ff = dev->ff;
206
207	if (!test_bit(EV_FF, dev->evbit))
208		return -ENOSYS;
209
210	guard(mutex)(&ff->mutex);
211	return erase_effect(dev, effect_id, file);
212}
213EXPORT_SYMBOL_GPL(input_ff_erase);
214
215/*
216 * input_ff_flush - erase all effects owned by a file handle
217 * @dev: input device to erase effect from
218 * @file: purported owner of the effects
219 *
220 * This function erases all force-feedback effects associated with
221 * the given owner from specified device. Note that @file may be %NULL,
222 * in which case all effects will be erased.
223 */
224int input_ff_flush(struct input_dev *dev, struct file *file)
225{
226	struct ff_device *ff = dev->ff;
227	int i;
228
229	dev_dbg(&dev->dev, "flushing now\n");
230
231	guard(mutex)(&ff->mutex);
232
233	for (i = 0; i < ff->max_effects; i++)
234		erase_effect(dev, i, file);
235
236	return 0;
237}
238EXPORT_SYMBOL_GPL(input_ff_flush);
239
240/**
241 * input_ff_event() - generic handler for force-feedback events
242 * @dev: input device to send the effect to
243 * @type: event type (anything but EV_FF is ignored)
244 * @code: event code
245 * @value: event value
246 */
247int input_ff_event(struct input_dev *dev, unsigned int type,
248		   unsigned int code, int value)
249{
250	struct ff_device *ff = dev->ff;
251
252	if (type != EV_FF)
253		return 0;
254
255	switch (code) {
256	case FF_GAIN:
257		if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
258			break;
259
260		ff->set_gain(dev, value);
261		break;
262
263	case FF_AUTOCENTER:
264		if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
265			break;
266
267		ff->set_autocenter(dev, value);
268		break;
269
270	default:
271		if (check_effect_access(ff, code, NULL) == 0)
272			ff->playback(dev, code, value);
273		break;
274	}
275
276	return 0;
277}
278EXPORT_SYMBOL_GPL(input_ff_event);
279
280/**
281 * input_ff_create() - create force-feedback device
282 * @dev: input device supporting force-feedback
283 * @max_effects: maximum number of effects supported by the device
284 *
285 * This function allocates all necessary memory for a force feedback
286 * portion of an input device and installs all default handlers.
287 * @dev->ffbit should be already set up before calling this function.
288 * Once ff device is created you need to setup its upload, erase,
289 * playback and other handlers before registering input device
290 */
291int input_ff_create(struct input_dev *dev, unsigned int max_effects)
292{
293	int i;
294
295	if (!max_effects) {
296		dev_err(&dev->dev, "cannot allocate device without any effects\n");
297		return -EINVAL;
298	}
299
300	if (max_effects > FF_MAX_EFFECTS) {
301		dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n");
302		return -EINVAL;
303	}
304
305	struct ff_device *ff __free(kfree) =
306		kzalloc(struct_size(ff, effect_owners, max_effects),
307			GFP_KERNEL);
308	if (!ff)
309		return -ENOMEM;
310
311	ff->effects = kcalloc(max_effects, sizeof(*ff->effects), GFP_KERNEL);
312	if (!ff->effects)
313		return -ENOMEM;
314
315	ff->max_effects = max_effects;
316	mutex_init(&ff->mutex);
317
318	dev->flush = input_ff_flush;
319	dev->event = input_ff_event;
320	__set_bit(EV_FF, dev->evbit);
321
322	/* Copy "true" bits into ff device bitmap */
323	for_each_set_bit(i, dev->ffbit, FF_CNT)
324		__set_bit(i, ff->ffbit);
325
326	/* we can emulate RUMBLE with periodic effects */
327	if (test_bit(FF_PERIODIC, ff->ffbit))
328		__set_bit(FF_RUMBLE, dev->ffbit);
329
330	dev->ff = no_free_ptr(ff);
331
332	return 0;
333}
334EXPORT_SYMBOL_GPL(input_ff_create);
335
336/**
337 * input_ff_destroy() - frees force feedback portion of input device
338 * @dev: input device supporting force feedback
339 *
340 * This function is only needed in error path as input core will
341 * automatically free force feedback structures when device is
342 * destroyed.
343 */
344void input_ff_destroy(struct input_dev *dev)
345{
346	struct ff_device *ff = dev->ff;
347
348	__clear_bit(EV_FF, dev->evbit);
349	if (ff) {
350		if (ff->destroy)
351			ff->destroy(ff);
352		kfree(ff->private);
353		kfree(ff->effects);
354		kfree(ff);
355		dev->ff = NULL;
356	}
357}
358EXPORT_SYMBOL_GPL(input_ff_destroy);
~/ Read-only file preview.