+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+
+struct sball {
+ int fd;
+};
+
+static int stty_sball(int fd);
+static int stty_mag(int fd);
+
+struct sball *sball_open(const char *dev)
+{
+ int fd;
+ struct sball *sb = 0;
+
+ 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;
+ }
+
+ if(!(sb = malloc(sizeof *sb))) {
+ fprintf(stderr, "sball_open: failed to allocate sball object\n");
+ goto err;
+ }
+ sb->fd = fd;
+
+ if(stty_sball(fd) == -1) {
+ goto err;
+ }
+
+ /* set detect receiver function pointer */
+
+ return sb;
+
+err:
+ close(fd);
+ free(sb);
+ return 0;
+}
+
+void sball_close(struct sball *sb)
+{
+ if(!sb) return;
+ close(sb->fd);
+}
+
+
+/* Labtec spaceball: 9600 8n1 XON/XOFF */
+static int stty_sball(int fd)
+{
+ struct termios term;
+
+ if(tcgetattr(fd, &term) == -1) {
+ perror("sball_open: tcgetattr");
+ return -1;
+ }
+
+ term.c_oflag = 0;
+ term.c_lflag = 0;
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 0;
+
+ term.c_cflag = CLOCAL | CREAD | CS8 | HUPCL;
+ term.c_iflag = IGNBRK | IGNPAR | IXON | IXOFF;
+
+ csetispeed(&term, B9600);
+ csetospeed(&term, B9600);
+
+ if(tcsetattr(fd, TCSANOW, &term) == -1) {
+ perror("sball_open: tcsetattr");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Logicad magellan spacemouse: 9600 8n2 CTS/RTS */
+static int stty_mag(int fd)
+{
+ struct termios term;
+
+ if(tcgetattr(fd, &term) == -1) {
+ perror("sball_open: tcgetattr");
+ return -1;
+ }
+
+ term.c_oflag = 0;
+ term.c_lflag = 0;
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 0;
+
+ term.c_cflag = CLOCAL | CREAD | CS8 | CSTOPB | HUPCL | CRTSCTS;
+ term.c_iflag = IGNBRK | IGNPAR |;
+
+ csetispeed(&term, B9600);
+ csetospeed(&term, B9600);
+
+ if(tcsetattr(fd, TCSANOW, &term) == -1) {
+ perror("sball_open: tcsetattr");
+ return -1;
+ }
+
+ return 0;
+}