restructuring, guarantee permutation property
authorStefan Huber <shuber2@gmx.at>
Sat, 24 Dec 2011 10:59:40 +0000 (11:59 +0100)
committerStefan Huber <shuber2@gmx.at>
Sat, 24 Dec 2011 10:59:40 +0000 (11:59 +0100)
src/main.c

index 93362dfc88bd4c38370e504bb8952415b49e3d05..aa794619044128c35ba7cfffaff824d53e774c0d 100644 (file)
@@ -15,7 +15,8 @@
 #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
@@ -48,21 +49,37 @@ void printHelp(FILE* out, int argc, char** argv)
 }
 
 
-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");
@@ -87,17 +104,10 @@ void listAxismap(int fd)
 
 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");
@@ -120,47 +130,116 @@ void listButtonmap(int fd)
 }
 
 
-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++)
@@ -177,45 +256,44 @@ void setAxismap(int fd, char* mapstr)
 
 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++)
@@ -224,7 +302,7 @@ void setButtonmap(int fd, char* mapstr)
 
        if( ioctl(fd, JSIOCSBTNMAP, &map) )
        {
-               perror( PACKAGE_STRING ": error setting button map");
+               perror( PACKAGE_STRING ": error setting axis map");
                exit(EXIT_IOCTL);
        }
 }
@@ -236,7 +314,7 @@ int main(int argc, char** argv)
        int argListButtonmap=0;
        char* argSetAxismap=0;
        char* argSetButtonmap=0;
-       char dev[MAXFN+1] = "";
+       char* dev;
 
 
 
@@ -254,7 +332,7 @@ int main(int argc, char** argv)
                        i++;
                        if( i >= argc )                 
                                reportMissingArgument(opt);
-                       strncpy(dev, argv[i], MAXFN);
+                       dev = argv[i];
                }
                else if( !strcmp(opt, "--list-axismap") )
                {
@@ -286,7 +364,7 @@ int main(int argc, char** argv)
        }
 
 
-       if( strcmp("", dev)==0 )
+       if( !dev )
        {
                fprintf(stderr, "You need to specify a device.\n");
                return EXIT_INVARG;