2 #include <linux/joystick.h>
3 #include <msp/core/algorithm.h>
4 #include <msp/core/systemerror.h>
5 #include <msp/fs/dir.h>
6 #include <msp/io/handle_private.h>
7 #include <msp/strings/format.h>
8 #include "gamecontroller.h"
9 #include "gamecontroller_platform.h"
16 vector<string> GameController::Private::detected_controllers;
18 GameController::GameController(unsigned index):
19 Device(GAME_CONTROLLER),
24 if(index>=Private::detected_controllers.size())
25 throw device_not_available(format("GameController(%d)", index));
27 JsDevice *device = new JsDevice(Private::detected_controllers[index]);
31 priv->dev->signal_data_available.connect(sigc::mem_fun(this, static_cast<void (GameController::*)()>(&GameController::tick)));
32 name = priv->dev->get_name();
36 GameController::~GameController()
42 unsigned GameController::detect()
44 Private::detected_controllers.clear();
46 FS::Path dev_input = "/dev/input";
47 vector<string> devices = FS::list_filtered(dev_input, "^js[0-9]+");
49 for(const string &f: devices)
50 // TODO check permissions
51 Private::detected_controllers.push_back((dev_input/f).str());
54 n_detected_controllers = Private::detected_controllers.size();
56 return Private::detected_controllers.size();
59 void GameController::use_event_dispatcher(IO::EventDispatcher *ed)
62 event_disp->remove(*priv->dev);
65 event_disp->add(*priv->dev);
68 void GameController::tick()
74 if(!first && !IO::poll(*priv->dev, IO::P_INPUT, Time::zero))
78 unsigned len = priv->dev->read(reinterpret_cast<char *>(events), sizeof(events));
80 unsigned count = len/sizeof(js_event);
81 for(unsigned i=0; i<count; ++i)
83 unsigned etype = events[i].type&0x7F;
84 bool init = events[i].type&JS_EVENT_INIT;
85 if(etype==JS_EVENT_AXIS)
86 set_axis_value(events[i].number, events[i].value/32768.0f, !init);
87 else if(etype==JS_EVENT_BUTTON)
88 set_button_state(events[i].number, events[i].value, !init);
91 if(len<sizeof(events))
97 void GameController::tick(const Time::TimeDelta &timeout)
99 if(IO::poll(*priv->dev, IO::P_INPUT, timeout))
104 JsDevice::JsDevice(const string &fn)
107 *handle = open(fn.c_str(), O_RDONLY);
109 throw system_error(format("open(%s)", fn));
110 set_events(IO::P_INPUT);
113 JsDevice::~JsDevice()
118 string JsDevice::get_name() const
120 char buf[128] = { 0 };
121 int ret = ioctl(*handle, JSIOCGNAME(sizeof(buf)), buf);
123 throw system_error("ioctl(JSIOCGNAME)");
127 size_t JsDevice::do_read(char *buf, size_t size)
129 return IO::sys_read(handle, buf, size);
132 size_t JsDevice::do_write(const char *, size_t)
134 throw IO::invalid_access(IO::M_WRITE);