diff options
author | Sascha Hlusiak <saschahlusiak@arcor.de> | 2007-04-07 17:30:09 -0400 |
---|---|---|
committer | Sascha Hlusiak <saschahlusiak@arcor.de> | 2007-04-07 17:30:09 -0400 |
commit | f7f63037fd01433c325b4bb45e76d8a21dd327c0 (patch) | |
tree | 5954ac9ba3b54dd15beea48832bd79a5c3bb1736 | |
parent | fcc717eb281328cd2722ba8fe2395e6719b88d8a (diff) |
Added USB-HID backend for *BSD
Added checks for platform in configure.ac and Makefile.am
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | src/Makefile.am | 17 | ||||
-rw-r--r-- | src/bsd_jstk.c | 303 | ||||
-rw-r--r-- | src/jstk.c | 2 | ||||
-rw-r--r-- | src/linux_jstk.c | 2 |
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; +} @@ -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" /*********************************************************************** |