+static void print_motion(short *mot)
+{
+ printf(" T[%+6d %+6d %+6d] R[%+6d %+6d %+6d]", mot[0], mot[1],
+ mot[2], mot[3], mot[4], mot[5]);
+}
+
+static void print_keystate(unsigned int keystate)
+{
+ int i;
+
+ for(i=0; i<16; i++) {
+ int b = 15 - i;
+ int hex = b < 10 ? b + '0' : b - 10 + 'a';
+ putchar(keystate & (1 << b) ? hex : '-');
+ }
+}
+
+static void print_state(struct sball *sb)
+{
+ print_motion(sb->mot);
+ printf(" B[");
+ print_keystate(sb->keystate);
+ printf("]\r");
+ fflush(stdout);
+}
+
+
+/* test all known button packets for all models */
+enum {
+ BTEST_SB2003,
+ BTEST_SB2003C,
+ BTEST_SB3003C,
+ BTEST_SB4000FLX,
+ BTEST_SMCLASSIC,
+ BTEST_SMPLUS,
+ BTEST_SB5000FLX,
+ BTEST_SPEXP,
+
+ NUM_BTEST_MODELS
+};
+
+static const char *btest_models[NUM_BTEST_MODELS] = {
+ "Spaceball 2003",
+ "Spaceball 2003C",
+ "Spaceball 3003C",
+ "Spaceball 4000FLX",
+ "Spacemouse classic",
+ "Spacemouse plus/xt",
+ "Spaceball 5000FLX",
+ "Space Explorer"
+};
+
+struct btest_data {
+ int device;
+ const char *label;
+ const char *pkt;
+};
+
+struct btest_data btest_data[] = {
+ {BTEST_SB2003, "bn 1", "K@A\r"},
+ {BTEST_SB2003, "bn 2", "K@B\r"},
+ {BTEST_SB2003, "bn 3", "K@D\r"},
+ {BTEST_SB2003, "bn 4", "K@H\r"},
+ {BTEST_SB2003, "bn 5", "KA@\r"},
+ {BTEST_SB2003, "bn 6", "KB@\r"},
+ {BTEST_SB2003, "bn 7", "KD@\r"},
+ {BTEST_SB2003, "bn 8", "KH@\r"},
+ {BTEST_SB2003, "pick", "KP@\r"},
+
+ {BTEST_SB2003C, "bn 1", "K@A\r"},
+ {BTEST_SB2003C, "bn 2", "K@B\r"},
+ {BTEST_SB2003C, "bn 3", "K@D\r"},
+ {BTEST_SB2003C, "bn 4", "K@H\r"},
+ {BTEST_SB2003C, "bn 5", "KA@\r"},
+ {BTEST_SB2003C, "bn 6", "KB@\r"},
+ {BTEST_SB2003C, "bn 7", "KD@\r"},
+ {BTEST_SB2003C, "bn 8", "KP@\r"},
+ {BTEST_SB2003C, "zero", "K`@\r"},
+
+ {BTEST_SB3003C, "bn R", "KPP\r"},
+ {BTEST_SB3003C, "bn L", "K@`\r"},
+ {BTEST_SB3003C, "zero", "K`@\r"},
+
+ {BTEST_SB4000FLX, "bn 1", ".@A\r"},
+ {BTEST_SB4000FLX, "bn 2", ".@B\r"},
+ {BTEST_SB4000FLX, "bn 3", ".@D\r"},
+ {BTEST_SB4000FLX, "bn 4", ".@H\r"},
+ {BTEST_SB4000FLX, "bn 5", ".@P\r"},
+ {BTEST_SB4000FLX, "bn 6", ".@`\r"},
+ {BTEST_SB4000FLX, "bn 7", ".@\xc0\r"},
+ {BTEST_SB4000FLX, "bn 8", ".A@\r"},
+ {BTEST_SB4000FLX, "bn 9", ".B@\r"},
+ {BTEST_SB4000FLX, "bn A", ".D@\r"},
+ {BTEST_SB4000FLX, "bn B", ".H@\r"},
+ {BTEST_SB4000FLX, "bn C", ".P@\r"},
+ {BTEST_SB4000FLX, "r.h.", ".`@\r"},
+
+ {BTEST_SMCLASSIC, "bn 1", "kA00\r"},
+ {BTEST_SMCLASSIC, "bn 2", "kB00\r"},
+ {BTEST_SMCLASSIC, "bn 3", "kD00\r"},
+ {BTEST_SMCLASSIC, "bn 4", "kH00\r"},
+ {BTEST_SMCLASSIC, "bn 5", "k0A0\r"},
+ {BTEST_SMCLASSIC, "bn 6", "k0B0\r"},
+ {BTEST_SMCLASSIC, "bn 7", "k0D0\r"},
+ {BTEST_SMCLASSIC, "bn 8", "k0H0\r"},
+ {BTEST_SMCLASSIC, "bn *", "k00A\r"},
+
+ {BTEST_SMPLUS, "bn 1", "kA00\r"},
+ {BTEST_SMPLUS, "bn 2", "kB00\r"},
+ {BTEST_SMPLUS, "bn 3", "kD00\r"},
+ {BTEST_SMPLUS, "bn 4", "kH00\r"},
+ {BTEST_SMPLUS, "bn 5", "k0A0\r"},
+ {BTEST_SMPLUS, "bn 6", "k0B0\r"},
+ {BTEST_SMPLUS, "bn 7", "k0D0\r"},
+ {BTEST_SMPLUS, "bn 8", "k0H0\r"},
+ {BTEST_SMPLUS, "bn *", "k00A\r"},
+ {BTEST_SMPLUS, "bn A", "k00B\r"},
+ {BTEST_SMPLUS, "bn B", "k00D\r"},
+
+ {BTEST_SB5000FLX, "bn 1", "kA00\r"},
+ {BTEST_SB5000FLX, "bn 2", "kB00\r"},
+ {BTEST_SB5000FLX, "bn 3", "kD00\r"},
+ {BTEST_SB5000FLX, "bn 4", "kH00\r"},
+ {BTEST_SB5000FLX, "bn 5", "k0A0\r"},
+ {BTEST_SB5000FLX, "bn 6", "k0B0\r"},
+ {BTEST_SB5000FLX, "bn 7", "k0D0\r"},
+ {BTEST_SB5000FLX, "bn 8", "k0H0\r"},
+ {BTEST_SB5000FLX, "bn 9", "k00A\r"},
+ {BTEST_SB5000FLX, "bn A", "k00B\r"},
+ {BTEST_SB5000FLX, "bn B", "k00D\r"},
+ {BTEST_SB5000FLX, "bn C", "k00H\r"},
+
+ {BTEST_SPEXP, "bn 1", "kA000\r"},
+ {BTEST_SPEXP, "bn 2", "kB000\r"},
+ {BTEST_SPEXP, "bn T", "kD000\r"},
+ {BTEST_SPEXP, "bn L", "kH000\r"},
+ {BTEST_SPEXP, "bn R", "k0A00\r"},
+ {BTEST_SPEXP, "bn F", "k0B00\r"},
+ {BTEST_SPEXP, " ALT", "k0D00\r"},
+ {BTEST_SPEXP, " ESC", "k0H00\r"},
+ {BTEST_SPEXP, "SHFT", "k00A0\r"},
+ {BTEST_SPEXP, "CTRL", "k00B0\r"},
+ {BTEST_SPEXP, " fit", "k00D0\r"},
+ {BTEST_SPEXP, "panl", "k00H0\r"},
+ {BTEST_SPEXP, "bn +", "k000A\r"},
+ {BTEST_SPEXP, "bn -", "k000B\r"},
+ {BTEST_SPEXP, " 2D", "k000D\r"},
+
+ {-1, 0, 0}
+};
+
+void sball_button_test(void)
+{
+ char pkt[16];
+ int dev = -1;
+ int (*parse)(struct sball*, int, char*, int);
+ struct btest_data *td = btest_data;
+ struct sball sb = {0};
+
+
+ while(td->device >= 0) {
+ if(td->device != dev) {
+ dev = td->device;
+ sb.keymask = dev == BTEST_SB3003C ? 3 : 0xffff;
+ parse = (dev < BTEST_SMCLASSIC) ? sball_parsepkt : mag_parsepkt;
+ printf("\n\nTesting button packets for: %s", btest_models[dev]);
+ }
+
+ strcpy(pkt, td->pkt + 1);
+ sb.flags = dev == BTEST_SB4000FLX ? SB4000 : 0;
+
+ printf("\n %s: ", td->label);
+ parse(&sb, td->pkt[0], pkt, strlen(pkt) - 1);
+ td++;
+ }
+ putchar('\n');
+}