jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=f70be6eb28a2ed6c6bfc23a14d6ad2cebfe1b95b

commit f70be6eb28a2ed6c6bfc23a14d6ad2cebfe1b95b
Author: Shinwoo Kim <kimcinoo....@gmail.com>
Date:   Mon Jun 13 19:41:38 2016 +0900

    Ecore_Input: define data type for joysticks
    
    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
---
 configure.ac                                      | 259 ++++++++-------
 src/Makefile_Ecore_Input.am                       |   1 +
 src/examples/ecore/ecore_input_joystick_example.c |  61 ++++
 src/lib/ecore_input/Ecore_Input.h                 |  81 +++++
 src/lib/ecore_input/ecore_input.c                 |   6 +
 src/lib/ecore_input/ecore_input_joystick.c        | 386 ++++++++++++++++++++++
 src/lib/ecore_input/ecore_input_private.h         |   2 +
 7 files changed, 668 insertions(+), 128 deletions(-)

diff --git a/configure.ac b/configure.ac
index 9b220f5..f1cf8df 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3135,6 +3135,135 @@ 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], [efl])
+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])
 
@@ -3153,6 +3282,8 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [eo])
 EFL_INTERNAL_DEPEND_PKG([ECORE_INPUT], [efl])
 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
@@ -3486,134 +3617,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], [efl])
-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"
diff --git a/src/Makefile_Ecore_Input.am b/src/Makefile_Ecore_Input.am
index 2b7aaba..a664cfb 100644
--- a/src/Makefile_Ecore_Input.am
+++ b/src/Makefile_Ecore_Input.am
@@ -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
index 0000000..ecf3433
--- /dev/null
+++ b/src/examples/ecore/ecore_input_joystick_example.c
@@ -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;
+}
diff --git a/src/lib/ecore_input/Ecore_Input.h 
b/src/lib/ecore_input/Ecore_Input.h
index c7a74a9..45f6c38 100644
--- a/src/lib/ecore_input/Ecore_Input.h
+++ b/src/lib/ecore_input/Ecore_Input.h
@@ -55,6 +55,7 @@ extern "C" {
    EAPI extern int ECORE_EVENT_MOUSE_OUT;
    EAPI extern int ECORE_EVENT_AXIS_UPDATE; /**< @since 1.13 */
    EAPI extern int ECORE_EVENT_MOUSE_BUTTON_CANCEL; /**< @since 1.15 */
+   EAPI extern int ECORE_EVENT_JOYSTICK; /**< @since 1.18 */
 
 #define ECORE_EVENT_MODIFIER_SHIFT      0x0001
 #define ECORE_EVENT_MODIFIER_CTRL       0x0002
@@ -82,6 +83,7 @@ extern "C" {
    typedef struct _Ecore_Event_Modifiers    Ecore_Event_Modifiers;
    typedef struct _Ecore_Event_Axis_Update  Ecore_Event_Axis_Update; /**< 
@since 1.13 */
    typedef struct _Ecore_Axis               Ecore_Axis; /**< @since 1.13 */
+   typedef struct _Ecore_Event_Joystick     Ecore_Event_Joystick; /**< @since 
1.18 */
 
    /**
     * @typedef Ecore_Event_Modifier
@@ -133,6 +135,59 @@ extern "C" {
      } Ecore_Compose_State;
 
    /**
+    * @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.
     */
@@ -314,6 +369,32 @@ extern "C" {
      };
 
    /**
+    * @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);
diff --git a/src/lib/ecore_input/ecore_input.c 
b/src/lib/ecore_input/ecore_input.c
index 6b52eff..32441dd 100644
--- a/src/lib/ecore_input/ecore_input.c
+++ b/src/lib/ecore_input/ecore_input.c
@@ -24,6 +24,7 @@ EAPI int ECORE_EVENT_MOUSE_IN = 0;
 EAPI int ECORE_EVENT_MOUSE_OUT = 0;
 EAPI int ECORE_EVENT_AXIS_UPDATE = 0;
 EAPI int ECORE_EVENT_MOUSE_BUTTON_CANCEL = 0;
+EAPI int ECORE_EVENT_JOYSTICK = 0;
 
 static int _ecore_event_init_count = 0;
 
@@ -56,6 +57,9 @@ ecore_event_init(void)
    ECORE_EVENT_MOUSE_OUT = ecore_event_type_new();
    ECORE_EVENT_AXIS_UPDATE = ecore_event_type_new();
    ECORE_EVENT_MOUSE_BUTTON_CANCEL = ecore_event_type_new();
+   ECORE_EVENT_JOYSTICK = ecore_event_type_new();
+
+   ecore_input_joystick_init();
 
    return _ecore_event_init_count;
 }
@@ -76,6 +80,8 @@ ecore_event_shutdown(void)
    ECORE_EVENT_MOUSE_OUT = 0;
    ECORE_EVENT_AXIS_UPDATE = 0;
    ECORE_EVENT_MOUSE_BUTTON_CANCEL = 0;
+   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
index 0000000..1f65ce4
--- /dev/null
+++ b/src/lib/ecore_input/ecore_input_joystick.c
@@ -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;
+}
diff --git a/src/lib/ecore_input/ecore_input_private.h 
b/src/lib/ecore_input/ecore_input_private.h
index 70af227..4d085a1 100644
--- a/src/lib/ecore_input/ecore_input_private.h
+++ b/src/lib/ecore_input/ecore_input_private.h
@@ -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

-- 


Reply via email to