magellan motion packets didn't need swapping on big endian
[sball] / src / sball.c
index 9dce2ae..e6ff48e 100644 (file)
 #include <sys/time.h>
 #include <sys/ioctl.h>
 
+#if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
+    (defined(__alpha__) || defined(__alpha)) || \
+     defined(__arm__) || \
+    (defined(__mips__) && defined(__MIPSEL__)) || \
+     defined(__SYMBIAN32__) || \
+     defined(__x86_64__) || \
+     defined(__LITTLE_ENDIAN__)
+#define SBALL_LITTLE_ENDIAN
+#else
+#define SBALL_BIG_ENDIAN
+#endif
+
 #define INP_BUF_SZ     256
 
 enum {
@@ -64,13 +76,11 @@ struct sball *sball_open(const char *dev)
                return 0;
        }
 
-       if(!(sb = malloc(sizeof *sb))) {
+       if(!(sb = calloc(1, sizeof *sb))) {
                fprintf(stderr, "sball_open: failed to allocate sball object\n");
                goto err;
        }
        sb->fd = fd;
-       sb->flags = 0;
-       sb->len = 0;
 
        stty_save(sb);
 
@@ -169,7 +179,13 @@ int sball_num_buttons(struct sball *sb)
        return sb->nbuttons;
 }
 
-/* Labtec spaceball: 9600 8n1 XON/XOFF */
+/* Labtec spaceball: 9600 8n1 XON/XOFF
+ * Can't use canonical mode to assemble input into lines for the spaceball,
+ * because binary data received for motion events can include newlines which
+ * would be eaten up by the line discipline. Therefore we'll rely on VTIME=1 to
+ * hopefully get more than 1 byte at a time. Alternatively we could request
+ * printable reports, but I don't feel like implementing that.
+ */
 static int stty_sball(struct sball *sb)
 {
        int mstat;
@@ -177,17 +193,12 @@ static int stty_sball(struct sball *sb)
 
        term = sb->saved_term;
        term.c_oflag = 0;
-       term.c_lflag = ICANON;
+       term.c_lflag = 0;
        term.c_cc[VMIN] = 0;
-       term.c_cc[VTIME] = 0;
-       term.c_cc[VEOF] = 0;
-       term.c_cc[VEOL] = '\r';
-       term.c_cc[VEOL2] = 0;
-       term.c_cc[VERASE] = 0;
-       term.c_cc[VKILL] = 0;
+       term.c_cc[VTIME] = 1;
 
        term.c_cflag = CLOCAL | CREAD | CS8 | HUPCL;
-       term.c_iflag = IGNBRK | IGNPAR;
+       term.c_iflag = IGNBRK | IGNPAR | IXON | IXOFF;
 
        cfsetispeed(&term, B9600);
        cfsetospeed(&term, B9600);
@@ -203,7 +214,10 @@ static int stty_sball(struct sball *sb)
        return 0;
 }
 
-/* Logicad magellan spacemouse: 9600 8n2 CTS/RTS */
+/* Logicad magellan spacemouse: 9600 8n2 CTS/RTS
+ * Since the magellan devices don't seem to send any newlines, we can rely on
+ * canonical mode to feed us nice whole lines at a time.
+ */
 static int stty_mag(struct sball *sb)
 {
        int mstat;
@@ -220,7 +234,12 @@ static int stty_mag(struct sball *sb)
        term.c_cc[VERASE] = 0;
        term.c_cc[VKILL] = 0;
 
-       term.c_cflag = CLOCAL | CREAD | CS8 | CSTOPB | HUPCL | CRTSCTS;
+       term.c_cflag = CLOCAL | CREAD | CS8 | CSTOPB | HUPCL;
+#ifdef CCTS_OFLOW
+       term.c_cflag |= CCTS_OFLOW;
+#elif defined(CRTSCTS)
+       term.c_cflag |= CRTSCTS;
+#endif
        term.c_iflag = IGNBRK | IGNPAR;
 
        cfsetispeed(&term, B9600);
@@ -290,13 +309,8 @@ static int mag_parsepkt(struct sball *sb, int id, char *data, int len)
                        return -1;
                }
                for(i=0; i<6; i++) {
-#ifdef SBALL_BIG_ENDIAN
-                       sb->mot[i] = ((((int)data[3] & 0xf) << 12) | (((int)data[2] & 0xf) << 8) |
-                                       (((int)data[1] & 0xf) << 4) | (data[0] & 0xf)) - 0x8000;
-#else
                        sb->mot[i] = ((((int)data[0] & 0xf) << 12) | (((int)data[1] & 0xf) << 8) |
                                        (((int)data[2] & 0xf) << 4) | (data[3] & 0xf)) - 0x8000;
-#endif
                        data += 4;
                }
                print_state(sb);
@@ -366,16 +380,15 @@ static int sball_parsepkt(struct sball *sb, int id, char *data, int len)
                }
 
 #ifndef SBALL_BIG_ENDIAN
+               rd = data;
                for(i=0; i<6; i++) {
-                       data += 2;
-                       c = data[0];
-                       data[0] = data[1];
-                       data[1] = c;
-                       sb->mot[i] = *(short*)data;
+                       rd += 2;
+                       c = rd[0];
+                       rd[0] = rd[1];
+                       rd[1] = c;
                }
-#else
-               memcpy(sb->mot, data + 2, 12);
 #endif
+               memcpy(sb->mot, data + 2, 12);
                print_state(sb);
                break;
 
@@ -423,7 +436,7 @@ static int sball_parsepkt(struct sball *sb, int id, char *data, int len)
        case 'E':
                fprintf(stderr, "sball: error:");
                for(i=0; i<len; i++) {
-                       if(isprint(data[i])) {
+                       if(isprint((int)data[i])) {
                                fprintf(stderr, " %c", data[i]);
                        } else {
                                fprintf(stderr, " %02xh", (unsigned int)data[i]);