Re: [PATCH] Add Force Feedback interface to joydev

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux