]> git.tdb.fi Git - libs/gui.git/blobdiff - source/input/linux/gamecontroller.cpp
Add a game controller input device
[libs/gui.git] / source / input / linux / gamecontroller.cpp
diff --git a/source/input/linux/gamecontroller.cpp b/source/input/linux/gamecontroller.cpp
new file mode 100644 (file)
index 0000000..bf69049
--- /dev/null
@@ -0,0 +1,80 @@
+#include <fcntl.h>
+#include <linux/joystick.h>
+#include <msp/core/systemerror.h>
+#include <msp/io/handle_private.h>
+#include <msp/strings/format.h>
+#include "gamecontroller.h"
+#include "gamecontroller_platform.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Input {
+
+GameController::GameController(unsigned index):
+       priv(new Private)
+{
+       priv->dev = new JsDevice(format("/dev/input/js%d", index));
+       name = priv->dev->get_name();
+       tick();
+}
+
+GameController::~GameController()
+{
+       delete priv->dev;
+       delete priv;
+}
+
+void GameController::tick()
+{
+       js_event events[16];
+       while(1)
+       {
+               unsigned len = priv->dev->read(reinterpret_cast<char *>(events), sizeof(events));
+
+               unsigned count = len/sizeof(js_event);
+               for(unsigned i=0; i<count; ++i)
+               {
+                       unsigned type = events[i].type&0x7F;
+                       bool init = events[i].type&JS_EVENT_INIT;
+                       if(type==JS_EVENT_AXIS)
+                               set_axis_value(events[i].number, events[i].value/32768.0f, !init);
+                       else if(type==JS_EVENT_BUTTON)
+                               set_button_state(events[i].number, events[i].value, !init);
+               }
+
+               if(len<sizeof(events))
+                       break;
+       }
+}
+
+
+JsDevice::JsDevice(const string &fn)
+{
+       mode = IO::M_READ;
+       *handle = open(fn.c_str(), O_RDONLY|O_NONBLOCK);
+       if(!handle)
+               throw system_error(format("open(%s)", fn));
+}
+
+string JsDevice::get_name() const
+{
+       char buf[128];
+       int ret = ioctl(*handle, JSIOCGNAME(sizeof(buf)), buf);
+       if(ret<0)
+               throw system_error("ioctl(JSIOCGNAME)");
+       return buf;
+}
+
+unsigned JsDevice::do_read(char *buf, unsigned size)
+{
+       return IO::sys_read(handle, buf, size);
+}
+
+unsigned JsDevice::do_write(const char *, unsigned)
+{
+       throw IO::invalid_access(IO::M_WRITE);
+}
+
+} // namespace Input
+} // namespace Msp