#include "config.h"
-#define MAXFN 1024
+#define BTN_CNT (KEY_MAX - BTN_MISC + 1)
+
#define EXIT_INVARG 1
#define EXIT_OPEN 2
#define EXIT_IOCTL 3
}
-void listAxismap(int fd)
+__u8 getNumberOfAxes(int fd)
{
__u8 cnt=0;
- __u8 map[ABS_CNT] = {-1};
-
-
if (ioctl(fd, JSIOCGAXES, &cnt) )
{
perror(PACKAGE_STRING ": error getting number of axes");
exit(EXIT_IOCTL);
}
+ return cnt;
+}
+
+
+__u8 getNumberOfButtons(int fd)
+{
+ __u8 cnt=0;
+ if (ioctl(fd, JSIOCGBUTTONS, &cnt) )
+ {
+ perror(PACKAGE_STRING ": error getting number of buttons");
+ exit(EXIT_IOCTL);
+ }
+ return cnt;
+}
+
+
+void listAxismap(int fd)
+{
+ __u8 map[ABS_CNT] = {-1};
+ const __u8 cnt = getNumberOfAxes(fd);
printf("Got %d axes:\n", cnt);
assert( cnt <= ABS_CNT);
-
if( ioctl(fd, JSIOCGAXMAP, &map) < 0 )
{
perror(PACKAGE_STRING ": error getting axis map");
void listButtonmap(int fd)
{
- __u8 cnt=0;
- __u16 map[KEY_MAX - BTN_MISC + 1] = {-1};
-
- if (ioctl(fd, JSIOCGBUTTONS, &cnt) )
- {
- perror(PACKAGE_STRING ": error getting number of buttons");
- exit(EXIT_IOCTL);
- }
+ __u16 map[BTN_CNT] = {-1};
+ const __u8 cnt = getNumberOfButtons(fd);
printf("Got %d buttons:\n", cnt);
-
if( ioctl(fd, JSIOCGBTNMAP, &map) < 0 )
{
perror(PACKAGE_STRING ": error getting button map");
}
-void setAxismap(int fd, char* mapstr)
+/** Fill an integer array of given size by comma-separated values in str.
+ * Return the number of values contained in str. */
+unsigned parseIntArray(int* array, unsigned size, char* str)
{
- __u8 cnt=0;
- __u8 map[ABS_CNT] = {-1};
+ unsigned i;
+ for(i=0; i<size; ++i)
+ {
+ sscanf(str, "%d", &array[i]);
+ // Move up to next comma, and one step further
+ str = strstr(str, ",");
+ if( !str )
+ break;
+ str++;
+ }
- if (ioctl(fd, JSIOCGAXES, &cnt) )
+ // Skip further commas
+ while( str )
{
- perror(PACKAGE_STRING ": error getting number of axes");
- exit(EXIT_IOCTL);
+ i++;
+ str = strstr(str, ",");
+ if( !str )
+ break;
+ str++;
}
- printf("Setting %d axes.\n", cnt);
- assert( cnt <= ABS_CNT);
+ return i+1;
+}
+
+
+/** Take an array of size that contains cnt values and fill the rest of array
+ * such that a permutation on {0, ..., size-1} results.
+ * Returns 1 if resulting array is a permutation */
+int fillPermutation(int* array, unsigned cnt, unsigned size)
+{
+ assert( cnt <= size );
+
+ int* contains = malloc(sizeof(int)*size );
+ memset(contains, 0, sizeof(int)*size );
- char* s = mapstr;
+
+ // Check which value is already there
for(unsigned i=0; i<cnt; ++i)
{
- if( !s )
+ const unsigned v = array[i];
+ if( v>=size || contains[v] )
+ return 0;
+ contains[v] = 1;
+ }
+
+ // Do it the hard way on array[cnt, max]
+ unsigned min=0;
+ for(unsigned i=cnt; i<size; ++i)
+ {
+ // Get minimum free value
+ while( contains[min] )
{
- fprintf(stderr, "Missing value for axis %d.\n", i);
- exit(EXIT_VALUE);
+ min++;
+ assert( min<size );
}
- int val=-1;
- sscanf(s, "%d", &val);
- if( val<0 || val>=(1<<8) )
+ array[i] = min;
+ contains[min] = 1;
+ }
+
+ return 1;
+}
+
+
+void setAxismap(int fd, char* mapstr)
+{
+ __u8 map[ABS_CNT] = {-1};
+ int imap[ABS_CNT] = {-1};
+
+
+ const __u8 cnt = getNumberOfAxes(fd);
+ printf("Setting %d axes.\n", cnt);
+ assert( cnt <= ABS_CNT);
+
+
+ const unsigned readcnt = parseIntArray(imap, cnt, mapstr);
+ if( readcnt != cnt )
+ {
+ fprintf(stderr, "Invalid number of values given: %d\n", readcnt);
+ exit(EXIT_VALUE);
+ }
+
+ // Nothing to do
+ if( cnt<=0 )
+ return;
+
+ // Fill the remaining array such that we obtain a permutation
+ if( !fillPermutation(imap, cnt, ABS_CNT) )
+ {
+ fprintf(stderr, "Mapping needs to be a permutation.\n");
+ exit(EXIT_VALUE);
+ }
+
+ // Copy array and check bounds
+ for(unsigned i=0; i<ABS_CNT; ++i)
+ {
+ if( imap[i]<0 || imap[i]>=ABS_CNT )
{
- fprintf(stderr, "Value out of bounds: %d\n", val);
+ fprintf(stderr, "Value out of bounds: %d\n", imap[i]);
exit(EXIT_VALUE);
}
- map[i] = val;
- s = strstr(s, ",");
- if(s)
- s++;
+ map[i] = imap[i];
}
- if( s )
- fprintf(stderr, "Too many values given for the axismap. Ignoring the rest.\n");
-
printf("Setting the following map:\n");
for(int i=0; i<cnt; i++)
void setButtonmap(int fd, char* mapstr)
{
- __u8 cnt=0;
- __u16 map[KEY_MAX - BTN_MISC + 1] = {-1};
+ __u16 map[BTN_CNT] = {-1};
+ int imap[BTN_CNT] = {-1};
- printf("foo: %d\n", 1<<8);
+ const __u8 cnt = getNumberOfButtons(fd);
+ printf("Setting %d buttons.\n", cnt);
+ assert( cnt <= ABS_CNT);
- if (ioctl(fd, JSIOCGBUTTONS, &cnt) )
+
+ const unsigned readcnt = parseIntArray(imap, cnt, mapstr);
+ if( readcnt != cnt )
{
- perror(PACKAGE_STRING ": error getting number of buttons");
- exit(EXIT_IOCTL);
+ fprintf(stderr, "Invalid number of values given: %d\n", readcnt);
+ exit(EXIT_VALUE);
}
- printf("Setting %d buttons.\n", cnt);
+ // Nothing to do
+ if( cnt<=0 )
+ return;
- char* s = mapstr;
- for(unsigned i=0; i<cnt; ++i)
+ // Fill the remaining array such that we obtain a permutation
+ if( !fillPermutation(imap, cnt, BTN_CNT) )
{
- if( !s )
- {
- fprintf(stderr, "Missing value for axis %d.\n", i);
- exit(EXIT_VALUE);
- }
+ fprintf(stderr, "Mapping needs to be a permutation.\n");
+ exit(EXIT_VALUE);
+ }
- int val=-1;
- sscanf(s, "%d", &val);
- if( val<0 || val>=(1<<16) )
+ // Copy array and check bounds
+ for(unsigned i=0; i<ABS_CNT; ++i)
+ {
+ if( imap[i]<0 || imap[i]>=BTN_CNT )
{
- fprintf(stderr, "Value out of bounds: %d\n", val);
+ fprintf(stderr, "Value out of bounds: %d\n", imap[i]);
exit(EXIT_VALUE);
}
- map[i] = val;
- s = strstr(s, ",");
- if(s)
- s++;
+ map[i] = imap[i];
}
- if( s )
- fprintf(stderr, "Too many values given for the axismap. Ignoring the rest.\n");
-
printf("Setting the following map:\n");
for(int i=0; i<cnt; i++)
if( ioctl(fd, JSIOCSBTNMAP, &map) )
{
- perror( PACKAGE_STRING ": error setting button map");
+ perror( PACKAGE_STRING ": error setting axis map");
exit(EXIT_IOCTL);
}
}
int argListButtonmap=0;
char* argSetAxismap=0;
char* argSetButtonmap=0;
- char dev[MAXFN+1] = "";
+ char* dev;
i++;
if( i >= argc )
reportMissingArgument(opt);
- strncpy(dev, argv[i], MAXFN);
+ dev = argv[i];
}
else if( !strcmp(opt, "--list-axismap") )
{
}
- if( strcmp("", dev)==0 )
+ if( !dev )
{
fprintf(stderr, "You need to specify a device.\n");
return EXIT_INVARG;