/* linux-raw-gamepad.c generated by valac 0.35.5, the Vala compiler
 * generated from linux-raw-gamepad.vala, do not modify */

/* This file is part of GNOME Games. License: GPLv3*/
/* FIXME Workaround the autotools working poorly with Vala.*/
/* FIXME This should be in LinuxRawGamepad but a bug in valac prevent us from using it in 'requires' statements.*/

#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <libevdev/libevdev.h>
#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <glib/gi18n-lib.h>
#include <errno.h>
#include <float.h>
#include <math.h>


#define GAMES_TYPE_RAW_GAMEPAD (games_raw_gamepad_get_type ())
#define GAMES_RAW_GAMEPAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_RAW_GAMEPAD, GamesRawGamepad))
#define GAMES_IS_RAW_GAMEPAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_RAW_GAMEPAD))
#define GAMES_RAW_GAMEPAD_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GAMES_TYPE_RAW_GAMEPAD, GamesRawGamepadIface))

typedef struct _GamesRawGamepad GamesRawGamepad;
typedef struct _GamesRawGamepadIface GamesRawGamepadIface;

#define GAMES_TYPE_LINUX_RAW_GAMEPAD (games_linux_raw_gamepad_get_type ())
#define GAMES_LINUX_RAW_GAMEPAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepad))
#define GAMES_LINUX_RAW_GAMEPAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepadClass))
#define GAMES_IS_LINUX_RAW_GAMEPAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_LINUX_RAW_GAMEPAD))
#define GAMES_IS_LINUX_RAW_GAMEPAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_LINUX_RAW_GAMEPAD))
#define GAMES_LINUX_RAW_GAMEPAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepadClass))

typedef struct _GamesLinuxRawGamepad GamesLinuxRawGamepad;
typedef struct _GamesLinuxRawGamepadClass GamesLinuxRawGamepadClass;
typedef struct _GamesLinuxRawGamepadPrivate GamesLinuxRawGamepadPrivate;
#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
#define _libevdev_free0(var) ((var == NULL) ? NULL : (var = (libevdev_free (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_io_channel_unref0(var) ((var == NULL) ? NULL : (var = (g_io_channel_unref (var), NULL)))

#define GAMES_TYPE_STANDARD_GAMEPAD_BUTTON (games_standard_gamepad_button_get_type ())

#define GAMES_TYPE_STANDARD_GAMEPAD_AXIS (games_standard_gamepad_axis_get_type ())
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _GamesRawGamepadIface {
	GTypeInterface parent_iface;
	const gchar* (*get_guid) (GamesRawGamepad* self);
};

struct _GamesLinuxRawGamepad {
	GObject parent_instance;
	GamesLinuxRawGamepadPrivate * priv;
};

struct _GamesLinuxRawGamepadClass {
	GObjectClass parent_class;
};

struct _GamesLinuxRawGamepadPrivate {
	gint fd;
	guint* event_source_id;
	struct libevdev* device;
	guint8 key_map[KEY_MAX];
	guint8 abs_map[ABS_MAX];
	struct input_absinfo abs_info[ABS_MAX];
	gchar* _guid;
};

typedef enum  {
	GAMES_STANDARD_GAMEPAD_BUTTON_UNKNOWN,
	GAMES_STANDARD_GAMEPAD_BUTTON_A,
	GAMES_STANDARD_GAMEPAD_BUTTON_B,
	GAMES_STANDARD_GAMEPAD_BUTTON_X,
	GAMES_STANDARD_GAMEPAD_BUTTON_Y,
	GAMES_STANDARD_GAMEPAD_BUTTON_SHOULDER_L,
	GAMES_STANDARD_GAMEPAD_BUTTON_SHOULDER_R,
	GAMES_STANDARD_GAMEPAD_BUTTON_TRIGGER_L,
	GAMES_STANDARD_GAMEPAD_BUTTON_TRIGGER_R,
	GAMES_STANDARD_GAMEPAD_BUTTON_SELECT,
	GAMES_STANDARD_GAMEPAD_BUTTON_START,
	GAMES_STANDARD_GAMEPAD_BUTTON_STICK_L,
	GAMES_STANDARD_GAMEPAD_BUTTON_STICK_R,
	GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_UP,
	GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_DOWN,
	GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_LEFT,
	GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_RIGHT,
	GAMES_STANDARD_GAMEPAD_BUTTON_HOME
} GamesStandardGamepadButton;

typedef enum  {
	GAMES_STANDARD_GAMEPAD_AXIS_UNKNOWN,
	GAMES_STANDARD_GAMEPAD_AXIS_LEFT_X,
	GAMES_STANDARD_GAMEPAD_AXIS_LEFT_Y,
	GAMES_STANDARD_GAMEPAD_AXIS_RIGHT_X,
	GAMES_STANDARD_GAMEPAD_AXIS_RIGHT_Y
} GamesStandardGamepadAxis;


static gpointer games_linux_raw_gamepad_parent_class = NULL;
static GamesRawGamepadIface * games_linux_raw_gamepad_games_raw_gamepad_parent_iface = NULL;

