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