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