30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/slab.h>
34 #include <linux/input.h>
35 #include <linux/gameport.h>
38 #define DRIVER_DESC "Microsoft SideWinder joystick family driver"
63 #define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
65 #define dbg(format, arg...) do {} while (0)
83 static char *sw_name[] = {
"3D Pro",
"GamePad",
"Precision Pro",
"Force Feedback Pro",
"FreeStyle Pro",
84 "Force Feedback Wheel" };
86 static char sw_abs[][7] = {
94 static char sw_bit[][7] = {
95 { 10, 10, 9, 10, 1, 1 },
97 { 10, 10, 6, 7, 1, 1 },
98 { 10, 10, 6, 7, 1, 1 },
102 static short sw_btn[][12] = {
104 {
BTN_A,
BTN_B,
BTN_C,
BTN_X,
BTN_Y,
BTN_Z,
BTN_TL,
BTN_TR,
BTN_START,
BTN_MODE },
107 {
BTN_A,
BTN_B,
BTN_C,
BTN_X,
BTN_Y,
BTN_Z,
BTN_TL,
BTN_TR,
BTN_START,
BTN_MODE,
BTN_SELECT },
113 } sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
140 unsigned char pending,
u,
v;
143 timeout =
id ? gameport_time(gameport,
SW_TIMEOUT * 1000) : 0;
144 kick =
id ? gameport_time(gameport,
SW_KICK) : 0;
145 start = gameport_time(gameport,
SW_START);
146 strobe = gameport_time(gameport,
SW_STROBE);
153 gameport_trigger(gameport);
154 v = gameport_read(gameport);
159 v = gameport_read(gameport);
160 }
while (!(~v & u & 0x10) && (bitout > 0));
165 while ((timeout > 0 || bitout > 0) && (i < length)) {
172 v = gameport_read(gameport);
174 if ((~u & v & 0x10) && (bitout > 0)) {
181 if (kick && (~v & u & 0x01)) {
187 if (pending && sched < 0 && (i > -
SW_END)) {
188 gameport_trigger(gameport);
201 for (j = 0; j <
i; j++)
printk(
"%d", buf[j]);
216 #define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
218 static __u64 sw_get_bits(
unsigned char *buf,
int pos,
int num,
char bits)
221 int tri = pos %
bits;
226 data |= (
__u64)((buf[i] >> tri++) & 1) << bit++;
241 static void sw_init_digital(
struct gameport *gameport)
243 int seq[] = { 140, 140+725, 140+300, 0 };
251 gameport_trigger(gameport);
252 t = gameport_time(gameport,
SW_TIMEOUT * 1000);
253 while ((gameport_read(gameport) & 1) && t) t--;
257 gameport_trigger(gameport);
266 static int sw_parity(
__u64 t)
268 int x = t ^ (t >> 32);
282 static int sw_check(
__u64 t)
284 unsigned char sum = 0;
286 if ((t & 0x8080808080808080ULL) ^ 0x80)
302 static int sw_parse(
unsigned char *buf,
struct sw *
sw)
305 struct input_dev *
dev;
311 if (sw_check(
GB(0,64)) || (hat = (
GB(6,1) << 3) |
GB(60,3)) > 8)
316 input_report_abs(dev,
ABS_X, (
GB( 3,3) << 7) |
GB(16,7));
317 input_report_abs(dev,
ABS_Y, (
GB( 0,3) << 7) |
GB(24,7));
318 input_report_abs(dev,
ABS_RZ, (
GB(35,2) << 7) |
GB(40,7));
321 input_report_abs(dev,
ABS_HAT0X, sw_hat_to_axis[hat].
x);
322 input_report_abs(dev,
ABS_HAT0Y, sw_hat_to_axis[hat].
y);
324 for (j = 0; j < 7; j++)
325 input_report_key(dev, sw_btn[
SW_ID_3DP][j], !
GB(j+8,1));
336 for (i = 0; i < sw->
number; i ++) {
338 if (sw_parity(
GB(i*15,15)))
341 input_report_abs(sw->
dev[i],
ABS_X,
GB(i*15+3,1) -
GB(i*15+2,1));
342 input_report_abs(sw->
dev[i],
ABS_Y,
GB(i*15+0,1) -
GB(i*15+1,1));
344 for (j = 0; j < 10; j++)
345 input_report_key(sw->
dev[i], sw_btn[
SW_ID_GP][j], !
GB(i*15+j+4,1));
347 input_sync(sw->
dev[i]);
355 if (!sw_parity(
GB(0,48)) || (hat =
GB(42,4)) > 8)
359 input_report_abs(dev,
ABS_X,
GB( 9,10));
360 input_report_abs(dev,
ABS_Y,
GB(19,10));
361 input_report_abs(dev,
ABS_RZ,
GB(36, 6));
364 input_report_abs(dev,
ABS_HAT0X, sw_hat_to_axis[hat].
x);
365 input_report_abs(dev,
ABS_HAT0Y, sw_hat_to_axis[hat].
y);
367 for (j = 0; j < 9; j++)
368 input_report_key(dev, sw_btn[
SW_ID_PP][j], !
GB(j,1));
376 if (!sw_parity(
GB(0,43)) || (hat =
GB(28,4)) > 8)
380 input_report_abs(dev,
ABS_X,
GB( 0,10));
381 input_report_abs(dev,
ABS_Y,
GB(16,10));
384 input_report_abs(dev,
ABS_HAT0X, sw_hat_to_axis[hat].
x);
385 input_report_abs(dev,
ABS_HAT0Y, sw_hat_to_axis[hat].
y);
387 for (j = 0; j < 6; j++)
388 input_report_key(dev, sw_btn[
SW_ID_FSP][j], !
GB(j+10,1));
390 input_report_key(dev,
BTN_TR, !
GB(26,1));
401 if (!sw_parity(
GB(0,33)))
405 input_report_abs(dev,
ABS_RX,
GB( 0,10));
409 for (j = 0; j < 8; j++)
410 input_report_key(dev, sw_btn[
SW_ID_FFW][j], !
GB(j+22,1));
426 static int sw_read(
struct sw *sw)
435 if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) {
437 " - going to reinitialize.\n", sw->
gameport->phys);
442 if (i < 66 &&
GB(0,64) ==
GB(i*3-66,64))
445 if (i < 66 &&
GB(0,64) ==
GB(66,64))
448 if (i < 66 &&
GB(i*3-132,64) ==
GB(i*3-66,64)) {
449 memmove(buf, buf + i - 22, 22);
454 if (i == sw->
length && !sw_parse(buf, sw)) {
463 " - enabling optimization again.\n", sw->
gameport->phys);
476 " - disabling optimization.\n", sw->
gameport->phys);
484 " - reinitializing joystick.\n", sw->
gameport->phys);
501 static void sw_poll(
struct gameport *gameport)
503 struct sw *sw = gameport_get_drvdata(gameport);
510 static int sw_open(
struct input_dev *dev)
512 struct sw *sw = input_get_drvdata(dev);
518 static void sw_close(
struct input_dev *dev)
520 struct sw *sw = input_get_drvdata(dev);
529 static void sw_print_packet(
char *
name,
int length,
unsigned char *buf,
char bits)
534 for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
535 printk(
"%x", (
int)sw_get_bits(buf, i << 2, 4, bits));
544 static void sw_3dp_id(
unsigned char *buf,
char *comment,
size_t size)
549 for (i = 0; i < 7; i++)
550 pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
552 for (i = 0; i < 8; i++)
553 rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
557 snprintf(comment, size,
" [PnP %d.%02d id %s rev %s]",
558 (
int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
559 sw_get_bits(buf, 16, 6, 1)) / 100,
560 (
int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
561 sw_get_bits(buf, 16, 6, 1)) % 100,
572 static int sw_guess_mode(
unsigned char *buf,
int len)
575 unsigned char xor = 0;
577 for (i = 1; i < len; i++)
578 xor |= (buf[i - 1] ^ buf[i]) & 6;
580 return !!xor * 2 + 1;
587 static int sw_connect(
struct gameport *gameport,
struct gameport_driver *drv)
590 struct input_dev *input_dev;
593 unsigned char *buf =
NULL;
594 unsigned char *idbuf =
NULL;
603 if (!sw || !buf || !idbuf) {
610 gameport_set_drvdata(gameport, sw);
616 dbg(
"Init 0: Opened %s, io %#x, speed %d",
619 i = sw_read_packet(gameport, buf,
SW_LENGTH, 0);
621 dbg(
"Init 1: Mode %d. Length %d.", m , i);
624 sw_init_digital(gameport);
626 i = sw_read_packet(gameport, buf,
SW_LENGTH, 0);
628 dbg(
"Init 1b: Length %d.", i);
635 j = sw_read_packet(gameport, idbuf,
SW_LENGTH, i);
636 m |= sw_guess_mode(idbuf, j);
637 dbg(
"Init 2: Mode %d. ID Length %d.", m, j);
641 i = sw_read_packet(gameport, buf,
SW_LENGTH, 0);
642 m |= sw_guess_mode(buf, i);
643 dbg(
"Init 2b: Mode %d. Length %d.", m, i);
649 j = sw_read_packet(gameport, idbuf,
SW_LENGTH, i);
650 dbg(
"Init 2c: ID Length %d.", j);
660 i = sw_read_packet(gameport, buf,
SW_LENGTH, 0);
661 dbg(
"Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
672 dbg(
"Init 3a: Case %d.\n", i * m);
696 sprintf(comment,
" [AC %s]", sw_get_bits(idbuf,38,1,3) ?
"off" :
"on");
707 sw_3dp_id(idbuf, comment,
sizeof(comment));
712 }
while (k && sw->
type == -1);
714 if (sw->
type == -1) {
717 sw_print_packet(
"ID", j * 3, idbuf, 3);
718 sw_print_packet(
"Data", i * m, buf, m);
724 sw_print_packet(
"ID", j * 3, idbuf, 3);
725 sw_print_packet(
"Data", i * m, buf, m);
728 gameport_set_poll_handler(gameport, sw_poll);
729 gameport_set_poll_interval(gameport, 20);
734 for (i = 0; i < sw->
number; i++) {
738 "Microsoft SideWinder %s", sw_name[sw->
type]);
740 "%s/input%d", gameport->
phys, i);
742 sw->
dev[
i] = input_dev = input_allocate_device();
748 input_dev->name = sw->
name;
749 input_dev->phys = sw->
phys[
i];
752 input_dev->id.product = sw->
type;
753 input_dev->id.version = 0x0100;
754 input_dev->dev.parent = &gameport->
dev;
756 input_set_drvdata(input_dev, sw);
758 input_dev->open = sw_open;
759 input_dev->close = sw_close;
763 for (j = 0; (bits = sw_bit[sw->
type][
j]); j++) {
766 code = sw_abs[sw->
type][
j];
767 min = bits == 1 ? -1 : 0;
768 max = (1 <<
bits) - 1;
769 fuzz = (bits >> 1) >= 2 ? 1 << ((bits >> 1) - 2) : 0;
773 input_set_abs_params(input_dev, code,
774 min, max, fuzz, flat);
777 for (j = 0; (code = sw_btn[sw->
type][
j]); j++)
780 dbg(
"%s%s [%d-bit id %d data %d]\n", sw->
name, comment, m, l, k);
782 err = input_register_device(sw->
dev[i]);
792 fail4: input_free_device(sw->
dev[i]);
793 fail3:
while (--i >= 0)
794 input_unregister_device(sw->
dev[i]);
796 fail1: gameport_set_drvdata(gameport,
NULL);
801 static void sw_disconnect(
struct gameport *gameport)
803 struct sw *sw = gameport_get_drvdata(gameport);
806 for (i = 0; i < sw->
number; i++)
807 input_unregister_device(sw->
dev[i]);
809 gameport_set_drvdata(gameport,
NULL);
815 .name =
"sidewinder",
819 .connect = sw_connect,
820 .disconnect = sw_disconnect,