From f0aba58c91933a4702a7cc74f7daf4192868f570 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 30 Dec 2010 17:58:01 +0100 Subject: Initial load of utouch-frame Compiles and runs on mtdev. ABI proof. Signed-off-by: Henrik Rydberg --- src/frame.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 src/frame.c (limited to 'src/frame.c') diff --git a/src/frame.c b/src/frame.c new file mode 100644 index 0000000..9c4be97 --- /dev/null +++ b/src/frame.c @@ -0,0 +1,303 @@ +/***************************************************************************** + * + * 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 "frame-impl.h" +#include +#include +#include +#include +#include + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +unsigned int utouch_frame_get_version(void) +{ + return UTOUCH_FRAME_VERSION; +} + +static void destroy_slots(struct utouch_contact **slots, int nslot) +{ + int i; + + if (slots) { + for (i = nslot - 1; i >= 0; i--) + free(slots[i]); + free(slots); + } +} + +static void destroy_frame(struct utouch_frame *frame, int nslot) +{ + if (frame) { + destroy_slots(frame->slots, nslot); + free(frame->active); + free(frame); + } +} + +static void destroy_frames(struct utouch_frame **frames, int nframe, int nslot) +{ + int i; + + if (frames) { + for (i = nframe - 1; i >= 0; i--) + destroy_frame(frames[i], nslot); + free(frames); + } +} + +static struct utouch_contact **create_slots(int nslot, int size) +{ + struct utouch_contact **slots; + struct utouch_contact *s; + int i; + + slots = calloc(nslot, sizeof(slots[0])); + if (!slots) + return 0; + + for (i = 0; i < nslot; i++) { + s = calloc(1, size); + if (!s) + goto out; + slots[i] = s; + s->slot = i; + s->id = -1; + } + + return slots; +out: + destroy_slots(slots, nslot); + return 0; +} + +static struct utouch_frame *create_frame(int nslot, + int frame_size, int slot_size) +{ + struct utouch_frame *frame; + int i; + + frame = calloc(1, frame_size); + if (!frame) + return 0; + + frame->active = calloc(nslot, sizeof(frame->active[0])); + frame->slots = create_slots(nslot, slot_size); + if (!frame->active || !frame->slots) + goto out; + + return frame; +out: + destroy_frame(frame, nslot); + return 0; +} + +static struct utouch_frame **create_frames(int nframe, int nslot, + int frame_size, int slot_size) +{ + struct utouch_frame **frames; + struct utouch_frame *f; + int i; + + frames = calloc(nframe, sizeof(frames[0])); + if (!frames) + return 0; + + for (i = 0; i < nframe; i++) { + f = create_frame(nslot, frame_size, slot_size); + if (!f) + goto out; + frames[i] = f; + } + + return frames; +out: + destroy_frames(frames, nframe, nslot); + return 0; +} + +utouch_frame_handle utouch_frame_new_engine_raw(unsigned int nframe, + unsigned int nslot, + unsigned int rate, + unsigned int version, + unsigned int surface_size, + unsigned int frame_size, + unsigned int slot_size) +{ + struct utouch_frame *f, *pf; + utouch_frame_handle fh; + int i, j; + + fh = calloc(1, sizeof(struct utouch_frame_engine)); + if (!fh) + return 0; + + fh->num_frames = nframe; + fh->num_slots = nslot; + fh->hold_ms = 1000 / rate; + + surface_size = MAX(surface_size, sizeof(struct utouch_surface)); + frame_size = MAX(frame_size, sizeof(struct utouch_frame)); + slot_size = MAX(slot_size, sizeof(struct utouch_contact)); + + fh->surface = calloc(1, surface_size); + fh->frames = create_frames(nframe, nslot, frame_size, slot_size); + fh->next = create_frame(nslot, frame_size, slot_size); + if (!fh->surface || !fh->frames || !fh->next) + goto out; + + pf = fh->frames[nframe - 1]; + for (i = 0; i < nframe; i++) { + f = fh->frames[i]; + for (j = 0; j < nslot; j++) + f->slots[j]->prev = pf->slots[j]; + f->prev = pf; + pf = f; + } + + return fh; +out: + utouch_frame_delete_engine(fh); + return 0; +} + +void utouch_frame_delete_engine(utouch_frame_handle fh) +{ + destroy_frame(fh->next, fh->num_slots); + destroy_frames(fh->frames, fh->num_frames, fh->num_slots); + free(fh->surface); + free(fh); +} + +struct utouch_surface *utouch_frame_get_surface(utouch_frame_handle fh) +{ + return fh->surface; +} + +struct utouch_contact *utouch_frame_get_current_slot(utouch_frame_handle fh) +{ + return fh->next->slots[fh->slot]; +} + +int utouch_frame_set_current_slot(utouch_frame_handle fh, int slot) +{ + if (slot < 0 || slot >= fh->num_slots) + return -EINVAL; + fh->slot = slot; + return 0; +} + +static void copy_contact(utouch_frame_handle fh, + struct utouch_contact *a, + const struct utouch_contact *b) +{ + struct utouch_surface *s = fh->surface; + + a->active = b->id != -1; + a->id = b->id; + a->tool_type = b->tool_type; + a->x = b->x; + a->y = b->y; + a->touch_major = b->touch_major; + a->touch_minor = s->use_touch_minor && b->touch_minor > 0 ? + b->touch_minor : b->touch_major; + a->width_major = b->width_major; + a->width_minor = s->use_width_minor && b->width_minor > 0 ? + b->width_minor : b->width_major; + a->orientation = b->orientation; + a->pressure = b->pressure; + a->distance = b->distance; +} + +static int detect_addrem(const struct utouch_contact *a, + const struct utouch_contact *b) +{ + return a->id != b->id || a->tool_type != b->tool_type; +} + +static int detect_mod(const struct utouch_contact *a, + const struct utouch_contact *b) +{ + return a->x != b->x || a->y != b->y || + a->touch_major != b->touch_major || + a->touch_minor != b->touch_minor || + a->width_major != b->width_major || + a->width_minor != b->width_minor || + a->orientation != b->orientation || + a->pressure != b->pressure || + a->distance != b->distance; +} + +static utouch_frame_time_t get_time_ms() +{ + static const utouch_frame_time_t ms = 1000; + struct timeval tv; + gettimeofday(&tv, 0); + return tv.tv_usec / ms + tv.tv_sec * ms; +} + +const struct utouch_frame *utouch_frame_sync(utouch_frame_handle fh, + utouch_frame_time_t time) +{ + struct utouch_frame *frame = fh->frames[fh->frame]; + const struct utouch_frame *prev = frame->prev; + struct utouch_frame *next = fh->next; + int naddrem = 0, nmod = 0; + int i; + + frame->num_active = 0; + for (i = 0; i < fh->num_slots; i++) { + struct utouch_contact *p = frame->slots[i]; + const struct utouch_contact *q = next->slots[i]; + + copy_contact(fh, p, q); + if (p->active) + frame->active[frame->num_active++] = p; + + naddrem += detect_addrem(p->prev, p); + nmod += detect_mod(p->prev, p); + } + if (naddrem + nmod == 0) + return 0; + + frame->time = time ? time : get_time_ms(); + if (naddrem == 0 && frame->time < prev->time + fh->hold_ms) + return 0; + + if (frame->num_active != prev->num_active) { + next->mod_time = frame->time; + next->revision++; + } + if (naddrem) { + next->slot_mod_time = frame->time; + next->slot_revision++; + } + + frame->revision = next->revision; + frame->slot_revision = next->slot_revision; + frame->mod_time = next->mod_time; + frame->slot_mod_time = next->slot_mod_time; + frame->sequence_id = next->sequence_id++; + + fh->frame = (fh->frame + 1) % fh->num_frames; + + return frame; +} -- cgit v1.2.3