From: <sk...@us...> - 2010-09-23 11:58:04
|
Revision: 2393 http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2393&view=rev Author: skitt Date: 2010-09-23 11:57:57 +0000 (Thu, 23 Sep 2010) Log Message: ----------- Handle both known versions of KEY_MAX when retrieving the button map; avoid segfaulting in any case! Modified Paths: -------------- trunk/utils/Makefile trunk/utils/jstest.c Added Paths: ----------- trunk/utils/axbtnmap.c trunk/utils/axbtnmap.h Modified: trunk/utils/Makefile =================================================================== --- trunk/utils/Makefile 2010-09-23 11:56:32 UTC (rev 2392) +++ trunk/utils/Makefile 2010-09-23 11:57:57 UTC (rev 2393) @@ -50,9 +50,17 @@ ffmvforce: ffmvforce.o $(CC) $^ -o $@ $(LDFLAGS) -g -lm `sdl-config --libs` -jscal: jscal.o +axbtnmap.o: axbtnmap.c axbtnmap.h + +jscal.o: jscal.c axbtnmap.h + +jscal: jscal.o axbtnmap.o $(CC) $(CFLAGS) $(CPPFLAGS) -lm $^ -o $@ +jstest.o: jstest.c axbtnmap.h + +jstest: jstest.o axbtnmap.o + gencodes: gencodes.c scancodes.h $(CC) $(CFLAGS) $(CPPFLAGS) gencodes.c -o gencodes Added: trunk/utils/axbtnmap.c =================================================================== --- trunk/utils/axbtnmap.c (rev 0) +++ trunk/utils/axbtnmap.c 2010-09-23 11:57:57 UTC (rev 2393) @@ -0,0 +1,89 @@ +/* + * Axis and button map support functions. + * Copyright © 2009 Stephen Kitt <st...@sk...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <errno.h> +#include <stdint.h> + +#include <sys/ioctl.h> +#include <sys/types.h> + +#include <linux/input.h> +#include <linux/joystick.h> + +#include "axbtnmap.h" + +/* The following values come from include/joystick.h in the kernel source. */ +#define JSIOCSBTNMAP_LARGE _IOW('j', 0x33, __u16[KEY_MAX_LARGE - BTN_MISC + 1]) +#define JSIOCSBTNMAP_SMALL _IOW('j', 0x33, __u16[KEY_MAX_SMALL - BTN_MISC + 1]) +#define JSIOCGBTNMAP_LARGE _IOR('j', 0x34, __u16[KEY_MAX_LARGE - BTN_MISC + 1]) +#define JSIOCGBTNMAP_SMALL _IOR('j', 0x34, __u16[KEY_MAX_SMALL - BTN_MISC + 1]) + +int determine_ioctl(int fd, int *ioctls, int *ioctl_used, void *argp) +{ + int i, retval = 0; + + /* Try each ioctl in turn. */ + for (i = 0; ioctls[i]; i++) { + if ((retval = ioctl(fd, ioctls[i], argp)) >= 0) { + /* The ioctl did something. */ + *ioctl_used = ioctls[i]; + return retval; + } else if (errno != -EINVAL) { + /* Some other error occurred. */ + return retval; + } + } + return retval; +} + +int getbtnmap(int fd, uint16_t *btnmap) +{ + static int jsiocgbtnmap = 0; + int ioctls[] = { JSIOCGBTNMAP, JSIOCGBTNMAP_LARGE, JSIOCGBTNMAP_SMALL, 0 }; + + if (jsiocgbtnmap != 0) { + /* We already know which ioctl to use. */ + return ioctl(fd, jsiocgbtnmap, btnmap); + } else { + return determine_ioctl(fd, ioctls, &jsiocgbtnmap, btnmap); + } +} + +int setbtnmap(int fd, uint16_t *btnmap) +{ + static int jsiocsbtnmap = 0; + int ioctls[] = { JSIOCSBTNMAP, JSIOCSBTNMAP_LARGE, JSIOCSBTNMAP_SMALL, 0 }; + + if (jsiocsbtnmap != 0) { + /* We already know which ioctl to use. */ + return ioctl(fd, jsiocsbtnmap, btnmap); + } else { + return determine_ioctl(fd, ioctls, &jsiocsbtnmap, btnmap); + } +} + +int getaxmap(int fd, uint8_t *axmap) +{ + return ioctl(fd, JSIOCGAXMAP, axmap); +} + +int setaxmap(int fd, uint8_t *axmap) +{ + return ioctl(fd, JSIOCSAXMAP, axmap); +} Added: trunk/utils/axbtnmap.h =================================================================== --- trunk/utils/axbtnmap.h (rev 0) +++ trunk/utils/axbtnmap.h 2010-09-23 11:57:57 UTC (rev 2393) @@ -0,0 +1,65 @@ +/* + * Axis and button map support functions. + * Copyright © 2009 Stephen Kitt <st...@sk...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __AXBTNMAP_H__ +#define __AXBTNMAP_H__ + +#include <stdint.h> +#include <linux/input.h> + +/* The following values come from include/input.h in the kernel + source; the small variant is used up to version 2.6.27, the large + one from 2.6.28 onwards. We need to handle both values because the + kernel doesn't; it only expects one of the values, and we need to + determine which one at run-time. */ +#define KEY_MAX_LARGE 0x2FF +#define KEY_MAX_SMALL 0x1FF + +/* Axis map size. */ +#define AXMAP_SIZE (ABS_MAX + 1) + +/* Button map size. */ +#define BTNMAP_SIZE (KEY_MAX_LARGE - BTN_MISC + 1) + +/* Retrieves the current axis map in the given array, which must + contain at least AXMAP_SIZE elements. Returns the result of the + ioctl(): negative in case of an error, 0 otherwise for kernels up + to 2.6.30, the length of the array actually copied for later + kernels. */ +int getaxmap(int fd, uint8_t *axmap); + +/* Uses the given array as the axis map. The array must contain at + least AXMAP_SIZE elements. Returns the result of the ioctl(): + negative in case of an error, 0 otherwise. */ +int setaxmap(int fd, uint8_t *axmap); + +/* Retrieves the current button map in the given array, which must + contain at least BTNMAP_SIZE elements. Returns the result of the + ioctl(): negative in case of an error, 0 otherwise for kernels up + to 2.6.30, the length of the array actually copied for later + kernels. */ +int getbtnmap(int fd, uint16_t *btnmap); + +/* Uses the given array as the button map. The array must contain at + least BTNMAP_SIZE elements. Returns the result of the ioctl(): + negative in case of an error, 0 otherwise. */ +int setbtnmap(int fd, uint16_t *btnmap); + +#endif + Modified: trunk/utils/jstest.c =================================================================== --- trunk/utils/jstest.c 2010-09-23 11:56:32 UTC (rev 2392) +++ trunk/utils/jstest.c 2010-09-23 11:57:57 UTC (rev 2393) @@ -49,6 +49,8 @@ #include <linux/input.h> #include <linux/joystick.h> +#include "axbtnmap.h" + char *axis_names[ABS_MAX + 1] = { "X", "Y", "Z", "Rx", "Ry", "Rz", "Throttle", "Rudder", "Wheel", "Gas", "Brake", "?", "?", "?", "?", "?", @@ -74,8 +76,9 @@ unsigned char buttons = 2; int version = 0x000800; char name[NAME_LENGTH] = "Unknown"; - uint16_t btnmap[KEY_MAX - BTN_MISC + 1]; - uint8_t axmap[ABS_MAX + 1]; + uint16_t btnmap[BTNMAP_SIZE]; + uint8_t axmap[AXMAP_SIZE]; + int btnmapok = 1; if (argc < 2 || argc > 3 || !strcmp("--help", argv[1])) { puts(""); @@ -99,15 +102,23 @@ ioctl(fd, JSIOCGAXES, &axes); ioctl(fd, JSIOCGBUTTONS, &buttons); ioctl(fd, JSIOCGNAME(NAME_LENGTH), name); - ioctl(fd, JSIOCGAXMAP, axmap); - ioctl(fd, JSIOCGBTNMAP, btnmap); + getaxmap(fd, axmap); + getbtnmap(fd, btnmap); printf("Driver version is %d.%d.%d.\n", version >> 16, (version >> 8) & 0xff, version & 0xff); - if (buttons > 0 && btnmap[0] < BTN_MISC) { + /* Determine whether the button map is usable. */ + for (i = 0; btnmapok && i < buttons; i++) { + if (btnmap[i] < BTN_MISC || btnmap[i] > KEY_MAX) { + btnmapok = 0; + break; + } + } + if (!btnmapok) { /* btnmap out of range for names. Don't print any. */ + puts("jstest is not fully compatible with your kernel. Unable to retrieve button map!"); printf("Joystick (%s) has %d axes ", name, axes); printf("and %d buttons.\n", buttons); } else { @@ -117,8 +128,9 @@ puts(")"); printf("and %d buttons (", buttons); - for (i = 0; i < buttons; i++) + for (i = 0; i < buttons; i++) { printf("%s%s", i > 0 ? ", " : "", button_names[btnmap[i] - BTN_MISC]); + } puts(")."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |