X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fsball.c;h=e6ff48e2fef147609633cbab6a96370540ce18c0;hb=4ab56d777d7e9e2ae2e69278d18d31bb480d6151;hp=327348062d24ad42b54282411e36fbfe621298a7;hpb=a7631559cc873cbfdd1ec34d0fafa650f285a11d;p=sball diff --git a/src/sball.c b/src/sball.c index 3273480..e6ff48e 100644 --- a/src/sball.c +++ b/src/sball.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -12,6 +11,18 @@ #include #include +#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 { @@ -30,11 +41,16 @@ struct sball { short mot[6]; unsigned int keystate; + struct termios saved_term; + int saved_mstat; + int (*parse)(struct sball*, int, char*, int); }; -static int stty_sball(int fd); -static int stty_mag(int fd); +static int stty_sball(struct sball *sb); +static int stty_mag(struct sball *sb); +static void stty_save(struct sball *sb); +static void stty_restore(struct sball *sb); static int proc_input(struct sball *sb); @@ -60,15 +76,15 @@ 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; - if(stty_sball(fd) == -1) { + stty_save(sb); + + if(stty_sball(sb) == -1) { goto err; } write(fd, "\r@RESET\r", 8); @@ -89,7 +105,7 @@ struct sball *sball_open(const char *dev) } /* try as a magellan spacemouse */ - if(stty_mag(fd) == -1) { + if(stty_mag(sb) == -1) { goto err; } write(fd, "vQ\r", 3); @@ -109,6 +125,7 @@ struct sball *sball_open(const char *dev) } err: + stty_restore(sb); close(fd); free(sb); return 0; @@ -117,6 +134,8 @@ err: void sball_close(struct sball *sb) { if(!sb) return; + + stty_restore(sb); close(sb->fd); } @@ -160,56 +179,51 @@ int sball_num_buttons(struct sball *sb) return sb->nbuttons; } -/* Labtec spaceball: 9600 8n1 XON/XOFF */ -static int stty_sball(int fd) +/* 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 status; + int mstat; struct termios term; - if(tcgetattr(fd, &term) == -1) { - perror("sball_open: tcgetattr"); - return -1; - } - + 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); - if(tcsetattr(fd, TCSANOW, &term) == -1) { + if(tcsetattr(sb->fd, TCSAFLUSH, &term) == -1) { perror("sball_open: tcsetattr"); return -1; } + tcflush(sb->fd, TCIOFLUSH); - if(ioctl(fd, TIOCMGET, &status) != -1) { - status |= TIOCM_DTR | TIOCM_RTS; - ioctl(fd, TIOCMSET, &status); - } + mstat = sb->saved_mstat | TIOCM_DTR | TIOCM_RTS; + ioctl(sb->fd, TIOCMGET, &mstat); return 0; } -/* Logicad magellan spacemouse: 9600 8n2 CTS/RTS */ -static int stty_mag(int fd) +/* 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 status; + int mstat; struct termios term; - if(tcgetattr(fd, &term) == -1) { - perror("sball_open: tcgetattr"); - return -1; - } - + term = sb->saved_term; term.c_oflag = 0; term.c_lflag = ICANON; term.c_cc[VMIN] = 0; @@ -220,25 +234,41 @@ static int stty_mag(int fd) 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); cfsetospeed(&term, B9600); - if(tcsetattr(fd, TCSAFLUSH, &term) == -1) { + if(tcsetattr(sb->fd, TCSAFLUSH, &term) == -1) { perror("sball_open: tcsetattr"); return -1; } - tcflush(fd, TCIOFLUSH); + tcflush(sb->fd, TCIOFLUSH); - if(ioctl(fd, TIOCMGET, &status) != -1) { - status |= TIOCM_DTR | TIOCM_RTS; - ioctl(fd, TIOCMGET, &status); - } + mstat = sb->saved_mstat | TIOCM_DTR | TIOCM_RTS; + ioctl(sb->fd, TIOCMGET, &mstat); return 0; } +static void stty_save(struct sball *sb) +{ + tcgetattr(sb->fd, &sb->saved_term); + ioctl(sb->fd, TIOCMGET, &sb->saved_mstat); +} + +static void stty_restore(struct sball *sb) +{ + tcsetattr(sb->fd, TCSAFLUSH, &sb->saved_term); + tcflush(sb->fd, TCIOFLUSH); + ioctl(sb->fd, TIOCMSET, &sb->saved_mstat); +} + static int proc_input(struct sball *sb) { @@ -279,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); @@ -355,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; @@ -412,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