diff --git a/repos/dde_linux/README b/repos/dde_linux/README index 555829c230..56bfcf304e 100644 --- a/repos/dde_linux/README +++ b/repos/dde_linux/README @@ -45,10 +45,15 @@ hid xml tag: !... ! -! +! ! !... +If a touchscreen is multi-touch-capable than the multitouch attribute gears +which type of Genode input events are generated. If set to 'no' (default) +than absolute events are generated and no multitouch events. If set to 'yes' +solely multitouch events are generated. + Storage ~~~~~~~ diff --git a/repos/dde_linux/src/lib/usb/include/lx_emul.h b/repos/dde_linux/src/lib/usb/include/lx_emul.h index 5393113e6e..9ff20f11f1 100644 --- a/repos/dde_linux/src/lib/usb/include/lx_emul.h +++ b/repos/dde_linux/src/lib/usb/include/lx_emul.h @@ -3781,7 +3781,8 @@ static inline void dump_stack(void) { } enum input_event_type { EVENT_TYPE_PRESS, EVENT_TYPE_RELEASE, /* key press and release */ EVENT_TYPE_MOTION, /* any type of (pointer) motion */ - EVENT_TYPE_WHEEL /* mouse scroll wheel */ + EVENT_TYPE_WHEEL, /* mouse scroll wheel */ + EVENT_TYPE_TOUCH /* touchscreen events */ }; struct input_handle; @@ -3822,13 +3823,13 @@ typedef void (*genode_input_event_cb)(enum input_event_type type, * \return 0 on success; !0 otherwise */ void genode_input_register(genode_input_event_cb handler, unsigned long res_x, - unsigned long res_y); + unsigned long res_y, bool multitouch); void genode_evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); -void start_input_service(void *ep, unsigned long res_x, unsigned long res_y); +void start_input_service(void *ep, void *); /****************** diff --git a/repos/dde_linux/src/lib/usb/include/platform.h b/repos/dde_linux/src/lib/usb/include/platform.h index bafa054522..ef82c1fce7 100644 --- a/repos/dde_linux/src/lib/usb/include/platform.h +++ b/repos/dde_linux/src/lib/usb/include/platform.h @@ -37,7 +37,8 @@ struct Services * Screen resolution used by touch devices to convert touchscreen * absolute coordinates to screen absolute coordinates */ - unsigned long screen_width = 0; + bool multitouch = false; + unsigned long screen_width = 0; unsigned long screen_height = 0; Services() @@ -49,9 +50,10 @@ struct Services hid = true; try { - Genode::Xml_node node_screen = node_hid.sub_node("screen"); + Genode::Xml_node node_screen = node_hid.sub_node("touchscreen"); node_screen.attribute("width").value(&screen_width); node_screen.attribute("height").value(&screen_height); + multitouch = node_screen.attribute("multitouch").has_value("yes"); } catch (...) { screen_width = screen_height = 0; PDBG("Could not read screen resolution in config node"); diff --git a/repos/dde_linux/src/lib/usb/input/evdev.c b/repos/dde_linux/src/lib/usb/input/evdev.c index 5bd97f4240..659e9b925f 100644 --- a/repos/dde_linux/src/lib/usb/input/evdev.c +++ b/repos/dde_linux/src/lib/usb/input/evdev.c @@ -4,6 +4,7 @@ * \author Dirk Vogt * \author Sebastian Sumpf * \author Christian Menard + * \author Alexander Boettcher * \date 2009-04-20 * * The original implementation was in the L4Env from the TUD:OS group @@ -12,7 +13,7 @@ */ /* - * Copyright (C) 2009-2014 Genode Labs GmbH + * Copyright (C) 2009-2015 Genode Labs GmbH * Copyright (C) 2014 Ksys Labs LLC * * This file is part of the Genode OS framework, which is distributed @@ -28,9 +29,41 @@ /* Callback function to Genode subsystem */ static genode_input_event_cb handler;; -static unsigned long screen_x = 0; -static unsigned long screen_y = 0; +static unsigned long screen_x = 0; +static unsigned long screen_y = 0; +static bool disable_multitouch = true; +static bool disable_absolute = false; +static struct slot +{ + int id; /* current tracking id */ + int x; /* last reported x axis */ + int y; /* last reported y axis */ + int event; /* last reported ABS_MT_ event */ +} slots[16]; + + +static bool transform(struct input_handle *handle, int x, int y, + int * arg_ax, int * arg_ay) +{ + int const min_x_dev = input_abs_get_min(handle->dev, ABS_X); + int const min_y_dev = input_abs_get_min(handle->dev, ABS_Y); + int const max_x_dev = input_abs_get_max(handle->dev, ABS_X); + int const max_y_dev = input_abs_get_max(handle->dev, ABS_Y); + int const max_y_norm = max_y_dev - min_y_dev; + int const max_x_norm = max_x_dev - min_x_dev; + + if (!max_x_norm || !max_y_norm || !arg_ax || !arg_ay || + x < min_x_dev || y < min_y_dev || x > max_x_dev || y > max_y_dev) { + printk("Ignore input source with coordinates out of range\n"); + return false; + } + + *arg_ax = screen_x * (x - min_x_dev) / (max_x_norm); + *arg_ay = screen_y * (y - min_y_dev) / (max_y_norm); + + return true; +} void genode_evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) @@ -39,8 +72,8 @@ void genode_evdev_event(struct input_handle *handle, unsigned int type, static unsigned long count = 0; #endif - static int last_ax = -1; /* store the last absolute x value */ - + static int slot = 0; /* store current input slot */ + /* filter sound events */ if (test_bit(EV_SND, handle->dev->evbit)) return; @@ -60,8 +93,12 @@ void genode_evdev_event(struct input_handle *handle, unsigned int type, case EV_KEY: arg_keycode = code; - /* map BTN_TOUCH events to BTN_LEFT */ - if (code == BTN_TOUCH) + /* don't generate press/release events for multitouch devices */ + if (code == BTN_TOUCH && !disable_multitouch) + return; + + /* map BTN_TOUCH events to BTN_LEFT for absolute events */ + if (code == BTN_TOUCH && !disable_absolute) arg_keycode = BTN_LEFT; switch (value) { @@ -83,68 +120,117 @@ void genode_evdev_event(struct input_handle *handle, unsigned int type, case EV_ABS: switch (code) { + case ABS_WHEEL: + + if (disable_absolute) return; + + arg_type = EVENT_TYPE_WHEEL; + arg_ry = value; + break; + case ABS_X: case ABS_MT_POSITION_X: + if (code == ABS_X && disable_absolute) return; + if (code == ABS_MT_POSITION_X && disable_multitouch) return; + + if (((slots[slot].event == ABS_MT_POSITION_X) || + (slots[slot].event == ABS_X)) && (slots[slot].y != -1)) { + + arg_keycode = slot; + arg_type = code == ABS_X ? EVENT_TYPE_MOTION : EVENT_TYPE_TOUCH; + arg_ax = slots[slot].x; + arg_ay = slots[slot].y; + + if (screen_x && screen_y && + !transform(handle, arg_ax, arg_ay, &arg_ax, &arg_ay)) + return; + + if (handler) + handler(arg_type, arg_keycode, arg_ax, arg_ay, arg_rx, arg_ry); + } + + slots[slot].event = code; + /* * Don't create an input event yet. Store the value and wait for the * subsequent Y event. */ - last_ax = value; + slots[slot].x = value; return; case ABS_Y: case ABS_MT_POSITION_Y: + if (code == ABS_Y && disable_absolute) return; + if (code == ABS_MT_POSITION_Y && disable_multitouch) return; + + slots[slot].event = code; + slots[slot].y = value; + + if (slots[slot].x == -1) + return; + /* * Create a unified input event with absolute positions on x and y * axis. */ - arg_type = EVENT_TYPE_MOTION; - arg_ax = last_ax; - arg_ay = value; + arg_keycode = slot; + arg_type = code == ABS_Y ? EVENT_TYPE_MOTION : EVENT_TYPE_TOUCH; + arg_ax = slots[slot].x; + arg_ay = value; /* transform if requested */ - if (screen_x && screen_y) { - int const min_x_dev = input_abs_get_min(handle->dev, ABS_X); - int const min_y_dev = input_abs_get_min(handle->dev, ABS_Y); - int const max_x_dev = input_abs_get_max(handle->dev, ABS_X); - int const max_y_dev = input_abs_get_max(handle->dev, ABS_Y); - int const max_y_norm = max_y_dev - min_y_dev; - int const max_x_norm = max_x_dev - min_x_dev; + if (screen_x && screen_y && + !transform(handle, arg_ax, value, &arg_ax, &arg_ay)) + return; - if ((max_x_norm == 0) || (max_y_norm == 0) || - (last_ax < min_x_dev) || (value < min_y_dev) || - (last_ax > max_x_dev) || (value > max_y_dev)) - { - printk("Ignore input source with coordinates out of range\n"); - return; - } + break; - arg_ax = screen_x * (last_ax - min_x_dev) / (max_x_norm); - arg_ay = screen_y * (value - min_y_dev) / (max_y_norm); - } + case ABS_MT_TRACKING_ID: - last_ax = -1; - if (arg_ax == -1) { - printk("Ignore absolute Y event without a preceeding X event\n"); + if (disable_multitouch) return; + + if (value != -1) { + if (slots[slot].id != -1) + dde_kit_printf("warning:: old tracking id in use and got new one\n"); + + slots[slot].id = value; return; } + + /* send end of slot usage event for clients */ + arg_keycode = slot; + arg_type = EVENT_TYPE_TOUCH; + arg_ax = slots[slot].x < 0 ? 0 : slots[slot].x; + arg_ay = slots[slot].y < 0 ? 0 : slots[slot].y; + arg_rx = arg_ry = -1; + + if (screen_x && screen_y) + transform(handle, arg_ax, arg_ay, &arg_ax, &arg_ay); + + slots[slot].event = slots[slot].x = slots[slot].y = -1; + slots[slot].id = value; + break; - case ABS_WHEEL: + case ABS_MT_SLOT: - /* - * XXX I do not know, how to handle this correctly. At least, this - * scheme works on Qemu. - */ - arg_type = EVENT_TYPE_WHEEL; - arg_ry = value; - break; + if (disable_multitouch) return; + + if (value >= sizeof(slots) / sizeof(slots[0])) { + dde_kit_printf("warning: drop slot id %d\n", value); + return; + } + + slot = value; + return; default: + printk("Unknown absolute event code %d - not handled\n", code); return; + } break; @@ -194,10 +280,18 @@ void genode_evdev_event(struct input_handle *handle, unsigned int type, void genode_input_register(genode_input_event_cb h, unsigned long res_x, - unsigned long res_y) + unsigned long res_y, bool multitouch) { + unsigned i = 0; + for (i = 0; i < sizeof(slots) / sizeof(slots[0]); i++) + slots[i].id = slots[i].event = slots[i].x = slots[i].y = -1; + handler = h; + /* XXX make it per usb device configurable XXX */ screen_x = res_x; screen_y = res_y; + + disable_multitouch = !multitouch; + disable_absolute = !disable_multitouch; } diff --git a/repos/dde_linux/src/lib/usb/input/input_component.cc b/repos/dde_linux/src/lib/usb/input/input_component.cc index 07c40c5bf2..90bd748376 100644 --- a/repos/dde_linux/src/lib/usb/input/input_component.cc +++ b/repos/dde_linux/src/lib/usb/input/input_component.cc @@ -22,6 +22,7 @@ #include #include +#include "platform.h" #undef RELEASE using namespace Genode; @@ -65,6 +66,7 @@ static void input_callback(enum input_event_type type, case EVENT_TYPE_RELEASE: t = Input::Event::RELEASE; break; case EVENT_TYPE_MOTION: t = Input::Event::MOTION; break; case EVENT_TYPE_WHEEL: t = Input::Event::WHEEL; break; + case EVENT_TYPE_TOUCH: t = Input::Event::TOUCH; break; } input_session().submit(Input::Event(t, code, @@ -73,11 +75,13 @@ static void input_callback(enum input_event_type type, } -void start_input_service(void *ep_ptr, unsigned long res_x, unsigned long res_y) +void start_input_service(void *ep_ptr, void * service_ptr) { Rpc_entrypoint *ep = static_cast(ep_ptr); + Services *service = static_cast(service_ptr); env()->parent()->announce(ep->manage(&input_root(ep))); - genode_input_register(input_callback, res_x, res_y); + genode_input_register(input_callback, service->screen_width, + service->screen_height, service->multitouch); } diff --git a/repos/dde_linux/src/lib/usb/main.cc b/repos/dde_linux/src/lib/usb/main.cc index d77530d400..99af661f01 100644 --- a/repos/dde_linux/src/lib/usb/main.cc +++ b/repos/dde_linux/src/lib/usb/main.cc @@ -44,7 +44,7 @@ extern "C" void module_ch_driver_init(); extern "C" void module_mt_driver_init(); extern "C" void module_raw_driver_init(); -extern "C" void start_input_service(void *ep, unsigned long, unsigned long); +extern "C" void start_input_service(void *ep, void *services); Routine *Routine::_current = 0; Routine *Routine::_dead = 0; @@ -94,8 +94,7 @@ void start_usb_driver(Server::Entrypoint &ep) Services services; if (services.hid) - start_input_service(&ep.rpc_ep(), services.screen_width, - services.screen_height); + start_input_service(&ep.rpc_ep(), &services); Timer::init(ep); Irq::init(ep);