LCOV - code coverage report
Current view: top level - drivers/input - ff-core.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 161 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 9 0.0 %

          Line data    Source code
       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             :  */
      24           0 : static int check_effect_access(struct ff_device *ff, int effect_id,
      25             :                                 struct file *file)
      26             : {
      27           0 :         if (effect_id < 0 || effect_id >= ff->max_effects ||
      28           0 :             !ff->effect_owners[effect_id])
      29             :                 return -EINVAL;
      30             : 
      31           0 :         if (file && ff->effect_owners[effect_id] != file)
      32           0 :                 return -EACCES;
      33             : 
      34             :         return 0;
      35             : }
      36             : 
      37             : /*
      38             :  * Checks whether 2 effects can be combined together
      39             :  */
      40           0 : static inline int check_effects_compatible(struct ff_effect *e1,
      41             :                                            struct ff_effect *e2)
      42             : {
      43           0 :         return e1->type == e2->type &&
      44           0 :                (e1->type != FF_PERIODIC ||
      45           0 :                 e1->u.periodic.waveform == e2->u.periodic.waveform);
      46             : }
      47             : 
      48             : /*
      49             :  * Convert an effect into compatible one
      50             :  */
      51           0 : static int compat_effect(struct ff_device *ff, struct ff_effect *effect)
      52             : {
      53           0 :         int magnitude;
      54             : 
      55           0 :         switch (effect->type) {
      56           0 :         case FF_RUMBLE:
      57           0 :                 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           0 :                 magnitude = effect->u.rumble.strong_magnitude / 3 +
      65           0 :                             effect->u.rumble.weak_magnitude / 6;
      66             : 
      67           0 :                 effect->type = FF_PERIODIC;
      68           0 :                 effect->u.periodic.waveform = FF_SINE;
      69           0 :                 effect->u.periodic.period = 50;
      70           0 :                 effect->u.periodic.magnitude = max(magnitude, 0x7fff);
      71           0 :                 effect->u.periodic.offset = 0;
      72           0 :                 effect->u.periodic.phase = 0;
      73           0 :                 effect->u.periodic.envelope.attack_length = 0;
      74           0 :                 effect->u.periodic.envelope.attack_level = 0;
      75           0 :                 effect->u.periodic.envelope.fade_length = 0;
      76           0 :                 effect->u.periodic.envelope.fade_level = 0;
      77             : 
      78           0 :                 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             :  */
      92           0 : int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
      93             :                     struct file *file)
      94             : {
      95           0 :         struct ff_device *ff = dev->ff;
      96           0 :         struct ff_effect *old;
      97           0 :         int ret = 0;
      98           0 :         int id;
      99             : 
     100           0 :         if (!test_bit(EV_FF, dev->evbit))
     101             :                 return -ENOSYS;
     102             : 
     103           0 :         if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
     104           0 :             !test_bit(effect->type, dev->ffbit)) {
     105           0 :                 dev_dbg(&dev->dev, "invalid or not supported effect type in upload\n");
     106           0 :                 return -EINVAL;
     107             :         }
     108             : 
     109           0 :         if (effect->type == FF_PERIODIC &&
     110           0 :             (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
     111           0 :              effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
     112           0 :              !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
     113           0 :                 dev_dbg(&dev->dev, "invalid or not supported wave form in upload\n");
     114           0 :                 return -EINVAL;
     115             :         }
     116             : 
     117           0 :         if (!test_bit(effect->type, ff->ffbit)) {
     118           0 :                 ret = compat_effect(ff, effect);
     119           0 :                 if (ret)
     120             :                         return ret;
     121             :         }
     122             : 
     123           0 :         mutex_lock(&ff->mutex);
     124             : 
     125           0 :         if (effect->id == -1) {
     126           0 :                 for (id = 0; id < ff->max_effects; id++)
     127           0 :                         if (!ff->effect_owners[id])
     128             :                                 break;
     129             : 
     130           0 :                 if (id >= ff->max_effects) {
     131           0 :                         ret = -ENOSPC;
     132           0 :                         goto out;
     133             :                 }
     134             : 
     135           0 :                 effect->id = id;
     136           0 :                 old = NULL;
     137             : 
     138             :         } else {
     139           0 :                 id = effect->id;
     140             : 
     141           0 :                 ret = check_effect_access(ff, id, file);
     142           0 :                 if (ret)
     143           0 :                         goto out;
     144             : 
     145           0 :                 old = &ff->effects[id];
     146             : 
     147           0 :                 if (!check_effects_compatible(effect, old)) {
     148           0 :                         ret = -EINVAL;
     149           0 :                         goto out;
     150             :                 }
     151             :         }
     152             : 
     153           0 :         ret = ff->upload(dev, effect, old);
     154           0 :         if (ret)
     155           0 :                 goto out;
     156             : 
     157           0 :         spin_lock_irq(&dev->event_lock);
     158           0 :         ff->effects[id] = *effect;
     159           0 :         ff->effect_owners[id] = file;
     160           0 :         spin_unlock_irq(&dev->event_lock);
     161             : 
     162           0 :  out:
     163           0 :         mutex_unlock(&ff->mutex);
     164           0 :         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             :  */
     172           0 : static int erase_effect(struct input_dev *dev, int effect_id,
     173             :                         struct file *file)
     174             : {
     175           0 :         struct ff_device *ff = dev->ff;
     176           0 :         int error;
     177             : 
     178           0 :         error = check_effect_access(ff, effect_id, file);
     179           0 :         if (error)
     180             :                 return error;
     181             : 
     182           0 :         spin_lock_irq(&dev->event_lock);
     183           0 :         ff->playback(dev, effect_id, 0);
     184           0 :         ff->effect_owners[effect_id] = NULL;
     185           0 :         spin_unlock_irq(&dev->event_lock);
     186             : 
     187           0 :         if (ff->erase) {
     188           0 :                 error = ff->erase(dev, effect_id);
     189           0 :                 if (error) {
     190           0 :                         spin_lock_irq(&dev->event_lock);
     191           0 :                         ff->effect_owners[effect_id] = file;
     192           0 :                         spin_unlock_irq(&dev->event_lock);
     193             : 
     194           0 :                         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             :  */
     211           0 : int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
     212             : {
     213           0 :         struct ff_device *ff = dev->ff;
     214           0 :         int ret;
     215             : 
     216           0 :         if (!test_bit(EV_FF, dev->evbit))
     217             :                 return -ENOSYS;
     218             : 
     219           0 :         mutex_lock(&ff->mutex);
     220           0 :         ret = erase_effect(dev, effect_id, file);
     221           0 :         mutex_unlock(&ff->mutex);
     222             : 
     223           0 :         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             :  */
     236           0 : int input_ff_flush(struct input_dev *dev, struct file *file)
     237             : {
     238           0 :         struct ff_device *ff = dev->ff;
     239           0 :         int i;
     240             : 
     241           0 :         dev_dbg(&dev->dev, "flushing now\n");
     242             : 
     243           0 :         mutex_lock(&ff->mutex);
     244             : 
     245           0 :         for (i = 0; i < ff->max_effects; i++)
     246           0 :                 erase_effect(dev, i, file);
     247             : 
     248           0 :         mutex_unlock(&ff->mutex);
     249             : 
     250           0 :         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             :  */
     261           0 : int input_ff_event(struct input_dev *dev, unsigned int type,
     262             :                    unsigned int code, int value)
     263             : {
     264           0 :         struct ff_device *ff = dev->ff;
     265             : 
     266           0 :         if (type != EV_FF)
     267             :                 return 0;
     268             : 
     269           0 :         switch (code) {
     270           0 :         case FF_GAIN:
     271           0 :                 if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
     272             :                         break;
     273             : 
     274           0 :                 ff->set_gain(dev, value);
     275           0 :                 break;
     276             : 
     277           0 :         case FF_AUTOCENTER:
     278           0 :                 if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
     279             :                         break;
     280             : 
     281           0 :                 ff->set_autocenter(dev, value);
     282           0 :                 break;
     283             : 
     284           0 :         default:
     285           0 :                 if (check_effect_access(ff, code, NULL) == 0)
     286           0 :                         ff->playback(dev, code, value);
     287             :                 break;
     288             :         }
     289             : 
     290           0 :         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             :  */
     305           0 : int input_ff_create(struct input_dev *dev, unsigned int max_effects)
     306             : {
     307           0 :         struct ff_device *ff;
     308           0 :         size_t ff_dev_size;
     309           0 :         int i;
     310             : 
     311           0 :         if (!max_effects) {
     312           0 :                 dev_err(&dev->dev, "cannot allocate device without any effects\n");
     313           0 :                 return -EINVAL;
     314             :         }
     315             : 
     316           0 :         if (max_effects > FF_MAX_EFFECTS) {
     317           0 :                 dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n");
     318           0 :                 return -EINVAL;
     319             :         }
     320             : 
     321           0 :         ff_dev_size = sizeof(struct ff_device) +
     322             :                                 max_effects * sizeof(struct file *);
     323           0 :         if (ff_dev_size < max_effects) /* overflow */
     324             :                 return -EINVAL;
     325             : 
     326           0 :         ff = kzalloc(ff_dev_size, GFP_KERNEL);
     327           0 :         if (!ff)
     328             :                 return -ENOMEM;
     329             : 
     330           0 :         ff->effects = kcalloc(max_effects, sizeof(struct ff_effect),
     331             :                               GFP_KERNEL);
     332           0 :         if (!ff->effects) {
     333           0 :                 kfree(ff);
     334           0 :                 return -ENOMEM;
     335             :         }
     336             : 
     337           0 :         ff->max_effects = max_effects;
     338           0 :         mutex_init(&ff->mutex);
     339             : 
     340           0 :         dev->ff = ff;
     341           0 :         dev->flush = input_ff_flush;
     342           0 :         dev->event = input_ff_event;
     343           0 :         __set_bit(EV_FF, dev->evbit);
     344             : 
     345             :         /* Copy "true" bits into ff device bitmap */
     346           0 :         for_each_set_bit(i, dev->ffbit, FF_CNT)
     347           0 :                 __set_bit(i, ff->ffbit);
     348             : 
     349             :         /* we can emulate RUMBLE with periodic effects */
     350           0 :         if (test_bit(FF_PERIODIC, ff->ffbit))
     351           0 :                 __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             :  */
     365           0 : void input_ff_destroy(struct input_dev *dev)
     366             : {
     367           0 :         struct ff_device *ff = dev->ff;
     368             : 
     369           0 :         __clear_bit(EV_FF, dev->evbit);
     370           0 :         if (ff) {
     371           0 :                 if (ff->destroy)
     372           0 :                         ff->destroy(ff);
     373           0 :                 kfree(ff->private);
     374           0 :                 kfree(ff->effects);
     375           0 :                 kfree(ff);
     376           0 :                 dev->ff = NULL;
     377             :         }
     378           0 : }
     379             : EXPORT_SYMBOL_GPL(input_ff_destroy);

Generated by: LCOV version 1.14