1509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
2509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *  Force feedback support for Linux input subsystem
3509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
4509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *  Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com>
5509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *  Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
6509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
7509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
8509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
9509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * This program is free software; you can redistribute it and/or modify
10509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * it under the terms of the GNU General Public License as published by
11509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * the Free Software Foundation; either version 2 of the License, or
12509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * (at your option) any later version.
13509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
14509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * This program is distributed in the hope that it will be useful,
15509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * but WITHOUT ANY WARRANTY; without even the implied warranty of
16509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * GNU General Public License for more details.
18509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
19509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * You should have received a copy of the GNU General Public License
20509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * along with this program; if not, write to the Free Software
21509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
23509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
24509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/* #define DEBUG */
25509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
26da0c490115de026618a7fdcd886602da44392a50Joe Perches#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
27509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
28509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula#include <linux/input.h>
29509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula#include <linux/module.h>
30509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula#include <linux/mutex.h>
3183680cdbcecd1fd284ad4df060d12bf214bb63a8Geert Uytterhoeven#include <linux/sched.h>
325a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
33509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
34509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
35509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Check that the effect_id is a valid effect and whether the user
36509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * is the owner
37509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
38509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulastatic int check_effect_access(struct ff_device *ff, int effect_id,
39509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula				struct file *file)
40509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
41509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (effect_id < 0 || effect_id >= ff->max_effects ||
42509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	    !ff->effect_owners[effect_id])
43509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -EINVAL;
44509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
45509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (file && ff->effect_owners[effect_id] != file)
46509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -EACCES;
47509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
48509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return 0;
49509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
50509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
51509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
52509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Checks whether 2 effects can be combined together
53509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
54509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulastatic inline int check_effects_compatible(struct ff_effect *e1,
55509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula					   struct ff_effect *e2)
56509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
57509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return e1->type == e2->type &&
58509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	       (e1->type != FF_PERIODIC ||
59509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		e1->u.periodic.waveform == e2->u.periodic.waveform);
60509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
61509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
62509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
63509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Convert an effect into compatible one
64509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
65509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulastatic int compat_effect(struct ff_device *ff, struct ff_effect *effect)
66509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
67509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int magnitude;
68509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
69509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	switch (effect->type) {
70509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	case FF_RUMBLE:
71509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (!test_bit(FF_PERIODIC, ff->ffbit))
72509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			return -EINVAL;
73509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
74509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		/*
75509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		 * calculate manginude of sine wave as average of rumble's
76509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		 * 2/3 of strong magnitude and 1/3 of weak magnitude
77509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		 */
78509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		magnitude = effect->u.rumble.strong_magnitude / 3 +
79509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			    effect->u.rumble.weak_magnitude / 6;
80509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
81509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->type = FF_PERIODIC;
82509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.waveform = FF_SINE;
83509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.period = 50;
84509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.magnitude = max(magnitude, 0x7fff);
85509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.offset = 0;
86509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.phase = 0;
87509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.envelope.attack_length = 0;
88509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.envelope.attack_level = 0;
89509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.envelope.fade_length = 0;
90509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->u.periodic.envelope.fade_level = 0;
91509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
92509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return 0;
93509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
94509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	default:
95509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		/* Let driver handle conversion */
96509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return 0;
97509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
98509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
99509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
100509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/**
101509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * input_ff_upload() - upload effect into force-feedback device
102509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @dev: input device
103509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @effect: effect to be uploaded
104509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @file: owner of the effect
105509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
106509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulaint input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
107509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		    struct file *file)
108509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
109509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff = dev->ff;
110509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_effect *old;
111509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int ret = 0;
112509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int id;
113509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
114509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!test_bit(EV_FF, dev->evbit))
115509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -ENOSYS;
116509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
117509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
118509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	    !test_bit(effect->type, dev->ffbit)) {
119da0c490115de026618a7fdcd886602da44392a50Joe Perches		pr_debug("invalid or not supported effect type in upload\n");
120509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -EINVAL;
121509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
122509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
123509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (effect->type == FF_PERIODIC &&
124509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	    (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
125509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	     effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
126509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	     !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
127da0c490115de026618a7fdcd886602da44392a50Joe Perches		pr_debug("invalid or not supported wave form in upload\n");
128509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -EINVAL;
129509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
130509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
131509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!test_bit(effect->type, ff->ffbit)) {
132509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		ret = compat_effect(ff, effect);
133509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (ret)
134509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			return ret;
135509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
136509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
137509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_lock(&ff->mutex);
138509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
139509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (effect->id == -1) {
140509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		for (id = 0; id < ff->max_effects; id++)
14141091ad0b8f843d36390058362c8f3c52a26a333Baodong Chen			if (!ff->effect_owners[id])
14241091ad0b8f843d36390058362c8f3c52a26a333Baodong Chen				break;
143509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
144509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (id >= ff->max_effects) {
145509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			ret = -ENOSPC;
146509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			goto out;
147509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		}
148509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
149509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		effect->id = id;
150509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		old = NULL;
151509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
152509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	} else {
153509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		id = effect->id;
154509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
155509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		ret = check_effect_access(ff, id, file);
156509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (ret)
157509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			goto out;
158509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
159509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		old = &ff->effects[id];
160509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
161509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (!check_effects_compatible(effect, old)) {
162509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			ret = -EINVAL;
163509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			goto out;
164509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		}
165509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
166509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
167509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ret = ff->upload(dev, effect, old);
168509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (ret)
169509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		goto out;
170509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
171656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov	spin_lock_irq(&dev->event_lock);
172509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ff->effects[id] = *effect;
173509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ff->effect_owners[id] = file;
174656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov	spin_unlock_irq(&dev->event_lock);
175509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
176509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula out:
177509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_unlock(&ff->mutex);
178509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return ret;
179509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
180509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi HannulaEXPORT_SYMBOL_GPL(input_ff_upload);
181509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
182509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
183509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Erases the effect if the requester is also the effect owner. The mutex
184509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * should already be locked before calling this function.
185509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
186509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulastatic int erase_effect(struct input_dev *dev, int effect_id,
187509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			struct file *file)
188509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
189509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff = dev->ff;
190509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int error;
191509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
192509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	error = check_effect_access(ff, effect_id, file);
193509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (error)
194509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return error;
195509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
196656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov	spin_lock_irq(&dev->event_lock);
197509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ff->playback(dev, effect_id, 0);
198656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov	ff->effect_owners[effect_id] = NULL;
199656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov	spin_unlock_irq(&dev->event_lock);
200509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
201509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (ff->erase) {
202509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		error = ff->erase(dev, effect_id);
203656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov		if (error) {
204656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov			spin_lock_irq(&dev->event_lock);
205656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov			ff->effect_owners[effect_id] = file;
206656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov			spin_unlock_irq(&dev->event_lock);
207656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov
208509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			return error;
209656acd2bbc4ce7f224de499ee255698701396c48Dmitry Torokhov		}
210509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
211509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
212509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return 0;
213509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
214509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
215509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/**
216e4477d2d1bc3e6c76e83926f7fa8c8f94ba42615Randy Dunlap * input_ff_erase - erase a force-feedback effect from device
217509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @dev: input device to erase effect from
218509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @effect_id: id of the ffect to be erased
219509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @file: purported owner of the request
220509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
221509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * This function erases a force-feedback effect from specified device.
222509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * The effect will only be erased if it was uploaded through the same
223509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * file handle that is requesting erase.
224509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
225509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulaint input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
226509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
227509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff = dev->ff;
228509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int ret;
229509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
230509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!test_bit(EV_FF, dev->evbit))
231509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -ENOSYS;
232509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
233509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_lock(&ff->mutex);
234509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ret = erase_effect(dev, effect_id, file);
235509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_unlock(&ff->mutex);
236509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
237509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return ret;
238509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
239509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi HannulaEXPORT_SYMBOL_GPL(input_ff_erase);
240509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
241509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/*
242509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * flush_effects - erase all effects owned by a file handle
243509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
244509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulastatic int flush_effects(struct input_dev *dev, struct file *file)
245509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
246509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff = dev->ff;
247509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int i;
248509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
249da0c490115de026618a7fdcd886602da44392a50Joe Perches	pr_debug("flushing now\n");
250509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
251509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_lock(&ff->mutex);
252509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
253509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	for (i = 0; i < ff->max_effects; i++)
254509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		erase_effect(dev, i, file);
255509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
256509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_unlock(&ff->mutex);
257509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
258509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return 0;
259509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
260509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
261509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/**
262509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * input_ff_event() - generic handler for force-feedback events
263509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @dev: input device to send the effect to
264509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @type: event type (anything but EV_FF is ignored)
265509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @code: event code
266509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @value: event value
267509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
268509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulaint input_ff_event(struct input_dev *dev, unsigned int type,
269509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		   unsigned int code, int value)
270509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
271509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff = dev->ff;
272509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
273509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (type != EV_FF)
274509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return 0;
275509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
276509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	switch (code) {
277509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	case FF_GAIN:
278509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
279509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			break;
280509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
281509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		ff->set_gain(dev, value);
282509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		break;
283509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
284509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	case FF_AUTOCENTER:
285509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff)
286509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			break;
287509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
288509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		ff->set_autocenter(dev, value);
289509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		break;
290509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
291509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	default:
292dec3eb01c2409ca8276c1152c167add66a37d1baDmitry Torokhov		if (check_effect_access(ff, code, NULL) == 0)
293dec3eb01c2409ca8276c1152c167add66a37d1baDmitry Torokhov			ff->playback(dev, code, value);
294509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		break;
295509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
296509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
297509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return 0;
298509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
299509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi HannulaEXPORT_SYMBOL_GPL(input_ff_event);
300509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
301509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/**
302509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * input_ff_create() - create force-feedback device
303509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @dev: input device supporting force-feedback
304509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @max_effects: maximum number of effects supported by the device
305509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
306509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * This function allocates all necessary memory for a force feedback
307509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * portion of an input device and installs all default handlers.
308509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * @dev->ffbit should be already set up before calling this function.
309509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * Once ff device is created you need to setup its upload, erase,
310509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * playback and other handlers before registering input device
311509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
31205be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenterint input_ff_create(struct input_dev *dev, unsigned int max_effects)
313509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
314509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	struct ff_device *ff;
31505be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter	size_t ff_dev_size;
316509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	int i;
317509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
318509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!max_effects) {
319da0c490115de026618a7fdcd886602da44392a50Joe Perches		pr_err("cannot allocate device without any effects\n");
320509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -EINVAL;
321509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
322509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
32305be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter	ff_dev_size = sizeof(struct ff_device) +
32405be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter				max_effects * sizeof(struct file *);
32505be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter	if (ff_dev_size < max_effects) /* overflow */
32605be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter		return -EINVAL;
32705be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter
32805be8b81aafd4f95106a91ff3fd8581fa984fad9Dan Carpenter	ff = kzalloc(ff_dev_size, GFP_KERNEL);
329509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!ff)
330509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -ENOMEM;
331509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
332509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
333509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula			      GFP_KERNEL);
334509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (!ff->effects) {
335509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		kfree(ff);
336509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		return -ENOMEM;
337509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
338509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
339509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	ff->max_effects = max_effects;
340509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	mutex_init(&ff->mutex);
341509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
342509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	dev->ff = ff;
343509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	dev->flush = flush_effects;
344509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	dev->event = input_ff_event;
345bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov	__set_bit(EV_FF, dev->evbit);
346509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
347509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	/* Copy "true" bits into ff device bitmap */
348509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	for (i = 0; i <= FF_MAX; i++)
349509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		if (test_bit(i, dev->ffbit))
350bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov			__set_bit(i, ff->ffbit);
351509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
352509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	/* we can emulate RUMBLE with periodic effects */
353509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	if (test_bit(FF_PERIODIC, ff->ffbit))
354bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov		__set_bit(FF_RUMBLE, dev->ffbit);
355509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
356509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	return 0;
357509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
358509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi HannulaEXPORT_SYMBOL_GPL(input_ff_create);
359509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula
360509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula/**
361721a730eceb009ba61f8eeee31360c02ed8f6abaRoger Quadros * input_ff_destroy() - frees force feedback portion of input device
362e4477d2d1bc3e6c76e83926f7fa8c8f94ba42615Randy Dunlap * @dev: input device supporting force feedback
363509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula *
364509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * This function is only needed in error path as input core will
365509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * automatically free force feedback structures when device is
366509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula * destroyed.
367509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula */
368509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannulavoid input_ff_destroy(struct input_dev *dev)
369509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula{
370bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov	struct ff_device *ff = dev->ff;
371bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov
372bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov	__clear_bit(EV_FF, dev->evbit);
373bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov	if (ff) {
374bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov		if (ff->destroy)
375bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov			ff->destroy(ff);
376bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov		kfree(ff->private);
3776a47081c37b7dd7810ce19e156c1a3bf11987e9aJari Vanhala		kfree(ff->effects);
378bf3204cbff7d2606e758afb0994e8da6ae1c6c26Dmitry Torokhov		kfree(ff);
379509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula		dev->ff = NULL;
380509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula	}
381509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi Hannula}
382509ca1a9383601fdc5612d3d3ba5b981f6eb6c8bAnssi HannulaEXPORT_SYMBOL_GPL(input_ff_destroy);
383