32 #include <linux/kernel.h>
33 #include <linux/slab.h>
34 #include <linux/module.h>
37 #include <linux/gameport.h>
38 #include <linux/input.h>
41 #define DRIVER_DESC "InterAct digital joystick driver"
47 #define INTERACT_MAX_START 600
48 #define INTERACT_MAX_STROBE 60
49 #define INTERACT_MAX_LENGTH 32
51 #define INTERACT_TYPE_HHFX 0
52 #define INTERACT_TYPE_PP8D 1
56 struct input_dev *
dev;
64 static short interact_abs_hhfx[] =
66 static short interact_abs_pp8d[] =
69 static short interact_btn_hhfx[] =
70 {
BTN_TR,
BTN_X,
BTN_Y,
BTN_Z,
BTN_A,
BTN_B,
BTN_C,
BTN_TL,
BTN_TL2,
BTN_TR2,
BTN_MODE,
BTN_SELECT, -1 };
71 static short interact_btn_pp8d[] =
84 { 0x6202, interact_abs_hhfx, interact_btn_hhfx,
"InterAct HammerHead/FX", 32, 4 },
85 { 0x53f8, interact_abs_pp8d, interact_btn_pp8d,
"InterAct ProPad 8 Digital", 16, 0 },
100 data[0] = data[1] = data[2] = 0;
105 gameport_trigger(gameport);
106 v = gameport_read(gameport);
108 while (t > 0 && i < length) {
110 u =
v; v = gameport_read(gameport);
112 data[0] = (data[0] << 1) | ((v >> 4) & 1);
113 data[1] = (data[1] << 1) | ((v >> 5) & 1);
114 data[2] = (data[2] << 1) | ((v >> 7) & 1);
129 static void interact_poll(
struct gameport *gameport)
132 struct input_dev *
dev = interact->
dev;
142 for (i = 0; i < 3; i++)
145 switch (interact->
type) {
149 for (i = 0; i < 4; i++)
150 input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
152 for (i = 0; i < 2; i++)
154 ((data[1] >> ((i << 1) + 17)) & 1) - ((data[1] >> ((i << 1) + 16)) & 1));
156 for (i = 0; i < 8; i++)
157 input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
159 for (i = 0; i < 4; i++)
160 input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
166 for (i = 0; i < 2; i++)
167 input_report_abs(dev, interact_abs_pp8d[i],
168 ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1));
170 for (i = 0; i < 8; i++)
171 input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
184 static int interact_open(
struct input_dev *dev)
186 struct interact *interact = input_get_drvdata(dev);
196 static void interact_close(
struct input_dev *dev)
198 struct interact *interact = input_get_drvdata(dev);
207 static int interact_connect(
struct gameport *gameport,
struct gameport_driver *drv)
209 struct interact *interact;
210 struct input_dev *input_dev;
215 interact = kzalloc(
sizeof(
struct interact),
GFP_KERNEL);
216 input_dev = input_allocate_device();
217 if (!interact || !input_dev) {
223 interact->
dev = input_dev;
225 gameport_set_drvdata(gameport, interact);
233 if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
238 for (i = 0; interact_type[
i].
length; i++)
239 if (interact_type[i].
id == (data[2] >> 16))
242 if (!interact_type[i].length) {
243 printk(
KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
244 gameport->
phys, i, data[0], data[1], data[2]);
249 gameport_set_poll_handler(gameport, interact_poll);
250 gameport_set_poll_interval(gameport, 20);
257 input_dev->name = interact_type[
i].
name;
258 input_dev->phys = interact->
phys;
261 input_dev->id.product = interact_type[
i].
id;
262 input_dev->id.version = 0x0100;
263 input_dev->dev.parent = &gameport->
dev;
265 input_set_drvdata(input_dev, interact);
267 input_dev->open = interact_open;
268 input_dev->close = interact_close;
272 for (i = 0; (t = interact_type[interact->
type].
abs[
i]) >= 0; i++) {
273 if (i < interact_type[interact->
type].
b8)
274 input_set_abs_params(input_dev, t, 0, 255, 0, 0);
276 input_set_abs_params(input_dev, t, -1, 1, 0, 0);
279 for (i = 0; (t = interact_type[interact->
type].
btn[
i]) >= 0; i++)
282 err = input_register_device(interact->
dev);
289 fail1: gameport_set_drvdata(gameport,
NULL);
290 input_free_device(input_dev);
295 static void interact_disconnect(
struct gameport *gameport)
297 struct interact *interact = gameport_get_drvdata(gameport);
299 input_unregister_device(interact->
dev);
301 gameport_set_drvdata(gameport,
NULL);
310 .connect = interact_connect,
311 .disconnect = interact_disconnect,