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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -127,6 +127,7 @@ public:
|
|||
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);
|
||||
std::string get_summary();
|
||||
void offline_all();
|
||||
private:
|
||||
set(const set&);
|
||||
set& operator=(const set&);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
threads::thread* joystick_thread_handle;
|
||||
void dummy_init() throw() {}
|
||||
void dummy_quit() throw() {}
|
||||
void dummy_thread_fn() throw() {}
|
||||
|
@ -16,6 +17,12 @@ namespace
|
|||
.signal = dummy_signal,
|
||||
.name = dummy_name
|
||||
};
|
||||
|
||||
void* joystick_thread(int _args)
|
||||
{
|
||||
driver.thread_fn();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
joystick_driver::joystick_driver(_joystick_driver drv)
|
||||
|
@ -27,19 +34,17 @@ void joystick_driver_init() throw()
|
|||
{
|
||||
lsnes_gamepads_init();
|
||||
driver.init();
|
||||
joystick_thread_handle = new threads::thread(joystick_thread, 6);
|
||||
}
|
||||
|
||||
void joystick_driver_quit() throw()
|
||||
{
|
||||
driver.quit();
|
||||
joystick_thread_handle->join();
|
||||
joystick_thread_handle = NULL;
|
||||
lsnes_gamepads_deinit();
|
||||
}
|
||||
|
||||
void joystick_driver_thread_fn() throw()
|
||||
{
|
||||
driver.thread_fn();
|
||||
}
|
||||
|
||||
void joystick_driver_signal() throw()
|
||||
{
|
||||
driver.signal();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "core/command.hpp"
|
||||
#include "core/instance.hpp"
|
||||
#include "core/joystickapi.hpp"
|
||||
#include "core/keymapper.hpp"
|
||||
#include "core/memorymanip.hpp"
|
||||
#include "core/messages.hpp"
|
||||
|
@ -104,4 +105,14 @@ namespace
|
|||
messages << lsnes_gamepads.get_summary() << 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)
|
||||
{
|
||||
threads::alock h(mlock);
|
||||
|
|
|
@ -169,22 +169,24 @@ namespace
|
|||
|
||||
std::map<int, unsigned> gamepad_map;
|
||||
|
||||
bool read_one_input_event(int fd)
|
||||
int read_one_input_event(int fd)
|
||||
{
|
||||
struct input_event ev;
|
||||
int r = read(fd, &ev, sizeof(ev));
|
||||
if(r < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return false;
|
||||
return 0;
|
||||
if(r < 0) {
|
||||
if(errno == ENODEV)
|
||||
return -1; //Disconnected.
|
||||
messages << "Error reading from joystick (fd=" << fd << "): " << strerror(errno)
|
||||
<< std::endl;
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if(ev.type == EV_KEY)
|
||||
lsnes_gamepads[gamepad_map[fd]].report_button(ev.code, ev.value != 0);
|
||||
if(ev.type == EV_ABS)
|
||||
lsnes_gamepads[gamepad_map[fd]].report_axis(ev.code, ev.value);
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool probe_joystick(int fd, const std::string& filename)
|
||||
|
@ -283,6 +285,8 @@ namespace
|
|||
|
||||
struct _joystick_driver drv = {
|
||||
.init = []() -> void {
|
||||
quit_signaled = false;
|
||||
quit_ack = false;
|
||||
probe_all_joysticks();
|
||||
quit_ack = quit_signaled = false;
|
||||
},
|
||||
|
@ -309,10 +313,35 @@ namespace
|
|||
int r = select(limit, &rfds, NULL, NULL, &tv);
|
||||
if(r <= 0)
|
||||
continue;
|
||||
std::set<int> cleanup;
|
||||
for(auto fd : gamepad_map)
|
||||
if(FD_ISSET(fd.first, &rfds))
|
||||
while(read_one_input_event(fd.first));
|
||||
if(FD_ISSET(fd.first, &rfds)) {
|
||||
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;
|
||||
},
|
||||
.signal = []() -> void {
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace
|
|||
|
||||
struct _joystick_driver drv = {
|
||||
.init = []() -> void {
|
||||
quit_signaled = false;
|
||||
quit_ack = false;
|
||||
int jcnt = SDL_SYS_JoystickInit();
|
||||
if(jcnt < 0)
|
||||
return;
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace
|
|||
|
||||
struct _joystick_driver drv = {
|
||||
.init = []() -> void {
|
||||
quit_signaled = false;
|
||||
quit_ack = false;
|
||||
unsigned max_joysticks = joyGetNumDevs();
|
||||
if(!max_joysticks)
|
||||
return; //No joystick support.
|
||||
|
|
|
@ -67,18 +67,11 @@ namespace
|
|||
volatile bool modal_dialog_active;
|
||||
threads::lock ui_mutex;
|
||||
threads::cv ui_condition;
|
||||
threads::thread* joystick_thread_handle;
|
||||
bool if_update_messages = false;
|
||||
bool if_update_screen = false;
|
||||
bool if_update_status = false;
|
||||
threads::lock if_mutex;
|
||||
|
||||
void* joystick_thread(int _args)
|
||||
{
|
||||
joystick_driver_thread_fn();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uiserv_event : public wxEvent
|
||||
{
|
||||
uiserv_event(int code)
|
||||
|
@ -516,12 +509,10 @@ bool lsnes_app::OnInit()
|
|||
if(settings_mode) {
|
||||
//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.
|
||||
joystick_thread_handle = new threads::thread(joystick_thread, 6);
|
||||
threads::thread* dummy_loop = new threads::thread(eloop_helper, 8);
|
||||
display_settings_dialog(NULL, lsnes_instance, NULL);
|
||||
platform::exit_dummy_event_loop();
|
||||
joystick_driver_signal();
|
||||
joystick_thread_handle->join();
|
||||
joystick_driver_quit();
|
||||
dummy_loop->join();
|
||||
save_configuration();
|
||||
return false;
|
||||
|
@ -529,8 +520,6 @@ bool lsnes_app::OnInit()
|
|||
init_lua();
|
||||
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->Show();
|
||||
|
||||
|
@ -593,8 +582,6 @@ int lsnes_app::OnExit()
|
|||
save_configuration();
|
||||
quit_lua();
|
||||
lsnes_instance.mlogic->release_memory();
|
||||
joystick_driver_signal();
|
||||
joystick_thread_handle->join();
|
||||
platform::quit();
|
||||
lsnes_instance.buttons->cleanup();
|
||||
cleanup_keymapper();
|
||||
|
|
Loading…
Add table
Reference in a new issue