in joystick/db9.c [355:505]
static void db9_timer(struct timer_list *t)
{
struct db9 *db9 = from_timer(db9, t, timer);
struct parport *port = db9->pd->port;
struct input_dev *dev = db9->dev[0];
struct input_dev *dev2 = db9->dev[1];
int data, i;
switch (db9->mode) {
case DB9_MULTI_0802_2:
data = parport_read_data(port) >> 3;
input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev2, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
fallthrough;
case DB9_MULTI_0802:
data = parport_read_status(port) >> 3;
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
break;
case DB9_MULTI_STICK:
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
break;
case DB9_MULTI2_STICK:
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2);
break;
case DB9_GENESIS_PAD:
parport_write_control(port, DB9_NOSELECT);
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
break;
case DB9_GENESIS5_PAD:
parport_write_control(port, DB9_NOSELECT);
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
break;
case DB9_GENESIS6_PAD:
parport_write_control(port, DB9_NOSELECT); /* 1 */
udelay(DB9_GENESIS6_DELAY);
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
data = parport_read_data(port);
input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
parport_write_control(port, DB9_NOSELECT); /* 2 */
udelay(DB9_GENESIS6_DELAY);
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
parport_write_control(port, DB9_NOSELECT); /* 3 */
udelay(DB9_GENESIS6_DELAY);
data=parport_read_data(port);
input_report_key(dev, BTN_X, ~data & DB9_LEFT);
input_report_key(dev, BTN_Y, ~data & DB9_DOWN);
input_report_key(dev, BTN_Z, ~data & DB9_UP);
input_report_key(dev, BTN_MODE, ~data & DB9_RIGHT);
parport_write_control(port, DB9_NORMAL);
udelay(DB9_GENESIS6_DELAY);
parport_write_control(port, DB9_NOSELECT); /* 4 */
udelay(DB9_GENESIS6_DELAY);
parport_write_control(port, DB9_NORMAL);
break;
case DB9_SATURN_PAD:
case DB9_SATURN_DPP:
case DB9_SATURN_DPP_2:
db9_saturn(db9->mode, port, db9->dev);
break;
case DB9_CD32_PAD:
data = parport_read_data(port);
input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
parport_write_control(port, 0x0a);
for (i = 0; i < 7; i++) {
data = parport_read_data(port);
parport_write_control(port, 0x02);
parport_write_control(port, 0x0a);
input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
}
parport_write_control(port, 0x00);
break;
}
input_sync(dev);
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}