summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2014-01-06 11:53:44 +0000
committerChris Michael <cp.michael@samsung.com>2014-01-29 15:27:23 +0000
commitc7b520cd804f45cf93bd1ca84e0f2cb3ce385f41 (patch)
tree3c6134f341ede9c6685b5caf7fff66c01b179688
parent49f0d2790b1593ac5c8fbe14d958e2efac6d4f81 (diff)
downloadefl-c7b520cd804f45cf93bd1ca84e0f2cb3ce385f41.tar.gz
Fix evdev code:
- Add code to setup devices and configure them - Add code to process input events (key down, mouse, etc). - Add code to create new Ecore_Drm_Evdev's Signed-off-by: Chris Michael <cp.michael@samsung.com>
-rw-r--r--src/lib/ecore_drm/ecore_drm_evdev.c369
1 files changed, 327 insertions, 42 deletions
diff --git a/src/lib/ecore_drm/ecore_drm_evdev.c b/src/lib/ecore_drm/ecore_drm_evdev.c
index a118a16ab4..0e5e840056 100644
--- a/src/lib/ecore_drm/ecore_drm_evdev.c
+++ b/src/lib/ecore_drm/ecore_drm_evdev.c
@@ -2,74 +2,359 @@
# include <config.h>
#endif
+/* copied from udev/extras/input_id/input_id.c */
+/* we must use this kernel-compatible implementation */
+#define BITS_PER_LONG (sizeof(unsigned long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define BIT(x) (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
+/* end copied */
+
#include "ecore_drm_private.h"
+#include <sys/ioctl.h>
+#include <linux/input.h>
-Ecore_Drm_Evdev *
-_ecore_drm_evdev_device_create(struct libinput *linput, struct libinput_device *ldevice)
+/* local functions */
+static Eina_Bool
+_device_configure(Ecore_Drm_Evdev *edev)
{
- Ecore_Drm_Evdev *evdev;
- struct libinput_seat *lseat;
+ Eina_Bool ret = EINA_FALSE;
- if (!(evdev = calloc(1, sizeof(Ecore_Drm_Evdev))))
- return NULL;
+ if (!edev) return EINA_FALSE;
- lseat = libinput_device_get_seat(ldevice);
+ if ((edev->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) &&
+ (edev->caps & EVDEV_BUTTON))
+ {
+ DBG("Input device %s is a pointer", edev->name);
+ edev->seat_caps |= EVDEV_SEAT_POINTER;
+ ret = EINA_TRUE;
+ }
- evdev->linput = linput;
- evdev->seat = libinput_seat_get_user_data(lseat);
- evdev->dev = ldevice;
+ if (edev->caps & EVDEV_KEYBOARD)
+ {
+ DBG("Input device %s is a keyboard", edev->name);
+ edev->seat_caps |= EVDEV_SEAT_KEYBOARD;
+ ret = EINA_TRUE;
+ }
- libinput_device_set_user_data(ldevice, evdev);
- libinput_device_ref(ldevice);
+ if (edev->caps & EVDEV_TOUCH)
+ {
+ DBG("Input device %s is a touchpad", edev->name);
+ edev->seat_caps |= EVDEV_SEAT_TOUCH;
+ ret = EINA_TRUE;
+ }
- return evdev;
+ return ret;
}
-void
-_ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev)
+static Eina_Bool
+_device_handle(Ecore_Drm_Evdev *edev)
{
- if (!evdev) return;
- libinput_device_unref(evdev->dev);
- if (evdev->name) eina_stringshare_del(evdev->name);
- free(evdev);
+ struct input_absinfo absinfo;
+ unsigned long dev_bits[NBITS(EV_MAX)];
+ unsigned long abs_bits[NBITS(ABS_MAX)];
+ unsigned long rel_bits[NBITS(REL_MAX)];
+ unsigned long key_bits[NBITS(KEY_MAX)];
+ /* Eina_Bool have_key = EINA_FALSE; */
+ Eina_Bool have_abs = EINA_FALSE;
+
+ if (!edev) return EINA_FALSE;
+
+ ioctl(edev->fd, EVIOCGBIT(0, sizeof(dev_bits)), dev_bits);
+ if (TEST_BIT(dev_bits, EV_ABS))
+ {
+ have_abs = EINA_TRUE;
+
+ ioctl(edev->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
+
+ if ((TEST_BIT(abs_bits, ABS_WHEEL)) ||
+ (TEST_BIT(abs_bits, ABS_GAS)) ||
+ (TEST_BIT(abs_bits, ABS_BRAKE)) ||
+ (TEST_BIT(abs_bits, ABS_HAT0X)))
+ {
+ /* ignore joystick */
+ return EINA_FALSE;
+ }
+
+ if (TEST_BIT(abs_bits, ABS_X))
+ {
+ ioctl(edev->fd, EVIOCGABS(ABS_X), &absinfo);
+ edev->abs.min_x = absinfo.minimum;
+ edev->abs.max_x = absinfo.maximum;
+ edev->caps |= EVDEV_MOTION_ABS;
+ }
+
+ if (TEST_BIT(abs_bits, ABS_Y))
+ {
+ ioctl(edev->fd, EVIOCGABS(ABS_Y), &absinfo);
+ edev->abs.min_y = absinfo.minimum;
+ edev->abs.max_y = absinfo.maximum;
+ edev->caps |= EVDEV_MOTION_ABS;
+ }
+
+ if ((TEST_BIT(abs_bits, ABS_MT_POSITION_X)) &&
+ (TEST_BIT(abs_bits, ABS_MT_POSITION_Y)))
+ {
+ DBG("Handle MultiTouch Device: %s", edev->path);
+ }
+ }
+
+ if (TEST_BIT(dev_bits, EV_REL))
+ {
+ ioctl(edev->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits);
+
+ if ((TEST_BIT(rel_bits, REL_X)) || (TEST_BIT(rel_bits, REL_Y)))
+ edev->caps |= EVDEV_MOTION_REL;
+ }
+
+ if (TEST_BIT(dev_bits, EV_KEY))
+ {
+ unsigned int i = 0;
+
+ /* have_key = EINA_TRUE; */
+
+ ioctl(edev->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
+
+ if (have_abs)
+ {
+ if ((TEST_BIT(key_bits, BTN_TOOL_FINGER)) &&
+ (!TEST_BIT(key_bits, BTN_TOOL_PEN)))
+ {
+ DBG("Device Is Touchpad: %s", edev->path);
+ }
+ }
+
+ for (i = KEY_ESC; i < KEY_MAX; i++)
+ {
+ if ((i >= BTN_MISC) && (i < KEY_OK)) continue;
+ if (TEST_BIT(key_bits, i))
+ {
+ edev->caps |= EVDEV_KEYBOARD;
+ break;
+ }
+ }
+
+ if (TEST_BIT(key_bits, BTN_TOUCH))
+ edev->caps |= EVDEV_TOUCH;
+
+ for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
+ {
+ if (TEST_BIT(key_bits, i))
+ {
+ edev->caps |= EVDEV_BUTTON;
+ edev->caps &= ~EVDEV_TOUCH;
+ break;
+ }
+ }
+ }
+
+ if (TEST_BIT(dev_bits, EV_LED)) edev->caps |= EVDEV_KEYBOARD;
+
+ return EINA_TRUE;
}
-int
-_ecore_drm_evdev_event_process(struct libinput_event *event)
+static void
+_device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
{
- /* struct libinput_device *device; */
- int ret = 1;
+ DBG("Key Event");
+ DBG("\tCode: %d", event->code);
+ DBG("\tValue: %d", event->value);
+
+ if ((event->code >= KEY_ESC) && (event->code <= KEY_COMPOSE))
+ {
+ /* ignore key repeat */
+ if (event->value == 2)
+ {
+ DBG("\tKey Repeat");
+ }
+ }
+}
- /* device = libinput_event_get_target(event).device; */
- switch (libinput_event_get_type(event))
+static void
+_device_process_flush(Ecore_Drm_Evdev *dev, unsigned int timestamp)
+{
+ switch (dev->pending_event)
{
- case LIBINPUT_EVENT_DEVICE_REGISTER_CAPABILITY:
- DBG("Evdev Register Capability");
+ case EVDEV_NONE:
+ return;
+ case EVDEV_RELATIVE_MOTION:
+ goto out;
break;
- case LIBINPUT_EVENT_DEVICE_UNREGISTER_CAPABILITY:
- DBG("Evdev Unregister Capability");
+ case EVDEV_ABSOLUTE_MT_DOWN:
+ goto out;
break;
- case LIBINPUT_EVENT_KEYBOARD_KEY:
- DBG("Evdev Event Key");
+ case EVDEV_ABSOLUTE_MT_MOTION:
+ goto out;
break;
- case LIBINPUT_EVENT_POINTER_MOTION:
- DBG("Evdev Event Pointer Motion");
+ case EVDEV_ABSOLUTE_MT_UP:
+ goto out;
break;
- case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
- DBG("Evdev Event Pointer Motion Absolute");
+ case EVDEV_ABSOLUTE_TOUCH_DOWN:
+ goto out;
break;
- case LIBINPUT_EVENT_POINTER_BUTTON:
- DBG("Evdev Event Pointer Button");
+ case EVDEV_ABSOLUTE_MOTION:
+ goto out;
break;
- case LIBINPUT_EVENT_POINTER_AXIS:
- DBG("Evdev Event Pointer Axis");
+ case EVDEV_ABSOLUTE_TOUCH_UP:
+ goto out;
break;
- case LIBINPUT_EVENT_TOUCH_TOUCH:
+ }
+
+out:
+ dev->pending_event = EVDEV_NONE;
+}
+
+static void
+_device_process_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
+{
+ if (event->code == BTN_TOUCH)
+ {
+ /* TODO: check for mt device */
+ return;
+ }
+
+ _device_process_flush(dev, timestamp);
+
+ switch (event->code)
+ {
+ case BTN_LEFT:
+ case BTN_RIGHT:
+ case BTN_MIDDLE:
+ case BTN_SIDE:
+ case BTN_EXTRA:
+ case BTN_FORWARD:
+ case BTN_BACK:
+ case BTN_TASK:
+ /* TODO: notify button */
break;
default:
- ret = 0;
+ _device_notify_key(dev, event, timestamp);
break;
}
+}
- return ret;
+static void
+_device_process(Ecore_Drm_Evdev *dev, struct input_event *event, int count)
+{
+ struct input_event *ev, *end;
+ unsigned int timestamp = 0;
+
+ DBG("Evdev Device Process");
+
+ ev = event;
+ end = ev + count;
+ for (ev = event; ev < end; ev++)
+ {
+ timestamp = (ev->time.tv_sec * 1000) + (ev->time.tv_usec / 1000);
+
+ switch (ev->type)
+ {
+ case EV_KEY:
+ _device_process_key(dev, ev, timestamp);
+ break;
+ case EV_REL:
+ DBG("\tRelative Event");
+ break;
+ case EV_ABS:
+ DBG("\tAbsolute Event");
+ break;
+ case EV_SYN:
+ _device_process_flush(dev, timestamp);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static Eina_Bool
+_cb_device_data(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+ Ecore_Drm_Evdev *edev;
+ struct input_event ev[32];
+ int len = 0;
+
+ if (!(edev = data)) return EINA_TRUE;
+
+ do
+ {
+ len = read(edev->fd, &ev, sizeof(ev));
+
+ if ((len < 0) || ((len % sizeof(ev[0])) != 0))
+ {
+ if ((len < 0) && (errno != EAGAIN) && (errno != EINTR))
+ {
+ ERR("Device Died");
+ }
+
+ return EINA_TRUE;
+ }
+
+ edev->event_process(edev, ev, (len / sizeof(ev[0])));
+
+ } while (len > 0);
+
+ return EINA_TRUE;
+}
+
+/* external functions */
+Ecore_Drm_Evdev *
+_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd)
+{
+ Ecore_Drm_Evdev *edev;
+ char name[256] = "unknown";
+
+ if (!(edev = calloc(1, sizeof(Ecore_Drm_Evdev))))
+ return NULL;
+
+ edev->seat = seat;
+ edev->path = eina_stringshare_add(path);
+ edev->fd = fd;
+
+ if (ioctl(edev->fd, EVIOCGNAME(sizeof(name)), name) < 0)
+ DBG("Error getting device name: %m");
+
+ name[sizeof(name) - 1] = '\0';
+ edev->name = eina_stringshare_add(name);
+
+ if (!_device_handle(edev))
+ {
+ ERR("Unhandled Input Device: %s", name);
+ _ecore_drm_evdev_device_destroy(edev);
+ return NULL;
+ }
+
+ if (!_device_configure(edev))
+ {
+ _ecore_drm_evdev_device_destroy(edev);
+ return NULL;
+ }
+
+ edev->event_process = _device_process;
+
+ edev->hdlr =
+ ecore_main_fd_handler_add(edev->fd, ECORE_FD_READ,
+ _cb_device_data, edev, NULL, NULL);
+ if (!edev->hdlr)
+ {
+ ERR("Could not create fd handler");
+ _ecore_drm_evdev_device_destroy(edev);
+ return NULL;
+ }
+
+ return edev;
+}
+
+void
+_ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *dev)
+{
+ if (!dev) return;
+
+ if (dev->path) eina_stringshare_del(dev->path);
+ if (dev->name) eina_stringshare_del(dev->name);
+ if (dev->hdlr) ecore_main_fd_handler_del(dev->hdlr);
+
+ free(dev);
}