linux/drivers/input/ff-core.c
<<
>>
Prefs
   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 */
  38static int check_effect_access(struct ff_device *ff, int effect_id,
  39                                struct file *file)
  40{
  41        if (effect_id < 0 || effect_id >= ff->max_effects ||
  42            !ff->effect_owners[effect_id])
  43                return -EINVAL;
  44
  45        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 */
  54static inline int check_effects_compatible(struct ff_effect *e1,
  55                                           struct ff_effect *e2)
  56{
  57        return e1->type == e2->type &&
  58               (e1->type != FF_PERIODIC ||
  59                e1->u.periodic.waveform == e2->u.periodic.waveform);
  60}
  61
  62/*
  63 * Convert an effect into compatible one
  64 */
  65static int compat_effect(struct ff_device *ff, struct ff_effect *effect)
  66{
  67        int magnitude;
  68
  69        switch (effect->type) {
  70        case FF_RUMBLE:
  71                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                magnitude = effect->u.rumble.strong_magnitude / 3 +
  79                            effect->u.rumble.weak_magnitude / 6;
  80
  81                effect->type = FF_PERIODIC;
  82                effect->u.periodic.waveform = FF_SINE;
  83                effect->u.periodic.period = 50;
  84                effect->u.periodic.magnitude = max(magnitude, 0x7fff);
  85                effect->u.periodic.offset = 0;
  86                effect->u.periodic.phase = 0;
  87                effect->u.periodic.envelope.attack_length = 0;
  88                effect->u.periodic.envelope.attack_level = 0;
  89                effect->u.periodic.envelope.fade_length = 0;
  90                effect->u.periodic.envelope.fade_level = 0;
  91
  92                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 */
 106int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 107                    struct file *file)
 108{
 109        struct ff_device *ff = dev->ff;
 110        struct ff_effect *old;
 111        int ret = 0;
 112        int id;
 113
 114        if (!test_bit(EV_FF, dev->evbit))
 115                return -ENOSYS;
 116
 117        if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
 118            !test_bit(effect->type, dev->ffbit)) {
 119                pr_debug("invalid or not supported effect type in upload\n");
 120                return -EINVAL;
 121        }
 122
 123        if (effect->type == FF_PERIODIC &&
 124            (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
 125             effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
 126             !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        if (!test_bit(effect->type, ff->ffbit)) {
 132                ret = compat_effect(ff, effect);
 133                if (ret)
 134                        return ret;
 135        }
 136
 137        mutex_lock(&ff->mutex);
 138
 139        if (effect->id == -1) {
 140                for (id = 0; id < ff->max_effects; id++)
 141                     if (!ff->effect_owners[id])
 142                        break;
 143
 144                if (id >= ff->max_effects) {
 145                        ret = -ENOSPC;
 146                        goto out;
 147                }
 148
 149                effect->id = id;
 150                old = NULL;
 151
 152        } else {
 153                id = effect->id;
 154
 155                ret = check_effect_access(ff, id, file);
 156                if (ret)
 157                        goto out;
 158
 159                old = &ff->effects[id];
 160
 161                if (!check_effects_compatible(effect, old)) {
 162                        ret = -EINVAL;
 163                        goto out;
 164                }
 165        }
 166
 167        ret = ff->upload(dev, effect, old);
 168        if (ret)
 169                goto out;
 170
 171        spin_lock_irq(&dev->event_lock);
 172        ff->effects[id] = *effect;
 173        ff->effect_owners[id] = file;
 174        spin_unlock_irq(&dev->event_lock);
 175
 176 out:
 177        mutex_unlock(&ff->mutex);
 178        return ret;
 179}
 180EXPORT_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 */
 186static int erase_effect(struct input_dev *dev, int effect_id,
 187                        struct file *file)
 188{
 189        struct ff_device *ff = dev->ff;
 190        int error;
 191
 192        error = check_effect_access(ff, effect_id, file);
 193        if (error)
 194                return error;
 195
 196        spin_lock_irq(&dev->event_lock);
 197        ff->playback(dev, effect_id, 0);
 198        ff->effect_owners[effect_id] = NULL;
 199        spin_unlock_irq(&dev->event_lock);
 200
 201        if (ff->erase) {
 202                error = ff->erase(dev, effect_id);
 203                if (error) {
 204                        spin_lock_irq(&dev->event_lock);
 205                        ff->effect_owners[effect_id] = file;
 206                        spin_unlock_irq(&dev->event_lock);
 207
 208                        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 */
 225int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
 226{
 227        struct ff_device *ff = dev->ff;
 228        int ret;
 229
 230        if (!test_bit(EV_FF, dev->evbit))
 231                return -ENOSYS;
 232
 233        mutex_lock(&ff->mutex);
 234        ret = erase_effect(dev, effect_id, file);
 235        mutex_unlock(&ff->mutex);
 236
 237        return ret;
 238}
 239EXPORT_SYMBOL_GPL(input_ff_erase);
 240
 241/*
 242 * flush_effects - erase all effects owned by a file handle
 243 */
 244static int flush_effects(struct input_dev *dev, struct file *file)
 245{
 246        struct ff_device *ff = dev->ff;
 247        int i;
 248
 249        pr_debug("flushing now\n");
 250
 251        mutex_lock(&ff->mutex);
 252
 253        for (i = 0; i < ff->max_effects; i++)
 254                erase_effect(dev, i, file);
 255
 256        mutex_unlock(&ff->mutex);
 257
 258        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 */
 268int input_ff_event(struct input_dev *dev, unsigned int type,
 269                   unsigned int code, int value)
 270{
 271        struct ff_device *ff = dev->ff;
 272
 273        if (type != EV_FF)
 274                return 0;
 275
 276        switch (code) {
 277        case FF_GAIN:
 278                if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
 279                        break;
 280
 281                ff->set_gain(dev, value);
 282                break;
 283
 284        case FF_AUTOCENTER:
 285                if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff)
 286                        break;
 287
 288                ff->set_autocenter(dev, value);
 289                break;
 290
 291        default:
 292                if (check_effect_access(ff, code, NULL) == 0)
 293                        ff->playback(dev, code, value);
 294                break;
 295        }
 296
 297        return 0;
 298}
 299EXPORT_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 */
 312int 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        if (!max_effects) {
 319                pr_err("cannot allocate device without any effects\n");
 320                return -EINVAL;
 321        }
 322
 323        ff_dev_size = sizeof(struct ff_device) +
 324                                max_effects * sizeof(struct file *);
 325        if (ff_dev_size < max_effects) /* overflow */
 326                return -EINVAL;
 327
 328        ff = kzalloc(ff_dev_size, GFP_KERNEL);
 329        if (!ff)
 330                return -ENOMEM;
 331
 332        ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
 333                              GFP_KERNEL);
 334        if (!ff->effects) {
 335                kfree(ff);
 336                return -ENOMEM;
 337        }
 338
 339        ff->max_effects = max_effects;
 340        mutex_init(&ff->mutex);
 341
 342        dev->ff = ff;
 343        dev->flush = flush_effects;
 344        dev->event = input_ff_event;
 345        __set_bit(EV_FF, dev->evbit);
 346
 347        /* Copy "true" bits into ff device bitmap */
 348        for (i = 0; i <= FF_MAX; i++)
 349                if (test_bit(i, dev->ffbit))
 350                        __set_bit(i, ff->ffbit);
 351
 352        /* we can emulate RUMBLE with periodic effects */
 353        if (test_bit(FF_PERIODIC, ff->ffbit))
 354                __set_bit(FF_RUMBLE, dev->ffbit);
 355
 356        return 0;
 357}
 358EXPORT_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 */
 368void input_ff_destroy(struct input_dev *dev)
 369{
 370        struct ff_device *ff = dev->ff;
 371
 372        __clear_bit(EV_FF, dev->evbit);
 373        if (ff) {
 374                if (ff->destroy)
 375                        ff->destroy(ff);
 376                kfree(ff->private);
 377                kfree(ff->effects);
 378                kfree(ff);
 379                dev->ff = NULL;
 380        }
 381}
 382EXPORT_SYMBOL_GPL(input_ff_destroy);
 383
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.