On Fri, Apr 08, 2005 at 08:29:52PM +0300, Anssi Hannula wrote:
> This patch adds Force Feedback interface to joydev. I felt this 
> necessary because games usually don't run as root while evdev usually 
> can't be read or written by anyone else. Patch is against 2.6.12-rc2. If 
> there is a reason this can't be applied or needs modifications, please 
> say it :)

Modern distros usually chown() the event devices to the user logged on
the console, so this shouldn't be a problem. Anyway, I'm not opposed to
adding the ioctl()s, but you should also add 64-bit compatible versions
of them.

> 
> If I have enough time and skills, I will start developing userspace 
> Force Feedback library, which would do (among other things) all 
> necessary force convertings between joystick, gamepad and wheel controllers.
> 
> Does anyone have any thoughts about this?
> 
> Signed-off-by: Anssi Hannula <[EMAIL PROTECTED]>
> 

> diff -Nurp linux-2.6.11/Documentation/input/ff.txt 
> linux-2.6.11-ffjoy/Documentation/input/ff.txt
> --- linux-2.6.11/Documentation/input/ff.txt   2005-03-02 09:38:12.000000000 
> +0200
> +++ linux-2.6.11-ffjoy/Documentation/input/ff.txt     2005-04-08 
> 00:07:50.000000000 +0300
> @@ -1,5 +1,6 @@
>  Force feedback for Linux.
>  By Johann Deneux <[EMAIL PROTECTED]> on 2001/04/22.
> +Updated & cleaned on 2005/04/04 by Anssi Hannula <[EMAIL PROTECTED]>
>  You may redistribute this file. Please remember to include shape.fig and
>  interactive.fig as well.
>  ----------------------------------------------------------------------------
> @@ -10,18 +11,11 @@ This document describes how to use force
>  goal is not to support these devices as if they were simple input-only 
> devices
>  (as it is already the case), but to really enable the rendering of force
>  effects.
> -At the moment, only I-Force devices are supported, and not officially. That
> -means I had to find out how the protocol works on my own. Of course, the
> -information I managed to grasp is far from being complete, and I can not
> -guarranty that this driver will work for you.
> -This document only describes the force feedback part of the driver for 
> I-Force
> -devices. Please read joystick.txt before reading further this document.
> +Please read joystick.txt before reading further this document.
>  
>  2. Instructions to the user
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -Here are instructions on how to compile and use the driver. In fact, this
> -driver is the normal iforce, input and evdev drivers written by Vojtech
> -Pavlik, plus additions to support force feedback.
> +Here are instructions on how to compile and use the driver.
>  
>  Before you start, let me WARN you that some devices shake violently during 
> the
>  initialisation phase. This happens for example with my "AVB Top Shot 
> Pegasus".
> @@ -29,19 +23,18 @@ To stop this annoying behaviour, move yo
>  should keep a hand on your device, in order to avoid it to brake down if
>  something goes wrong.
>  
> -At the kernel's compilation:
> -     - Enable IForce/Serial
> -     - Enable Event interface
> +At the kernel's compilation enable the Force Feedback support for devices you
> +have.
>  
>  Compile the modules, install them.
>  
> -You also need inputattach.
> +For serial devices you also need inputattach.
>  
>  You then need to insert the modules into the following order:
>  % modprobe joydev
>  % modprobe serport           # Only for serial
> -% modprobe iforce
> -% modprobe evdev
> +% modprobe iforce            # Example of FF driver
> +% modprobe evdev             # For evdev-interface
>  % ./inputattach -ifor $2 &   # Only for serial
>  If you are using USB, you don't need the inputattach step.
>  
> @@ -66,23 +59,37 @@ mknod input/event3 c 13 67
>  2.1 Does it work ?
>  ~~~~~~~~~~~~~~~~~~
>  There is an utility called fftest that will allow you to test the driver.
> +% fftest /dev/input/jsXX
> +
> +You can test the evdev interface with:
>  % fftest /dev/input/eventXX
>  
> +Please note that joydev (jsXX) interface is recommended over evdev due to
> +security issues involved in allowing users to access evdev devices.
> +
>  3. Instructions to the developper
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -  All interactions are done using the event API. That is, you can use ioctl()
> -and write() on /dev/input/eventXX.
> -  This information is subject to change.
> +All interactions are done using the joydev API. That is, you can use ioctl()
> +and write() on /dev/input/jsXX. There is also an evdev interface on
> +/dev/input/eventXX.
> +
> +Joydev FF API is present in JS_VERSION >= 0x020200.
> +Evdev FF API is present in all 2.6 series kernels.
> +Use the joydev API instead of evdev whenever possible.
> +
> +This information is subject to change.
>  
>  3.1 Querying device capabilities
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  #include <linux/input.h>
> +#include <linux/joystick.h>
>  #include <sys/ioctl.h>
>  
>  unsigned long features[1 + FF_MAX/sizeof(unsigned long)];
>  int ioctl(int file_descriptor, int request, unsigned long *features);
>  
> -"request" must be EVIOCGBIT(EV_FF, size of features array in bytes )
> +"request" must be JSIOCGFFBIT(size of features array in bytes).
> +The evdev version is EVIOCGBIT(EV_FF, size of features array in bytes ).
>  
>  Returns the features supported by the device. features is a bitfield with the
>  following bits:
> @@ -100,6 +107,7 @@ following bits:
>  - FF_INERTIA    can simulate inertia
>  
>  
> +int ioctl(int fd, JSIOCGEFFECTS, int *n);
>  int ioctl(int fd, EVIOCGEFFECTS, int *n);
>  
>  Returns the number of effects the device can keep in its memory.
> @@ -107,11 +115,12 @@ Returns the number of effects the device
>  3.2 Uploading effects to the device
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  #include <linux/input.h>
> +#include <linux/joystick.h>
>  #include <sys/ioctl.h>
>   
>  int ioctl(int file_descriptor, int request, struct ff_effect *effect);
>  
> -"request" must be EVIOCSFF.
> +"request" must be JSIOCSFF (EVIOCSFF for evdev).
>  
>  "effect" points to a structure describing the effect to upload. The effect is
>  uploaded, but not played.
> @@ -126,6 +135,7 @@ You need xfig to visualize these files.
>  
>  3.3 Removing an effect from the device
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +int ioctl(int fd, JSIOCRMFF, effect.id);
>  int ioctl(int fd, EVIOCRMFF, effect.id);
>  
>  This makes room for new effects in the device's memory. Please note this 
> won't
> @@ -136,6 +146,7 @@ stop the effect if it was playing.
>  Control of playing is done with write(). Below is an example:
>  
>  #include <linux/input.h>
> +#include <linux/joystick.h>
>  #include <unistd.h>
>  
>       struct input_event play;
> @@ -143,7 +154,7 @@ Control of playing is done with write().
>       struct ff_effect effect;
>       int fd;
>  ...
> -     fd = open("/dev/input/eventXX", O_RDWR);
> +     fd = open("/dev/input/jsXX", O_RDWR);
>  ...
>       /* Play three times */
>       play.type = EV_FF;
> @@ -207,8 +218,11 @@ case, the driver stops the effect, up-lo
>  
>  3.8 Information about the status of effects
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -Every time the status of an effect is changed, an event is sent. The values
> -and meanings of the fields of the event are as follows:
> +Every time the status of an effect is changed, an event is sent.
> +
> +NOTE: This appears to not be implemented in all drivers at the moment.
> +
> +The values and meanings of the fields of the event are as follows:
>  struct input_event {
>  /* When the status of the effect changed */
>       struct timeval time;
> diff -Nurp linux-2.6.11/drivers/input/joydev.c 
> linux-2.6.11-ffjoy/drivers/input/joydev.c
> --- linux-2.6.11/drivers/input/joydev.c       2005-04-07 23:57:21.000000000 
> +0300
> +++ linux-2.6.11-ffjoy/drivers/input/joydev.c 2005-04-08 00:04:40.000000000 
> +0300
> @@ -141,6 +141,13 @@ static int joydev_fasync(int fd, struct 
>       return retval < 0 ? retval : 0;
>  }
>  
> +static int joydev_flush(struct file * file)
> +{
> +     struct joydev_list *list = file->private_data;
> +     if (!list->joydev->exist) return -ENODEV;
> +     return input_flush_device(&list->joydev->handle, file);
> +}
> +
>  static void joydev_free(struct joydev *joydev)
>  {
>       joydev_table[joydev->minor] = NULL;
> @@ -191,7 +198,21 @@ static int joydev_open(struct inode *ino
>  
>  static ssize_t joydev_write(struct file * file, const char __user * buffer, 
> size_t count, loff_t *ppos)
>  {
> -     return -EINVAL;
> +     struct joydev_list *list = file->private_data;
> +     struct input_event event;
> +     int retval = 0;
> +
> +     if (!list->joydev->exist) return -ENODEV;
> +
> +     while (retval < count) {
> +
> +             if (copy_from_user(&event, buffer + retval, sizeof(struct 
> input_event)))
> +                     return -EFAULT;
> +             input_event(list->joydev->handle.dev, event.type, event.code, 
> event.value);
> +             retval += sizeof(struct input_event);
> +     }
> +
> +     return retval;
>  }
>  
>  static ssize_t joydev_read(struct file *file, char __user *buf, size_t 
> count, loff_t *ppos)
> @@ -358,6 +379,26 @@ static int joydev_ioctl(struct inode *in
>               case JSIOCGBTNMAP:
>                       return copy_to_user(argp, joydev->keypam,
>                                               sizeof(__u16) * (KEY_MAX - 
> BTN_MISC + 1)) ? -EFAULT : 0;
> +             case JSIOCSFF:
> +                     if (dev->upload_effect) {
> +                             struct ff_effect effect;
> +                             int err;
> +                             if (copy_from_user(&effect, argp, 
> sizeof(effect)))
> +                                     return -EFAULT;
> +                             err = dev->upload_effect(dev, &effect);
> +                             if (put_user(effect.id, &(((struct ff_effect 
> __user *)arg)->id)))
> +                                     return -EFAULT;
> +                             return err;
> +                     }
> +                     else return -ENOSYS;
> +             case JSIOCRMFF:
> +                     if (dev->erase_effect)
> +                             return dev->erase_effect(dev, (int)arg);
> +                     return -ENOSYS;
> +             case JSIOCGEFFECTS:
> +                     if (put_user(dev->ff_effects_max, (int __user *)arg))
> +                             return -EFAULT;
> +                     return 0;
>               default:
>                       if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == 
> JSIOCGNAME(0)) {
>                               int len;
> @@ -367,6 +408,15 @@ static int joydev_ioctl(struct inode *in
>                               if (copy_to_user(argp, dev->name, len)) return 
> -EFAULT;
>                               return len;
>                       }
> +                     if (_IOC_NR(cmd) == _IOC_NR(JSIOCGFFBIT(0))) {
> +                             int len;
> +                             len = NBITS(FF_MAX) * sizeof(long);
> +                             if (len > _IOC_SIZE(cmd))
> +                                     len = _IOC_SIZE(cmd);
> +                             if (copy_to_user(argp, dev->ffbit, len))
> +                                     return -EFAULT;
> +                             return len;
> +                     }
>       }
>       return -EINVAL;
>  }
> @@ -380,6 +430,7 @@ static struct file_operations joydev_fop
>       .release =      joydev_release,
>       .ioctl =        joydev_ioctl,
>       .fasync =       joydev_fasync,
> +     .flush =        joydev_flush,
>  };
>  
>  static struct input_handle *joydev_connect(struct input_handler *handler, 
> struct input_dev *dev, struct input_device_id *id)
> diff -Nurp linux-2.6.11/include/linux/joystick.h 
> linux-2.6.11-ffjoy/include/linux/joystick.h
> --- linux-2.6.11/include/linux/joystick.h     2005-04-07 23:57:42.000000000 
> +0300
> +++ linux-2.6.11-ffjoy/include/linux/joystick.h       2005-04-07 
> 23:59:59.000000000 +0300
> @@ -36,7 +36,7 @@
>   * Version
>   */
>  
> -#define JS_VERSION           0x020100
> +#define JS_VERSION           0x020200
>  
>  /*
>   * Types and constants for reading from /dev/js
> @@ -71,6 +71,13 @@ struct js_event {
>  #define JSIOCSBTNMAP         _IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC + 1])  
> /* set button mapping */
>  #define JSIOCGBTNMAP         _IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC + 1])  
> /* get button mapping */
>  
> +#define JSIOCGFFBIT(len)     _IOC(_IOC_READ, 'j', 0x41, len)                 
> /* get force effect bits */
> +#define JSIOCSFF             _IOW('j', 0x42, struct ff_effect)
> +                     /* upload a force effect to a force feedback device */
> +#define JSIOCRMFF            _IOW('j', 0x43, int)                            
> /* erase a force effect */
> +#define JSIOCGEFFECTS                _IOR('j', 0x44, int)
> +                     /* get number of effects playable at the same time */
> +
>  /*
>   * Types and constants for get/set correction
>   */
> 


-- 
Vojtech Pavlik
SuSE Labs, SuSE CR
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to