Ecore_Input: define data type for joysticks 55/117655/1
authorShinwoo Kim <kimcinoo.efl@gmail.com>
Mon, 13 Jun 2016 10:41:38 +0000 (19:41 +0900)
committerShinwoo Kim <cinoo.kim@samsung.com>
Tue, 7 Mar 2017 04:55:31 +0000 (13:55 +0900)
Summary: This adds support for joysticks for ecore_input

Reviewers: cedric, devilhorns, Sergeant_Whitespace, raster, thiepha, zmike, jpeg

Reviewed By: thiepha, zmike, jpeg

Subscribers: thiepha, stefan_schmidt, zmike, singh.amitesh, Sergeant_Whitespace, jgerecke, cedric, seoz

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D1538

Change-Id: Iba40a1a4be0e0d830c3d09cb719179f4b27b9190

configure.ac
src/Makefile_Ecore_Input.am
src/examples/ecore/ecore_input_joystick_example.c [new file with mode: 0644]
src/lib/ecore_input/Ecore_Input.h
src/lib/ecore_input/ecore_input.c
src/lib/ecore_input/ecore_input_joystick.c [new file with mode: 0644]
src/lib/ecore_input/ecore_input_private.h

index 9fb84d8..7621fdb 100755 (executable)
@@ -2761,6 +2761,134 @@ EFL_LIB_END([Ecore_File])
 #### End of Ecore_File
 
 
+#### Eeze
+have_libmount_new="no"
+have_libmount_old="no"
+have_eeze_mount="no"
+
+EFL_LIB_START_OPTIONAL([Eeze], [test "x${build_libeeze}" = "xyes"])
+
+### Additional options to configure
+AC_ARG_WITH([mount],
+  [AS_HELP_STRING([--with-mount], [specify mount bin @<:@default=detect@:>@])],
+  [with_eeze_mount=$withval], [with_eeze_mount="detect"])
+AC_ARG_WITH([umount],
+  [AS_HELP_STRING([--with-umount], [specify umount bin @<:@default=detect@:>@])],
+  [with_eeze_umount=$withval], [with_eeze_umount="detect"])
+AC_ARG_WITH([eject],
+  [AS_HELP_STRING([--with-eject], [specify eject bin @<:@default=detect@:>@])],
+  [with_eeze_eject=$withval], [with_eeze_eject="detect"])
+
+### Default values
+
+### Checks for programs
+
+### Checks for libraries
+EFL_INTERNAL_DEPEND_PKG([EEZE], [eina])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [eo])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore-file])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore-con])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [eet])
+EFL_INTERNAL_DEPEND_PKG([EEZE], [emile])
+
+EFL_DEPEND_PKG([EEZE], [UDEV], [libudev >= 148])
+
+AC_ARG_ENABLE([libmount],
+   [AS_HELP_STRING([--disable-libmount],[disable libmount support. @<:@default=enabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_libmount="yes"
+    else
+       want_libmount="no"
+       CFOPT_WARNING="xyes"
+    fi
+   ],
+   [want_libmount="yes"])
+
+EFL_OPTIONAL_DEPEND_PKG([EEZE], [${want_libmount}],
+   [EEZE_MOUNT], [mount >= 2.18.0])
+EFL_ADD_FEATURE([EEZE], [libmount], [${have_eeze_mount}])
+
+PKG_CHECK_EXISTS([libudev < 199],
+                 [have_libudev_old="yes"],
+                 [have_libudev_old="no"])
+AC_MSG_CHECKING([Use old libudev API (before 199)])
+AC_MSG_RESULT([${have_libudev_old}])
+
+PKG_CHECK_EXISTS([mount < 2.19.0],
+                 [have_libmount_old="yes"],
+                 [have_libmount_old="no"])
+AC_MSG_CHECKING([Use old libmount API (before 2.19.0)])
+AC_MSG_RESULT([${have_libmount_old}])
+
+PKG_CHECK_EXISTS([mount == 2.19.0],
+                 [have_libmount_219="yes"],
+                 [have_libmount_219="no"])
+AC_MSG_CHECKING([Use libmount 2.19.0 API])
+AC_MSG_RESULT([${have_libmount_219}])
+
+PKG_CHECK_EXISTS([mount > 2.19.0],
+                 [have_libmount_new="yes"],
+                 [have_libmount_new="no"])
+AC_MSG_CHECKING([Use new libmount API (newer than 2.19.0)])
+AC_MSG_RESULT([${have_libmount_new}])
+
+if test "x${have_libudev_old}" = "xyes"; then
+  AC_DEFINE_UNQUOTED([OLD_LIBUDEV], [1], [using older version of libudev])
+fi
+
+if test "x${have_libmount_old}" = "xyes"; then
+  AC_DEFINE_UNQUOTED([OLD_LIBMOUNT], [1], [using first version of libmount])
+fi
+
+## modules
+if test "${want_tizen}"  = "yes"; then
+  PKG_CHECK_MODULES([TIZEN_SENSOR], [capi-system-sensor >= 0.1.17])
+fi
+EFL_ADD_FEATURE([EEZE], [tizen])
+
+EFL_EVAL_PKGS([EEZE])
+
+### Checks for header files
+
+### Checks for types
+
+### Checks for structures
+
+### Checks for compiler characteristics
+
+### Checks for linker characteristics
+
+### Checks for library functions
+
+### Checks for binaries
+if test "x$with_eeze_mount" = "xdetect"; then
+  AC_PATH_PROG([with_eeze_mount], [mount], [])
+fi
+AC_DEFINE_UNQUOTED([EEZE_MOUNT_BIN], ["$with_eeze_mount"], [mount bin to use])
+
+if test "x$with_eeze_umount" = "xdetect";then
+  AC_PATH_PROG([with_eeze_umount], [umount], [])
+fi
+AC_DEFINE_UNQUOTED([EEZE_UNMOUNT_BIN], ["$with_eeze_umount"], [umount bin to use])
+
+if test "x$with_eeze_eject" = "xdetect";then
+  AC_PATH_PROG([with_eeze_eject], [eject], [])
+fi
+AC_DEFINE_UNQUOTED([EEZE_EJECT_BIN], ["$with_eeze_eject"], [eject bin to use])
+
+EFL_LIB_END_OPTIONAL([Eeze])
+
+AM_CONDITIONAL([EEZE_LIBMOUNT_AFTER_219],
+               [test "x${have_libmount_new}" = "xyes"])
+AM_CONDITIONAL([EEZE_LIBMOUNT_BEFORE_219],
+               [test "x${have_libmount_old}" = "xyes"])
+AM_CONDITIONAL([HAVE_EEZE_MOUNT], [test "x${have_eeze_mount}" = "xyes"])
+AM_CONDITIONAL([HAVE_EEZE_TIZEN], [test "x${want_tizen}" = "xyes"])
+#### End of Eeze
+
+
 #### Ecore_Input
 EFL_LIB_START([Ecore_Input])
 
@@ -2778,6 +2906,8 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [ecore])
 EFL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [eo])
 EFL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [eina])
 
+EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [${efl_lib_optional_eeze}], [eeze])
+
 ### Checks for header files
 
 ### Checks for types
@@ -3065,134 +3195,6 @@ EFL_LIB_END([Eldbus])
 #### End of Eldbus
 
 
-#### Eeze
-have_libmount_new="no"
-have_libmount_old="no"
-have_eeze_mount="no"
-
-EFL_LIB_START_OPTIONAL([Eeze], [test "x${build_libeeze}" = "xyes"])
-
-### Additional options to configure
-AC_ARG_WITH([mount],
-  [AS_HELP_STRING([--with-mount], [specify mount bin @<:@default=detect@:>@])],
-  [with_eeze_mount=$withval], [with_eeze_mount="detect"])
-AC_ARG_WITH([umount],
-  [AS_HELP_STRING([--with-umount], [specify umount bin @<:@default=detect@:>@])],
-  [with_eeze_umount=$withval], [with_eeze_umount="detect"])
-AC_ARG_WITH([eject],
-  [AS_HELP_STRING([--with-eject], [specify eject bin @<:@default=detect@:>@])],
-  [with_eeze_eject=$withval], [with_eeze_eject="detect"])
-
-### Default values
-
-### Checks for programs
-
-### Checks for libraries
-EFL_INTERNAL_DEPEND_PKG([EEZE], [eina])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [eo])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore-file])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [ecore-con])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [eet])
-EFL_INTERNAL_DEPEND_PKG([EEZE], [emile])
-
-EFL_DEPEND_PKG([EEZE], [UDEV], [libudev >= 148])
-
-AC_ARG_ENABLE([libmount],
-   [AS_HELP_STRING([--disable-libmount],[disable libmount support. @<:@default=enabled@:>@])],
-   [
-    if test "x${enableval}" = "xyes" ; then
-       want_libmount="yes"
-    else
-       want_libmount="no"
-       CFOPT_WARNING="xyes"
-    fi
-   ],
-   [want_libmount="yes"])
-
-EFL_OPTIONAL_DEPEND_PKG([EEZE], [${want_libmount}],
-   [EEZE_MOUNT], [mount >= 2.18.0])
-EFL_ADD_FEATURE([EEZE], [libmount], [${have_eeze_mount}])
-
-PKG_CHECK_EXISTS([libudev < 199],
-                 [have_libudev_old="yes"],
-                 [have_libudev_old="no"])
-AC_MSG_CHECKING([Use old libudev API (before 199)])
-AC_MSG_RESULT([${have_libudev_old}])
-
-PKG_CHECK_EXISTS([mount < 2.19.0],
-                 [have_libmount_old="yes"],
-                 [have_libmount_old="no"])
-AC_MSG_CHECKING([Use old libmount API (before 2.19.0)])
-AC_MSG_RESULT([${have_libmount_old}])
-
-PKG_CHECK_EXISTS([mount == 2.19.0],
-                 [have_libmount_219="yes"],
-                 [have_libmount_219="no"])
-AC_MSG_CHECKING([Use libmount 2.19.0 API])
-AC_MSG_RESULT([${have_libmount_219}])
-
-PKG_CHECK_EXISTS([mount > 2.19.0],
-                 [have_libmount_new="yes"],
-                 [have_libmount_new="no"])
-AC_MSG_CHECKING([Use new libmount API (newer than 2.19.0)])
-AC_MSG_RESULT([${have_libmount_new}])
-
-if test "x${have_libudev_old}" = "xyes"; then
-  AC_DEFINE_UNQUOTED([OLD_LIBUDEV], [1], [using older version of libudev])
-fi
-
-if test "x${have_libmount_old}" = "xyes"; then
-  AC_DEFINE_UNQUOTED([OLD_LIBMOUNT], [1], [using first version of libmount])
-fi
-
-## modules
-if test "${want_tizen}"  = "yes"; then
-  PKG_CHECK_MODULES([TIZEN_SENSOR], [capi-system-sensor >= 0.1.17])
-fi
-EFL_ADD_FEATURE([EEZE], [tizen])
-
-EFL_EVAL_PKGS([EEZE])
-
-### Checks for header files
-
-### Checks for types
-
-### Checks for structures
-
-### Checks for compiler characteristics
-
-### Checks for linker characteristics
-
-### Checks for library functions
-
-### Checks for binaries
-if test "x$with_eeze_mount" = "xdetect"; then
-  AC_PATH_PROG([with_eeze_mount], [mount], [])
-fi
-AC_DEFINE_UNQUOTED([EEZE_MOUNT_BIN], ["$with_eeze_mount"], [mount bin to use])
-
-if test "x$with_eeze_umount" = "xdetect";then
-  AC_PATH_PROG([with_eeze_umount], [umount], [])
-fi
-AC_DEFINE_UNQUOTED([EEZE_UNMOUNT_BIN], ["$with_eeze_umount"], [umount bin to use])
-
-if test "x$with_eeze_eject" = "xdetect";then
-  AC_PATH_PROG([with_eeze_eject], [eject], [])
-fi
-AC_DEFINE_UNQUOTED([EEZE_EJECT_BIN], ["$with_eeze_eject"], [eject bin to use])
-
-EFL_LIB_END_OPTIONAL([Eeze])
-
-AM_CONDITIONAL([EEZE_LIBMOUNT_AFTER_219],
-               [test "x${have_libmount_new}" = "xyes"])
-AM_CONDITIONAL([EEZE_LIBMOUNT_BEFORE_219],
-               [test "x${have_libmount_old}" = "xyes"])
-AM_CONDITIONAL([HAVE_EEZE_MOUNT], [test "x${have_eeze_mount}" = "xyes"])
-AM_CONDITIONAL([HAVE_EEZE_TIZEN], [test "x${want_tizen}" = "xyes"])
-#### End of Eeze
-
-
 #### Ecore_Drm
 have_libinput_new="no"
 EFL_LIB_START_OPTIONAL([Ecore_Drm], [test "${want_drm}" = "yes"])
index 2b7aaba..a664cfb 100644 (file)
@@ -11,6 +11,7 @@ lib/ecore_input/Ecore_Input.h
 lib_ecore_input_libecore_input_la_SOURCES = \
 lib/ecore_input/ecore_input.c \
 lib/ecore_input/ecore_input_compose.c \
+lib/ecore_input/ecore_input_joystick.c \
 lib/ecore_input/ecore_input_compose.h \
 lib/ecore_input/ecore_input_private.h
 
diff --git a/src/examples/ecore/ecore_input_joystick_example.c b/src/examples/ecore/ecore_input_joystick_example.c
new file mode 100644 (file)
index 0000000..ecf3433
--- /dev/null
@@ -0,0 +1,61 @@
+//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);
+
+   printf("start the main loop.\n");
+
+   ecore_main_loop_begin();
+
+   ecore_shutdown();
+
+   return 0;
+}
index c68c47a..556a5be 100644 (file)
@@ -63,6 +63,7 @@ extern "C" {
    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.18 */
 
 #define ECORE_EVENT_MODIFIER_SHIFT      0x0001
 #define ECORE_EVENT_MODIFIER_CTRL       0x0002
@@ -92,6 +93,7 @@ extern "C" {
    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.18 */
 
    /**
     * @typedef Ecore_Event_Modifier
@@ -152,6 +154,59 @@ extern "C" {
      };
 
    /**
+    * @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_META,
+        ECORE_EVENT_JOYSTICK_BUTTON_LAST
+     } Ecore_Event_Joystick_Button; /**< @since 1.18 */
+
+   /**
+    * @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.18 */
+
+   /**
+    * @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.18 */
+
+   /**
     * @struct _Ecore_Event_Key
     * Contains information about an Ecore keyboard event.
     */
@@ -351,11 +406,38 @@ extern "C" {
      };
 
    /**
-    * Initializes the Ecore Event system.
+    * @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.
     *
     * @if MOBILE @since_tizen 2.4
     * @elseif WEARABLE @since_tizen 3.0
     * @endif
+    * @struct _Ecore_Event_Joystick
     */
    EAPI int                  ecore_event_init(void);
    /**
index bd5dab2..40c0318 100644 (file)
@@ -26,6 +26,7 @@ EAPI int ECORE_EVENT_MOUSE_BUTTON_CANCEL = 0;
 EAPI int ECORE_EVENT_DEVICE_ADD = 0;
 EAPI int ECORE_EVENT_DEVICE_DEL = 0;
 EAPI int ECORE_EVENT_DETENT_ROTATE = 0; //TIZEN ONLY
+EAPI int ECORE_EVENT_JOYSTICK = 0;
 
 static int _ecore_event_init_count = 0;
 
@@ -61,6 +62,9 @@ ecore_event_init(void)
    ECORE_EVENT_DEVICE_ADD = ecore_event_type_new();
    ECORE_EVENT_DEVICE_DEL = ecore_event_type_new();
    ECORE_EVENT_DETENT_ROTATE = ecore_event_type_new(); //TIZEN ONLY
+   ECORE_EVENT_JOYSTICK = ecore_event_type_new();
+
+   ecore_input_joystick_init();
 
    return _ecore_event_init_count;
 }
@@ -84,6 +88,8 @@ ecore_event_shutdown(void)
    ECORE_EVENT_DEVICE_ADD = 0;
    ECORE_EVENT_DEVICE_DEL = 0;
    ECORE_EVENT_DETENT_ROTATE = 0; //TIZEN ONLY
+   ECORE_EVENT_JOYSTICK = 0;
+   ecore_input_joystick_shutdown();
    eina_log_domain_unregister(_ecore_input_log_dom);
    _ecore_input_log_dom = -1;
    ecore_shutdown();
diff --git a/src/lib/ecore_input/ecore_input_joystick.c b/src/lib/ecore_input/ecore_input_joystick.c
new file mode 100644 (file)
index 0000000..1f65ce4
--- /dev/null
@@ -0,0 +1,386 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/*FIXME: change OS specific value */
+#ifdef __linux__
+# include <linux/joystick.h>
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_EEZE
+ #include "Eeze.h"
+#endif
+#include "Ecore.h"
+#include "Ecore_Input.h"
+#include "ecore_input_private.h"
+
+static int _ecore_input_joystick_init_count = 0;
+
+#ifdef HAVE_EEZE
+
+typedef void (*Joystick_Mapper)(struct js_event *event, Ecore_Event_Joystick *e);
+static void _joystick_xiinput_mapper(struct js_event *event, Ecore_Event_Joystick *e);
+
+struct _Joystick_Info
+{
+   Ecore_Fd_Handler *fd_handler;
+   Eina_Stringshare *system_path;
+   int index;
+   Joystick_Mapper mapper;
+};
+typedef struct _Joystick_Info Joystick_Info;
+
+struct _Joystick_Mapping_Info
+{
+   const char *vendor;
+   const char *product;
+   Joystick_Mapper mapper;
+} Joystick_Mapping_Info[] = {{"045e", "028e", _joystick_xiinput_mapper}};
+
+static const char joystickPrefix[] = "/dev/input/js";
+static Eina_List *joystick_list;
+static Eeze_Udev_Watch *watch = NULL;
+
+static void
+_joystick_connected_event_add(int index, Eina_Bool connected)
+{
+   Ecore_Event_Joystick *e;
+   if (!(e = calloc(1, 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_xiinput_mapper(struct js_event *event, Ecore_Event_Joystick *e)
+{
+   if (event->type == JS_EVENT_BUTTON)
+     {
+        e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_BUTTON;
+        e->button.value = event->value;
+        switch (event->number)
+          {
+           case 0:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_0;
+             break;
+
+           case 1:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_1;
+             break;
+
+           case 2:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_2;
+             break;
+
+           case 3:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_FACE_3;
+             break;
+
+           case 4:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_LEFT_SHOULDER;
+             break;
+
+           case 5:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_SHOULDER;
+             break;
+
+           case 6:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_SELECT;
+             break;
+
+           case 7:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_START;
+             break;
+
+           case 8:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_META;
+             break;
+
+           case 9:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_LEFT_ANALOG_STICK;
+             break;
+
+           case 10:
+             e->button.index = ECORE_EVENT_JOYSTICK_BUTTON_RIGHT_ANALOG_STICK;
+             break;
+
+           default:
+             ERR("Unsupported joystick event: %d", event->number);
+             break;
+          }
+     }
+   else
+     {
+        e->type = ECORE_EVENT_JOYSTICK_EVENT_TYPE_AXIS;
+        e->axis.value = event->value / 32767.0f;;
+        switch (event->number)
+          {
+           case 0:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_HOR;
+             break;
+
+           case 1:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_ANALOG_VER;
+             break;
+
+           case 2:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_LEFT_SHOULDER;
+             break;
+
+           case 3:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_HOR;
+             break;
+
+           case 4:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_ANALOG_VER;
+             break;
+
+           case 5:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_RIGHT_SHOULDER;
+             break;
+
+           case 6:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_HAT_X;
+             break;
+
+           case 7:
+             e->axis.index = ECORE_EVENT_JOYSTICK_AXIS_HAT_Y;
+             break;
+
+           default:
+             ERR("Unsupported joystick event: %d", event->number);
+             break;
+          }
+     }
+}
+
+static void
+_joystick_event_add(struct js_event *event, Joystick_Info *ji)
+{
+   Ecore_Event_Joystick *e;
+
+   if ((event->type != JS_EVENT_BUTTON) && (event->type != JS_EVENT_AXIS)) return;
+   if (!(e = calloc(1, sizeof(Ecore_Event_Joystick)))) return;
+
+   e->index = ji->index;
+   e->timestamp = event->time;
+
+   ji->mapper(event, e);
+
+   ecore_event_add(ECORE_EVENT_JOYSTICK, e, NULL, NULL);
+}
+
+static Eina_Bool
+_fd_handler_cb(void* userData, Ecore_Fd_Handler* fdHandler)
+{
+   int fd;
+   Joystick_Info *ji = userData;
+   struct js_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, number: %d, value: %d",
+       ji->index, event.type, event.number, event.value);
+
+   _joystick_event_add(&event, ji);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Joystick_Mapper
+_joystick_mapping_info_get(const char* syspath)
+{
+   int index, mapping_info_size;
+   const char *parent, *vendor, *product;
+   Joystick_Mapper ret;
+
+   ret = NULL;
+   parent = eeze_udev_syspath_get_parent_filtered(syspath, "input", NULL);
+   vendor = eeze_udev_syspath_get_sysattr(parent, "id/vendor");
+   product = eeze_udev_syspath_get_sysattr(parent, "id/product");
+
+   mapping_info_size = (int)(sizeof(Joystick_Mapping_Info) / sizeof(Joystick_Mapping_Info[0]));
+   for (index = 0; index < mapping_info_size; index++)
+     {
+        if ((vendor && !strcmp(vendor, Joystick_Mapping_Info[index].vendor)) &&
+            (product && !strcmp(product, Joystick_Mapping_Info[index].product)))
+          {
+             INF("joystick mapping info found (vendor: %s, product: %s)", vendor, product);
+             ret = Joystick_Mapping_Info[index].mapper;
+             break;
+          }
+     }
+
+   eina_stringshare_del(parent);
+   eina_stringshare_del(vendor);
+   eina_stringshare_del(product);
+
+   return ret;
+}
+
+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* syspath)
+{
+   int fd, index;
+   const char *devnode;
+   Joystick_Info *ji;
+   Joystick_Mapper mapper;
+
+   devnode = eeze_udev_syspath_get_devpath(syspath);
+   if (!devnode) return;
+   if (!eina_str_has_prefix(devnode, joystickPrefix)) goto register_failed;
+
+   mapper = _joystick_mapping_info_get(syspath);
+   if (!mapper)
+     {
+        ERR("Unsupported joystick.");
+        goto register_failed;
+     }
+
+   index = _joystick_index_get(devnode);
+   if (index == -1)
+     {
+        ERR("Invalid index value.");
+        goto register_failed;
+     }
+
+   ji = calloc(1, sizeof(Joystick_Info));
+   if (!ji)
+     {
+        ERR("Cannot allocate memory.");
+        goto register_failed;
+     }
+
+   ji->index = index;
+   ji->mapper = mapper;
+   ji->system_path = eina_stringshare_ref(syspath);
+
+   fd = open(devnode, 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);
+
+register_failed:
+   eina_stringshare_del(devnode);
+}
+
+static void
+_joystick_unregister(const char *syspath)
+{
+   int   fd;
+   Eina_List *l, *l2;
+   Joystick_Info *ji;
+
+   EINA_LIST_FOREACH_SAFE(joystick_list, l, l2, ji)
+     {
+        if (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);
+             eina_stringshare_del(ji->system_path);
+             free(ji);
+             break;
+          }
+     }
+}
+
+static void
+_watch_cb(const char *syspath, Eeze_Udev_Event  event,
+          void *data EINA_UNUSED, Eeze_Udev_Watch *w EINA_UNUSED)
+{
+   switch (event) {
+   case EEZE_UDEV_EVENT_ADD:
+       _joystick_register(syspath);
+       break;
+   case EEZE_UDEV_EVENT_REMOVE:
+        _joystick_unregister(syspath);
+       break;
+   default:
+       break;
+   }
+
+   eina_stringshare_del(syspath);
+}
+#endif
+
+int
+ecore_input_joystick_init(void)
+{
+#ifdef HAVE_EEZE
+   Eina_List *syspaths;
+   const char *syspath;
+
+   if (++_ecore_input_joystick_init_count != 1)
+     return _ecore_input_joystick_init_count;
+
+   if (!eeze_init())
+     return --_ecore_input_joystick_init_count;
+
+   watch = eeze_udev_watch_add(EEZE_UDEV_TYPE_JOYSTICK,
+                               (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE),
+                               _watch_cb, NULL);
+
+   syspaths = eeze_udev_find_by_type(EEZE_UDEV_TYPE_JOYSTICK, NULL);
+   EINA_LIST_FREE(syspaths, syspath)
+     {
+        _joystick_register(syspath);
+        eina_stringshare_del(syspath);
+     }
+#endif
+
+   return _ecore_input_joystick_init_count;
+}
+
+int
+ecore_input_joystick_shutdown(void)
+{
+#ifdef HAVE_EEZE
+   if (--_ecore_input_joystick_init_count != 0)
+      return _ecore_input_joystick_init_count;
+
+   if (watch)
+     {
+        eeze_udev_watch_del(watch);
+        watch = NULL;
+     }
+   eeze_shutdown();
+#endif
+
+   return _ecore_input_joystick_init_count;
+}
index 70af227..4d085a1 100644 (file)
@@ -34,4 +34,6 @@ extern int _ecore_input_log_dom;
 #endif
 #define CRI(...) EINA_LOG_DOM_CRIT(_ecore_input_log_dom, __VA_ARGS__)
 
+int ecore_input_joystick_init(void);
+int ecore_input_joystick_shutdown(void);
 #endif