Re: Joystick not found on Linux/amd64

From: Bernhard Ager
Date: Mon Dec 20 2004 - 17:36:01 EST

On Sun, 19 Dec 2004, Joshua Wise wrote:

> As far as I can tell, the problem is that my code uses the joystick
> ioctls to get the version, passing it a 32-bit address to return the
> version into.

I have a long night behind me, and here is, what I found out:

It's about the ioctls, because they need to be marked compatible for a
32bit call or a wrapper has to be written, otherwise the ioctl handler
will not even be called.

Marking compatible can be done with this <patch>

diff -ur linux-2.6.9-gentoo-r1/arch/x86_64/ia32/ia32_ioctl.c linux-2.6.9-gentoo-r1-js/arch/x86_64/ia32/ia32_ioctl.c
--- linux-2.6.9-gentoo-r1/arch/x86_64/ia32/ia32_ioctl.c 2004-12-20 22:58:20.000000000 +0100
+++ linux-2.6.9-gentoo-r1-js/arch/x86_64/ia32/ia32_ioctl.c 2004-12-20 22:19:36.000000000 +0100
@@ -174,6 +174,10 @@
COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */
COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */
+COMPATIBLE_IOCTL(JSIOCGNAME(0x200)) /* for X-Plane 8.03 */

/* And these ioctls need translation */
diff -ur linux-2.6.9-gentoo-r1/fs/compat_ioctl.c linux-2.6.9-gentoo-r1-js/fs/compat_ioctl.c
--- linux-2.6.9-gentoo-r1/fs/compat_ioctl.c 2004-12-20 22:58:20.000000000 +0100
+++ linux-2.6.9-gentoo-r1-js/fs/compat_ioctl.c 2004-12-20 21:48:37.000000000 +0100
@@ -11,6 +11,7 @@

+#include <linux/joystick.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/compat.h>


Making a special case for JSIOCGNAME(0x200) is very nasty (0x200 is the
return buffer length, coded into the ioctl number), but I don't know how
to work around this in an elegant way.

As my test program (attached) shows, the patch actually works. (Compile
with -m32 or in a 32bit chroot/on a real x86). However, X-Plane does not
work correctly yet: It recognizes a joystick and the buttons are working,
but the axes don't. Joshua: if you send me your joystick code, I'll gladly
take a look at it.

Isn't making a smoking section in a restaurant like making a peeing
section in a swimming pool?#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/joystick.h>

/* function 3rd arg */
/* #define JSIOCGAXES get number of axes char */
/* #define JSIOCGBUTTONS get number of buttons char */
/* #define JSIOCGVERSION get driver version int */
/* #define JSIOCGNAME(len) get identifier string char */
/* #define JSIOCSCORR set correction values &js_corr */
/* #define JSIOCGCORR get correction values &js_corr */

int main (int argc, char **argv) {
char number_of_axes, number_of_buttons, js_name[0x200];
int version;
struct js_event e;
size_t size;
int js;

/* printf ("Value of JSIOCGAXES = %u\n", JSIOCGAXES); */
/* printf ("Value of JSIOCGBUTTONS = %u\n", JSIOCGBUTTONS); */
/* printf ("Value of JSIOCGVERSION = %u\n", JSIOCGVERSION); */
/* printf ("Value of JSIOCGNAME(0x200) = %x\n", JSIOCGNAME(0x200)); */

js = open ("/dev/js0", O_RDONLY);

if (ioctl (js, JSIOCGAXES, &number_of_axes) == -1) {
number_of_axes = -1;
if (ioctl (js, JSIOCGBUTTONS, &number_of_buttons) == -1) {
number_of_buttons = -1;
if (ioctl (js, JSIOCGVERSION, &version) == -1) {
version = -1;
if (ioctl (js, JSIOCGNAME(0x200), js_name) == -1) {
strcpy (js_name, "Unknown");

printf ("Axes: %3d Buttons: %3d Version: %d Name: %s\n",
number_of_axes, number_of_buttons, version, js_name);

while (size = read (js, &e, sizeof(struct js_event))) {
if (size != sizeof(struct js_event)) {
printf ("read failed, data too small");
printf("time: %9u value: %6d type: %3u number: %2u\r",
e.time, e.value, e.type, e.number);