summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSascha Hlusiak <saschahlusiak@arcor.de>2007-04-07 17:30:09 -0400
committerSascha Hlusiak <saschahlusiak@arcor.de>2007-04-07 17:30:09 -0400
commitf7f63037fd01433c325b4bb45e76d8a21dd327c0 (patch)
tree5954ac9ba3b54dd15beea48832bd79a5c3bb1736
parentfcc717eb281328cd2722ba8fe2395e6719b88d8a (diff)
Added USB-HID backend for *BSD
Added checks for platform in configure.ac and Makefile.am
-rw-r--r--configure.ac18
-rw-r--r--src/Makefile.am17
-rw-r--r--src/bsd_jstk.c303
-rw-r--r--src/jstk.c2
-rw-r--r--src/linux_jstk.c2
5 files changed, 338 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 92ee78d..d90be0f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,24 @@ AH_TOP([#include "xorg-server.h"])
# AC_DEFINE(XKB,1,[Enable XKB support])
#fi
+case $host_os in
+ linux*)
+ IS_LINUX="yes"
+ ;;
+
+ freebsd* | kfreebsd-gnu* | netbsd* | openbsd*)
+ IS_BSD="yes"
+ ;;
+
+ *)
+ AC_MSG_ERROR([Your operating system is not supported by the joystick driver.
+ Contact xorg@lists.freedesktop.org if you are interested in
+ porting it.])
+ ;;
+esac
+AM_CONDITIONAL(LINUX, [test "x$IS_LINUX" = xyes])
+AM_CONDITIONAL(BSD, [test "x$IS_BSD" = xyes])
+
AC_ARG_WITH(xorg-module-dir,
AC_HELP_STRING([--with-xorg-module-dir=DIR],
[Default xorg module directory [[default=$libdir/xorg/modules]]]),
diff --git a/src/Makefile.am b/src/Makefile.am
index 1beb07c..b64ebb9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,20 @@
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_ladir = @inputdir@
-@DRIVER_NAME@_drv_la_SOURCES = jstk.c jstk.h \
- linux_jstk.c linux_jstk.h \
+@DRIVER_NAME@_drv_la_SOURCES = jstk.c jstk.h jstk_hw.h \
jstk_axis.c jstk_axis.h \
jstk_options.c jstk_options.h
+
+BSD_SRCS = bsd_jstk.c
+LINUX_SRCS = linux_jstk.c
+
+if BSD
+@DRIVER_NAME@_drv_la_SOURCES += $(BSD_SRCS)
+@DRIVER_NAME@_drv_la_LDFLAGS += -lusbhid
+endif
+
+if LINUX
+@DRIVER_NAME@_drv_la_SOURCES += $(LINUX_SRCS)
+endif
+
+EXTRA_DIST = $(BSD_SRCS) $(LINUX_SRCS)
diff --git a/src/bsd_jstk.c b/src/bsd_jstk.c
new file mode 100644
index 0000000..3df02d2
--- /dev/null
+++ b/src/bsd_jstk.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2007 by Sascha Hlusiak. <saschahlusiak@freedesktop.org>
+ *
+ * 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.
+ *
+ */
+
+
+#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 "jstk_hw.h"
+
+
+struct jstk_bsd_hid_data {
+ int dlen;
+ char *data_buf;
+ struct hid_item axis_item[MAXAXES];
+ struct hid_item button_item[MAXBUTTONS];
+ struct hid_item hat_item[MAXAXES];
+ int hats;
+ int hotdata;
+};
+
+
+
+
+
+/***********************************************************************
+ *
+ * jstkOpenDevice --
+ *
+ * Open and initialize a joystick device
+ * Returns the filedescriptor, or -1 in case of error
+ *
+ ***********************************************************************
+ */
+
+int
+jstkOpenDevice(JoystickDevPtr joystick)
+{
+ int cur_axis, cur_button;
+ 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;
+ }
+ joystick->axes = 0;
+ joystick->buttons = 0;
+
+ 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);
+ 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);
+ 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);
+ return -1;
+ }
+
+ is_joystick = 0;
+ got_something = 0;
+ cur_axis = 0;
+ cur_button = 0;
+ bsddata->hats = 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);
+
+ /* This test is somewhat too simplistic, but this is how MicroSoft
+ * does, so I guess it works for all joysticks/game pads. */
+ 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) && (joystick->axes <= MAXAXES-2)) {
+ got_something = 1;
+ memcpy(&bsddata->hat_item[bsddata->hats],&h,sizeof(h));
+ bsddata->hats++;
+ joystick->axes += 2;
+ }
+ }
+ else
+ {
+ if (joystick->axes < MAXAXES) {
+ got_something = 1;
+ memcpy(&bsddata->axis_item[cur_axis],&h,sizeof(h));
+ cur_axis++;
+ joystick->axes++;
+ }
+ }
+ }
+ else if (page == HUP_BUTTON)
+ {
+ if (joystick->buttons < MAXBUTTONS) {
+ got_something = 1;
+ memcpy(&bsddata->button_item[cur_button], &h, sizeof(h));
+ cur_button++;
+ joystick->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);
+ return -1;
+ }
+
+ bsddata->hotdata = 0;
+ joystick->devicedata = (void*) bsddata;
+ xf86Msg(X_INFO, "Joystick: %d buttons, %d axes\n",
+ joystick->axes, joystick->buttons);
+
+ return joystick->fd;
+}
+
+
+/***********************************************************************
+ *
+ * jstkCloseDevice --
+ *
+ * close the handle.
+ *
+ ***********************************************************************
+ */
+
+void
+jstkCloseDevice(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) != NULL)
+ 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(JoystickDevPtr joystick,
+ enum 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<joystick->axes - (bsddata->hats * 2); j++)
+ {
+ d = hid_get_data(bsddata->data_buf, &bsddata->axis_item[j]);
+ 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].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 + joystick->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].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].value = v2_data[d];
+ if (event != NULL) *event = EVENT_AXIS;
+ if (number != NULL) *number = a+1;
+ return 2;
+ }
+ }
+
+ for (j=0; j<joystick->buttons; j++)
+ {
+ d = hid_get_data(bsddata->data_buf, &bsddata->button_item[j]);
+ if (((d == bsddata->button_item[j].logical_minimum)?0:1) != joystick->button[j].pressed) {
+ joystick->button[j].pressed = (d == bsddata->button_item[j].logical_minimum)?0:1;
+ if (event != NULL) *event = EVENT_BUTTON;
+ if (number != NULL) *number = j;
+ return 2;
+ }
+ }
+
+ bsddata->hotdata = 0;
+
+ return 1;
+}
diff --git a/src/jstk.c b/src/jstk.c
index f0dabc5..578e1f3 100644
--- a/src/jstk.c
+++ b/src/jstk.c
@@ -229,7 +229,7 @@ jstkReadProc(LocalDevicePtr local)
break;
}
}
- while (r == 2);
+ } while (r == 2);
}
diff --git a/src/linux_jstk.c b/src/linux_jstk.c
index dc4461e..7746d02 100644
--- a/src/linux_jstk.c
+++ b/src/linux_jstk.c
@@ -39,7 +39,7 @@
#include <xf86_OSproc.h>
#include "jstk.h"
-#include "linux_jstk.h"
+#include "jstk_hw.h"
/***********************************************************************