#define GUID_LENGTH 8
GType games_raw_gamepad_get_type (void) G_GNUC_CONST;
GType games_linux_raw_gamepad_get_type (void) G_GNUC_CONST;
#define GAMES_LINUX_RAW_GAMEPAD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepadPrivate))
enum  {
	GAMES_LINUX_RAW_GAMEPAD_DUMMY_PROPERTY,
	GAMES_LINUX_RAW_GAMEPAD_GUID
};
static void games_linux_raw_gamepad_remove_event_source (GamesLinuxRawGamepad* self);
GamesLinuxRawGamepad* games_linux_raw_gamepad_new (const gchar* file_name, GError** error);
GamesLinuxRawGamepad* games_linux_raw_gamepad_construct (GType object_type, const gchar* file_name, GError** error);
static gboolean games_linux_raw_gamepad_is_joystick (GamesLinuxRawGamepad* self);
static gboolean games_linux_raw_gamepad_poll_events (GamesLinuxRawGamepad* self);
static gboolean _games_linux_raw_gamepad_poll_events_gio_func (GIOChannel* source, GIOCondition condition, gpointer self);
static guint* _uint_dup (guint* self);
static struct input_absinfo* _abs_info_dup (struct input_absinfo* self);
static void games_linux_raw_gamepad_handle_evdev_event (GamesLinuxRawGamepad* self);
static gboolean games_linux_raw_gamepad_has_key (GamesLinuxRawGamepad* self, guint code);
static gboolean games_linux_raw_gamepad_has_abs (GamesLinuxRawGamepad* self, guint code);
GType games_standard_gamepad_button_get_type (void) G_GNUC_CONST;
static GamesStandardGamepadButton games_linux_raw_gamepad_button_to_standard_button (GamesLinuxRawGamepad* self, gint code);
GType games_standard_gamepad_axis_get_type (void) G_GNUC_CONST;
static GamesStandardGamepadAxis games_linux_raw_gamepad_axis_to_standard_axis (GamesLinuxRawGamepad* self, gint code);
static gdouble games_linux_raw_gamepad_centered_axis_value (struct input_absinfo* abs_info, gint32 value);
static gchar* games_linux_raw_gamepad_uint16s_to_hex_string (GamesLinuxRawGamepad* self, guint16* data, int data_length1);
static void games_linux_raw_gamepad_finalize (GObject * obj);
const gchar* games_raw_gamepad_get_guid (GamesRawGamepad* self);
static void _vala_games_linux_raw_gamepad_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);


static gboolean _games_linux_raw_gamepad_poll_events_gio_func (GIOChannel* source, GIOCondition condition, gpointer self) {
	gboolean result;
	result = games_linux_raw_gamepad_poll_events ((GamesLinuxRawGamepad*) self);
	return result;
}


static guint* _uint_dup (guint* self) {
	guint* dup;
	dup = g_new0 (guint, 1);
	memcpy (dup, self, sizeof (guint));
	return dup;
}


static gpointer __uint_dup0 (gpointer self) {
	return self ? _uint_dup (self) : NULL;
}


static struct input_absinfo* _abs_info_dup (struct input_absinfo* self) {
	struct input_absinfo* dup;
	dup = g_new0 (struct input_absinfo, 1);
	memcpy (dup, self, sizeof (struct input_absinfo));
	return dup;
}


static gpointer __abs_info_dup0 (gpointer self) {
	return self ? _abs_info_dup (self) : NULL;
}


