--- /dev/null
+id strings
+==========
+
+Spaceballs
+----------
+Spaceball 1003 (buttons: 8)
+ Firmware version 2.02 created on 11-Jun-1991.
+
+Spaceball 2003/2003C (buttons: 8)
+ Firmware version 2.02 created on 11-Jun-1991 (2003)
+ Firmware version 2.13 created on 07-Apr-1993 (2003)
+ Firmware version 2.15 created on 08-Jul-1993 (2003)
+ Firmware version 2.42 created on 24-Oct-1997 (2003C)
+
+Spaceball 3003/3003C (buttons: 2)
+ Firmware version 2.35 created on 23-Aug-1995 (Model 3003)
+ Firmware version 2.62 created on 24-Oct-1997 (Model 3003C)
+ Firmware version 2.63 created on 28-Sep-1998 (Model 3003C)
+
+Spaceball 4000 FLX/5000 FLX-A (buttons: 12)
+ Firmware version 2.42 created on 24-Oct-1997
+ Firmware version 2.43 created on 13-Oct-2000
+ Firmware version 2.45 created on 06-May-2003 (5000 FLX-A)
+
+
+Magellan
+--------
+SpaceMouse classic (buttons: 9)
+ MAGELLAN Version 5.49 by LOGITECH INC. 10/22/96
+ MAGELLAN Version 5.79 by LOGITECH INC. 10/10/97
+
+SpaceMouse plus (buttons: 9)
+ MAGELLAN Version 6.50 by LogiCad3D GmbH 05/11/00
+ MAGELLAN Version 6.60 3Dconnexion GmbH 05/11/01
+ MAGELLAN Version 6.70 3Dconnexion GmbH 05/11/02
+
+Puckman (buttons: 0?)
+ MAGELLAN Version 5.79 by LOGITECH INC. 10/10/97
+
+SpaceMouse plus XT (buttons: 9)
+ MAGELLAN Version 6.50 by LogiCad3D GmbH 05/11/00
+ MAGELLAN Version 6.60 3Dconnexion GmbH 05/11/01
+ MAGELLAN Version 6.70 3Dconnexion GmbH 05/11/02
+
+Cadman (buttons: 2)
+ CadMan Version 7.10 3Dconnexion GmbH 21/03/02
+
+Spaceball 5000 (buttons: 12)
+ SPACEBALL Version 8.20 3Dconnexion GmbH 05/11/02. (serial model only)
#define INP_BUF_SZ 256
+enum {
+ SB4000 = 1,
+ FLIPXY = 2
+};
+
struct sball {
int fd;
+ unsigned int flags;
+ int nbuttons;
char buf[INP_BUF_SZ];
int len;
- int (*parse)(int, char*, int);
+ int (*parse)(struct sball*, int, char*, int);
};
static int stty_sball(int fd);
static int proc_input(struct sball *sb);
-static int mag_parsepkt(int id, char *data, int len);
-static int sball_parsepkt(int id, char *data, int len);
+static int mag_parsepkt(struct sball *sb, int id, char *data, int len);
+static int sball_parsepkt(struct sball *sb, int id, char *data, int len);
+
+static int guess_num_buttons(const char *verstr);
static void make_printable(char *buf, int len);
static int read_timeout(int fd, char *buf, int bufsz, long tm_usec);
goto err;
}
sb->fd = fd;
+ sb->flags = 0;
+ sb->len = 0;
if(stty_sball(fd) == -1) {
goto err;
make_printable(buf, sz);
printf("Spaceball detected: %s\n", buf);
- /* set SS mode */
- write(fd, "MSS\r", 4);
+ sb->nbuttons = guess_num_buttons(buf);
+ printf("%d buttons\n", sb->nbuttons);
+
+ /* set binary mode and enable automatic data packet sending */
+ write(fd, "\rCB\rMSS\r", 8);
sb->parse = sball_parsepkt;
return sb;
make_printable(buf, sz);
printf("Magellan SpaceMouse detected: %s\n", buf);
+ sb->nbuttons = guess_num_buttons(buf);
+ printf("%d buttons\n", sb->nbuttons);
+
/* set 3D mode, not-dominant-axis, pass through motion and button packets */
write(fd, "m3\r", 3);
while(bptr < end) {
if(*bptr == '\r') {
*bptr = 0;
- sb->parse(*start, start + 1, bptr - start - 1);
+ sb->parse(sb, *start, start + 1, bptr - start - 1);
start = ++bptr;
} else {
bptr++;
putchar('\n');
}
-static int mag_parsepkt(int id, char *data, int len)
+static int mag_parsepkt(struct sball *sb, int id, char *data, int len)
{
int i, mot[6];
unsigned int keystate;
return 0;
}
-static int sball_parsepkt(int id, char *data, int len)
+static int sball_parsepkt(struct sball *sb, int id, char *data, int len)
{
int i;
unsigned int keystate;
fprintf(stderr, "sball: invalid key packet, expected 2 bytes, got: %d\n", len);
return -1;
}
- keystate = (data[1] & 0x30) >> 4;
+ if(sb->flags & SB4000) break; /* ignore K packets from spaceball 4000 devices */
+
+ /* data[1] bits 0-3 -> buttons 0,1,2,3
+ * data[1] bits 4,5 (3003 L/R) -> buttons 0, 1
+ * data[0] bits 0-2 -> buttons 4,5,6
+ * data[0] bit 4 is (2003 pick) -> button 7
+ */
+ keystate = (data[1] & 0xf) | ((data[1] >> 4) & 3) | ((data[0] & 7) << 4) |
+ ((data[0] & 0x10) >> 1);
+ print_keystate(keystate);
+ break;
+
+ case '.':
+ if(len != 2) {
+ fprintf(stderr, "sball: invalid sb4k key packet, expected 2 bytes, got: %d\n", len);
+ return -1;
+ }
+ /* spaceball 4000 key packet */
+ sb->flags |= SB4000;
+ /* update orientation flag */
+ if(data[0] & 0x20) {
+ sb->flags |= FLIPXY;
+ } else {
+ sb->flags &= ~FLIPXY;
+ }
+
+ /* data[1] bits 0-5 -> buttons 0,1,2,3,4,5
+ * data[1] bit 7 -> button 6
+ * data[0] bits 0-4 -> buttons 7,8,9,10,11
+ */
+ keystate = (data[1] & 0x3f) | ((data[1] & 0x80) >> 1) | ((data[0] & 0x1f) << 7);
print_keystate(keystate);
break;
return 0;
}
+static int guess_num_buttons(const char *verstr)
+{
+ int major, minor;
+ const char *s, *model;
+
+ if((s = strstr(verstr, "Firmware version"))) { /* spaceball */
+
+ /* if we got a model number, guess based on that */
+ if((model = strchr(s, '('))) {
+ if(memcmp(model, "(Model ", 7) == 0) {
+ model += 7;
+ } else {
+ model++;
+ }
+ switch(atoi(model)) {
+ case 2003:
+ return 8;
+ case 3003:
+ return 2;
+ case 5000:
+ return 12;
+ default:
+ break;
+ }
+ }
+ /* try to guess based on firmware number */
+ if(sscanf(s + 17, "%d.%d", &major, &minor) == 2 && major == 2) {
+ if(minor == 35 || minor == 62 || minor == 63) {
+ return 2; /* spaceball 3003/3003C */
+ }
+ if(minor == 42 || minor == 43 || minor == 45) {
+ /* 2.42 is also used by spaceball 2003C, but this should be
+ * caught before we get here by the model number guess
+ */
+ return 12; /* spaceball 4000flx/5000flx-a */
+ }
+ if(minor == 2 || minor == 13 || minor == 15) {
+ return 8; /* spaceball 1003/2003/2003c */
+ }
+ }
+ }
+
+ if(strstr(verstr, "MAGELLAN Version")) {
+ return 9; /* magellan spacemouse */
+ }
+
+ if(strstr(verstr, "SPACEBALL Version")) {
+ return 12; /* spaceball 5000 */
+ }
+
+ if(strstr(verstr, "CadMan Version")) {
+ return 2;
+ }
+
+ fprintf(stderr, "Can't guess number of buttons, default to 8, report this as a bug!\n");
+ return 8;
+}
+
static void make_printable(char *buf, int len)
{
int i, c;