Makefile.am | 2 config/50-x11-input-joystick.fdi | 16 ++ config/Makefile.am | 1 configure.ac | 60 ++++--- man/joystick.man | 25 ++- src/Makefile.am | 15 + src/backend_bsd.c | 309 +++++++++++++++++++++++++++++++++++++++ src/backend_bsd.h | 35 ++++ src/backend_evdev.c | 294 +++++++++++++++++++++++++++++++++++++ src/backend_evdev.h | 35 ++++ src/backend_joystick.c | 197 ++++++++++++++++++++++++ src/backend_joystick.h | 35 ++++ src/bsd_jstk.c | 308 -------------------------------------- src/jstk.c | 66 +++++++- src/jstk.h | 16 +- src/jstk_hw.h | 38 ---- src/jstk_key.c | 1 src/jstk_options.c | 1 src/linux_jstk.c | 195 ------------------------ 19 files changed, 1066 insertions(+), 583 deletions(-)
New commits: commit 01637abd2b059923f5c41ab80c80ab93579cbe9b Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Fri Dec 7 00:17:56 2007 +0100 Mentioned hotplugging and hal policy in man page diff --git a/man/joystick.man b/man/joystick.man index 786228b..8e48883 100644 --- a/man/joystick.man +++ b/man/joystick.man @@ -42,12 +42,14 @@ The following Driver are supported: .TP 7 .BI "Option \*qDevice\*q \*q" string \*q +.TP 7 +.BI "Option \*qPath\*q \*q" string \*q Specifies the device through which the joystick can be accessed. This option is mandatory and there is no default setting. For Linux, joysticks are mostly accessible as .IR /dev/input/jsX " or " /dev/input/eventX . -For *BSD, joysticks are recognized as +In *BSD, joysticks are usually recognized as .IR /dev/uhidX . .TP 7 .BI "Option \*qDebugLevel\*q \*q" integer \*q @@ -292,9 +294,15 @@ Axes in the mode will be ignored. The mode has no effect on the reported value. The axis does not need to be assigned to a direction. .SH "NOTES" -The driver does not do hotplugging. The joystick needs to be plugged in when the driver is loaded. +The driver does not do hotplugging on it's own. The joystick needs to be plugged in when the driver is loaded. If the joystick is unplugged, the device will be deactivated. .P +There is an example hal policy in +.I ${sourcecode}/config/50-x11-input-joystick.fdi +which will take care of hotplugging. Place it in +.I /etc/hal/fdi/policy +and customize it to your needs. This is highly experimental and for now you can't pass options to the driver. +.P Make sure you add the .I \*qSendCoreEvents\*q keyword to the device entry of your commit 47cd8141f9bf3e69d5418f3b5f448366f500cf0d Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 23:55:20 2007 +0100 Bumped to version 1.3.1 diff --git a/configure.ac b/configure.ac index a511b83..a4b9e4a 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-input-joystick], - 1.3.0, + 1.3.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-input-joystick) commit c463776b8b35e6e721128a7348e088d306c4ee02 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 23:48:49 2007 +0100 Added example hal policy file for input hotplugging of joysticks Hal policy config/50-x11-input-joystick.fdi is not installed by default and you probably don't want to. diff --git a/Makefile.am b/Makefile.am index af2effb..6bef39a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AUTOMAKE_OPTIONS = foreign -SUBDIRS = src man +SUBDIRS = src man config EXTRA_DIST = autogen.sh ChangeLog diff --git a/config/50-x11-input-joystick.fdi b/config/50-x11-input-joystick.fdi new file mode 100644 index 0000000..f32a36a --- /dev/null +++ b/config/50-x11-input-joystick.fdi @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<deviceinfo version="0.2"> + <device> + <match key="info.capabilities" contains="input"> + <!-- Match on anything you like from lshal --> + <match key="input.product" string="Logitech Logitech Dual Action"> + <!-- Currently Xorg looks for these two capabilities, so + we need to add them. This might confuse other hal clients. --> + <append key="info.capabilities" type="strlist">input.keys</append> + <append key="info.capabilities" type="strlist">input.mouse</append> + <merge key="input.x11_driver" type="string">joystick</merge> + <!-- How to add custom parameters to configure the device? --> + </match> + </match> + </device> +</deviceinfo> diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 0000000..c96ffeb --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = 50-x11-input-joystick.fdi diff --git a/configure.ac b/configure.ac index 4660213..a511b83 100644 --- a/configure.ac +++ b/configure.ac @@ -108,7 +108,7 @@ AC_HEADER_STDC XORG_MANPAGE_SECTIONS XORG_RELEASE_VERSION -AC_OUTPUT([Makefile src/Makefile man/Makefile]) +AC_OUTPUT([Makefile src/Makefile man/Makefile config/Makefile]) echo echo Building Linux joystick backend: $linux_backend commit 833454bd7bea04924b85105bf38ed57dd2b5e5c2 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 23:22:43 2007 +0100 Looking for Path parameter besides Device (used by HAL+input hotplug) diff --git a/src/jstk.c b/src/jstk.c index ee3d602..f55405b 100644 --- a/src/jstk.c +++ b/src/jstk.c @@ -548,6 +548,8 @@ jstkCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags) /* Joystick device is mandatory */ priv->device = xf86SetStrOption(dev->commonOptions, "Device", NULL); + if (!priv->device) + priv->device = xf86SetStrOption(dev->commonOptions, "Path", NULL); if (!priv->device) { xf86Msg (X_ERROR, "%s: No Device specified.\n", local->name); commit dca42ff25dde490073a798dc873b048c4bfeb0f4 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 23:22:06 2007 +0100 Fixed default button mappings Default button mappings were set to buttons 4, 5 and 6 instead of 1, 2 and 3. diff --git a/src/jstk.c b/src/jstk.c index c98c521..ee3d602 100644 --- a/src/jstk.c +++ b/src/jstk.c @@ -509,13 +509,15 @@ jstkCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags) priv->button[i].keys[j] = 0; } + priv->buttonmap.map[0] = 0; + /* First three joystick buttons generate mouse clicks */ priv->button[0].mapping = MAPPING_BUTTON; - priv->button[0].buttonnumber = 1; + priv->button[0].buttonnumber = jstkGetButtonNumberInMap(priv, 1); priv->button[1].mapping = MAPPING_BUTTON; - priv->button[1].buttonnumber = 2; + priv->button[1].buttonnumber = jstkGetButtonNumberInMap(priv, 2); priv->button[2].mapping = MAPPING_BUTTON; - priv->button[2].buttonnumber = 3; + priv->button[2].buttonnumber = jstkGetButtonNumberInMap(priv, 3); /* First two axes are a stick for moving */ priv->axis[0].type = TYPE_BYVALUE; @@ -539,7 +541,6 @@ jstkCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags) priv->buttonmap.scrollbutton[1] = jstkGetButtonNumberInMap(priv, 5); priv->buttonmap.scrollbutton[2] = jstkGetButtonNumberInMap(priv, 6); priv->buttonmap.scrollbutton[3] = jstkGetButtonNumberInMap(priv, 7); - priv->buttonmap.map[0] = 0; xf86CollectInputOptions(local, NULL, NULL); commit fba24465bc4867568cbefc3d554bae756abc1204 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 22:56:26 2007 +0100 Return NULL on device configure fail instead of unconfigured device, which made X segfault. diff --git a/src/jstk.c b/src/jstk.c index 9f9c455..c98c521 100644 --- a/src/jstk.c +++ b/src/jstk.c @@ -622,7 +622,8 @@ SetupProc_fail: xfree(priv); if (local) local->private = NULL; - return (local); + return NULL; +/* return (local); */ /* Makes X segfault on error */ } commit 2fba11efcafdbc2002bc7083a2b74cb7d908b3a9 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Thu Dec 6 22:28:12 2007 +0100 New: evdev backend diff --git a/src/backend_evdev.c b/src/backend_evdev.c index 6eeab08..aaad342 100644 --- a/src/backend_evdev.c +++ b/src/backend_evdev.c @@ -36,7 +36,7 @@ #include <errno.h> #include <string.h> #include <stdlib.h> -#include <linux/joystick.h> +#include <linux/input.h> #include <xf86.h> #include <xf86_OSproc.h> @@ -45,6 +45,22 @@ #include "backend_evdev.h" +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define LONG(x) ((x)/BITS_PER_LONG) +#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) + + +struct jstk_evdev_data { + struct jstk_evdev_axis_data { + int number; + int min, max; + } axis[ABS_MAX]; + int key[KEY_MAX]; +}; + + /*********************************************************************** * * jstkOpenDevice -- @@ -59,17 +75,114 @@ int jstkOpenDevice_evdev(JoystickDevPtr joystick) { - if (1) { - xf86Msg(X_ERROR, "Joystick: '%s': evdev failed: IMPLEMENTATION MISSING\n", - joystick->device); + int driver_version; + char name[256]; + char uniq[256]; + struct input_id id; + struct jstk_evdev_data *evdevdata; + unsigned long button_bits[NBITS(ABS_MAX)]; + unsigned long key_bits[NBITS(KEY_MAX)]; + int axes, buttons, j; + + if ((joystick->fd = open(joystick->device, O_RDONLY | O_NDELAY, 0)) < 0) { + xf86Msg(X_ERROR, "Cannot open joystick '%s' (%s)\n", + joystick->device, strerror(errno)); + return -1; + } + + if (ioctl(joystick->fd, EVIOCGVERSION, &driver_version) == -1) { + xf86Msg(X_ERROR, "Joystick: ioctl EVIOCGVERSION on '%s' failed: %s\n", + joystick->device, strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + if (ioctl(joystick->fd, EVIOCGID, &id) == -1) { + xf86Msg(X_ERROR, "Joystick: ioctl EVIOCGID on '%s' failed: %s\n", + joystick->device, strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + + memset(button_bits, 0, sizeof(button_bits)); + if (ioctl(joystick->fd, EVIOCGBIT(EV_ABS, ABS_MAX), button_bits) == -1) + { + xf86Msg(X_ERROR, "Joystick: ioctl EVIOCGBIT on '%s' failed: %s\n", + joystick->device, strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + evdevdata = (struct jstk_evdev_data*) + malloc(sizeof(struct jstk_evdev_data)); + for (axes=0; axes<ABS_MAX; axes++) + { + evdevdata->axis[axes].number = -1; + evdevdata->axis[axes].min = 0; + evdevdata->axis[axes].max = 1; + } + for (buttons=0; buttons<KEY_MAX; buttons++) + { + evdevdata->key[buttons] = -1; + } + + axes = 0; /* Our logical index */ + for (j = 0; j < ABS_MAX; j++) + if (test_bit(j, button_bits)) + { + struct input_absinfo abs; + if (ioctl(joystick->fd, EVIOCGABS(j), &abs) == -1) { + xf86Msg(X_ERROR, "Joystick: ioctl EVIOCGABS on '%s' failed: %s\n", + joystick->device, strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + free(evdevdata); + return -1; + } + evdevdata->axis[j].number = axes; /* physical -> logical mapping */ + evdevdata->axis[j].min = abs.minimum; + evdevdata->axis[j].max = abs.maximum; + DBG(3, ErrorF("Axis %d: phys %d min %d max %d\n", + axes, j, abs.minimum, abs.maximum)); + + axes++; + } + + memset(key_bits, 0, sizeof(key_bits)); + if (ioctl(joystick->fd, EVIOCGBIT(EV_KEY, KEY_MAX), key_bits) == -1) + { + xf86Msg(X_ERROR, "Joystick: ioctl EVIOCGBIT on '%s' failed: %s\n", + joystick->device, strerror(errno)); + close(joystick->fd); + joystick->fd = -1; return -1; } + buttons = 0; /* Our logical index */ + for (j = 0; j < KEY_MAX; j++) + if (test_bit(j, key_bits)) + { + evdevdata->key[j] = buttons; + DBG(3, ErrorF("Button %d: phys %d\n", buttons, j)); + buttons++; + } + + if (ioctl(joystick->fd, EVIOCGNAME(sizeof(name)), name) == -1) + strcpy(name, "No name"); -/* xf86Msg(X_INFO, "Joystick: %s. %d axes, %d buttons\n", - joy_name, axes, buttons); */ + if (ioctl(joystick->fd, EVIOCGUNIQ(sizeof(uniq)), uniq) == -1) + strcpy(uniq, "No name"); + + xf86Msg(X_INFO, "Joystick: %s. %d axes, %d buttons.\n", name, axes, buttons); + xf86Msg(X_INFO, "Joystick: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", + id.bustype, id.vendor, id.product, id.version); joystick->read_proc = jstkReadData_evdev; joystick->close_proc = jstkCloseDevice_evdev; + joystick->devicedata = (void*) evdevdata; return joystick->fd; } @@ -86,10 +199,14 @@ jstkOpenDevice_evdev(JoystickDevPtr joystick) void jstkCloseDevice_evdev(JoystickDevPtr joystick) { -/* if ((joystick->fd >= 0)) { + if ((joystick->fd >= 0)) { xf86CloseSerial(joystick->fd); + if (joystick->devicedata) { + free(joystick->devicedata); + joystick->devicedata = NULL; + } joystick->fd = -1; - }*/ + } } @@ -110,8 +227,68 @@ jstkReadData_evdev(JoystickDevPtr joystick, JOYSTICKEVENT *event, int *number) { + struct input_event iev; + signed int value; + struct jstk_evdev_data *data; if (event != NULL) *event = EVENT_NONE; - return 0; + if (xf86ReadSerial(joystick->fd, &iev, sizeof(struct input_event)) != + sizeof(struct input_event)) + return 0; + if (!joystick->devicedata) return 0; /* we are supposed to have devicedata */ + data = (struct jstk_evdev_data*)joystick->devicedata; + DBG(10, if (iev.type) + ErrorF("Event (evdev): type: 0x%04X, code: 0x%04X, value: 0x%04X\n", + (unsigned int)iev.type, + (unsigned int)iev.code, + (int)iev.value)); + + switch(iev.type) { + case EV_KEY: + if ((data->key[iev.code] >= 0) && + (data->key[iev.code] < MAXBUTTONS)) + { + if (joystick->button[data->key[iev.code]].pressed != iev.value) + { + joystick->button[data->key[iev.code]].pressed = iev.value; + if (event != NULL) *event = EVENT_BUTTON; + if (number != NULL) *number = data->key[iev.code]; + } + } + break; + case EV_ABS: + if (iev.code < ABS_MAX) { + struct jstk_evdev_axis_data *axis; + axis = &data->axis[iev.code]; + if ((axis->number >= 0) && (axis->number < MAXAXES)) { + value = (iev.value - axis->min) * 65535 + / (axis->max - axis->min) - 32768; + if (abs(value) < joystick->axis[axis->number].deadzone) { + /* We only want one event when in deadzone */ + if (joystick->axis[axis->number].value != 0) { + joystick->axis[axis->number].oldvalue = + joystick->axis[axis->number].value; + joystick->axis[axis->number].value = 0; + if (event != NULL) *event = EVENT_AXIS; + if (number != NULL) *number = axis->number; + } + }else{ + joystick->axis[axis->number].oldvalue = + joystick->axis[axis->number].value; + joystick->axis[axis->number].value = value; + if (event != NULL) *event = EVENT_AXIS; + if (number != NULL) *number = axis->number; + } + } + } + break; + default: + DBG(3, if (iev.type) + ErrorF("Unhandled evdev event: type: 0x%04X, code: 0x%04X, " + "value: 0x%04X\n", + (unsigned int)iev.type, + (unsigned int)iev.code, + (int)iev.value)); + } return 1; } commit 78616fb8174e93a2c3c523bd425acc33a4b8773c Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Wed Dec 5 22:17:36 2007 +0100 Mentioned multiple backends in man page diff --git a/man/joystick.man b/man/joystick.man index cd08098..786228b 100644 --- a/man/joystick.man +++ b/man/joystick.man @@ -13,8 +13,15 @@ joystick \- Joystick input driver .fi .SH DESCRIPTION .B joystick -is an __xservername__ input driver for Joysticks, using either Linux's -joystick devices or *BSD's uhid devices. The driver reports cursor movement +is an __xservername__ input driver for Joysticks. There are 3 backends available that are used in the following order, if support was found: + +.nf +.B - Linux's evdev interface +.B - Linux's joystick interface +.B - BSD's usbhid interface +.fi + +The driver reports cursor movement as well as raw axis values through valuators. .SH SUPPORTED HARDWARE @@ -38,7 +45,7 @@ are supported: Specifies the device through which the joystick can be accessed. This option is mandatory and there is no default setting. For Linux, joysticks are mostly accessible as -.IR /dev/input/jsX . +.IR /dev/input/jsX " or " /dev/input/eventX . For *BSD, joysticks are recognized as .IR /dev/uhidX . commit 9e5f4e6fccb8c9e1b6c4dfccb39f1f0c89f79b60 Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Wed Dec 5 21:33:27 2007 +0100 Fixed implicit declaration warnings because of missed header files diff --git a/src/jstk_key.c b/src/jstk_key.c index 5cddf25..a5c5106 100644 --- a/src/jstk_key.c +++ b/src/jstk_key.c @@ -29,6 +29,7 @@ #include <xf86.h> +#include <xf86Xinput.h> #include <X11/extensions/XKB.h> #include <X11/extensions/XKBstr.h> #include <X11/extensions/XKBsrv.h> diff --git a/src/jstk_options.c b/src/jstk_options.c index 66b8f37..f1dfcc8 100644 --- a/src/jstk_options.c +++ b/src/jstk_options.c @@ -142,7 +142,6 @@ jstkParseButtonOption(const char* org, const char* name) { char *param; - char *tmp; int value; float fvalue; char p[64]; commit 43790502b5d1077fc74e81b7eedd9c880673463c Author: Sascha Hlusiak <[EMAIL PROTECTED]> Date: Wed Dec 5 21:30:12 2007 +0100 Renamed backend files from *_jstk.{c,h} to backend_*.{c,h} diff --git a/src/Makefile.am b/src/Makefile.am index d65c859..cdb96b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,9 +34,9 @@ jstk_options.c jstk_options.h \ StrKeysym.c StrKeysym.h ks_tables.h -BSD_SRCS = bsd_jstk.c bsd_jstk.h -LINUX_SRCS = linux_jstk.c linux_jstk.h -EVDEV_SRCS = evdev_jstk.c evdev_jstk.h +BSD_SRCS = backend_bsd.c backend_bsd.h +LINUX_SRCS = backend_joystick.c backend_joystick.h +EVDEV_SRCS = backend_evdev.c backend_evdev.h if BSD_BACKEND @[EMAIL PROTECTED] += $(BSD_SRCS) diff --git a/src/backend_bsd.c b/src/backend_bsd.c new file mode 100644 index 0000000..4628c0d --- /dev/null +++ b/src/backend_bsd.c @@ -0,0 +1,309 @@ +/* + * Copyright 2007 by Sascha Hlusiak. <[EMAIL PROTECTED]> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Sascha Hlusiak not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Sascha Hlusiak makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * SASCHA HLUSIAK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SASCHA HLUSIAK BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ + +/** + * This provides the backend for USB-HIDs for NetBSD, OpenBSD and FreeBSD + * Needs the uhid module loaded. Device names are /dev/uhid? + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> + +#include <xf86.h> +#include <xf86_OSproc.h> + +#include <usbhid.h> +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> + +#include "jstk.h" +#include "backend_bsd.h" + + +struct jstk_bsd_hid_data { + int dlen; /* Length of one data chunk */ + char *data_buf; /* Data buffer with right size */ + struct hid_item axis_item[MAXAXES]; /* Axis HID items */ + struct hid_item button_item[MAXBUTTONS]; /* Button HID items */ + struct hid_item hat_item[MAXAXES]; /* HID items for hats */ + int hats; /* Number of hats */ + int axes; /* Number of found axes */ + int buttons; /* Number of found buttons */ + int hotdata; /* Is unprocessed data available + in data_buf? */ +}; + + + +/*********************************************************************** + * + * jstkOpenDevice -- + * + * Open and initialize a joystick device + * Returns the filedescriptor, or -1 in case of error + * + *********************************************************************** + */ + +int +jstkOpenDevice_bsd(JoystickDevPtr joystick) +{ + int cur_axis; + int is_joystick, report_id = 0; + int got_something; + struct hid_data *d; + struct hid_item h; + report_desc_t rd; + struct jstk_bsd_hid_data *bsddata; + + if ((joystick->fd = open(joystick->device, O_RDWR | O_NDELAY, 0)) < 0) { + xf86Msg(X_ERROR, "Cannot open joystick '%s' (%s)\n", joystick->device, + strerror(errno)); + return -1; + } + + if ((rd = hid_get_report_desc(joystick->fd)) == 0) { + xf86Msg(X_ERROR, "Joystick: hid_get_report_desc failed: %s\n", + strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + if (ioctl(joystick->fd, USB_GET_REPORT_ID, &report_id) < 0) { + xf86Msg(X_ERROR, "Joystick: ioctl USB_GET_REPORT_ID failed: %s\n", + strerror(errno)); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + bsddata = (struct jstk_bsd_hid_data*) + malloc(sizeof(struct jstk_bsd_hid_data)); + bsddata->dlen = hid_report_size(rd, hid_input, report_id); + + if ((bsddata->data_buf = malloc(bsddata->dlen)) == NULL) { + fprintf(stderr, "error: couldn't malloc %d bytes\n", bsddata->dlen); + hid_dispose_report_desc(rd); + free(bsddata); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + is_joystick = 0; + got_something = 0; + cur_axis = 0; + bsddata->hats = 0; + bsddata->axes = 0; + bsddata->buttons = 0; + + for (d = hid_start_parse(rd, 1 << hid_input, report_id); + hid_get_item(d, &h); ) + { + int usage, page; + + page = HID_PAGE(h.usage); + usage = HID_USAGE(h.usage); + + is_joystick = is_joystick || + (h.kind == hid_collection && + page == HUP_GENERIC_DESKTOP && + (usage == HUG_JOYSTICK || usage == HUG_GAME_PAD)); + + if (h.kind != hid_input) + continue; + + if (!is_joystick) + continue; + + if (page == HUP_GENERIC_DESKTOP) { + if (usage == HUG_HAT_SWITCH) { + if ((bsddata->hats < MAXAXES) && (bsddata->axes <= MAXAXES-2)) { + got_something = 1; + memcpy(&bsddata->hat_item[bsddata->hats], &h, sizeof(h)); + bsddata->hats++; + bsddata->axes += 2; + } + } else { + if (bsddata->axes < MAXAXES) { + got_something = 1; + memcpy(&bsddata->axis_item[cur_axis], &h, sizeof(h)); + cur_axis++; + bsddata->axes++; + } + } + } else if (page == HUP_BUTTON) { + if (bsddata->buttons < MAXBUTTONS) { + got_something = 1; + memcpy(&bsddata->button_item[bsddata->buttons], &h, sizeof(h)); + bsddata->buttons++; + } + } + } + hid_end_parse(d); + + if (!got_something) { + free(bsddata->data_buf); + xf86Msg(X_ERROR, "Joystick: Didn't find any usable axes.\n"); + free(bsddata); + close(joystick->fd); + joystick->fd = -1; + return -1; + } + + bsddata->hotdata = 0; + joystick->devicedata = (void*) bsddata; + xf86Msg(X_INFO, "Joystick: %d buttons, %d axes\n", + bsddata->buttons, bsddata->axes); + + joystick->read_proc = jstkReadData_bsd; + joystick->close_proc = jstkCloseDevice_bsd; + + return joystick->fd; +} + + +/*********************************************************************** + * + * jstkCloseDevice -- + * + * close the handle. + * + *********************************************************************** + */ + +void +jstkCloseDevice_bsd(JoystickDevPtr joystick) +{ + if ((joystick->fd >= 0)) { + xf86CloseSerial(joystick->fd); + joystick->fd = -1; + } + if (joystick->devicedata != NULL) { + if (((struct jstk_bsd_hid_data*)joystick->devicedata)->data_buf) + free(((struct jstk_bsd_hid_data*)joystick->devicedata)->data_buf); + free(joystick->devicedata); + } +} + + +/*********************************************************************** + * + * jstkReadData -- + * + * Reads data from fd and stores it in the JoystickDevRec struct + * fills in the type of event and the number of the button/axis + * return 1 if success, 0 otherwise. Success does not neccessarily + * mean that there is a new event waiting. + * + *********************************************************************** + */ + +int +jstkReadData_bsd(JoystickDevPtr joystick, + JOYSTICKEVENT *event, + int *number) +{ + int j,d; + struct jstk_bsd_hid_data *bsddata = + (struct jstk_bsd_hid_data*)(joystick->devicedata); + + if (event != NULL) *event = EVENT_NONE; + if (bsddata->hotdata == 0) { + j= xf86ReadSerial(joystick->fd, + bsddata->data_buf, + bsddata->dlen); + if (j != bsddata->dlen) { + ErrorF("Read: %d byte! Should be %d\n",j,bsddata->dlen); + return 0; + } + bsddata->hotdata = 1; + } + + for (j=0; j<bsddata->axes - (bsddata->hats * 2); j++) { + d = hid_get_data(bsddata->data_buf, &bsddata->axis_item[j]); + /* Scale the range to our expected range of -32768 to 32767 */ + d = d - (bsddata->axis_item[j].logical_maximum + - bsddata->axis_item[j].logical_minimum) / 2; + d = d * 65536 / (bsddata->axis_item[j].logical_maximum + - bsddata->axis_item[j].logical_minimum); + if (abs(d) < joystick->axis[j].deadzone) d = 0; + if (d != joystick->axis[j].value) { + joystick->axis[j].oldvalue = joystick->axis[j].value; + joystick->axis[j].value = d; + if (event != NULL) *event = EVENT_AXIS; + if (number != NULL) *number = j; + return 2; + } + } + + for (j=0; j<bsddata->hats; j++) { + int a; + int v1_data[9] = + { 0, 32767, 32767, 32767, 0, -32768, -32768, -32768, 0 }; + int v2_data[9] = + { -32768, -32768, 0, 32767, 32767, 32767, 0, -32767, 0 }; + + a = j*2 + bsddata->axes - bsddata->hats *2; + d = hid_get_data(bsddata->data_buf, &bsddata->hat_item[j]) + - bsddata->hat_item[j].logical_minimum; + if (joystick->axis[a].value != v1_data[d]) { + joystick->axis[a].oldvalue = joystick->axis[a].value; + joystick->axis[a].value = v1_data[d]; + if (event != NULL) *event = EVENT_AXIS; + if (number != NULL) *number = a; + return 2; + } + if (joystick->axis[a+1].value != v2_data[d]) { + joystick->axis[a+1].oldvalue = joystick->axis[a+1].value; + joystick->axis[a+1].value = v2_data[d]; + if (event != NULL) *event = EVENT_AXIS; + if (number != NULL) *number = a+1; + return 2; + } + } + + for (j=0; j<bsddata->buttons; j++) { + int pressed; + d = hid_get_data(bsddata->data_buf, &bsddata->button_item[j]); + pressed = (d == bsddata->button_item[j].logical_minimum) ? 0 : 1; + if (pressed != joystick->button[j].pressed) { + joystick->button[j].pressed = pressed; + if (event != NULL) *event = EVENT_BUTTON; + if (number != NULL) *number = j; + return 2; + } + } + + bsddata->hotdata = 0; + return 1; +} diff --git a/src/backend_bsd.h b/src/backend_bsd.h new file mode 100644 index 0000000..452b206 --- /dev/null +++ b/src/backend_bsd.h @@ -0,0 +1,35 @@ +/* + * Copyright 2007 by Sascha Hlusiak. <[EMAIL PROTECTED]> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Sascha Hlusiak not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Sascha Hlusiak makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * SASCHA HLUSIAK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SASCHA HLUSIAK BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef _BACKEND_BSD_H_INCLUDED_ +#define _BACKEND_BSD_H_INCLUDED_ + +#include "jstk.h" + +int jstkOpenDevice_bsd(JoystickDevPtr joystick); +void jstkCloseDevice_bsd(JoystickDevPtr joystick); +int jstkReadData_bsd(JoystickDevPtr joystick, + JOYSTICKEVENT *event, + int *number); + +#endif diff --git a/src/backend_evdev.c b/src/backend_evdev.c new file mode 100644 index 0000000..6eeab08 --- /dev/null +++ b/src/backend_evdev.c @@ -0,0 +1,117 @@ +/* + * Copyright 2007 by Sascha Hlusiak. <[EMAIL PROTECTED]> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Sascha Hlusiak not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Sascha Hlusiak makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * SASCHA HLUSIAK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SASCHA HLUSIAK BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ + +/** + * This provides the backend for Linux evdev devices. + * Devices are usually /dev/input/event? + **/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <linux/joystick.h> + +#include <xf86.h> +#include <xf86_OSproc.h> + +#include "jstk.h" +#include "backend_evdev.h" + + +/*********************************************************************** + * + * jstkOpenDevice -- + * + * Open and initialize a joystick device. The device name is + * taken from JoystickDevPtr + * Returns the filedescriptor, or -1 in case of error + * + *********************************************************************** + */ + +int +jstkOpenDevice_evdev(JoystickDevPtr joystick) +{ + if (1) { + xf86Msg(X_ERROR, "Joystick: '%s': evdev failed: IMPLEMENTATION MISSING\n", + joystick->device); -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]