GamesLinuxRawGamepad* games_linux_raw_gamepad_construct (GType object_type, const gchar* file_name, GError** error) {
	GamesLinuxRawGamepad * self = NULL;
	const gchar* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	struct libevdev* _tmp7_;
	struct libevdev* _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gboolean _tmp15_;
	GIOChannel* channel;
	gint _tmp18_;
	GIOChannel* _tmp19_;
	GIOChannel* _tmp20_;
	guint _tmp21_;
	guint* _tmp22_;
	gint buttons_number;
	gint axes_number;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (file_name != NULL, NULL);
	self = (GamesLinuxRawGamepad*) g_object_new (object_type, NULL);
	_tmp0_ = file_name;
	_tmp1_ = open (_tmp0_, O_RDONLY | O_NONBLOCK, (mode_t) 0);
	self->priv->fd = _tmp1_;
	_tmp2_ = self->priv->fd;
	if (_tmp2_ < 0) {
		const gchar* _tmp3_;
		gint _tmp4_;
		const gchar* _tmp5_;
		GError* _tmp6_;
		_tmp3_ = file_name;
		_tmp4_ = errno;
		_tmp5_ = strerror (_tmp4_);
		_tmp6_ = g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, _ ("Unable to open file “%s”: %s"), _tmp3_, _tmp5_);
		_inner_error_ = _tmp6_;
		if (_inner_error_->domain == G_FILE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp7_ = libevdev_new ();
	_libevdev_free0 (self->priv->device);
	self->priv->device = _tmp7_;
	_tmp8_ = self->priv->device;
	_tmp9_ = self->priv->fd;
	_tmp10_ = libevdev_set_fd (_tmp8_, _tmp9_);
	if (_tmp10_ < 0) {
		const gchar* _tmp11_;
		gint _tmp12_;
		const gchar* _tmp13_;
		GError* _tmp14_;
		_tmp11_ = file_name;
		_tmp12_ = errno;
		_tmp13_ = strerror (_tmp12_);
		_tmp14_ = g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, _ ("Evdev is unable to open “%s”: %s"), _tmp11_, _tmp13_);
		_inner_error_ = _tmp14_;
		if (_inner_error_->domain == G_FILE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp15_ = games_linux_raw_gamepad_is_joystick (self);
	if (!_tmp15_) {
		const gchar* _tmp16_;
		GError* _tmp17_;
		_tmp16_ = file_name;
		_tmp17_ = g_error_new (G_FILE_ERROR, G_FILE_ERROR_NXIO, "“%s” is not a joystick", _tmp16_);
		_inner_error_ = _tmp17_;
		if (_inner_error_->domain == G_FILE_ERROR) {
			g_propagate_error (error, _inner_error_);
			_g_object_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp18_ = self->priv->fd;
	_tmp19_ = g_io_channel_unix_new (_tmp18_);
	channel = _tmp19_;
	_tmp20_ = channel;
	_tmp21_ = g_io_add_watch (_tmp20_, G_IO_IN, _games_linux_raw_gamepad_poll_events_gio_func, self);
	_tmp22_ = __uint_dup0 (&_tmp21_);
	_g_free0 (self->priv->event_source_id);
	self->priv->event_source_id = _tmp22_;
	buttons_number = 0;
	{
		gint i;
		i = BTN_JOYSTICK;
		{
			gboolean _tmp23_;
			_tmp23_ = TRUE;
			while (TRUE) {
				gint _tmp25_;
				struct libevdev* _tmp26_;
				gint _tmp27_;
				gboolean _tmp28_;
				if (!_tmp23_) {
					gint _tmp24_;
					_tmp24_ = i;
					i = _tmp24_ + 1;
				}
				_tmp23_ = FALSE;
				_tmp25_ = i;
				if (!(_tmp25_ < KEY_MAX)) {
					break;
				}
				_tmp26_ = self->priv->device;
				_tmp27_ = i;
				_tmp28_ = libevdev_has_event_code (_tmp26_, (guint) EV_KEY, (guint) _tmp27_);
				if (_tmp28_) {
					gint _tmp29_;
					gint _tmp30_;
					guint8 _tmp31_;
					gint _tmp32_;
					_tmp29_ = i;
					_tmp30_ = buttons_number;
					self->priv->key_map[_tmp29_ - BTN_MISC] = (guint8) _tmp30_;
					_tmp31_ = self->priv->key_map[_tmp29_ - BTN_MISC];
					_tmp32_ = buttons_number;
					buttons_number = _tmp32_ + 1;
				}
			}
		}
	}
	{
		gint i;
		i = BTN_MISC;
		{
			gboolean _tmp33_;
			_tmp33_ = TRUE;
			while (TRUE) {
				gint _tmp35_;
				struct libevdev* _tmp36_;
				gint _tmp37_;
				gboolean _tmp38_;
				if (!_tmp33_) {
					gint _tmp34_;
					_tmp34_ = i;
					i = _tmp34_ + 1;
				}
				_tmp33_ = FALSE;
				_tmp35_ = i;
				if (!(_tmp35_ < BTN_JOYSTICK)) {
					break;
				}
				_tmp36_ = self->priv->device;
				_tmp37_ = i;
				_tmp38_ = libevdev_has_event_code (_tmp36_, (guint) EV_KEY, (guint) _tmp37_);
				if (_tmp38_) {
					gint _tmp39_;
					gint _tmp40_;
					guint8 _tmp41_;
					gint _tmp42_;
					_tmp39_ = i;
					_tmp40_ = buttons_number;
					self->priv->key_map[_tmp39_ - BTN_MISC] = (guint8) _tmp40_;
					_tmp41_ = self->priv->key_map[_tmp39_ - BTN_MISC];
					_tmp42_ = buttons_number;
					buttons_number = _tmp42_ + 1;
				}
			}
		}
	}
	axes_number = 0;
	{
		gint i;
		i = 0;
		{
			gboolean _tmp43_;
			_tmp43_ = TRUE;
			while (TRUE) {
				gint _tmp45_;
				gint _tmp46_;
				struct libevdev* _tmp47_;
				gint _tmp48_;
				gboolean _tmp49_;
				if (!_tmp43_) {
					gint _tmp44_;
					_tmp44_ = i;
					i = _tmp44_ + 1;
				}
				_tmp43_ = FALSE;
				_tmp45_ = i;
				if (!(_tmp45_ < ABS_MAX)) {
					break;
				}
				_tmp46_ = i;
				if (_tmp46_ == ABS_HAT0X) {
					i = ABS_HAT3Y;
					continue;
				}
				_tmp47_ = self->priv->device;
				_tmp48_ = i;
				_tmp49_ = libevdev_has_event_code (_tmp47_, (guint) EV_ABS, (guint) _tmp48_);
				if (_tmp49_) {
					struct input_absinfo* absinfo;
					struct libevdev* _tmp50_;
					gint _tmp51_;
					struct input_absinfo* _tmp52_;
					struct input_absinfo* _tmp53_;
					gint _tmp54_;
					gint _tmp55_;
					guint8 _tmp56_;
					gint _tmp57_;
					struct input_absinfo* _tmp58_;
					struct input_absinfo _tmp59_;
					gint _tmp60_;
					_tmp50_ = self->priv->device;
					_tmp51_ = i;
					_tmp52_ = libevdev_get_abs_info (_tmp50_, (guint) _tmp51_);
					_tmp53_ = __abs_info_dup0 (_tmp52_);
					absinfo = _tmp53_;
					_tmp54_ = i;
					_tmp55_ = axes_number;
					self->priv->abs_map[_tmp54_] = (guint8) _tmp55_;
					_tmp56_ = self->priv->abs_map[_tmp54_];
					_tmp57_ = axes_number;
					_tmp58_ = absinfo;
					self->priv->abs_info[_tmp57_] = *_tmp58_;
					_tmp59_ = self->priv->abs_info[_tmp57_];
					_tmp60_ = axes_number;
					axes_number = _tmp60_ + 1;
					_g_free0 (absinfo);
				}
			}
		}
	}
	_g_io_channel_unref0 (channel);
	return self;
}


GamesLinuxRawGamepad* games_linux_raw_gamepad_new (const gchar* file_name, GError** error) {
	return games_linux_raw_gamepad_construct (GAMES_TYPE_LINUX_RAW_GAMEPAD, file_name, error);
}


static gboolean games_linux_raw_gamepad_poll_events (GamesLinuxRawGamepad* self) {
	gboolean result = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	while (TRUE) {
		struct libevdev* _tmp0_;
		gint _tmp1_;
		_tmp0_ = self->priv->device;
		_tmp1_ = libevdev_has_event_pending (_tmp0_);
		if (!(_tmp1_ > 0)) {
			break;
		}
		games_linux_raw_gamepad_handle_evdev_event (self);
	}
	result = TRUE;
	return result;
}


static gboolean games_linux_raw_gamepad_has_key (GamesLinuxRawGamepad* self, guint code) {
	gboolean result = FALSE;
	struct libevdev* _tmp0_;
	guint _tmp1_;
	gboolean _tmp2_;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->device;
	_tmp1_ = code;
	_tmp2_ = libevdev_has_event_code (_tmp0_, (guint) EV_KEY, _tmp1_);
	result = _tmp2_;
	return result;
}


static gboolean games_linux_raw_gamepad_has_abs (GamesLinuxRawGamepad* self, guint code) {
	gboolean result = FALSE;
	struct libevdev* _tmp0_;
	guint _tmp1_;
	gboolean _tmp2_;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->device;
	_tmp1_ = code;
	_tmp2_ = libevdev_has_event_code (_tmp0_, (guint) EV_ABS, _tmp1_);
	result = _tmp2_;
	return result;
}


static gboolean games_linux_raw_gamepad_is_joystick (GamesLinuxRawGamepad* self) {
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp4_ = FALSE;
	gboolean _tmp5_ = FALSE;
	gboolean _tmp6_ = FALSE;
	gboolean _tmp7_ = FALSE;
	gboolean _tmp8_ = FALSE;
	gboolean _tmp9_ = FALSE;
	gboolean _tmp10_;
	gboolean has_joystick_axes_or_buttons;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp10_ = games_linux_raw_gamepad_has_key (self, (guint) BTN_TRIGGER);
	if (_tmp10_) {
		_tmp9_ = TRUE;
	} else {
		gboolean _tmp11_;
		_tmp11_ = games_linux_raw_gamepad_has_key (self, (guint) BTN_A);
		_tmp9_ = _tmp11_;
	}
	if (_tmp9_) {
		_tmp8_ = TRUE;
	} else {
		gboolean _tmp12_;
		_tmp12_ = games_linux_raw_gamepad_has_key (self, (guint) BTN_1);
		_tmp8_ = _tmp12_;
	}
	if (_tmp8_) {
		_tmp7_ = TRUE;
	} else {
		gboolean _tmp13_;
		_tmp13_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_RX);
		_tmp7_ = _tmp13_;
	}
	if (_tmp7_) {
		_tmp6_ = TRUE;
	} else {
		gboolean _tmp14_;
		_tmp14_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_RY);
		_tmp6_ = _tmp14_;
	}
	if (_tmp6_) {
		_tmp5_ = TRUE;
	} else {
		gboolean _tmp15_;
		_tmp15_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_RZ);
		_tmp5_ = _tmp15_;
	}
	if (_tmp5_) {
		_tmp4_ = TRUE;
	} else {
		gboolean _tmp16_;
		_tmp16_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_THROTTLE);
		_tmp4_ = _tmp16_;
	}
	if (_tmp4_) {
		_tmp3_ = TRUE;
	} else {
		gboolean _tmp17_;
		_tmp17_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_RUDDER);
		_tmp3_ = _tmp17_;
	}
	if (_tmp3_) {
		_tmp2_ = TRUE;
	} else {
		gboolean _tmp18_;
		_tmp18_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_WHEEL);
		_tmp2_ = _tmp18_;
	}
	if (_tmp2_) {
		_tmp1_ = TRUE;
	} else {
		gboolean _tmp19_;
		_tmp19_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_GAS);
		_tmp1_ = _tmp19_;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp20_;
		_tmp20_ = games_linux_raw_gamepad_has_abs (self, (guint) ABS_BRAKE);
		_tmp0_ = _tmp20_;
	}
	has_joystick_axes_or_buttons = _tmp0_;
	result = has_joystick_axes_or_buttons;
	return result;
}


static void games_linux_raw_gamepad_handle_evdev_event (GamesLinuxRawGamepad* self) {
	struct input_event event = {0};
	struct libevdev* _tmp0_;
	struct input_event _tmp1_ = {0};
	gint _tmp2_;
	gint code;
	struct input_event _tmp3_;
	guint16 _tmp4_;
	struct input_event _tmp5_;
	guint16 _tmp6_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->device;
	_tmp2_ = libevdev_next_event (_tmp0_, (guint) LIBEVDEV_READ_FLAG_NORMAL, &_tmp1_);
	event = _tmp1_;
	if (_tmp2_ != 0) {
		return;
	}
	_tmp3_ = event;
	_tmp4_ = _tmp3_.code;
	code = (gint) _tmp4_;
	_tmp5_ = event;
	_tmp6_ = _tmp5_.type;
	switch (_tmp6_) {
		case EV_KEY:
		{
			gint _tmp7_;
			gint _tmp12_;
			guint8 _tmp13_;
			struct input_event _tmp14_;
			gint32 _tmp15_;
			_tmp7_ = code;
			if ((_tmp7_ & BTN_GAMEPAD) == BTN_GAMEPAD) {
				gint _tmp8_;
				GamesStandardGamepadButton _tmp9_;
				struct input_event _tmp10_;
				gint32 _tmp11_;
				_tmp8_ = code;
				_tmp9_ = games_linux_raw_gamepad_button_to_standard_button (self, _tmp8_);
				_tmp10_ = event;
				_tmp11_ = _tmp10_.value;
				g_signal_emit_by_name ((GamesRawGamepad*) self, "standard-button-event", _tmp9_, (gboolean) _tmp11_);
			}
			_tmp12_ = code;
			_tmp13_ = self->priv->key_map[_tmp12_ - BTN_MISC];
			_tmp14_ = event;
			_tmp15_ = _tmp14_.value;
			g_signal_emit_by_name ((GamesRawGamepad*) self, "button-event", (gint) _tmp13_, (gboolean) _tmp15_);
			break;
		}
		case EV_ABS:
		{
			gint _tmp16_;
			guint8 axis;
			gint _tmp33_;
			guint8 _tmp34_;
			gdouble value;
			guint8 _tmp35_;
			struct input_absinfo _tmp36_;
			struct input_event _tmp37_;
			gint32 _tmp38_;
			gdouble _tmp39_;
			guint8 _tmp40_;
			gdouble _tmp41_;
			_tmp16_ = code;
			switch (_tmp16_) {
				case ABS_HAT0X:
				case ABS_HAT0Y:
				case ABS_HAT1X:
				case ABS_HAT1Y:
				case ABS_HAT2X:
				case ABS_HAT2Y:
				case ABS_HAT3X:
				case ABS_HAT3Y:
				{
					gint _tmp17_;
					gint _tmp18_;
					gint _tmp19_;
					struct input_event _tmp20_;
					gint32 _tmp21_;
					_tmp17_ = code;
					code = _tmp17_ - ABS_HAT0X;
					_tmp18_ = code;
					_tmp19_ = code;
					_tmp20_ = event;
					_tmp21_ = _tmp20_.value;
					g_signal_emit_by_name ((GamesRawGamepad*) self, "dpad-event", _tmp18_ / 2, _tmp19_ % 2, (gint) _tmp21_);
					return;
				}
				case ABS_X:
				case ABS_Y:
				case ABS_RX:
				case ABS_RY:
				{
					GamesStandardGamepadAxis standard_axis;
					gint _tmp22_;
					GamesStandardGamepadAxis _tmp23_;
					guint8 axis;
					gint _tmp24_;
					guint8 _tmp25_;
					gdouble value;
					guint8 _tmp26_;
					struct input_absinfo _tmp27_;
					struct input_event _tmp28_;
					gint32 _tmp29_;
					gdouble _tmp30_;
					GamesStandardGamepadAxis _tmp31_;
					gdouble _tmp32_;
					_tmp22_ = code;
					_tmp23_ = games_linux_raw_gamepad_axis_to_standard_axis (self, _tmp22_);
					standard_axis = _tmp23_;
					_tmp24_ = code;
					_tmp25_ = self->priv->abs_map[_tmp24_];
					axis = _tmp25_;
					_tmp26_ = axis;
					_tmp27_ = self->priv->abs_info[_tmp26_];
					_tmp28_ = event;
					_tmp29_ = _tmp28_.value;
					_tmp30_ = games_linux_raw_gamepad_centered_axis_value (&_tmp27_, _tmp29_);
					value = _tmp30_;
					_tmp31_ = standard_axis;
					_tmp32_ = value;
					g_signal_emit_by_name ((GamesRawGamepad*) self, "standard-axis-event", _tmp31_, _tmp32_);
					break;
				}
				default:
				break;
			}
			_tmp33_ = code;
			_tmp34_ = self->priv->abs_map[_tmp33_];
			axis = _tmp34_;
			_tmp35_ = axis;
			_tmp36_ = self->priv->abs_info[_tmp35_];
			_tmp37_ = event;
			_tmp38_ = _tmp37_.value;
			_tmp39_ = games_linux_raw_gamepad_centered_axis_value (&_tmp36_, _tmp38_);
			value = _tmp39_;
			_tmp40_ = axis;
			_tmp41_ = value;
			g_signal_emit_by_name ((GamesRawGamepad*) self, "axis-event", (gint) _tmp40_, _tmp41_);
			break;
		}
		default:
		break;
	}
}


