|
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.
|