#include <boost/assert.hpp>
#include <glib.h>
-
+#include <gio/gunixinputstream.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
WheelPrivate();
~WheelPrivate();
- int fd;
- char doShutdown;
- char isShutdown;
+ void gotData(GAsyncResult *res);
private:
-// boost::thread pollThread;
+ struct js_event jsEvent;
+ GInputStream *gis;
+ int *axis;
+ char *button;
};
//PIMPL:
-void pollJS(WheelPrivate *wp)
+void readCallback(GObject *srcObj, GAsyncResult *res, gpointer userData)
{
- if (!wp) {
- throw std::runtime_error("NULL WheelPrivate in pollJS!");
- return;
+ if (!userData) {
+ throw std::runtime_error("Got a null WheelPrivate in the Read Callback!");
}
- while (!wp->doShutdown) {
-
- }
- wp->isShutdown = 1;
+
+ WheelPrivate *wp = (WheelPrivate *)userData;
+ wp->gotData(res);
+
}
WheelPrivate::WheelPrivate()
-:fd(-1), isShutdown(0), doShutdown(0)
+:gis(nullptr), axis(nullptr), button(nullptr)
{
- unsigned char axes = 0;
- unsigned char buttons = 0;
+ unsigned char numAxes = 0;
+ unsigned char numButtons = 0;
int version = 0;
+ int fd;
char name[JSNAMELEN] = "Unknown";
//FIXME: Support config file with joystick device mapping, button/axis mappings, etc.
- if ((this->fd = open("/dev/input/js0", O_RDONLY)) < 0) {
+ if ((fd = open("/dev/input/js0", O_RDONLY)) < 0) {
throw std::runtime_error("Could not find a joystick class device!"); //FIXME: Later, don't throw, watch input devices, and jump on to any JS devices that appear
return;
}
ioctl(fd, JSIOCGVERSION, &version);
- ioctl(fd, JSIOCGAXES, &axes);
- ioctl(fd, JSIOCGBUTTONS, &buttons);
+ ioctl(fd, JSIOCGAXES, &numAxes);
+ ioctl(fd, JSIOCGBUTTONS, &numButtons);
ioctl(fd, JSIOCGNAME(JSNAMELEN), name);
cout << "Driver version: " << (version >> 16) << "." << ((version >> 8) & 0xFF) << "." << (version & 0xFF) << "\n";
cout << "JS Name: " << name << "\n";
- cout << "JS Axes/Buttons: " << (int)axes << "/" << (int)buttons << "\n";
- cout << "Starting polling thread...\n";
+ cout << "JS Axes/Buttons: " << (int)numAxes << "/" << (int)numButtons << "\n";
+ cout << "Converting FD to GIO Input Stream...\n";
+ this->axis = (int *)calloc(numAxes, sizeof(int));
+ this->button = (char *)calloc(numButtons, sizeof(char));
+ this->gis = g_unix_input_stream_new(fd, TRUE);
+ g_input_stream_read_async(this->gis, &this->jsEvent, sizeof(struct js_event), G_PRIORITY_DEFAULT, nullptr, &readCallback, this);
}
WheelPrivate::~WheelPrivate()
{
- if (this->fd != -1)
- close(fd);
+
+ if (this->gis)
+ g_input_stream_close_async(this->gis, G_PRIORITY_DEFAULT, NULL, NULL, NULL);
+}
+
+void WheelPrivate::gotData(GAsyncResult *res)
+{
+ GError *gerror = NULL;
+ int size = g_input_stream_read_finish(this->gis, res, &gerror);
+
+ if (res < 0) {
+ throw std::runtime_error(gerror->message);
+ g_error_free(gerror);
+ }
+ if (size != sizeof(struct js_event)) {
+ cout << "Only read " << size << " bytes from js device - should have been " << sizeof(struct js_event) << " bytes!";
+ throw std::runtime_error("Bad read from JS device!");
+ return;
+
+ } else {
+ switch (this->jsEvent.type & ~JS_EVENT_INIT) {
+ case JS_EVENT_BUTTON:
+ this->button[this->jsEvent.number] = this->jsEvent.value;
+ cout << "Got button event, btn# " << (int)this->jsEvent.number << ", val " << this->jsEvent.value << "\n";
+ break;
+ case JS_EVENT_AXIS:
+ this->axis[this->jsEvent.number] = this->jsEvent.value;
+ cout << "Got axis event, axis# " << (int)this->jsEvent.number << ", val " << this->jsEvent.value << "\n";
+ break;
+ default:
+ cout << "Got JS event that wasn't button or axis!\n";
+ break;
+ }
+ }
+
+ g_input_stream_read_async(this->gis, &this->jsEvent, sizeof(struct js_event), G_PRIORITY_DEFAULT, nullptr, &readCallback, this);
}
+