static void games_linux_raw_gamepad_remove_event_source (GamesLinuxRawGamepad* self) {
	guint* _tmp0_;
	guint* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->event_source_id;
	if (_tmp0_ == NULL) {
		return;
	}
	_tmp1_ = self->priv->event_source_id;
	g_source_remove (*_tmp1_);
	_g_free0 (self->priv->event_source_id);
	self->priv->event_source_id = NULL;
}


static gchar string_get (const gchar* self, glong index) {
	gchar result = '\0';
	glong _tmp0_;
	gchar _tmp1_;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = index;
	_tmp1_ = ((gchar*) self)[_tmp0_];
	result = _tmp1_;
	return result;
}


static gchar* games_linux_raw_gamepad_uint16s_to_hex_string (GamesLinuxRawGamepad* self, guint16* data, int data_length1) {
	gchar* result = NULL;
	guint16* _tmp0_;
	gint _tmp0__length1;
	static const char hex_to_ascii_map[] = "0123456789abcdef";
	GString* builder;
	GString* _tmp1_;
	guint16* _tmp2_;
	gint _tmp2__length1;
	GString* _tmp17_;
	const gchar* _tmp18_;
	gchar* _tmp19_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = data;
	_tmp0__length1 = data_length1;
	_vala_return_val_if_fail (_tmp0__length1 == GUID_LENGTH, "data.length == GUID_LENGTH", NULL);
	_tmp1_ = g_string_new ("");
	builder = _tmp1_;
	_tmp2_ = data;
	_tmp2__length1 = data_length1;
	{
		guint16* el_collection = NULL;
		gint el_collection_length1 = 0;
		gint _el_collection_size_ = 0;
		gint el_it = 0;
		el_collection = _tmp2_;
		el_collection_length1 = _tmp2__length1;
		for (el_it = 0; el_it < _tmp2__length1; el_it = el_it + 1) {
			guint16 el = 0U;
			el = el_collection[el_it];
			{
				guint8 c;
				guint16 _tmp3_;
				GString* _tmp4_;
				guint8 _tmp5_;
				gchar _tmp6_;
				GString* _tmp7_;
				guint8 _tmp8_;
				gchar _tmp9_;
				guint16 _tmp10_;
				GString* _tmp11_;
				guint8 _tmp12_;
				gchar _tmp13_;
				GString* _tmp14_;
				guint8 _tmp15_;
				gchar _tmp16_;
				_tmp3_ = el;
				c = (guint8) _tmp3_;
				_tmp4_ = builder;
				_tmp5_ = c;
				_tmp6_ = string_get (hex_to_ascii_map, (glong) (_tmp5_ >> 4));
				g_string_append_unichar (_tmp4_, (gunichar) _tmp6_);
				_tmp7_ = builder;
				_tmp8_ = c;
				_tmp9_ = string_get (hex_to_ascii_map, (glong) (_tmp8_ & 0x0F));
				g_string_append_unichar (_tmp7_, (gunichar) _tmp9_);
				_tmp10_ = el;
				c = (guint8) (_tmp10_ >> 8);
				_tmp11_ = builder;
				_tmp12_ = c;
				_tmp13_ = string_get (hex_to_ascii_map, (glong) (_tmp12_ >> 4));
				g_string_append_unichar (_tmp11_, (gunichar) _tmp13_);
				_tmp14_ = builder;
				_tmp15_ = c;
				_tmp16_ = string_get (hex_to_ascii_map, (glong) (_tmp15_ & 0x0F));
				g_string_append_unichar (_tmp14_, (gunichar) _tmp16_);
			}
		}
	}
	_tmp17_ = builder;
	_tmp18_ = _tmp17_->str;
	_tmp19_ = g_strdup (_tmp18_);
	result = _tmp19_;
	_g_string_free0 (builder);
	return result;
}


static GamesStandardGamepadButton games_linux_raw_gamepad_button_to_standard_button (GamesLinuxRawGamepad* self, gint code) {
	GamesStandardGamepadButton result = 0;
	gint _tmp0_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = code;
	switch (_tmp0_) {
		case BTN_A:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_A;
			return result;
		}
		case BTN_B:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_B;
			return result;
		}
		case BTN_X:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_Y;
			return result;
		}
		case BTN_Y:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_X;
			return result;
		}
		case BTN_TL:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_SHOULDER_L;
			return result;
		}
		case BTN_TR:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_SHOULDER_R;
			return result;
		}
		case BTN_TL2:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_TRIGGER_L;
			return result;
		}
		case BTN_TR2:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_TRIGGER_R;
			return result;
		}
		case BTN_SELECT:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_SELECT;
			return result;
		}
		case BTN_START:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_START;
			return result;
		}
		case BTN_MODE:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_HOME;
			return result;
		}
		case BTN_THUMBL:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_STICK_L;
			return result;
		}
		case BTN_THUMBR:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_STICK_R;
			return result;
		}
		default:
		{
			result = GAMES_STANDARD_GAMEPAD_BUTTON_UNKNOWN;
			return result;
		}
	}
}


static GamesStandardGamepadAxis games_linux_raw_gamepad_axis_to_standard_axis (GamesLinuxRawGamepad* self, gint code) {
	GamesStandardGamepadAxis result = 0;
	gint _tmp0_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = code;
	switch (_tmp0_) {
		case ABS_X:
		{
			result = GAMES_STANDARD_GAMEPAD_AXIS_LEFT_X;
			return result;
		}
		case ABS_Y:
		{
			result = GAMES_STANDARD_GAMEPAD_AXIS_LEFT_Y;
			return result;
		}
		case ABS_RX:
		{
			result = GAMES_STANDARD_GAMEPAD_AXIS_RIGHT_X;
			return result;
		}
		case ABS_RY:
		{
			result = GAMES_STANDARD_GAMEPAD_AXIS_RIGHT_Y;
			return result;
		}
		default:
		{
			result = GAMES_STANDARD_GAMEPAD_AXIS_UNKNOWN;
			return result;
		}
	}
}


