/***************************************************************************** * * utouch-frame - Touch Frame Library * * Copyright (C) 2010 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * ****************************************************************************/ #include #include "frame-impl.h" #include #include #include static int is_pointer(const struct evemu_device *dev) { return evemu_has_event(dev, EV_REL, REL_X) || evemu_has_event(dev, EV_KEY, BTN_TOOL_FINGER) || evemu_has_event(dev, EV_KEY, BTN_TOOL_PEN) || evemu_has_event(dev, EV_KEY, BTN_STYLUS) || evemu_has_event(dev, EV_KEY, BTN_MOUSE) || evemu_has_event(dev, EV_KEY, BTN_LEFT); } int utouch_frame_is_supported_mtdev(const struct evemu_device *dev) { /* only support pure absolute devices at this time */ if (evemu_has_event(dev, EV_REL, REL_X) || evemu_has_event(dev, EV_REL, REL_Y)) return 0; if (evemu_has_event(dev, EV_ABS, ABS_MT_POSITION_X) && evemu_has_event(dev, EV_ABS, ABS_MT_POSITION_Y)) return 1; return evemu_has_event(dev, EV_ABS, ABS_X) && evemu_has_event(dev, EV_ABS, ABS_Y) && evemu_has_event(dev, EV_KEY, BTN_TOUCH) && evemu_has_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP); } int utouch_frame_init_mtdev(utouch_frame_handle fh, const struct evemu_device *dev) { struct utouch_surface *s = fh->surface; float tmp; if (!utouch_frame_is_supported_mtdev(dev)) return -ENODEV; if (is_pointer(dev)) { s->needs_pointer = 1; s->is_direct = 0; } else { s->needs_pointer = 0; s->is_direct = 1; } s->is_buttonpad = 0; s->is_semi_mt = 0; #ifdef INPUT_PROP_POINTER s->needs_pointer |= evemu_has_prop(dev, INPUT_PROP_POINTER); s->is_direct |= evemu_has_prop(dev, INPUT_PROP_DIRECT); s->is_buttonpad |= evemu_has_prop(dev, INPUT_PROP_BUTTONPAD); s->is_semi_mt |= evemu_has_prop(dev, INPUT_PROP_SEMI_MT); #endif s->use_touch_major = evemu_has_event(dev, EV_ABS, ABS_MT_TOUCH_MAJOR); s->use_touch_minor = evemu_has_event(dev, EV_ABS, ABS_MT_TOUCH_MINOR); s->use_width_major = evemu_has_event(dev, EV_ABS, ABS_MT_WIDTH_MAJOR); s->use_width_minor = evemu_has_event(dev, EV_ABS, ABS_MT_WIDTH_MINOR); s->use_orientation = evemu_has_event(dev, EV_ABS, ABS_MT_ORIENTATION); s->use_pressure = evemu_has_event(dev, EV_ABS, ABS_MT_PRESSURE); #ifdef ABS_MT_DISTANCE s->use_distance = evemu_has_event(dev, EV_ABS, ABS_MT_DISTANCE); #endif s->min_x = evemu_get_abs_minimum(dev, ABS_MT_POSITION_X); s->min_y = evemu_get_abs_minimum(dev, ABS_MT_POSITION_Y); s->max_x = evemu_get_abs_maximum(dev, ABS_MT_POSITION_X); s->max_y = evemu_get_abs_maximum(dev, ABS_MT_POSITION_Y); if (s->min_x == s->max_x) { s->min_x = 0; s->max_x = 1024; } if (s->min_y == s->max_y) { s->min_y = 0; s->max_y = 768; } s->max_pressure = evemu_get_abs_maximum(dev, ABS_MT_PRESSURE); if (s->max_pressure == 0) s->max_pressure = 256; s->max_orient = evemu_get_abs_maximum(dev, ABS_MT_ORIENTATION); if (s->max_orient == 0) s->max_orient = 1; tmp = evemu_get_abs_resolution(dev, ABS_MT_POSITION_X); if (tmp > 0) s->phys_width = (s->max_x - s->min_x) / tmp; else if (s->needs_pointer) s->phys_width = 100; else s->phys_width = 250; tmp = evemu_get_abs_resolution(dev, ABS_MT_POSITION_Y); if (tmp > 0) s->phys_height = (s->max_y - s->min_y) / tmp; else if (s->needs_pointer) s->phys_height = 65; else s->phys_height = 160; tmp = evemu_get_abs_resolution(dev, ABS_MT_PRESSURE); if (tmp > 0) s->phys_pressure = s->max_pressure / tmp; else s->phys_pressure = 10; /* defaults expected by initial frame version */ s->mapped_min_x = s->min_x; s->mapped_min_y = s->min_y; s->mapped_max_x = s->max_x; s->mapped_max_y = s->max_y; s->mapped_max_pressure = s->max_pressure; return 0; } static int handle_abs_event(utouch_frame_handle fh, const struct input_event *ev) { struct utouch_contact *t = utouch_frame_get_current_slot(fh); switch (ev->code) { case ABS_MT_SLOT: utouch_frame_set_current_slot(fh, ev->value); return 1; case ABS_MT_POSITION_X: t->x = ev->value; return 1; case ABS_MT_POSITION_Y: t->y = ev->value; return 1; case ABS_MT_TOUCH_MAJOR: t->touch_major = ev->value; return 1; case ABS_MT_TOUCH_MINOR: t->touch_minor = ev->value; return 1; case ABS_MT_WIDTH_MAJOR: t->width_major = ev->value; return 1; case ABS_MT_WIDTH_MINOR: t->width_minor = ev->value; return 1; case ABS_MT_ORIENTATION: t->orientation = ev->value; return 1; case ABS_MT_PRESSURE: t->pressure = ev->value; return 1; #ifdef ABS_MT_DISTANCE case ABS_MT_DISTANCE: t->distance = ev->value; return 1; #endif case ABS_MT_TOOL_TYPE: t->tool_type = ev->value; return 1; case ABS_MT_TRACKING_ID: t->id = ev->value; return 1; default: return 0; } } static utouch_frame_time_t get_evtime_ms(const struct input_event *syn) { static const utouch_frame_time_t ms = 1000; return syn->time.tv_usec / ms + syn->time.tv_sec * ms; } const struct utouch_frame * utouch_frame_pump_mtdev(utouch_frame_handle fh, const struct input_event *ev) { const struct utouch_frame *f = 0; if (ev->type == EV_SYN && ev->code == SYN_REPORT) f = utouch_frame_sync(fh, get_evtime_ms(ev)); else if (ev->type == EV_ABS) handle_abs_event(fh, ev); return f; }