Commit 6bfa831e authored by Jan Holthuis's avatar Jan Holthuis
Browse files

Merge pull request #752 from reicast/holzhaus/linux-input-overhaul

Linux Input overhaul (Better evdev input & multiplayer support)
parents 6137152f 1661c236
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include "linux-dist/evdev.h"
#include "linux-dist/main.h"
#if defined(USE_EVDEV)
int input_evdev_init(Controller* controller, const char* device)
{
char name[256] = "Unknown";
printf("evdev: Trying to open device at '%s'\n", device);
int fd = open(device, O_RDONLY);
if (fd >= 0)
{
fcntl(fd, F_SETFL, O_NONBLOCK);
if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)
{
perror("evdev: ioctl");
return -2;
}
else
{
printf("evdev: Found '%s' at '%s'\n", name, device);
controller->fd = fd;
#if defined(TARGET_PANDORA)
*controller.mapping = &controller_mapping_pandora;
#elif defined(TARGET_GCW0)
*controller.mapping = &controller_mapping_gcwz;
#else
if (strcmp(name, "Microsoft X-Box 360 pad") == 0 ||
strcmp(name, "Xbox 360 Wireless Receiver") == 0 ||
strcmp(name, "Xbox 360 Wireless Receiver (XBOX)") == 0)
{
controller->mapping = &controller_mapping_xpad;
}
else if (strstr(name, "Xbox Gamepad (userspace driver)") != NULL)
{
controller->mapping = &controller_mapping_xboxdrv;
}
else if (strstr(name, "keyboard") != NULL ||
strstr(name, "Keyboard") != NULL)
{
controller->mapping = &controller_mapping_keyboard;
}
else
{
controller->mapping = &controller_mapping_generic;
}
#endif
printf("evdev: Using '%s' mapping\n", controller->mapping->name);
return 0;
}
}
else
{
perror("evdev: open");
return -1;
}
}
bool input_evdev_handle(Controller* controller, u32 port)
{
#define SET_FLAG(field, mask, expr) field =((expr) ? (field & ~mask) : (field | mask))
if (controller->fd < 0 || controller->mapping == NULL)
{
return false;
}
input_event ie;
while(read(controller->fd, &ie, sizeof(ie)) == sizeof(ie))
{
if(ie.type != EV_SYN && ie.type != EV_MSC)
{
printf("type %i key %i state %i\n", ie.type, ie.code, ie.value);
}
switch(ie.type)
{
case EV_KEY:
if (ie.code == controller->mapping->Btn_A) {
SET_FLAG(kcode[port], DC_BTN_A, ie.value);
} else if (ie.code == controller->mapping->Btn_B) {
SET_FLAG(kcode[port], DC_BTN_B, ie.value);
} else if (ie.code == controller->mapping->Btn_C) {
SET_FLAG(kcode[port], DC_BTN_C, ie.value);
} else if (ie.code == controller->mapping->Btn_D) {
SET_FLAG(kcode[port], DC_BTN_D, ie.value);
} else if (ie.code == controller->mapping->Btn_X) {
SET_FLAG(kcode[port], DC_BTN_X, ie.value);
} else if (ie.code == controller->mapping->Btn_Y) {
SET_FLAG(kcode[port], DC_BTN_Y, ie.value);
} else if (ie.code == controller->mapping->Btn_Z) {
SET_FLAG(kcode[port], DC_BTN_Z, ie.value);
} else if (ie.code == controller->mapping->Btn_Start) {
SET_FLAG(kcode[port], DC_BTN_START, ie.value);
} else if (ie.code == controller->mapping->Btn_Escape) {
die("death by escape key");
} else if (ie.code == controller->mapping->Btn_DPad_Left) {
SET_FLAG(kcode[port], DC_DPAD_LEFT, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad_Right) {
SET_FLAG(kcode[port], DC_DPAD_RIGHT, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad_Up) {
SET_FLAG(kcode[port], DC_DPAD_UP, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad_Down) {
SET_FLAG(kcode[port], DC_DPAD_DOWN, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad2_Left) {
SET_FLAG(kcode[port], DC_DPAD2_LEFT, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad2_Right) {
SET_FLAG(kcode[port], DC_DPAD2_RIGHT, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad2_Up) {
SET_FLAG(kcode[port], DC_DPAD2_UP, ie.value);
} else if (ie.code == controller->mapping->Btn_DPad2_Down) {
SET_FLAG(kcode[port], DC_DPAD2_DOWN, ie.value);
} else if (ie.code == controller->mapping->Btn_Trigger_Left) {
lt[port] = (ie.value ? 255 : 0);
} else if (ie.code == controller->mapping->Btn_Trigger_Right) {
rt[port] = (ie.value ? 255 : 0);
}
break;
case EV_ABS:
if (ie.code == controller->mapping->Axis_DPad_X) {
switch(ie.value)
{
case -1:
SET_FLAG(kcode[port], DC_DPAD_LEFT, 1);
SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
break;
case 0:
SET_FLAG(kcode[port], DC_DPAD_LEFT, 0);
SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
break;
case 1:
SET_FLAG(kcode[port], DC_DPAD_LEFT, 0);
SET_FLAG(kcode[port], DC_DPAD_RIGHT, 1);
break;
}
} else if (ie.code == controller->mapping->Axis_DPad_Y) {
switch(ie.value)
{
case -1:
SET_FLAG(kcode[port], DC_DPAD_UP, 1);
SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
break;
case 0:
SET_FLAG(kcode[port], DC_DPAD_UP, 0);
SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
break;
case 1:
SET_FLAG(kcode[port], DC_DPAD_UP, 0);
SET_FLAG(kcode[port], DC_DPAD_DOWN, 1);
break;
}
} else if (ie.code == controller->mapping->Axis_DPad2_X) {
switch(ie.value)
{
case -1:
SET_FLAG(kcode[port], DC_DPAD2_LEFT, 1);
SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
break;
case 0:
SET_FLAG(kcode[port], DC_DPAD2_LEFT, 0);
SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
break;
case 1:
SET_FLAG(kcode[port], DC_DPAD2_LEFT, 0);
SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 1);
break;
}
} else if (ie.code == controller->mapping->Axis_DPad2_X) {
switch(ie.value)
{
case -1:
SET_FLAG(kcode[port], DC_DPAD2_UP, 1);
SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
break;
case 0:
SET_FLAG(kcode[port], DC_DPAD2_UP, 0);
SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
break;
case 1:
SET_FLAG(kcode[port], DC_DPAD2_UP, 0);
SET_FLAG(kcode[port], DC_DPAD2_DOWN, 1);
break;
}
} else if (ie.code == controller->mapping->Axis_Analog_X) {
printf("%d", ie.value);
joyx[port] = (s8)(ie.value/256);
} else if (ie.code == controller->mapping->Axis_Analog_Y) {
joyy[port] = (s8)(ie.value/256);
} else if (ie.code == controller->mapping->Axis_Trigger_Left) {
lt[port] = (s8)ie.value;
} else if (ie.code == controller->mapping->Axis_Trigger_Right) {
rt[port] = (s8)ie.value;
}
break;
}
}
}
#endif
\ No newline at end of file
#include "types.h"
#include "linux-dist/evdev_mappings.h"
#pragma once
struct s_controller
{
int fd;
ControllerMapping* mapping;
};
typedef struct s_controller Controller;
#define EVDEV_DEVICE_STRING "/dev/input/event%d"
#ifdef TARGET_PANDORA
#define EVDEV_DEFAULT_DEVICE_ID_1 4
#else
#define EVDEV_DEFAULT_DEVICE_ID_1 0
#endif
#define EVDEV_DEFAULT_DEVICE_ID(port) (port == 1 ? EVDEV_DEFAULT_DEVICE_ID_1 : -1)
extern int input_evdev_init(Controller* controller, const char* device);
extern bool input_evdev_handle(Controller* controller, u32 port);
\ No newline at end of file
#include "linux-dist/evdev_mappings.h"
#if defined(USE_EVDEV)
ControllerMapping controller_mapping_generic = {
"Generic Controller",
BTN_A,
BTN_B,
BTN_C,
BTN_THUMBL,
BTN_X,
BTN_Y,
BTN_Z,
BTN_START,
BTN_SELECT,
BTN_DPAD_LEFT,
BTN_DPAD_RIGHT,
BTN_DPAD_UP,
BTN_DPAD_DOWN,
-1,
-1,
-1,
-1,
BTN_TL,
BTN_TR,
ABS_HAT0X,
ABS_HAT0Y,
ABS_HAT1X,
ABS_HAT1Y,
ABS_X,
ABS_Y,
ABS_Z,
ABS_RZ,
};
ControllerMapping controller_mapping_keyboard = {
"Generic Keyboard",
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_X,
KEY_Y,
KEY_Z,
KEY_ENTER,
KEY_ESC,
KEY_LEFT,
KEY_RIGHT,
KEY_UP,
KEY_DOWN,
-1,
-1,
-1,
-1,
KEY_LEFTCTRL,
KEY_RIGHTCTRL,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
};
ControllerMapping controller_mapping_xpad = {
"Xbox 360 Controller (xpad driver)",
BTN_A,
BTN_B,
BTN_TL,
BTN_TR,
BTN_X,
BTN_Y,
BTN_THUMBL,
BTN_START,
BTN_SELECT,
BTN_TRIGGER_HAPPY1,
BTN_TRIGGER_HAPPY2,
BTN_TRIGGER_HAPPY3,
BTN_TRIGGER_HAPPY4,
-1,
-1,
-1,
-1,
-1,
-1,
ABS_HAT0X,
ABS_HAT0Y,
ABS_HAT1X,
ABS_HAT1Y,
ABS_X,
ABS_Y,
ABS_Z,
ABS_RZ
};
ControllerMapping controller_mapping_xboxdrv = {
"Xbox 360 Controller (xboxdrv userspace driver)",
BTN_A,
BTN_B,
BTN_TL,
BTN_TR,
BTN_X,
BTN_Y,
BTN_THUMBL,
BTN_START,
BTN_SELECT,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
ABS_HAT0X,
ABS_HAT0Y,
ABS_HAT1X,
ABS_HAT1Y,
ABS_X,
ABS_Y,
ABS_BRAKE,
ABS_GAS
};
ControllerMapping controller_mapping_gcwz = {
"GCW Zero",
0x1D, // GCWZ_BTN_A
0x38, // GCWZ_BTN_B
0x0F, // GCWZ_BTN_L
0x0E, // GCWZ_BTN_R
0x2A, // GCWZ_BTN_X
0x39, // GCWZ_BTN_Y
-1,
0x1C, // GCWZ_BTN_START
0x01, // GCWZ_BTN_SELECT
0x69, // GCWZ_BTN_LEFT
0x6A, // GCWZ_BTN_RIGHT
0x67, // GCWZ_BTN_UP
0x6C, // GCWZ_BTN_DOWN
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
};
ControllerMapping controller_mapping_pandora = {
"Pandora",
KEY_PAGEDOWN,
KEY_END,
KEY_SPACE,
-1,
KEY_HOME,
KEY_PAGEUP,
-1,
KEY_LEFTALT,
KEY_MENU,
KEY_LEFT,
KEY_RIGHT,
KEY_UP,
KEY_DOWN,
-1,
-1,
-1,
-1,
KEY_RIGHTSHIFT,
KEY_RIGHTCTRL,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
};
#endif
\ No newline at end of file
#include <linux/input.h>
#pragma once
struct s_evdev_controller_mapping
{
const char* name;
const int Btn_A;
const int Btn_B;
const int Btn_C;
const int Btn_D;
const int Btn_X;
const int Btn_Y;
const int Btn_Z;
const int Btn_Start;
const int Btn_Escape;
const int Btn_DPad_Left;
const int Btn_DPad_Right;
const int Btn_DPad_Up;
const int Btn_DPad_Down;
const int Btn_DPad2_Left;
const int Btn_DPad2_Right;
const int Btn_DPad2_Up;
const int Btn_DPad2_Down;
const int Btn_Trigger_Left;
const int Btn_Trigger_Right;
const int Axis_DPad_X;
const int Axis_DPad_Y;
const int Axis_DPad2_X;
const int Axis_DPad2_Y;
const int Axis_Analog_X;
const int Axis_Analog_Y;
const int Axis_Trigger_Left;
const int Axis_Trigger_Right;
};
typedef struct s_evdev_controller_mapping ControllerMapping;
extern ControllerMapping controller_mapping_generic;
extern ControllerMapping controller_mapping_keyboard;
extern ControllerMapping controller_mapping_xpad;
extern ControllerMapping controller_mapping_xboxdrv;
extern ControllerMapping controller_mapping_gcwz;
extern ControllerMapping controller_mapping_pandora;
\ No newline at end of file
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/joystick.h>
#include "linux-dist/joystick.h"
#if defined(USE_JOYSTICK)
const u32 joystick_map_btn_usb[JOYSTICK_MAP_SIZE] = { DC_BTN_Y, DC_BTN_B, DC_BTN_A, DC_BTN_X, 0, 0, 0, 0, 0, DC_BTN_START };
const u32 joystick_map_axis_usb[JOYSTICK_MAP_SIZE] = { DC_AXIS_X, DC_AXIS_Y, 0, 0, 0, 0, 0, 0, 0, 0 };
const u32 joystick_map_btn_xbox360[JOYSTICK_MAP_SIZE] = { DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, 0, 0, 0, DC_BTN_START, 0, 0 };
const u32 joystick_map_axis_xbox360[JOYSTICK_MAP_SIZE] = { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_DPAD_LEFT, DC_DPAD_UP, 0, 0 };
const u32* joystick_map_btn = joystick_map_btn_usb;
const u32* joystick_map_axis = joystick_map_axis_usb;
int input_joystick_init(const char* device)
{
int axis_count = 0;
int button_count = 0;
char name[128] = "Unknown";
printf("joystick: Trying to open device at '%s'\n", device);
int fd = open(device, O_RDONLY);
if(fd >= 0)
{
fcntl(fd, F_SETFL, O_NONBLOCK);
ioctl(fd, JSIOCGAXES, &axis_count);
ioctl(fd, JSIOCGBUTTONS, &button_count);
ioctl(fd, JSIOCGNAME(sizeof(name)), &name);
printf("joystick: Found '%s' with %d axis and %d buttons at '%s'.\n", name, axis_count, button_count, device);
if (strcmp(name, "Microsoft X-Box 360 pad") == 0 ||
strcmp(name, "Xbox Gamepad (userspace driver)") == 0 ||
strcmp(name, "Xbox 360 Wireless Receiver (XBOX)") == 0)
{
joystick_map_btn = joystick_map_btn_xbox360;
joystick_map_axis = joystick_map_axis_xbox360;
printf("joystick: Using Xbox 360 map\n");
}
}
else
{
perror("joystick open");
}
return fd;
}
bool input_joystick_handle(int fd, u32 port)
{
// Joystick must be connected
if(fd < 0) {
return false;
}
struct js_event JE;
while(read(fd, &JE, sizeof(JE)) == sizeof(JE))
if (JE.number < JOYSTICK_MAP_SIZE)
{
switch(JE.type & ~JS_EVENT_INIT)
{
case JS_EVENT_AXIS:
{
u32 mt = joystick_map_axis[JE.number] >> 16;
u32 mo = joystick_map_axis[JE.number] & 0xFFFF;
//printf("AXIS %d,%d\n",JE.number,JE.value);
s8 v=(s8)(JE.value/256); //-127 ... + 127 range
if (mt == 0)
{
kcode[port] |= mo;
kcode[port] |= mo*2;
if (v<-64)
{
kcode[port] &= ~mo;
}
else if (v>64)
{
kcode[port] &= ~(mo*2);
}
//printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
}
else if (mt == 1)
{
if (v >= 0)
{
v++; //up to 255
}
//printf("AXIS %d,%d Mapped to %d %d %d\n",JE.number,JE.value,mo,v,v+127);
if (mo == 0)
{
lt[port] = (v + 127);
}
else if (mo == 1)
{
rt[port] = (v + 127);
}
}
else if (mt == 2)
{
// printf("AXIS %d,%d Mapped to %d %d [%d]",JE.number,JE.value,mo,v);
if (mo == 0)
{
joyx[port] = v;
}
else if (mo == 1)
{
joyy[port] = v;
}
}
}
break;
case JS_EVENT_BUTTON:
{
u32 mt = joystick_map_btn[JE.number] >> 16;
u32 mo = joystick_map_btn[JE.number] & 0xFFFF;
// printf("BUTTON %d,%d\n",JE.number,JE.value);
if (mt == 0)
{
// printf("Mapped to %d\n",mo);
if (JE.value)
{
kcode[port] &= ~mo;
}
else
{
kcode[port] |= mo;
}
}
else if (mt == 1)
{
// printf("Mapped to %d %d\n",mo,JE.value?255:0);
if (mo==0)
{
lt[port] = JE.value ? 255 : 0;
}
else if (