xref: /openbmc/linux/drivers/input/ff-core.c (revision c727e46f)
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/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  */
check_effect_access(struct ff_device * ff,int effect_id,struct file * file)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  */
check_effects_compatible(struct ff_effect * e1,struct ff_effect * e2)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  */
compat_effect(struct ff_device * ff,struct ff_effect * effect)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  */
input_ff_upload(struct input_dev * dev,struct ff_effect * effect,struct file * file)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  */
erase_effect(struct input_dev * dev,int effect_id,struct file * file)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  */
input_ff_erase(struct input_dev * dev,int effect_id,struct file * file)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  */
input_ff_flush(struct input_dev * dev,struct file * file)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  */
input_ff_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)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  */
input_ff_create(struct input_dev * dev,unsigned int max_effects)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  */
input_ff_destroy(struct input_dev * dev)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);
378