static gdouble games_linux_raw_gamepad_centered_axis_value (struct input_absinfo* abs_info, gint32 value) {
	gdouble result = 0.0;
	gint64 min_absolute;
	struct input_absinfo _tmp0_;
	gint32 _tmp1_;
	gint64 _tmp2_;
	gint64 max_normalized;
	struct input_absinfo _tmp3_;
	gint32 _tmp4_;
	gint64 _tmp5_;
	gint64 value_normalized;
	gint32 _tmp6_;
	gint64 _tmp7_;
	gint64 max_centered;
	gint64 _tmp8_;
	gint64 value_centered;
	gint64 _tmp9_;
	gint64 _tmp10_;
	gint64 _tmp11_;
	gint64 _tmp12_ = 0LL;
	gint64 _tmp13_;
	gint64 divisor;
	gint64 _tmp16_;
	g_return_val_if_fail (abs_info != NULL, 0.0);
	_tmp0_ = *abs_info;
	_tmp1_ = _tmp0_.minimum;
	_tmp2_ = llabs ((gint64) _tmp1_);
	min_absolute = _tmp2_;
	_tmp3_ = *abs_info;
	_tmp4_ = _tmp3_.maximum;
	_tmp5_ = min_absolute;
	max_normalized = ((gint64) _tmp4_) + _tmp5_;
	_tmp6_ = value;
	_tmp7_ = min_absolute;
	value_normalized = ((gint64) _tmp6_) + _tmp7_;
	_tmp8_ = max_normalized;
	max_centered = _tmp8_ / 2;
	_tmp9_ = value_normalized;
	_tmp10_ = max_normalized;
	_tmp11_ = max_centered;
	value_centered = (_tmp9_ - _tmp10_) + _tmp11_;
	_tmp13_ = value_centered;
	if (_tmp13_ < ((gint64) 0)) {
		gint64 _tmp14_;
		_tmp14_ = max_centered;
		_tmp12_ = _tmp14_ + 1;
	} else {
		gint64 _tmp15_;
		_tmp15_ = max_centered;
		_tmp12_ = _tmp15_;
	}
	divisor = _tmp12_;
	_tmp16_ = value_centered;
	result = ((gdouble) _tmp16_) / ((gdouble) divisor);
	return result;
}


static const gchar* games_linux_raw_gamepad_real_get_guid (GamesRawGamepad* base) {
	const gchar* result;
	GamesLinuxRawGamepad* self;
	const gchar* _tmp0_;
	const gchar* _tmp26_;
	self = (GamesLinuxRawGamepad*) base;
	_tmp0_ = self->priv->_guid;
	if (_tmp0_ == NULL) {
		guint16 guid_array[GUID_LENGTH] = {0};
		struct libevdev* _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _tmp4_;
		guint16 _tmp5_;
		guint16 _tmp6_;
		struct libevdev* _tmp7_;
		gint _tmp8_;
		gint _tmp9_;
		gint _tmp10_;
		guint16 _tmp11_;
		guint16 _tmp12_;
		struct libevdev* _tmp13_;
		gint _tmp14_;
		gint _tmp15_;
		gint _tmp16_;
		guint16 _tmp17_;
		guint16 _tmp18_;
		struct libevdev* _tmp19_;
		gint _tmp20_;
		gint _tmp21_;
		gint _tmp22_;
		guint16 _tmp23_;
		guint16 _tmp24_;
		gchar* _tmp25_;
		_tmp1_ = self->priv->device;
		_tmp2_ = libevdev_get_id_bustype (_tmp1_);
		_tmp3_ = _tmp2_;
		_tmp4_ = GINT_TO_LE (_tmp3_);
		guid_array[0] = (guint16) _tmp4_;
		_tmp5_ = guid_array[0];
		guid_array[1] = (guint16) 0;
		_tmp6_ = guid_array[1];
		_tmp7_ = self->priv->device;
		_tmp8_ = libevdev_get_id_vendor (_tmp7_);
		_tmp9_ = _tmp8_;
		_tmp10_ = GINT_TO_LE (_tmp9_);
		guid_array[2] = (guint16) _tmp10_;
		_tmp11_ = guid_array[2];
		guid_array[3] = (guint16) 0;
		_tmp12_ = guid_array[3];
		_tmp13_ = self->priv->device;
		_tmp14_ = libevdev_get_id_product (_tmp13_);
		_tmp15_ = _tmp14_;
		_tmp16_ = GINT_TO_LE (_tmp15_);
		guid_array[4] = (guint16) _tmp16_;
		_tmp17_ = guid_array[4];
		guid_array[5] = (guint16) 0;
		_tmp18_ = guid_array[5];
		_tmp19_ = self->priv->device;
		_tmp20_ = libevdev_get_id_version (_tmp19_);
		_tmp21_ = _tmp20_;
		_tmp22_ = GINT_TO_LE (_tmp21_);
		guid_array[6] = (guint16) _tmp22_;
		_tmp23_ = guid_array[6];
		guid_array[7] = (guint16) 0;
		_tmp24_ = guid_array[7];
		_tmp25_ = games_linux_raw_gamepad_uint16s_to_hex_string (self, guid_array, GUID_LENGTH);
		_g_free0 (self->priv->_guid);
		self->priv->_guid = _tmp25_;
	}
	_tmp26_ = self->priv->_guid;
	result = _tmp26_;
	return result;
}


static void games_linux_raw_gamepad_class_init (GamesLinuxRawGamepadClass * klass) {
	games_linux_raw_gamepad_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (GamesLinuxRawGamepadPrivate));
	G_OBJECT_CLASS (klass)->get_property = _vala_games_linux_raw_gamepad_get_property;
	G_OBJECT_CLASS (klass)->finalize = games_linux_raw_gamepad_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), GAMES_LINUX_RAW_GAMEPAD_GUID, g_param_spec_string ("guid", "guid", "guid", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
}


static void games_linux_raw_gamepad_games_raw_gamepad_interface_init (GamesRawGamepadIface * iface) {
	games_linux_raw_gamepad_games_raw_gamepad_parent_iface = g_type_interface_peek_parent (iface);
	iface->get_guid = games_linux_raw_gamepad_real_get_guid;
}


static void games_linux_raw_gamepad_instance_init (GamesLinuxRawGamepad * self) {
	self->priv = GAMES_LINUX_RAW_GAMEPAD_GET_PRIVATE (self);
}


static void games_linux_raw_gamepad_finalize (GObject * obj) {
	GamesLinuxRawGamepad * self;
	gint _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepad);
	_tmp0_ = self->priv->fd;
	close (_tmp0_);
	games_linux_raw_gamepad_remove_event_source (self);
	_g_free0 (self->priv->event_source_id);
	_libevdev_free0 (self->priv->device);
	_g_free0 (self->priv->_guid);
	G_OBJECT_CLASS (games_linux_raw_gamepad_parent_class)->finalize (obj);
}


GType games_linux_raw_gamepad_get_type (void) {
	static volatile gsize games_linux_raw_gamepad_type_id__volatile = 0;
	if (g_once_init_enter (&games_linux_raw_gamepad_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (GamesLinuxRawGamepadClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) games_linux_raw_gamepad_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GamesLinuxRawGamepad), 0, (GInstanceInitFunc) games_linux_raw_gamepad_instance_init, NULL };
		static const GInterfaceInfo games_raw_gamepad_info = { (GInterfaceInitFunc) games_linux_raw_gamepad_games_raw_gamepad_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
		GType games_linux_raw_gamepad_type_id;
		games_linux_raw_gamepad_type_id = g_type_register_static (G_TYPE_OBJECT, "GamesLinuxRawGamepad", &g_define_type_info, 0);
		g_type_add_interface_static (games_linux_raw_gamepad_type_id, GAMES_TYPE_RAW_GAMEPAD, &games_raw_gamepad_info);
		g_once_init_leave (&games_linux_raw_gamepad_type_id__volatile, games_linux_raw_gamepad_type_id);
	}
	return games_linux_raw_gamepad_type_id__volatile;
}


static void _vala_games_linux_raw_gamepad_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
	GamesLinuxRawGamepad * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GAMES_TYPE_LINUX_RAW_GAMEPAD, GamesLinuxRawGamepad);
	switch (property_id) {
		case GAMES_LINUX_RAW_GAMEPAD_GUID:
		g_value_set_string (value, games_raw_gamepad_get_guid ((GamesRawGamepad*) self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}



