#include <fcntl.h>
#include <linux/joystick.h>
#include <msp/core/systemerror.h>
+#include <msp/fs/dir.h>
#include <msp/io/handle_private.h>
#include <msp/strings/format.h>
#include "gamecontroller.h"
namespace Msp {
namespace Input {
+vector<string> GameController::Private::detected_controllers;
+
GameController::GameController(unsigned index):
- priv(new Private)
+ event_disp(0)
{
- priv->dev = new JsDevice(format("/dev/input/js%d", index));
+ if(!detect_done)
+ detect();
+ if(index>=Private::detected_controllers.size())
+ throw device_not_available(format("GameController(%d)", index));
+
+ JsDevice *device = new JsDevice(Private::detected_controllers[index]);
+
+ priv = new Private;
+ priv->dev = device;
+ priv->dev->signal_data_available.connect(sigc::mem_fun(this, static_cast<void (GameController::*)()>(&GameController::tick)));
name = priv->dev->get_name();
- tick();
+ tick(Time::zero);
}
GameController::~GameController()
delete priv;
}
+unsigned GameController::detect()
+{
+ Private::detected_controllers.clear();
+
+ FS::Path dev_input = "/dev/input";
+ list<string> devices = FS::list_filtered(dev_input, "^js[0-9]+");
+ devices.sort();
+ for(list<string>::const_iterator i=devices.begin(); i!=devices.end(); ++i)
+ // TODO check permissions
+ Private::detected_controllers.push_back((dev_input / *i).str());
+
+ detect_done = true;
+ n_detected_controllers = Private::detected_controllers.size();
+
+ return Private::detected_controllers.size();
+}
+
+void GameController::use_event_dispatcher(IO::EventDispatcher *ed)
+{
+ if(event_disp)
+ event_disp->remove(*priv->dev);
+ event_disp = ed;
+ if(event_disp)
+ event_disp->add(*priv->dev);
+}
+
void GameController::tick()
{
js_event events[16];
+ bool first = true;
while(1)
{
+ if(!first && !IO::poll(*priv->dev, IO::P_INPUT, Time::zero))
+ break;
+
+ first = false;
unsigned len = priv->dev->read(reinterpret_cast<char *>(events), sizeof(events));
unsigned count = len/sizeof(js_event);
}
+void GameController::tick(const Time::TimeDelta &timeout)
+{
+ if(IO::poll(*priv->dev, IO::P_INPUT, timeout))
+ tick();
+}
+
+
JsDevice::JsDevice(const string &fn)
{
mode = IO::M_READ;
- *handle = open(fn.c_str(), O_RDONLY|O_NONBLOCK);
+ *handle = open(fn.c_str(), O_RDONLY);
if(!handle)
throw system_error(format("open(%s)", fn));
+ set_events(IO::P_INPUT);
+}
+
+JsDevice::~JsDevice()
+{
+ sys_close(handle);
}
string JsDevice::get_name() const
{
- char buf[128];
+ char buf[128] = { 0 };
int ret = ioctl(*handle, JSIOCGNAME(sizeof(buf)), buf);
if(ret<0)
throw system_error("ioctl(JSIOCGNAME)");