Commit f9b9ed00 authored by Jan Holthuis's avatar Jan Holthuis
Browse files

Linux: Adapt Linux Joystick implementation to InputHandler pattern

parent b0f79195
#if defined(USE_JOYSTICK)
#include "handler_linuxjs.h"
#include <cstring>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <linux/joystick.h>
#define LINUXJS_DEVICE_STRING "/dev/input/js%s"
void LinuxJoystickInputHandler::get_axis_limits(const InputAxisCode code, InputAxisLimits& limits)
{
// The Linux Joystick API's axes always normalized to this minimum/maximum
limits.minimum = -32767;
limits.maximum = 32767;
limits.deadzone = 0;
}
std::string LinuxJoystickInputHandler::get_api_name()
{
return "linuxjs";
}
bool LinuxJoystickInputHandler::setup_device(std::string device)
{
size_t size_needed = snprintf(NULL, 0, LINUXJS_DEVICE_STRING, device.c_str()) + 1;
char* linuxjs_fname = (char*)malloc(size_needed);
sprintf(linuxjs_fname, LINUXJS_DEVICE_STRING, device.c_str());
printf("linuxjs: Trying to open device '%s'\n", linuxjs_fname);
this->m_linuxjs_fd = open(linuxjs_fname, O_RDONLY);
if (this->m_linuxjs_fd < 0)
{
printf("linuxjs: Opening device '%s' failed - %s", linuxjs_fname, strerror(errno));
free(linuxjs_fname);
return false;
}
fcntl(this->m_linuxjs_fd, F_SETFL, O_NONBLOCK);
char device_name[256] = "Unknown";
int button_count = 0;
int axis_count = 0;
// Get device name
if(ioctl(this->m_linuxjs_fd, JSIOCGNAME(sizeof(device_name)), device_name) < 0)
{
printf("linuxjs: Getting name of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
free(linuxjs_fname);
return false;
}
// Get number of buttons
if(ioctl(this->m_linuxjs_fd, JSIOCGBUTTONS, &button_count) < 0)
{
printf("linuxjs: Getting button count of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
free(linuxjs_fname);
return false;
}
// Get number of axes
if(ioctl(this->m_linuxjs_fd, JSIOCGAXES, &axis_count) < 0)
{
printf("linuxjs: Getting axis count of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
free(linuxjs_fname);
return false;
}
printf("linuxjs: Found '%s' with %d axes and %d buttons at '%s'\n", device_name, axis_count, button_count, linuxjs_fname);
this->m_linuxjs_devname = std::string(device_name);
free(linuxjs_fname);
return true;
}
std::string LinuxJoystickInputHandler::get_default_mapping_filename()
{
if (this->m_linuxjs_devname.empty())
{
return "";
}
std::string mapping_filename;
if (strstr(this->m_linuxjs_devname.c_str(), "Microsoft X-Box 360 pad") != NULL ||
strstr(this->m_linuxjs_devname.c_str(), "Xbox Gamepad (userspace driver)") != NULL ||
strstr(this->m_linuxjs_devname.c_str(), "Xbox 360 Wireless Receiver") != NULL)
{
mapping_filename = "controller_xbox360.cfg";
}
else
{
mapping_filename = "controller_generic.cfg";
}
return mapping_filename;
}
void LinuxJoystickInputHandler::handle()
{
if (!this->is_initialized())
{
return;
}
struct js_event je;
while(read(this->m_linuxjs_fd, &je, sizeof(je)) == sizeof(je))
{
printf("linuxjs: type = %d - code = %d - value = %d\n", je.type, je.number, je.value);
switch(je.type)
{
case JS_EVENT_BUTTON:
{
this->handle_button(je.number, je.value);
break;
}
case JS_EVENT_AXIS:
{
this->handle_axis(je.number, je.value);
break;
}
}
}
}
#endif
\ No newline at end of file
#pragma once
#include "handler.h"
class LinuxJoystickInputHandler : public InputHandler
{
private:
int m_linuxjs_fd;
std::string m_linuxjs_devname;
void get_axis_limits(const InputAxisCode code, InputAxisLimits& limits);
public:
void handle();
std::string get_api_name();
std::string get_default_mapping_filename();
bool setup_device(std::string device);
};
\ 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_TRIGGER_LEFT, 0, 0, DC_AXIS_TRIGGER_RIGHT, DC_BTN_DPAD1_LEFT, DC_BTN_DPAD1_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 (mo==1)
{
rt[port] = JE.value ? 255 : 0;
}
}
}
break;
}
}
return true;
}
#endif
#include "types.h"
#include "linux-dist/main.h"
#pragma once
#define JOYSTICK_DEVICE_STRING "/dev/input/js%d"
#define JOYSTICK_DEFAULT_DEVICE_ID -1
#define JOYSTICK_MAP_SIZE 32
extern int input_joystick_init(const char* device);
extern bool input_joystick_handle(int fd, u32 port);
......@@ -37,7 +37,7 @@
#endif
#if defined(USE_JOYSTICK)
#include "linux-dist/joystick.h"
#include "linux-dist/handler_linuxjs.h"
#endif
#ifdef TARGET_PANDORA
......@@ -85,11 +85,6 @@ s8 joyx[4], joyy[4];
void emit_WriteCodeCache();
#if defined(USE_JOYSTICK)
/* legacy joystick input */
static int joystick_fd = -1; // Joystick file descriptor
#endif
static InputHandlerProxy input_handlers;
void SetupInput()
......@@ -137,17 +132,21 @@ void SetupInput()
#endif
#if defined(USE_JOYSTICK)
int joystick_device_id = cfgLoadInt("input", "joystick_device_id", JOYSTICK_DEFAULT_DEVICE_ID);
if (joystick_device_id < 0) {
puts("Legacy Joystick input disabled by config.\n");
#define JOYSTICK_DEFAULT_DEVICE_ID "-1"
std::string linuxjs_device;
std::string custom_mapping_filename = "";
linuxjs_device = cfgLoadStr("input", "joystick_device_id", JOYSTICK_DEFAULT_DEVICE_ID);
if (linuxjs_device.c_str()[0] == '-')
{
puts("LinuxJoystick input disabled by config.\n");
}
else
{
int joystick_device_length = snprintf(NULL, 0, JOYSTICK_DEVICE_STRING, joystick_device_id);
char* joystick_device = (char*)malloc(joystick_device_length + 1);
sprintf(joystick_device, JOYSTICK_DEVICE_STRING, joystick_device_id);
joystick_fd = input_joystick_init(joystick_device);
free(joystick_device);
LinuxJoystickInputHandler* handler = new LinuxJoystickInputHandler();
handler->initialize(0, linuxjs_device, custom_mapping_filename);
input_handlers.add(0, handler);
}
#endif
......@@ -168,10 +167,6 @@ void UpdateInputState(u32 port)
input_handlers.handle(port);
#if defined(USE_JOYSTICK)
input_joystick_handle(joystick_fd, port);
#endif
#if defined(USE_SDL)
input_sdl_handle(port);
#endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment