--- /dev/null
+//Compile with:
+// gcc -g -Wall -o ecore_input_joystick_example ecore_input_joystick_example.c `pkg-config --cflags --libs ecore ecore-input`
+
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+static Eina_Bool
+_joystick_event_handler_cb(void *data, int type EINA_UNUSED, void *event)
+{
+ Ecore_Event_Joystick *ev = event;
+ switch (ev->type)
+ {
+ case ECORE_EVENT_JOYSTICK_EVENT_TYPE_CONNECTED:
+ printf("joystick is connected: %d\n", ev->index);
+ break;
+ case ECORE_EVENT_JOYSTICK_EVENT_TYPE_DISCONNECTED:
+ printf("joystick is disconnected: %d\n", ev->index);
+ break;
+ case ECORE_EVENT_JOYSTICK_EVENT_TYPE_BUTTON:
+ printf("joystick(%d) button index: %d, value: %f, time: %u\n",
+ ev->index, ev->button.index,
+ ev->button.value, ev->timestamp);
+ break;
+ case ECORE_EVENT_JOYSTICK_EVENT_TYPE_AXIS:
+ printf("joystick(%d) axis index: %d, value: %f, time: %u\n",
+ ev->index, ev->axis.index,
+ ev->axis.value, ev->timestamp);
+ break;
+ default:
+ printf("unhandled event type: %d\n", ev->type);
+ break;
+ }
+
+ if (ev->type == ECORE_EVENT_JOYSTICK_EVENT_TYPE_BUTTON &&
+ ev->button.index == ECORE_EVENT_JOYSTICK_BUTTON_START)
+ ecore_main_loop_quit();
+
+ return ECORE_CALLBACK_DONE;
+}
+
+int
+main(void)
+{
+ if (!ecore_event_init())
+ {
+ printf("ERROR: Cannot init Ecore!\n");
+ return -1;
+ }
+
+ ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
+ _joystick_event_handler_cb,
+ NULL);
+
+ ecore_input_joystick_init();
+
+ printf("start the main loop.\n");
+
+ ecore_main_loop_begin();
+
+ ecore_input_joystick_shutdown();
+ ecore_shutdown();
+
+ return 0;
+}
EAPI extern int ECORE_EVENT_DEVICE_ADD;
EAPI extern int ECORE_EVENT_DEVICE_DEL;
EAPI extern int ECORE_EVENT_DETENT_ROTATE; //TIZEN ONLY
+ EAPI extern int ECORE_EVENT_JOYSTICK; /**< @since 1.15 */
#define ECORE_EVENT_MODIFIER_SHIFT 0x0001
#define ECORE_EVENT_MODIFIER_CTRL 0x0002
typedef struct _Ecore_Axis Ecore_Axis; /**< @since 1.13 */
typedef struct _Ecore_Event_Device_Info Ecore_Event_Device_Info;
typedef struct _Ecore_Event_Detent_Rotate Ecore_Event_Detent_Rotate; //TIZEN ONLY
+ typedef struct _Ecore_Event_Joystick Ecore_Event_Joystick; /**< @since 1.15 */
/**
* @typedef Ecore_Event_Modifier
};
/**
+ * @struct _Ecore_Event_Joystic_Button
+ * Contains information about a joystick button event.
+ */
+ typedef enum _Ecore_Event_Joystick_Button
+ {
+ ECORE_EVENT_JOYSTICK_BUTTON_NONE,
+ ECORE_EVENT_JOYSTICK_BUTTON_FACE_0,
+ ECORE_EVENT_JOYSTICK_BUTTON_FACE_1,
+ ECORE_EVENT_JOYSTICK_BUTTON_FACE_2,
+ ECORE_EVENT_JOYSTICK_BUTTON_FACE_3,
+ ECORE_EVENT_JOYSTICK_BUTTON_LEFT_SHOULDER,
+ ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_SHOULDER,
+ ECORE_EVENT_JOYSTICK_BUTTON_SELECT,
+ ECORE_EVENT_JOYSTICK_BUTTON_START,
+ ECORE_EVENT_JOYSTICK_BUTTON_LEFT_ANALOG_STICK,
+ ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_ANALOG_STICK,
+ ECORE_EVENT_JOYSTICK_BUTTON_LAST
+ } Ecore_Event_Joystick_Button; /**< @since 1.15 */
+
+ /**
+ * @struct _Ecore_Event_Joystic_Axis
+ * Contains information about a joystick axis event.
+ */
+ typedef enum _Ecore_Event_Joystick_Axis
+ {
+ ECORE_EVENT_JOYSTICK_AXIS_NONE,
+ ECORE_EVENT_JOYSTICK_AXIS_HAT_X,
+ ECORE_EVENT_JOYSTICK_AXIS_HAT_Y,
+ ECORE_EVENT_JOYSTICK_AXIS_LEFT_SHOULDER,
+ ECORE_EVENT_JOYSTICK_AXIS_RIGHT_SHOULDER,
+ ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_HOR,
+ ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_VER,
+ ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_HOR,
+ ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_VER,
+ ECORE_EVENT_JOYSTICK_AXIS_LAST
+ } Ecore_Event_Joystick_Axis; /**< @since 1.15 */
+
+ /**
+ * @struct _Ecore_Event_Joystic_Event_Type
+ * Contains information about a joystick event type.
+ */
+ typedef enum _Ecore_Event_Joystick_Event
+ {
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_NONE,
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_CONNECTED,
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_DISCONNECTED,
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_BUTTON,
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_AXIS,
+ ECORE_EVENT_JOYSTICK_EVENT_TYPE_LAST
+ } Ecore_Event_Joystick_Event_Type; /**< @since 1.15 */
+
+ /**
* @struct _Ecore_Event_Key
* Contains information about an Ecore keyboard event.
*/
};
/**
+ * @struct _Ecore_Event_Joystick
+ * Contains information about a joystick event.
+ */
+ struct _Ecore_Event_Joystick
+ {
+ Ecore_Event_Joystick_Event_Type type;
+ unsigned int index;
+ unsigned int timestamp;
+
+ union
+ {
+ struct
+ {
+ Ecore_Event_Joystick_Axis index;
+ double value; /* [-1.0 .. 1.0] -1.0 == up or left, 1.0 == down or right */
+ } axis;
+
+ struct
+ {
+ Ecore_Event_Joystick_Button index;
+ double value; /* [0.0 .. 1.0] 0.0 == fully unpressed, 1.0 == fully pressed */
+ } button;
+ };
+ };
+
+ /**
* Initialises the Ecore Event system.
*/
EAPI int ecore_event_init(void);
* @return The status of the composition.
*/
EAPI Ecore_Compose_State ecore_compose_get(const Eina_List *seq, char **seqstr_ret);
-
+//TIZEN_ONLY(20160627) - Initial version of ecore joystick event
+ /**
+ * Initialises the Ecore Input Joystick system.
+ * @since 1.15
+ */
+ EAPI int ecore_input_joystick_init(void);
+ /**
+ * Shutdowns the Ecore Input Joystick system.
+ * @since 1.15
+ */
+ EAPI int ecore_input_joystick_shutdown(void);
+//
#ifdef __cplusplus
}
#endif
--- /dev/null
+#include <libudev.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/input.h>
+
+#include "Ecore.h"
+#include "Ecore_Input.h"
+#include "ecore_input_private.h"
+
+static const char joystickPrefix[] = "/dev/input/event";
+
+static Eina_List *joystick_list;
+
+struct _Joystick_Info
+{
+ Ecore_Fd_Handler *fd_handler;
+ char *system_path;
+ int index;
+};
+typedef struct _Joystick_Info Joystick_Info;
+
+static int _ecore_input_joystick_init_count = 0;
+static struct udev_monitor *monitor = NULL;
+static Ecore_Fd_Handler *monitor_handler = NULL;
+
+static void
+_joystick_connected_event_add(int index, Eina_Bool connected)
+{
+ Ecore_Event_Joystick *e;
+ if (!(e = malloc(sizeof(Ecore_Event_Joystick)))) return;
+
+ e->index = index;
+ if (connected)
+ e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_CONNECTED;
+ else
+ e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_DISCONNECTED;
+
+ INF("index: %d, connected: %d", index, connected);
+ ecore_event_add(ECORE_EVENT_JOYSTICK, e, NULL, NULL);
+}
+
+static void
+_joystick_event_add(struct input_event *event, int index)
+{
+ Ecore_Event_Joystick *e;
+
+ if ((event->type != EV_KEY) && (event->type != EV_ABS)) return;
+ if (!(e = malloc(sizeof(Ecore_Event_Joystick)))) return;
+
+ if (event->type == EV_KEY)
+ {
+ e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_BUTTON;
+ e->button.value = event->value;
+ }
+ else
+ {
+ e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_AXIS;
+ e->axis.value = event->value;
+ }
+
+ e->index = index;
+ e->timestamp = ((event->time.tv_sec * 1000) + (event->time.tv_usec / 1000));
+
+ switch (event->code)
+ {
+ case BTN_A:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_0;
+ break;
+
+ case BTN_B:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_1;
+ break;
+
+ case BTN_C:
+ /* TODO: */
+ break;
+
+ case BTN_X:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_2;
+ break;
+
+ case BTN_Y:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_3;
+ break;
+
+ case BTN_Z:
+ /* TODO: */
+ break;
+
+ case BTN_TL:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_LEFT_SHOULDER;
+ break;
+
+ case BTN_TR:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_SHOULDER;
+ break;
+
+ case BTN_SELECT:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_SELECT;
+ break;
+
+ case BTN_START:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_START;
+ break;
+
+ case BTN_THUMBL:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_LEFT_ANALOG_STICK;
+ break;
+
+ case BTN_THUMBR:
+ e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_ANALOG_STICK;
+ break;
+
+ case 0x13f:
+ /* TODO: button "PLAY" */
+ break;
+
+ case ABS_X:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_HOR;
+ e->axis.value = event->value / 32767.0f;
+ break;
+
+ case ABS_Y:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_VER;
+ e->axis.value = event->value / 32767.0f;
+ break;
+
+ case ABS_Z:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_SHOULDER;
+ break;
+
+ case ABS_RX:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_HOR;
+ e->axis.value = event->value / 32767.0f;
+ break;
+
+ case ABS_RY:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_HOR;
+ e->axis.value = event->value / 32767.0f;
+ break;
+
+ case ABS_RZ:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_SHOULDER;
+ break;
+
+ case ABS_HAT0X: /* D-pad */
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_HAT_X;
+ break;
+
+ case ABS_HAT0Y:
+ e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_HAT_Y;
+ break;
+
+ default:
+ break;
+ }
+
+ ecore_event_add(ECORE_EVENT_JOYSTICK, e, NULL, NULL);
+}
+
+Eina_Bool _fd_handler_cb(void* userData, Ecore_Fd_Handler* fdHandler)
+{
+ int fd;
+ Joystick_Info *ji = userData;
+ struct input_event event;
+ ssize_t len;
+
+ fd = ecore_main_fd_handler_fd_get(fdHandler);
+
+ len = read(fd, &event, sizeof(event));
+ if (len == -1) return ECORE_CALLBACK_RENEW;
+
+ INF("index: %d, type: %d, code: %d, value: %d",
+ ji->index, event.type, event.code, event.value);
+
+ _joystick_event_add(&event, ji->index);
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static int
+_joystick_index_get(const char *dev)
+{
+ int plen, dlen, diff, ret = -1;
+
+ dlen = strlen(dev);
+ plen = strlen(joystickPrefix);
+ diff = dlen - plen;
+
+ if (diff > 0)
+ {
+ ret = atoi(dev + plen);
+ }
+
+ return ret;
+}
+
+static void
+_joystick_register(const char *dev, const char* syspath)
+{
+ int fd, index;
+ Joystick_Info *ji;
+
+ if (!dev) return;
+
+ index = _joystick_index_get(dev);
+ if (index == -1)
+ {
+ ERR("Invalid index value.");
+ return;
+ }
+
+ ji = calloc(1, sizeof(Joystick_Info));
+ if (!ji)
+ {
+ ERR("Cannot allocate memory.");
+ return;
+ }
+
+ ji->index = index;
+ ji->system_path = strdup(syspath);
+
+ fd = open(dev, O_RDONLY | O_NONBLOCK);
+ ji->fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ,
+ _fd_handler_cb, ji, 0, 0);
+
+ joystick_list = eina_list_append(joystick_list, ji);
+ _joystick_connected_event_add(index, EINA_TRUE);
+}
+
+static void
+_joystick_unregister(const char *syspath)
+{
+ int fd;
+ Eina_List *l;
+ Joystick_Info *ji;
+
+ EINA_LIST_FOREACH(joystick_list, l, ji)
+ {
+ if (!strcmp(syspath, ji->system_path))
+ {
+ fd = ecore_main_fd_handler_fd_get(ji->fd_handler);
+ close(fd);
+ ecore_main_fd_handler_del(ji->fd_handler);
+ joystick_list = eina_list_remove(joystick_list, ji);
+ _joystick_connected_event_add(ji->index, EINA_FALSE);
+ free(ji->system_path);
+ free(ji);
+ }
+ }
+}
+
+Eina_Bool _monitor_handler_cb(void* userData EINA_UNUSED, Ecore_Fd_Handler* fdHandler)
+{
+ struct udev_device *device;
+ const char *syspath, *action, *devnode;
+
+ if (!ecore_main_fd_handler_active_get(fdHandler, ECORE_FD_READ))
+ return ECORE_CALLBACK_RENEW;
+
+ device = udev_monitor_receive_device(monitor);
+ if (!device)
+ {
+ ERR("Cannot get device from monitor.");
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ syspath = udev_device_get_syspath(device);
+ if (!syspath)
+ {
+ ERR("Cannot get syspath from device.");
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ action = udev_device_get_action(device);
+ if (!action)
+ {
+ ERR("Action value is NULL.");
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ if (!strcmp(action, "add"))
+ {
+ devnode = udev_device_get_devnode(device);
+ _joystick_register(devnode, syspath);
+ udev_device_unref(device);
+ }
+ else if (!strcmp(action, "remove"))
+ {
+ _joystick_unregister(syspath);
+ }
+ else
+ {
+ WRN("Unhandled action: %s", action);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+EAPI int
+ecore_input_joystick_init(void)
+{
+ struct udev *udev;
+ struct udev_enumerate *en;
+ struct udev_list_entry *devs, *cur;
+ struct udev_device *device;
+ const char *syspath;
+ const char *devnode;
+ int fd;
+
+ if (++_ecore_input_joystick_init_count != 1)
+ return _ecore_input_joystick_init_count;
+
+ udev = udev_new();
+ if (!udev)
+ {
+ ERR("Cannot create udev.");
+ return --_ecore_input_joystick_init_count;
+ }
+
+ en = udev_enumerate_new(udev);
+ if (!en)
+ {
+ ERR("Cannot create udev enumerate.");
+ return --_ecore_input_joystick_init_count;
+ }
+
+ udev_enumerate_add_match_subsystem(en, "input");
+ udev_enumerate_add_match_property(en, "ID_INPUT_JOYSTICK", "1");
+
+ udev_enumerate_scan_devices(en);
+ devs = udev_enumerate_get_list_entry(en);
+ udev_list_entry_foreach(cur, devs)
+ {
+ syspath = udev_list_entry_get_name(cur);
+ device = udev_device_new_from_syspath(udev, syspath);
+ devnode = udev_device_get_devnode(device);
+
+ if (devnode && eina_str_has_prefix(devnode, joystickPrefix))
+ {
+ INF("syspath: %s, devnode: %s", syspath, devnode);
+ _joystick_register(devnode, syspath);
+ }
+ udev_device_unref(device);
+ }
+
+ /* add monitor */
+ monitor = udev_monitor_new_from_netlink(udev, "udev");
+ if (!monitor)
+ {
+ ERR("Cannot create monitor.");
+ --_ecore_input_joystick_init_count;
+ goto end;
+ }
+
+ udev_monitor_filter_add_match_subsystem_devtype(monitor, "input", NULL);
+ if (udev_monitor_enable_receiving(monitor))
+ {
+ ERR("Cannot enable monitor.");
+ --_ecore_input_joystick_init_count;
+ goto end;
+ }
+
+ fd = udev_monitor_get_fd(monitor);
+ monitor_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ,
+ _monitor_handler_cb,
+ NULL, 0, 0);
+end:
+ udev_enumerate_unref(en);
+ return _ecore_input_joystick_init_count;
+}
+
+EAPI int
+ecore_input_joystick_shutdown(void)
+{
+ int fd;
+
+ if (--_ecore_input_joystick_init_count != 0)
+ return _ecore_input_joystick_init_count;
+
+ if (monitor) udev_monitor_unref(monitor);
+ if (monitor_handler)
+ {
+ fd = ecore_main_fd_handler_fd_get(monitor_handler);
+ close(fd);
+ ecore_main_fd_handler_del(monitor_handler);
+ }
+
+ return _ecore_input_joystick_init_count;
+}