[PATCH] evdev and 3DConnexion SpaceTraveler
Barton C Massey
bart at cs.pdx.edu
Tue Feb 6 00:30:19 PST 2007
You probably want to fix the Linux driver such that the
device features will be correctly recognized. This is
usually doable if you're OK with touching the kernel.
I have no idea what kernel Ubuntu 6.10 uses, but kernels
2.6.18 and later have a bugfix I put in that might just fix
your problem already.
Bart
In message <45C7DB87.8040403 at ccom.unh.edu> you wrote:
> Hello all,
>
> This is my first list message, first patch submission, first time using
> git and first time hacking Xserver code, so please be gentle with me! :)
>
> Anyways, I have been trying to get my 3DConnexion SpaceTraveler to be
> supported by glut like the old SpaceBalls used to be. Fortunately, the
> device automatically showed up as an input device when plugged into my
> Ubuntu 6.10 box. Here's the relevant section from /proc/bus/input/devices
>
> I: Bus=0003 Vendor=046d Product=c623 Version=0311
> N: Name="3Dconnexion SpaceTraveler USB"
> P: Phys=usb-0000:00:02.0-5/input0
> S: Sysfs=/class/input/input7
> H: Handlers=event3
> B: EV=7
> B: KEY=ff 0 0 0 0
> B: REL=3f
>
> A few problems surfaced as I tried to configure it as an XInput device
> using the evdev driver. Here are the problems and how I dealt with them
> in the attached patch.
>
> * The axis are reported as relative, but they should be treated as absolute.
>
> - I simply allowed the "Mode" "Absolute" option to work with relative axes.
>
> * Min and Max values are not made available to XInput, but glut expects
> them to be valid.
>
> - I just hard coded the values used in the magellan input driver. (I
> probably should have added options for this as well...)
>
> * Glut expects the device to be named "spaceball", not
> "spaceball-some-other-stuff"
>
> - I added a "ForceID" option that allows to override the generated name
> for the device. I'm assuming the generated name is to prevent name
> conflicts, so using this option should be considered risky, and should
> only be used if really needed.
>
> * An event was created for each individual axes.
>
> - I added a "Type" option, and if it is set to "Spaceball", state->sync
> is set to 1, fixing the problem. It also sets the type_name to
> XI_SPACEBALL instead of the default XI_MOUSE.
>
>
> Here's my resulting xorg.conf entry to make it work:
>
> Section "InputDevice"
> Identifier "spaceball"
> Driver "evdev"
> Option "Name" "3Dconnexion*"
> Option "Mode" "Absolute"
> Option "ZRelativeAxisButtons" "0 0"
> Option "Type" "Spaceball"
> Option "ForceID" "spaceball"
> EndSection
>
>
> This allowed me to move and rotate the dinosaur in the glut dinoball
> demo! (Woohoo a working spaceball!!!)
>
> Does this seem like a reasonable way of getting the SpaceTraveler to
> work, or is it better to have a separate, specific driver? I suspect
> that other devices might have some of the problems I encountered, and
> could use the added options, making this patch belong here. On the other
> hand, maybe evdev is not meant to get bloated with such special cases.
>
> Either way, what's the best way to make this, or an alternative solution
> to supporting 3DConnexion devices part of a future release?
>
> Thanks
>
> Roland
>
>
>
> --
> Roland Arsenault
>
> Center for Coastal and Ocean Mapping
> University of New Hampshire
> Durham, New Hampshire
> 03824-3525
>
> roland at ccom.unh.edu
>
> Work: (603)862-3702
> Fax: (603)862-0839
>
> --------------040904010700020508030208
> Content-Type: text/x-patch;
> name="xf86-input-evdev-spaceball.patch"
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline;
> filename="xf86-input-evdev-spaceball.patch"
>
> #
> # Updated but not checked in:
> # (will commit)
> #
> # modified: src/evdev.c
> # modified: src/evdev.h
> # modified: src/evdev_axes.c
> # modified: src/evdev_btn.c
> #
> #
> # Untracked files:
> # (use "git add" to add to commit)
> #
> # mkinstalldirs
> # xf86-input-evdev-spaceball.patch
> diff --git a/src/evdev.c b/src/evdev.c
> index 1bcaef8..b0eef30 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -236,10 +236,7 @@ EvdevSwitchMode (ClientPtr client, Devic
> case Absolute:
> case Relative:
> xf86Msg(X_INFO, "%s: Switching mode to %d.\n", pInfo->name, mode);
> - if (state->abs)
> state->mode = mode;
> - else
> - return !Success;
> break;
> #if 0
> case SendCoreEvents:
> @@ -259,15 +256,13 @@ EvdevNew(evdevDriverPtr driver, evdevDev
> {
> InputInfoPtr pInfo;
> char name[512] = {0};
> + char *s, option[64];
>
> if (!(pInfo = xf86AllocateInput(driver->drv, 0)))
> return 0;
>
> /* Initialise the InputInfoRec. */
> - strncat (name, driver->dev->identifier, sizeof(name));
> - strncat (name, "-", sizeof(name));
> - strncat (name, device->phys, sizeof(name));
> - pInfo->name = xstrdup(name);
> +
> pInfo->flags = 0;
> pInfo->type_name = "UNKNOWN";
> pInfo->device_control = EvdevProc;
> @@ -285,6 +280,10 @@ #endif
>
> xf86CollectInputOptions(pInfo, NULL, NULL);
> xf86ProcessCommonOptions(pInfo, pInfo->options);
> + strncat (name, driver->dev->identifier, sizeof(name));
> + strncat (name, "-", sizeof(name));
> + strncat (name, device->phys, sizeof(name));
> + pInfo->name = xstrdup(xf86SetStrOption(pInfo->options, "ForceID", name));
>
> if ((pInfo->fd = evdevGetFDForDevice (device)) == -1) {
> xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
> diff --git a/src/evdev.h b/src/evdev.h
> index f682312..a46381f 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -183,12 +183,16 @@ typedef struct {
> int axes;
> int v[REL_MAX];
> int count;
> + int min[REL_MAX];
> + int max[REL_MAX];
> int map[REL_MAX];
> int btnMap[REL_MAX][2];
> } evdevRelRec, *evdevRelPtr;
>
> typedef struct {
> int axes;
> + int min[ABS_MAX];
> + int max[ABS_MAX];
> int v[ABS_MAX];
> } evdevAxesRec, *evdevAxesPtr;
>
> diff --git a/src/evdev_axes.c b/src/evdev_axes.c
> index 9d2ef20..b10ecc5 100644
> --- a/src/evdev_axes.c
> +++ b/src/evdev_axes.c
> @@ -318,8 +318,12 @@ EvdevAxesRelSynRep (InputInfoPtr pInfo)
> rel->v[i] = 0;
> }
>
> - EvdevAxesRealSyn (pInfo, 0, 0);
> - rel->count = 0;
> + if(state->mode == Relative)
> + EvdevAxesRealSyn (pInfo, 0, 0);
> + else
> + EvdevAxesRealSyn (pInfo, 1, 0);
> + state->rel->count = 0;
> +
> }
>
> void
> @@ -369,11 +373,18 @@ EvdevAxesRelProcess (InputInfoPtr pInfo,
> if (ev->code >= REL_MAX)
> return;
>
> +
> map = state->rel->map[ev->code];
> if (map >= 0)
> + if (state->mode == Relative)
> state->rel->v[map] += ev->value;
> else
> + state->rel->v[map] = ev->value;
> + else
> + if (state->mode == Relative)
> state->rel->v[-map] -= ev->value;
> + else
> + state->rel->v[-map] = ev->value;
>
> state->rel->count++;
>
> @@ -539,7 +550,18 @@ EvdevAxisRelNew0(InputInfoPtr pInfo)
> xf86Msg(X_INFO, "%s: Configuring as pointer.\n", pInfo->name);
> pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
> XI86_CONFIGURED;
> - pInfo->type_name = XI_MOUSE;
> +
> + s = xf86SetStrOption(pInfo->options, "Type", "Mouse");
> + if (!strcasecmp(s, "Spaceball")) {
> + pInfo->type_name = XI_SPACEBALL;
> + state->sync = 1;
> + xf86Msg(X_CONFIG, "%s: Configuring type as %s mode.\n", pInfo->name, s);
> + } else {
> + pInfo->type_name = XI_MOUSE;
> + }
> +
> +
> +
> pInfo->conversion_proc = EvdevConvert;
>
> for (i = 0, j = 0; i < REL_MAX; i++) {
> @@ -575,6 +597,9 @@ EvdevAxisRelNew0(InputInfoPtr pInfo)
> xf86Msg(X_CONFIG, "%s: %s: %d %d.\n", pInfo->name, option,
> state->rel->btnMap[k][0], state->rel->btnMap[k][1]);
>
> + state->rel->min[state->rel->map[i]]=-1800;
> + state->rel->max[state->rel->map[i]]= 1800;
> +
> j++;
> }
>
> @@ -594,13 +619,25 @@ EvdevAxisRelNew1(InputInfoPtr pInfo)
> {
> evdevDevicePtr pEvdev = pInfo->private;
> evdevStatePtr state = &pEvdev->state;
> + char *s;
>
> if (!state->rel)
> - return !Success;
> + return !Success;
>
> xf86Msg(X_CONFIG, "%s: Configuring %d relative axes.\n", pInfo->name,
> state->rel->axes);
>
> + s = xf86SetStrOption(pInfo->options, "Mode", "Relative");
> + if (!strcasecmp(s, "Absolute")) {
> + state->mode = Absolute;
> + xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s);
> + } else if (!strcasecmp(s, "Relative")) {
> + state->mode = Relative;
> + xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s);
> + } else {
> + state->mode = Relative;
> + xf86Msg(X_CONFIG, "%s: Unknown Mode: %s.\n", pInfo->name, s);
> + }
> return Success;
> }
>
> @@ -633,12 +670,12 @@ EvdevAxesNew1 (InputInfoPtr pInfo)
>
> state->axes = Xcalloc (sizeof (evdevAxesRec));
> if (EvdevAxisAbsNew1(pInfo) != Success)
> - ret = !Success;
> + ret = !Success;
> if (EvdevAxisRelNew1(pInfo) != Success)
> - ret = !Success;
> + ret = !Success;
> if (!state->abs && !state->rel) {
> - Xfree (state->axes);
> - state->axes = NULL;
> + Xfree (state->axes);
> + state->axes = NULL;
> }
>
> return ret;
> @@ -660,9 +697,23 @@ EvdevAxesInit (DeviceIntPtr device)
> int i, axes = 0;
>
> if (state->abs && state->abs->axes > axes)
> - axes = state->abs->axes;
> + {
> + axes = state->abs->axes;
> + for (i = 0; i < axes; i++)
> + {
> + state->axes->min[i] = state->abs->min[i];
> + state->axes->max[i] = state->abs->max[i];
> + }
> + }
> if (state->rel && state->rel->axes > axes)
> - axes = state->rel->axes;
> + {
> + axes = state->rel->axes;
> + for (i = 0; i < axes; i++)
> + {
> + state->axes->min[i] = state->rel->min[i];
> + state->axes->max[i] = state->rel->max[i];
> + }
> + }
>
> state->axes->axes = axes;
>
> @@ -683,7 +734,7 @@ #endif
> return !Success;
>
> for (i = 0; i < axes; i++) {
> - xf86InitValuatorAxisStruct(device, i, 0, -1, 0, 0, 1);
> + xf86InitValuatorAxisStruct(device, i, state->axes->min[i], state->axes->max[i], 1, 1, 1);
> xf86InitValuatorDefaults(device, i);
> }
>
> diff --git a/src/evdev_btn.c b/src/evdev_btn.c
> index b9bfe07..a769434 100644
> --- a/src/evdev_btn.c
> +++ b/src/evdev_btn.c
> @@ -346,6 +346,7 @@ EvdevBtnNew1(InputInfoPtr pInfo)
> {
> evdevDevicePtr pEvdev = pInfo->private;
> evdevStatePtr state = &pEvdev->state;
> + char *s;
>
> if (!state->btn)
> return !Success;
> @@ -365,7 +366,14 @@ EvdevBtnNew1(InputInfoPtr pInfo)
> * FIXME: Mouse may not be accurate.
> * Check buttons to see if we're actually a joystick or something.
> */
> - pInfo->type_name = XI_MOUSE;
> + s = xf86SetStrOption(pInfo->options, "Type", "Mouse");
> + if (!strcasecmp(s, "Spaceball")) {
> + pInfo->type_name = XI_SPACEBALL;
> + state->sync = 1;
> + xf86Msg(X_CONFIG, "%s: Configuring type as %s mode.\n", pInfo->name, s);
> + } else {
> + pInfo->type_name = XI_MOUSE;
> + }
>
> return Success;
> }
>
> --------------040904010700020508030208
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline
>
> _______________________________________________
> xorg mailing list
> xorg at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xorg
> --------------040904010700020508030208--
More information about the xorg
mailing list