Added USB-HID backend for *BSD

Added checks for platform in configure.ac and Makefile.am
This commit is contained in:
Sascha Hlusiak
2007-04-07 17:30:09 -04:00
parent fcc717eb28
commit f7f63037fd
5 changed files with 338 additions and 4 deletions

View File

@@ -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]]]),

View File

@@ -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)

303
src/bsd_jstk.c Normal file
View File

@@ -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;
}

View File

@@ -229,7 +229,7 @@ jstkReadProc(LocalDevicePtr local)
break;
}
}
while (r == 2);
} while (r == 2);
}

View File

@@ -39,7 +39,7 @@
#include <xf86_OSproc.h>
#include "jstk.h"
#include "linux_jstk.h"
#include "jstk_hw.h"
/***********************************************************************