input: support for Wiimote, some tweaks for DS4.

This commit is contained in:
sorgelig
2019-05-01 01:57:29 +08:00
parent 4385e24989
commit 61383d1422

125
input.cpp
View File

@@ -970,11 +970,15 @@ uint32_t get_key_mod()
return modifier & MODMASK;
}
#define QUIRK_DS4TOUCH 1
#define QUIRK_WIIMOTE 2
typedef struct
{
uint16_t vid, pid;
uint8_t led;
uint8_t axis_state[256];
uint8_t axis_edge[256];
int8_t axis_pos[256];
uint8_t num;
uint8_t has_map;
@@ -988,6 +992,7 @@ typedef struct
uint8_t kbdmap[256];
int accx, accy;
int quirk;
int lightgun_req;
int lightgun;
@@ -1526,6 +1531,8 @@ static int ds_mouse_emu = 0;
static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev)
{
int sub_dev = dev;
//check if device is a part of multifunctional device
if (input[dev].bind >= 0) dev = input[dev].bind;
@@ -2082,18 +2089,39 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
case EV_ABS:
if (!user_io_osd_is_visible())
{
// TODO: implement inversion
int dead = 2;
if (input[dev].quirk == QUIRK_WIIMOTE)
{
if(ev->code == 3 || ev->code == 4) dead = 10;
}
//convert to 0..255 range
int value = (ev->value < absinfo->minimum) ? 0 : (ev->value > absinfo->maximum) ? 255 :
((ev->value - absinfo->minimum) * 256) / (absinfo->maximum - absinfo->minimum + 1);
int value = ev->value;
if (ev->value < absinfo->minimum) value = absinfo->minimum;
else if (ev->value > absinfo->maximum) value = absinfo->maximum;
value = (value < 127 || value>129 || input[dev].lightgun) ? value - 128 : 0;
// normalize to -range/2...+range/2
value = value - (absinfo->minimum + absinfo->maximum) / 2;
int hrange = (absinfo->maximum - absinfo->minimum) / 2;
if (value < -127) value = -127; // -128 is prohibited.
//printf("ABS: axis %d = %d -> %d\n", ev->code, ev->value, value);
if (ev->code > 1 || !input[dev].lightgun) //lightgun has no dead zone
{
// check the dead-zone and remove it from the range
hrange -= dead;
if (value < -dead) value += dead;
else if (value > dead) value -= dead;
else value = 0;
}
else if (ev->code == (input[dev].mmap[AXIS_MX] & 0xFFFF) && mouse_emu)
value = (value * 127) / hrange;
//final check to eliminate additive error
if (value < -127) value = -127;
else if (value > 127) value = 127;
if (input[sub_dev].axis_pos[ev->code & 0xFF] == (int8_t)value) break;
input[sub_dev].axis_pos[ev->code & 0xFF] = (int8_t)value;
if (ev->code == (input[dev].mmap[AXIS_MX] & 0xFFFF) && mouse_emu)
{
mouse_emu_x = 0;
if (value < -1 || value>1) mouse_emu_x = value;
@@ -2107,7 +2135,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
mouse_emu_y /= 12;
return;
}
else if (ev->code == (input[dev].mmap[AXIS_X] & 0xFFFF))
else if (ev->code == (input[dev].mmap[AXIS_X] & 0xFFFF) || (ev->code == 0 && input[dev].lightgun))
{
// skip if first joystick is not defined.
if (!input[dev].num) break;
@@ -2118,7 +2146,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
joy_analog(input[dev].num, 0, offset);
return;
}
else if (ev->code == (input[dev].mmap[AXIS_Y] & 0xFFFF))
else if (ev->code == (input[dev].mmap[AXIS_Y] & 0xFFFF) || (ev->code == 1 && input[dev].lightgun))
{
// skip if first joystick is not defined.
if (!input[dev].num) break;
@@ -2227,6 +2255,16 @@ int input_test(int getchar)
ioctl(pool[n].fd, EVIOCGUNIQ(sizeof(input[n].uniq)), input[n].uniq);
ioctl(pool[n].fd, EVIOCGNAME(sizeof(input[n].name)), input[n].name);
input[n].bind = -1;
if (strcasestr(input[n].name, "Wiimote"))
{
input[n].quirk = QUIRK_WIIMOTE;
input[n].lightgun = 1;
}
if (input[n].vid == 0x054c && (input[n].pid == 0x05c4 || input[n].pid == 0x09cc) && strcasestr(input[n].name, "Touchpad"))
{
input[n].quirk = QUIRK_DS4TOUCH;
}
n++;
if (n >= NUMDEV) break;
@@ -2252,7 +2290,7 @@ int input_test(int getchar)
for (int i = 0; i < n; i++)
{
printf("opened %d(%2d): %s (%04x:%04x) \"%s\" \"%s\"\n", i, input[i].bind, input[i].devname, input[i].vid, input[i].pid, input[i].uniq, input[i].name);
printf("opened %d(%2d): %s (%04x:%04x) %d \"%s\" \"%s\"\n", i, input[i].bind, input[i].devname, input[i].vid, input[i].pid, input[i].quirk, input[i].uniq, input[i].name);
}
}
cur_leds |= 0x80;
@@ -2312,7 +2350,7 @@ int input_test(int getchar)
if (ev.type == EV_ABS)
{
//Dualshock: drop accelerator and raw touchpad events
if (ds_ver == 4 && ev.code == 57)
if (input[i].quirk == QUIRK_DS4TOUCH && ev.code == 57)
{
input[dev].lightgun_req = (ev.value >= 0);
}
@@ -2324,22 +2362,21 @@ int input_test(int getchar)
//DS4 specific: touchpad as lightgun
if (ds_ver == 4 && ev.code <= 1)
{
if (absinfo.maximum > 255)
if (input[i].quirk == QUIRK_DS4TOUCH)
{
if (!input[dev].lightgun || user_io_osd_is_visible()) continue;
if (ev.code == 1)
{
absinfo.minimum = 300;
absinfo.maximum = 850;
}
if (ev.code == 0)
else if (ev.code == 0)
{
absinfo.minimum = 200;
absinfo.maximum = 1720;
}
//DS4: drop mapped touchpad events.
if (!input[dev].lightgun) continue;
else continue;
}
else
{
@@ -2347,6 +2384,15 @@ int input_test(int getchar)
}
}
}
if (input[i].quirk == QUIRK_WIIMOTE)
{
if (ev.code == 3 || ev.code == 4)
{
absinfo.minimum = 30;
absinfo.maximum = 225;
}
}
}
//Menu combo on 8BitDo receiver in PSC mode
@@ -2431,16 +2477,25 @@ int input_test(int getchar)
}
}
if(!noabs) input_cb(&ev, &absinfo, dev);
if (input[i].quirk == QUIRK_WIIMOTE && ev.type == EV_ABS)
{
if (ev.code <= 1 && user_io_osd_is_visible())
{
// don't pass IR tracking to OSD
continue;
}
}
if(!noabs) input_cb(&ev, &absinfo, i);
//sumulate digital directions from analog
if (ev.type == EV_ABS && !(mapping && mapping_type<=1 && mapping_button<-4) && (user_io_osd_is_visible() || !input[dev].lightgun))
if (ev.type == EV_ABS && !(mapping && mapping_type<=1 && mapping_button<-4) && (user_io_osd_is_visible() || !(ev.code<=1 && input[dev].lightgun)))
{
uint8_t axis_state = 0;
uint8_t axis_edge = 0;
if ((absinfo.maximum == 1 && absinfo.minimum == -1) || (absinfo.maximum == 2 && absinfo.minimum == 0))
{
if (ev.value == absinfo.minimum) axis_state = 1;
if (ev.value == absinfo.maximum) axis_state = 2;
if (ev.value == absinfo.minimum) axis_edge = 1;
if (ev.value == absinfo.maximum) axis_edge = 2;
}
else
{
@@ -2451,15 +2506,15 @@ int input_test(int getchar)
int only_max = 1;
for (int n = 0; n < 4; n++) if (input[dev].mmap[AXIS1_X + n] && ((input[dev].mmap[AXIS1_X + n] & 0xFFFF) == ev.code)) only_max = 0;
if (ev.value < center - treshold && !only_max) axis_state = 1;
if (ev.value > center + treshold) axis_state = 2;
if (ev.value < center - treshold && !only_max) axis_edge = 1;
if (ev.value > center + treshold) axis_edge = 2;
}
uint8_t last_state = input[dev].axis_state[ev.code & 255];
input[dev].axis_state[ev.code & 255] = axis_state;
uint8_t last_state = input[dev].axis_edge[ev.code & 255];
input[dev].axis_edge[ev.code & 255] = axis_edge;
//printf("last_state=%d, axis_state=%d\n", last_state, axis_state);
if (last_state != axis_state)
//printf("last_state=%d, axis_edge=%d\n", last_state, axis_edge);
if (last_state != axis_edge)
{
uint16_t ecode = KEY_EMU + (ev.code << 1) - 1;
ev.type = EV_KEY;
@@ -2467,14 +2522,14 @@ int input_test(int getchar)
{
ev.value = 0;
ev.code = ecode + last_state;
input_cb(&ev, 0, dev);
input_cb(&ev, 0, i);
}
if (axis_state)
if (axis_edge)
{
ev.value = 1;
ev.code = ecode + axis_state;
input_cb(&ev, 0, dev);
ev.code = ecode + axis_edge;
input_cb(&ev, 0, i);
}
}
@@ -2483,7 +2538,7 @@ int input_test(int getchar)
{
ev.type = EV_KEY;
ev.code = KEY_EMU + (ev.code << 1);
input_cb(&ev, &absinfo, dev);
input_cb(&ev, &absinfo, i);
}
}
}