Reinitialize gamepads command and fix EVDEV going bonkers on gamepad suddenly disconnecting
This commit is contained in:
parent
c68048d029
commit
5ddf119ef0
9 changed files with 71 additions and 31 deletions
|
@ -32,12 +32,6 @@ void joystick_driver_init() throw();
|
||||||
* - Implemented by the joystick plugin.
|
* - Implemented by the joystick plugin.
|
||||||
*/
|
*/
|
||||||
void joystick_driver_quit() throw();
|
void joystick_driver_quit() throw();
|
||||||
/**
|
|
||||||
* This thread becomes the joystick polling thread.
|
|
||||||
*
|
|
||||||
* - Called in joystick polling thread.
|
|
||||||
*/
|
|
||||||
void joystick_driver_thread_fn() throw();
|
|
||||||
/**
|
/**
|
||||||
* Signal the joystick thread to quit.
|
* Signal the joystick thread to quit.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -127,6 +127,7 @@ public:
|
||||||
void set_axismode_cb(std::function<void(unsigned jnum, unsigned num, int mode, double tolerance)> fn);
|
void set_axismode_cb(std::function<void(unsigned jnum, unsigned num, int mode, double tolerance)> fn);
|
||||||
void set_newitem_cb(std::function<void(unsigned jnum, unsigned num, int type)> fn);
|
void set_newitem_cb(std::function<void(unsigned jnum, unsigned num, int type)> fn);
|
||||||
std::string get_summary();
|
std::string get_summary();
|
||||||
|
void offline_all();
|
||||||
private:
|
private:
|
||||||
set(const set&);
|
set(const set&);
|
||||||
set& operator=(const set&);
|
set& operator=(const set&);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
threads::thread* joystick_thread_handle;
|
||||||
void dummy_init() throw() {}
|
void dummy_init() throw() {}
|
||||||
void dummy_quit() throw() {}
|
void dummy_quit() throw() {}
|
||||||
void dummy_thread_fn() throw() {}
|
void dummy_thread_fn() throw() {}
|
||||||
|
@ -16,6 +17,12 @@ namespace
|
||||||
.signal = dummy_signal,
|
.signal = dummy_signal,
|
||||||
.name = dummy_name
|
.name = dummy_name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void* joystick_thread(int _args)
|
||||||
|
{
|
||||||
|
driver.thread_fn();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joystick_driver::joystick_driver(_joystick_driver drv)
|
joystick_driver::joystick_driver(_joystick_driver drv)
|
||||||
|
@ -27,19 +34,17 @@ void joystick_driver_init() throw()
|
||||||
{
|
{
|
||||||
lsnes_gamepads_init();
|
lsnes_gamepads_init();
|
||||||
driver.init();
|
driver.init();
|
||||||
|
joystick_thread_handle = new threads::thread(joystick_thread, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void joystick_driver_quit() throw()
|
void joystick_driver_quit() throw()
|
||||||
{
|
{
|
||||||
driver.quit();
|
driver.quit();
|
||||||
|
joystick_thread_handle->join();
|
||||||
|
joystick_thread_handle = NULL;
|
||||||
lsnes_gamepads_deinit();
|
lsnes_gamepads_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void joystick_driver_thread_fn() throw()
|
|
||||||
{
|
|
||||||
driver.thread_fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void joystick_driver_signal() throw()
|
void joystick_driver_signal() throw()
|
||||||
{
|
{
|
||||||
driver.signal();
|
driver.signal();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "core/command.hpp"
|
#include "core/command.hpp"
|
||||||
#include "core/instance.hpp"
|
#include "core/instance.hpp"
|
||||||
|
#include "core/joystickapi.hpp"
|
||||||
#include "core/keymapper.hpp"
|
#include "core/keymapper.hpp"
|
||||||
#include "core/memorymanip.hpp"
|
#include "core/memorymanip.hpp"
|
||||||
#include "core/messages.hpp"
|
#include "core/messages.hpp"
|
||||||
|
@ -104,4 +105,14 @@ namespace
|
||||||
messages << lsnes_gamepads.get_summary() << std::endl;
|
messages << lsnes_gamepads.get_summary() << std::endl;
|
||||||
messages << "--------------------------------------------" << std::endl;
|
messages << "--------------------------------------------" << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
command::fnptr<> reset_joysticks(lsnes_cmds, "reset-gamepads", "Reset gamepads",
|
||||||
|
"Syntax: reset-gamepads\nResets gamepads.\n",
|
||||||
|
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||||
|
joystick_driver_quit();
|
||||||
|
lsnes_gamepads.offline_all(); //Not supposed to have online gamepads.
|
||||||
|
joystick_driver_init();
|
||||||
|
messages << "Reset gamepads" << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -724,6 +724,15 @@ unsigned set::add(const std::string& name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set::offline_all()
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < _gamepads.size(); i++) {
|
||||||
|
if(_gamepads[i]->online()) {
|
||||||
|
_gamepads[i]->set_online(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void set::set_axis_cb(std::function<void(unsigned jnum, unsigned num, int16_t val)> fn)
|
void set::set_axis_cb(std::function<void(unsigned jnum, unsigned num, int16_t val)> fn)
|
||||||
{
|
{
|
||||||
threads::alock h(mlock);
|
threads::alock h(mlock);
|
||||||
|
|
|
@ -169,22 +169,24 @@ namespace
|
||||||
|
|
||||||
std::map<int, unsigned> gamepad_map;
|
std::map<int, unsigned> gamepad_map;
|
||||||
|
|
||||||
bool read_one_input_event(int fd)
|
int read_one_input_event(int fd)
|
||||||
{
|
{
|
||||||
struct input_event ev;
|
struct input_event ev;
|
||||||
int r = read(fd, &ev, sizeof(ev));
|
int r = read(fd, &ev, sizeof(ev));
|
||||||
if(r < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
if(r < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
||||||
return false;
|
return 0;
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
|
if(errno == ENODEV)
|
||||||
|
return -1; //Disconnected.
|
||||||
messages << "Error reading from joystick (fd=" << fd << "): " << strerror(errno)
|
messages << "Error reading from joystick (fd=" << fd << "): " << strerror(errno)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
if(ev.type == EV_KEY)
|
if(ev.type == EV_KEY)
|
||||||
lsnes_gamepads[gamepad_map[fd]].report_button(ev.code, ev.value != 0);
|
lsnes_gamepads[gamepad_map[fd]].report_button(ev.code, ev.value != 0);
|
||||||
if(ev.type == EV_ABS)
|
if(ev.type == EV_ABS)
|
||||||
lsnes_gamepads[gamepad_map[fd]].report_axis(ev.code, ev.value);
|
lsnes_gamepads[gamepad_map[fd]].report_axis(ev.code, ev.value);
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool probe_joystick(int fd, const std::string& filename)
|
bool probe_joystick(int fd, const std::string& filename)
|
||||||
|
@ -283,6 +285,8 @@ namespace
|
||||||
|
|
||||||
struct _joystick_driver drv = {
|
struct _joystick_driver drv = {
|
||||||
.init = []() -> void {
|
.init = []() -> void {
|
||||||
|
quit_signaled = false;
|
||||||
|
quit_ack = false;
|
||||||
probe_all_joysticks();
|
probe_all_joysticks();
|
||||||
quit_ack = quit_signaled = false;
|
quit_ack = quit_signaled = false;
|
||||||
},
|
},
|
||||||
|
@ -309,10 +313,35 @@ namespace
|
||||||
int r = select(limit, &rfds, NULL, NULL, &tv);
|
int r = select(limit, &rfds, NULL, NULL, &tv);
|
||||||
if(r <= 0)
|
if(r <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
std::set<int> cleanup;
|
||||||
for(auto fd : gamepad_map)
|
for(auto fd : gamepad_map)
|
||||||
if(FD_ISSET(fd.first, &rfds))
|
if(FD_ISSET(fd.first, &rfds)) {
|
||||||
while(read_one_input_event(fd.first));
|
while(true) {
|
||||||
|
int r = read_one_input_event(fd.first);
|
||||||
|
if(!r)
|
||||||
|
break;
|
||||||
|
if(r < 0) {
|
||||||
|
cleanup.insert(fd.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto i : cleanup) {
|
||||||
|
unsigned jid = gamepad_map[i];
|
||||||
|
close(i);
|
||||||
|
gamepad_map.erase(i);
|
||||||
|
lsnes_gamepads[jid].set_online(false);
|
||||||
|
messages << "Gamepad #" << jid << "[" << lsnes_gamepads[jid].name()
|
||||||
|
<< "] disconnected." << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//Get rid of joystick handles.
|
||||||
|
for(auto fd : gamepad_map) {
|
||||||
|
close(fd.first);
|
||||||
|
lsnes_gamepads[fd.second].set_online(false);
|
||||||
|
}
|
||||||
|
gamepad_map.clear();
|
||||||
|
|
||||||
quit_ack = true;
|
quit_ack = true;
|
||||||
},
|
},
|
||||||
.signal = []() -> void {
|
.signal = []() -> void {
|
||||||
|
|
|
@ -38,6 +38,8 @@ namespace
|
||||||
|
|
||||||
struct _joystick_driver drv = {
|
struct _joystick_driver drv = {
|
||||||
.init = []() -> void {
|
.init = []() -> void {
|
||||||
|
quit_signaled = false;
|
||||||
|
quit_ack = false;
|
||||||
int jcnt = SDL_SYS_JoystickInit();
|
int jcnt = SDL_SYS_JoystickInit();
|
||||||
if(jcnt < 0)
|
if(jcnt < 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace
|
||||||
|
|
||||||
struct _joystick_driver drv = {
|
struct _joystick_driver drv = {
|
||||||
.init = []() -> void {
|
.init = []() -> void {
|
||||||
|
quit_signaled = false;
|
||||||
|
quit_ack = false;
|
||||||
unsigned max_joysticks = joyGetNumDevs();
|
unsigned max_joysticks = joyGetNumDevs();
|
||||||
if(!max_joysticks)
|
if(!max_joysticks)
|
||||||
return; //No joystick support.
|
return; //No joystick support.
|
||||||
|
|
|
@ -67,18 +67,11 @@ namespace
|
||||||
volatile bool modal_dialog_active;
|
volatile bool modal_dialog_active;
|
||||||
threads::lock ui_mutex;
|
threads::lock ui_mutex;
|
||||||
threads::cv ui_condition;
|
threads::cv ui_condition;
|
||||||
threads::thread* joystick_thread_handle;
|
|
||||||
bool if_update_messages = false;
|
bool if_update_messages = false;
|
||||||
bool if_update_screen = false;
|
bool if_update_screen = false;
|
||||||
bool if_update_status = false;
|
bool if_update_status = false;
|
||||||
threads::lock if_mutex;
|
threads::lock if_mutex;
|
||||||
|
|
||||||
void* joystick_thread(int _args)
|
|
||||||
{
|
|
||||||
joystick_driver_thread_fn();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uiserv_event : public wxEvent
|
struct uiserv_event : public wxEvent
|
||||||
{
|
{
|
||||||
uiserv_event(int code)
|
uiserv_event(int code)
|
||||||
|
@ -516,12 +509,10 @@ bool lsnes_app::OnInit()
|
||||||
if(settings_mode) {
|
if(settings_mode) {
|
||||||
//We got to boot this up quite a bit to get the joystick driver working.
|
//We got to boot this up quite a bit to get the joystick driver working.
|
||||||
//In practicular, we need joystick thread and emulator thread in pause.
|
//In practicular, we need joystick thread and emulator thread in pause.
|
||||||
joystick_thread_handle = new threads::thread(joystick_thread, 6);
|
|
||||||
threads::thread* dummy_loop = new threads::thread(eloop_helper, 8);
|
threads::thread* dummy_loop = new threads::thread(eloop_helper, 8);
|
||||||
display_settings_dialog(NULL, lsnes_instance, NULL);
|
display_settings_dialog(NULL, lsnes_instance, NULL);
|
||||||
platform::exit_dummy_event_loop();
|
platform::exit_dummy_event_loop();
|
||||||
joystick_driver_signal();
|
joystick_driver_quit();
|
||||||
joystick_thread_handle->join();
|
|
||||||
dummy_loop->join();
|
dummy_loop->join();
|
||||||
save_configuration();
|
save_configuration();
|
||||||
return false;
|
return false;
|
||||||
|
@ -529,8 +520,6 @@ bool lsnes_app::OnInit()
|
||||||
init_lua();
|
init_lua();
|
||||||
lsnes_instance.mdumper->set_output(&messages.getstream());
|
lsnes_instance.mdumper->set_output(&messages.getstream());
|
||||||
|
|
||||||
joystick_thread_handle = new threads::thread(joystick_thread, 7);
|
|
||||||
|
|
||||||
msg_window = new wxwin_messages(lsnes_instance);
|
msg_window = new wxwin_messages(lsnes_instance);
|
||||||
msg_window->Show();
|
msg_window->Show();
|
||||||
|
|
||||||
|
@ -593,8 +582,6 @@ int lsnes_app::OnExit()
|
||||||
save_configuration();
|
save_configuration();
|
||||||
quit_lua();
|
quit_lua();
|
||||||
lsnes_instance.mlogic->release_memory();
|
lsnes_instance.mlogic->release_memory();
|
||||||
joystick_driver_signal();
|
|
||||||
joystick_thread_handle->join();
|
|
||||||
platform::quit();
|
platform::quit();
|
||||||
lsnes_instance.buttons->cleanup();
|
lsnes_instance.buttons->cleanup();
|
||||||
cleanup_keymapper();
|
cleanup_keymapper();
|
||||||
|
|
Loading…
Add table
Reference in a new issue