^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 1996-2001 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Analog joystick and gamepad driver for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/gameport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/timekeeping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DRIVER_DESC "Analog joystick and gamepad driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static bool use_ktime = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) module_param(use_ktime, bool, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Option parsing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define ANALOG_PORTS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static char *js[ANALOG_PORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static unsigned int js_nargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int analog_options[ANALOG_PORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) module_param_array_named(map, js, charp, &js_nargs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Times, feature definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ANALOG_RUDDER 0x00004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ANALOG_THROTTLE 0x00008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define ANALOG_AXES_STD 0x0000f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ANALOG_BTNS_STD 0x000f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ANALOG_BTNS_CHF 0x00100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define ANALOG_HAT1_CHF 0x00200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ANALOG_HAT2_CHF 0x00400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ANALOG_HAT_FCS 0x00800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define ANALOG_HATS_ALL 0x00e00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define ANALOG_BTN_TL 0x01000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ANALOG_BTN_TR 0x02000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define ANALOG_BTN_TL2 0x04000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ANALOG_BTN_TR2 0x08000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define ANALOG_BTNS_TLR 0x03000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ANALOG_BTNS_TLR2 0x0c000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define ANALOG_BTNS_GAMEPAD 0x0f000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define ANALOG_HBTN_CHF 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define ANALOG_ANY_CHF 0x10700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define ANALOG_SAITEK 0x20000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ANALOG_EXTENSIONS 0x7ff00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define ANALOG_GAMEPAD 0x80000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define ANALOG_MAX_TIME 3 /* 3 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define ANALOG_LOOP_TIME 2000 /* 2 * loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ANALOG_SAITEK_DELAY 200 /* 200 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ANALOG_SAITEK_TIME 2000 /* 2000 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ANALOG_AXIS_TIME 2 /* 2 * refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ANALOG_INIT_RETRIES 8 /* 8 times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ANALOG_FUZZ_BITS 2 /* 2 bit more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define ANALOG_FUZZ_MAGIC 36 /* 36 u*ms/loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define ANALOG_MAX_NAME_LENGTH 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define ANALOG_MAX_PHYS_LENGTH 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static short analog_pads[] = { BTN_Y, BTN_Z, BTN_TL, BTN_TR };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static short analog_exts[] = { ANALOG_HAT1_CHF, ANALOG_HAT2_CHF, ANALOG_HAT_FCS };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static short analog_pad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_BASE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_BASE6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct analog {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) short *buttons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char name[ANALOG_MAX_NAME_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) char phys[ANALOG_MAX_PHYS_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct analog_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct gameport *gameport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct analog analog[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned char mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) char saitek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) char cooked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int bads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int reads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int fuzz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int axes[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int buttons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int initial[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int axtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Time macros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #ifdef __i386__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #include <linux/i8253.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define GET_TIME(x) do { if (boot_cpu_has(X86_FEATURE_TSC)) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define DELTA(x,y) (boot_cpu_has(X86_FEATURE_TSC) ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define TIME_NAME (boot_cpu_has(X86_FEATURE_TSC)?"TSC":"PIT")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static unsigned int get_time_pit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) raw_spin_lock_irqsave(&i8253_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) outb_p(0x00, 0x43);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) count = inb_p(0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) count |= inb_p(0x40) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) raw_spin_unlock_irqrestore(&i8253_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #elif defined(__x86_64__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define DELTA(x,y) ((y)-(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define TIME_NAME "TSC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_PPC) || defined(CONFIG_RISCV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define GET_TIME(x) do { x = get_cycles(); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define DELTA(x,y) ((y)-(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define TIME_NAME "get_cycles"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define FAKE_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static unsigned long analog_faketime = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define GET_TIME(x) do { x = analog_faketime++; } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define DELTA(x,y) ((y)-(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define TIME_NAME "Unreliable"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #warning Precise timer not defined for this architecture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static inline u64 get_time(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (use_ktime) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) GET_TIME(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static inline unsigned int delta(u64 x, u64 y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (use_ktime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return y - x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return DELTA((unsigned int)x, (unsigned int)y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * analog_decode() decodes analog joystick data and reports input events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct input_dev *dev = analog->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (analog->mask & ANALOG_HAT_FCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (axes[3] < ((initial[3] * ((i << 1) + 1)) >> 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) buttons |= 1 << (i + 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = j = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (analog->mask & (0x10 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) input_report_key(dev, analog->buttons[j++], (buttons >> i) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (analog->mask & ANALOG_HBTN_CHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) input_report_key(dev, analog->buttons[j++], (buttons >> (i + 10)) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (analog->mask & ANALOG_BTN_TL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) input_report_key(dev, analog_pads[0], axes[2] < (initial[2] >> 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (analog->mask & ANALOG_BTN_TR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) input_report_key(dev, analog_pads[1], axes[3] < (initial[3] >> 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (analog->mask & ANALOG_BTN_TL2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) input_report_key(dev, analog_pads[2], axes[2] > (initial[2] + (initial[2] >> 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (analog->mask & ANALOG_BTN_TR2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) input_report_key(dev, analog_pads[3], axes[3] > (initial[3] + (initial[3] >> 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (i = j = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (analog->mask & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) input_report_abs(dev, analog_axes[j++], axes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (i = j = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (analog->mask & analog_exts[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) input_report_abs(dev, analog_hats[j++],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ((buttons >> ((i << 2) + 7)) & 1) - ((buttons >> ((i << 2) + 9)) & 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) input_report_abs(dev, analog_hats[j++],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ((buttons >> ((i << 2) + 8)) & 1) - ((buttons >> ((i << 2) + 6)) & 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * analog_cooked_read() reads analog joystick data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int analog_cooked_read(struct analog_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct gameport *gameport = port->gameport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u64 time[4], start, loop, now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned int loopout, timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) unsigned char data[4], this, last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) loopout = (ANALOG_LOOP_TIME * port->loop) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) timeout = ANALOG_MAX_TIME * port->speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) gameport_trigger(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) now = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) start = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) this = port->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) loop = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) last = this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) this = gameport_read(gameport) & port->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) now = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if ((last ^ this) && (delta(loop, now) < loopout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) data[i] = last ^ this;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) time[i] = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) } while (this && (i < 4) && (delta(start, now) < timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) this <<= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) for (--i; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) this |= data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (j = 0; j < 4; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (data[i] & (1 << j))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) port->axes[j] = (delta(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return -(this != port->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int analog_button_read(struct analog_port *port, char saitek, char chf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned char u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int t = 1, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int strobe = gameport_time(port->gameport, ANALOG_SAITEK_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u = gameport_read(port->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (!chf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) port->buttons = (~u >> 4) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) port->buttons = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) while ((~u & 0xf0) && (i < 16) && t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) port->buttons |= 1 << analog_chf[(~u >> 4) & 0xf];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!saitek) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) udelay(ANALOG_SAITEK_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) t = strobe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) gameport_trigger(port->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) while (((u = gameport_read(port->gameport)) & port->mask) && t) t--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -(!t || (i == 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * analog_poll() repeatedly polls the Analog joysticks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void analog_poll(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct analog_port *port = gameport_get_drvdata(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) char chf = !!(port->analog[0].mask & ANALOG_ANY_CHF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (port->cooked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) port->bads -= gameport_cooked_read(port->gameport, port->axes, &port->buttons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (chf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) port->buttons = port->buttons ? (1 << analog_chf[port->buttons]) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) port->reads++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (!port->axtime--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) port->bads -= analog_cooked_read(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) port->bads -= analog_button_read(port, saitek, chf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) port->reads++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) port->axtime = ANALOG_AXIS_TIME - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!saitek)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) analog_button_read(port, saitek, chf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (port->analog[i].mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * analog_open() is a callback from the input open routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static int analog_open(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct analog_port *port = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) gameport_start_polling(port->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * analog_close() is a callback from the input close routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static void analog_close(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct analog_port *port = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) gameport_stop_polling(port->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * analog_calibrate_timer() calibrates the timer and computes loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * and timeout values for a joystick port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void analog_calibrate_timer(struct analog_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct gameport *gameport = port->gameport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) unsigned int i, t, tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u64 t1, t2, t3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (use_ktime) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) port->speed = 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) t1 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) #ifdef FAKE_TIME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) analog_faketime += 830;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) t2 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) t3 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) port->speed = delta(t1, t2) - delta(t2, t3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tx = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) for (i = 0; i < 50; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) t1 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) for (t = 0; t < 50; t++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) gameport_read(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) t2 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) t3 = get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) udelay(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) t = delta(t1, t2) - delta(t2, t3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (t < tx) tx = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) port->loop = tx / 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * analog_name() constructs a name for an analog joystick.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static void analog_name(struct analog *analog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) snprintf(analog->name, sizeof(analog->name), "Analog %d-axis %d-button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) hweight8(analog->mask & ANALOG_AXES_STD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (analog->mask & ANALOG_HATS_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) snprintf(analog->name, sizeof(analog->name), "%s %d-hat",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (analog->mask & ANALOG_HAT_FCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) strlcat(analog->name, " FCS", sizeof(analog->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (analog->mask & ANALOG_ANY_CHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) strlcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) sizeof(analog->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) strlcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) sizeof(analog->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * analog_init_device()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int analog_init_device(struct analog_port *port, struct analog *analog, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int i, j, t, v, w, x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) analog_name(analog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) snprintf(analog->phys, sizeof(analog->phys),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) "%s/input%d", port->gameport->phys, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) analog->dev = input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!input_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) input_dev->name = analog->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) input_dev->phys = analog->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) input_dev->id.bustype = BUS_GAMEPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) input_dev->id.product = analog->mask >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) input_dev->id.version = 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) input_dev->dev.parent = &port->gameport->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) input_set_drvdata(input_dev, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) input_dev->open = analog_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) input_dev->close = analog_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) for (i = j = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (analog->mask & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) t = analog_axes[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) x = port->axes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) y = (port->axes[0] + port->axes[1]) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) z = y - port->axes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) z = z > 0 ? z : -z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) v = (x >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) w = (x >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) x = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (analog->mask & ANALOG_SAITEK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (i == 2) x = port->axes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) v = x - (x >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) w = (x >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) for (i = j = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (analog->mask & analog_exts[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) for (x = 0; x < 2; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) t = analog_hats[j++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) input_set_abs_params(input_dev, t, -1, 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for (i = j = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (analog->mask & (0x10 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) set_bit(analog->buttons[j++], input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (analog->mask & ANALOG_BTNS_CHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) set_bit(analog->buttons[j++], input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (analog->mask & ANALOG_HBTN_CHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) set_bit(analog->buttons[j++], input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (analog->mask & (ANALOG_BTN_TL << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) set_bit(analog_pads[i], input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) analog_decode(analog, port->axes, port->initial, port->buttons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) error = input_register_device(analog->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) input_free_device(analog->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * analog_init_devices() sets up device-specific values and registers the input devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static int analog_init_masks(struct analog_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct analog *analog = port->analog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int max[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!port->mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if ((port->mask & 3) != 3 && port->mask != 0xc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) printk(KERN_WARNING "analog.c: Unknown joystick device found "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) "(data=%#x, %s), probably not analog joystick.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) port->mask, port->gameport->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) i = analog_options[0]; /* FIXME !!! - need to specify options for different ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) analog[0].mask = i & 0xfffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) | port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) | ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) analog[0].mask &= ~(ANALOG_HAT2_CHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) | ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) | ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) | ((~analog[0].mask & ANALOG_HAT_FCS) << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) | ((~analog[0].mask & ANALOG_HAT_FCS) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) | (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) & ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) : (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (port->cooked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) gameport_calibrate(port->gameport, port->axes, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) port->initial[i] = port->axes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -!(analog[0].mask || analog[1].mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int i, t, u, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) port->gameport = gameport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) gameport_set_drvdata(gameport, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) analog_calibrate_timer(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) gameport_trigger(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) t = gameport_read(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) msleep(ANALOG_MAX_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) port->mask = (gameport_read(gameport) ^ t) & t & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!analog_cooked_read(port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) msleep(ANALOG_MAX_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) u = v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) msleep(ANALOG_MAX_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) gameport_trigger(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) while ((gameport_read(port->gameport) & port->mask) && (u < t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) u++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) udelay(ANALOG_SAITEK_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) t = gameport_time(gameport, ANALOG_SAITEK_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) gameport_trigger(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) while ((gameport_read(port->gameport) & port->mask) && (v < t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) v++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (v < (u >> 1)) { /* FIXME - more than one port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) analog_options[0] |= /* FIXME - more than one port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) gameport_close(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) for (i = 0; i < ANALOG_INIT_RETRIES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (port->axes[i] != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) port->mask |= 1 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) port->fuzz = gameport->fuzz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) port->cooked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct analog_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return - ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) err = analog_init_port(gameport, drv, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) err = analog_init_masks(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) gameport_set_poll_handler(gameport, analog_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) gameport_set_poll_interval(gameport, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (port->analog[i].mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) err = analog_init_device(port, port->analog + i, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto fail3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) fail3: while (--i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (port->analog[i].mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) input_unregister_device(port->analog[i].dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) fail2: gameport_close(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) fail1: gameport_set_drvdata(gameport, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) kfree(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static void analog_disconnect(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct analog_port *port = gameport_get_drvdata(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (port->analog[i].mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) input_unregister_device(port->analog[i].dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) gameport_close(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) gameport_set_drvdata(gameport, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) port->gameport->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) kfree(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct analog_types {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static struct analog_types analog_types[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) { "none", 0x00000000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) { "auto", 0x000000ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) { "2btn", 0x0000003f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) { "y-joy", 0x0cc00033 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) { "y-pad", 0x8cc80033 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) { "fcs", 0x000008f7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) { "chf", 0x000002ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) { "fullchf", 0x000007ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) { "gamepad", 0x000830f3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) { "gamepad8", 0x0008f0f3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) { NULL, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static void analog_parse_options(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) for (i = 0; i < js_nargs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) for (j = 0; analog_types[j].name; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!strcmp(analog_types[j].name, js[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) analog_options[i] = analog_types[j].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (analog_types[j].name) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) analog_options[i] = simple_strtoul(js[i], &end, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (end != js[i]) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) analog_options[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!strlen(js[i])) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) for (; i < ANALOG_PORTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) analog_options[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * The gameport device structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static struct gameport_driver analog_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .name = "analog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .description = DRIVER_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .connect = analog_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .disconnect = analog_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int __init analog_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) analog_parse_options();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return gameport_register_driver(&analog_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static void __exit analog_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) gameport_unregister_driver(&analog_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) module_init(analog_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) module_exit(analog_exit);