--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: joystick: Adding axis and button remapping capability to the included jscal tool
- From: Dr. László Kaján <kajla@home.bioinfo.pl>
- Date: Wed, 26 Sep 2007 13:11:52 +0200
- Message-id: <20070926111152.27795.59789.reportbug@home.bioinfo.pl>
Package: joystick
Version: 20051019-1
Severity: wishlist
Tags: patch
Motivation
I found no simple tool that would remap the joystick axes
and buttons on the device driver level (joydev module), while the driver
clearly provides the interface for this. My patch extends to
capabilities of jscal in order to remap axes and buttons. While
remapping in the X configuration file is possible, that mapping does not
seem to help in all games.
Detail
I bought a Trust GM-2550 Predator joystick the other day, and I noticed
that the axes were mapped incorrectly: the throttle in place of the
rudder, and the pinky button's axes were shifted up 1 slot in the axis
map. I found no tool to re-map the axes on the device driver (joydev)
level. While remapping is possible in the X config, this did not solve
the problem for - for example - SearchAndRescue.
Also I found no way to remap joystick buttons on the device driver
level. This is quite necessary for example for tuxkart, because some of
the buttons the game uses are unfortunately unreachable while holding
the joystick comfortably (some buttons are too far on the stick).
I found that the joydev kernel module does provide the API for axes and
button remapping. I added two command line options to jscal and two
corresponding functions that utilize the API and remap buttons and axes.
I have tested the axes and button remapping, and it works as intended. I
can swap buttons and axes as I wish.
Implementation
Please find the diff of jscal.c in joystick attached (joystick.diff).
The modified jscal.c adds two command line arguments:
-q --print-mappings Print the current axis and button
mappings as a jscal command line
and
-u <n_of_axes,axmap1,axmap2,...,
n_of_buttons,btnmap1,btnmap2,
...> --set-mappings Sets axis and button mappings to the
specified values
An example output of -q looks like this (./jscal -q /dev/input/js0):
jscal -u
10,0,1,2,5,6,16,17,40,41,42,13,288,289,290,291,292,293,294,295,296,297,298,299,300
/dev/input/js0
The joystick has 10 axes and 13 buttons. If now one is to switch axes 2
and 5 (to get the rudder and the throttle right), one has to execute:
jscal -u
10,0,1,5,2,6,16,17,40,41,42,13,288,289,290,291,292,293,294,295,296,297,298,299,300
/dev/input/js0
changing 2,5 to 5,2 on the line.
Remapping buttons is done the same way.
-- System Information:
Debian Release: lenny/sid
APT prefers testing
APT policy: (500, 'testing'), (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.18-4-686 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8)
Shell: /bin/sh linked to /bin/bash
Only in joystick-20051019: debian
Only in /home/kajla/usr/src/joystick/: .svn
diff -ur joystick-20051019/utils/jscal.c /home/kajla/usr/src/joystick/utils/jscal.c
--- joystick-20051019/utils/jscal.c 2004-10-19 09:51:52.000000000 +0200
+++ /home/kajla/usr/src/joystick/utils/jscal.c 2007-09-26 12:56:33.000000000 +0200
@@ -61,6 +61,8 @@
int fd;
struct js_corr corr[MAX_AXES];
+__u8 axmap[ABS_MAX + 1];
+__u16 buttonmap[(KEY_MAX - BTN_MISC + 1)];
char axes, buttons, fuzz;
int version;
struct correction_data corda[MAX_AXES];
@@ -163,6 +165,12 @@
puts(" -V --version Prints the version numbers");
puts(" -p --print-correction Prints the current settings as a jscal");
puts(" command line");
+ puts(" -q --print-mappings Print the current axis and button");
+ puts(" mappings as a jscal command line");
+ puts(" -u <n_of_axes,axmap1,axmap2,...,");
+ puts(" n_of_buttons,btnmap1,btnmap2,");
+ puts(" ...> --set-mappings Sets axis and button mappings to the");
+ puts(" specified values");
putchar('\n');
}
@@ -316,6 +324,42 @@
(version >> 8) & 0xff, version & 0xff);
}
+void print_mappings(char *devicename)
+{
+ int i;
+
+ if (ioctl(fd, JSIOCGAXES, &axes)) {
+ perror("jscal: error getting axes");
+ exit(1);
+ }
+ if (ioctl(fd, JSIOCGBUTTONS, &buttons)) {
+ perror("jscal: error getting buttons");
+ exit(1);
+ }
+ if (ioctl(fd, JSIOCGAXMAP, &axmap)) {
+ perror("jscal: error getting axis map");
+ exit(1);
+ }
+ if (ioctl(fd, JSIOCGBTNMAP, &buttonmap)) {
+ perror("jscal: error getting button map");
+ exit(1);
+ }
+
+ printf("jscal -u %d", axes);
+ for (i = 0; i < axes; i++)
+ {
+ printf( ",%d", axmap[i]);
+ }
+
+ printf(",%d", buttons);
+ for (i = 0; i < buttons; i++)
+ {
+ printf( ",%d", buttonmap[i]);
+ }
+
+ printf(" %s\n",devicename);
+}
+
void print_settings(char *devicename)
{
int i,j;
@@ -342,6 +386,107 @@
printf(" %s\n",devicename);
}
+// n axes n buttons
+// 10,0,1,2,5,6,16,17,40,41,42:13,288,289,290,291,292,293,294,295,296,297,298,299,300
+void set_mappings(char *p)
+{
+ int i;
+ int axes_on_cl = 0;
+ int btns_on_cl = 0;
+ int axis_mapping = 0;
+ int btn_mapping = 0;
+
+ if (ioctl(fd, JSIOCGAXES, &axes)) {
+ perror("jscal: error getting axes");
+ exit(1);
+ }
+ if (ioctl(fd, JSIOCGBUTTONS, &buttons)) {
+ perror("jscal: error getting buttons");
+ exit(1);
+ }
+
+ if (axes > MAX_AXES) axes = MAX_AXES;
+
+ if (!p) {
+ fprintf(stderr, "jscal: missing argument for --set-mappings\n");
+ exit(1);
+ }
+
+ //axes
+ sscanf(p, "%d", &axes_on_cl);
+ p = strstr(p, ",");
+
+ if (axes_on_cl != axes) {
+ fprintf(stderr, "jscal: joystick has %d axes and not %d as specified on command line\n",
+ axes, axes_on_cl);
+ exit(1);
+ }
+
+
+ for (i = 0; i < axes; i++)
+ {
+ if (!p) {
+ fprintf(stderr, "jscal: missing mapping for axis %d\n", i);
+ exit(1);
+ }
+ sscanf(++p, "%d", &axis_mapping);
+ p = strstr(p, ",");
+
+
+ if (axis_mapping > ABS_MAX + 1) {
+ fprintf(stderr, "jscal: invalid axis mapping for axis %d (max is %d)\n", i, ABS_MAX + 1);
+ exit(1);
+ }
+ axmap[i] = axis_mapping;
+ }
+
+ //buttons
+ sscanf(++p, "%d", &btns_on_cl);
+ p = strstr(p, ",");
+
+ if (btns_on_cl != buttons) {
+ fprintf(stderr, "jscal: joystick has %d buttons and not %d as specified on command line\n",
+ buttons, btns_on_cl);
+ exit(1);
+ }
+
+
+ for (i = 0; i < buttons; i++)
+ {
+ if (!p) {
+ fprintf(stderr, "jscal: missing mapping for button %d\n", i);
+ exit(1);
+ }
+ sscanf(++p, "%d", &btn_mapping);
+ p = strstr(p, ",");
+
+
+ if (btn_mapping > KEY_MAX) {
+ fprintf(stderr, "jscal: invalid button mapping for button %d (max is %d)\n", i, KEY_MAX);
+ exit(1);
+ }
+ if (btn_mapping < BTN_MISC) {
+ fprintf(stderr, "jscal: invalid button mapping for button %d (min is %d)\n", i, BTN_MISC);
+ exit(1);
+ }
+ buttonmap[i] = btn_mapping;
+ }
+
+ if (p) {
+ fprintf(stderr, "jscal: too many values\n");
+ exit(1);
+ }
+
+ if (ioctl(fd, JSIOCSAXMAP, &axmap)) {
+ perror("jscal: error setting axis map");
+ exit(1);
+ }
+ if (ioctl(fd, JSIOCSBTNMAP, &buttonmap)) {
+ perror("jscal: error setting button map");
+ exit(1);
+ }
+}
+
void set_correction(char *p)
{
int i,j;
@@ -461,14 +606,18 @@
char *parameter = NULL;
int t;
+ // /usr/include/getopt.h
static struct option long_options[] =
{
{"calibrate", no_argument, NULL, 'c'},
{"help", no_argument, NULL, 'h'},
{"set-correction", required_argument, NULL, 's'},
+ {"set-mappings", required_argument, NULL, 'u'},
{"test-center", no_argument, NULL, 't'},
{"version", no_argument, NULL, 'V'},
- {"print-correction", no_argument, NULL, 'p'}
+ {"print-correction", no_argument, NULL, 'p'},
+ {"print-mappings", no_argument, NULL, 'q'},
+ {NULL, no_argument, NULL, 0 }
};
if (argc == 1) {
@@ -477,10 +626,12 @@
}
do {
- t = getopt_long(argc, argv, "chps:vVt", long_options, &option_index);
+ t = getopt_long(argc, argv, "chpqu:s:vVt", long_options, &option_index);
switch (t) {
case 'p':
+ case 'q':
case 's':
+ case 'u':
case 'c':
case 't':
case 'V':
@@ -540,9 +691,15 @@
case 'p':
print_settings(argv[argc -1]);
break;
+ case 'q':
+ print_mappings(argv[argc -1]);
+ break;
case 's':
set_correction(parameter);
break;
+ case 'u':
+ set_mappings(parameter);
+ break;
case 't':
test_center();
break;
Only in /home/kajla/usr/src/joystick/utils: .svn
--- End Message ---