X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=sball;a=blobdiff_plain;f=src%2Fsball.c;h=9dce2ae1c58636c0adf7388b1f52931eb4174657;hp=4b0304050d09aeab890f5d080d3555b8c26f2fd3;hb=9f32047b6512fb261f5b57f62571b658ba6e3330;hpb=9c67b30c9aacfdd2bf783ed25848a152d73ea8b3 diff --git a/src/sball.c b/src/sball.c index 4b03040..9dce2ae 100644 --- a/src/sball.c +++ b/src/sball.c @@ -4,12 +4,12 @@ #include #include #include -#include #include #include #include #include #include +#include #define INP_BUF_SZ 256 @@ -29,11 +29,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); @@ -54,7 +59,7 @@ struct sball *sball_open(const char *dev) char buf[128]; struct sball *sb = 0; - if((fd = open(dev, O_RDWR | O_NOCTTY)) == -1) { + if((fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1) { fprintf(stderr, "sball_open: failed to open device: %s: %s\n", dev, strerror(errno)); return 0; } @@ -67,11 +72,14 @@ struct sball *sball_open(const char *dev) 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); - if((sz = read_timeout(fd, buf, sizeof buf - 1, 2000000)) > 0 && memcmp(buf, "\r@1", 3) == 0) { + if((sz = read_timeout(fd, buf, sizeof buf - 1, 2000000)) > 0 && strstr(buf, "\r@1")) { /* we got a response, so it's a spaceball */ make_printable(buf, sz); printf("Spaceball detected: %s\n", buf); @@ -80,14 +88,14 @@ struct sball *sball_open(const char *dev) printf("%d buttons\n", sb->nbuttons); /* set binary mode and enable automatic data packet sending */ - write(fd, "\rCB\rMSS\r", 8); + write(fd, "\rCB\rMSSV\r", 9); sb->parse = sball_parsepkt; return sb; } /* try as a magellan spacemouse */ - if(stty_mag(fd) == -1) { + if(stty_mag(sb) == -1) { goto err; } write(fd, "vQ\r", 3); @@ -107,6 +115,7 @@ struct sball *sball_open(const char *dev) } err: + stty_restore(sb); close(fd); free(sb); return 0; @@ -115,6 +124,8 @@ err: void sball_close(struct sball *sb) { if(!sb) return; + + stty_restore(sb); close(sb->fd); } @@ -159,48 +170,55 @@ int sball_num_buttons(struct sball *sb) } /* Labtec spaceball: 9600 8n1 XON/XOFF */ -static int stty_sball(int fd) +static int stty_sball(struct sball *sb) { + 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 = 0; + term.c_lflag = ICANON; term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; + 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_cflag = CLOCAL | CREAD | CS8 | HUPCL; - term.c_iflag = IGNBRK | IGNPAR | IXON | IXOFF; + term.c_iflag = IGNBRK | IGNPAR; 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); + 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) +static int stty_mag(struct sball *sb) { + 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 = 0; + term.c_lflag = ICANON; term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; + 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_cflag = CLOCAL | CREAD | CS8 | CSTOPB | HUPCL | CRTSCTS; term.c_iflag = IGNBRK | IGNPAR; @@ -208,14 +226,30 @@ static int stty_mag(int fd) 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); + 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) {