The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/evdev/evdev_mt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016, 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 /*-
   29  * Copyright (c) 2015, 2016 Ulf Brosziewski
   30  *
   31  * Permission to use, copy, modify, and distribute this software for any
   32  * purpose with or without fee is hereby granted, provided that the above
   33  * copyright notice and this permission notice appear in all copies.
   34  *
   35  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   36  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   37  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   38  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   39  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   40  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   41  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/lock.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mutex.h>
   48 #include <sys/systm.h>
   49 
   50 #include <dev/evdev/evdev.h>
   51 #include <dev/evdev/evdev_private.h>
   52 #include <dev/evdev/input.h>
   53 
   54 #ifdef DEBUG
   55 #define debugf(fmt, args...)    printf("evdev: " fmt "\n", ##args)
   56 #else
   57 #define debugf(fmt, args...)
   58 #endif
   59 
   60 typedef u_int   slotset_t;
   61 
   62 _Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big");
   63 
   64 #define FOREACHBIT(v, i) \
   65         for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1)
   66 
   67 struct {
   68         uint16_t        mt;
   69         uint16_t        st;
   70         int32_t         max;
   71 } static evdev_mtstmap[] = {
   72         { ABS_MT_POSITION_X,    ABS_X,          0 },
   73         { ABS_MT_POSITION_Y,    ABS_Y,          0 },
   74         { ABS_MT_PRESSURE,      ABS_PRESSURE,   255 },
   75         { ABS_MT_TOUCH_MAJOR,   ABS_TOOL_WIDTH, 15 },
   76 };
   77 
   78 struct evdev_mt {
   79         int                     last_reported_slot;
   80         uint16_t                tracking_id;
   81         int32_t                 tracking_ids[MAX_MT_SLOTS];
   82         bool                    type_a;
   83         u_int                   mtst_events;
   84         /* the set of slots with active touches */
   85         slotset_t               touches;
   86         /* the set of slots with unsynchronized state */
   87         slotset_t               frame;
   88         /* the set of slots to match with active touches */
   89         slotset_t               match_frame;
   90         int                     match_slot;
   91         union evdev_mt_slot     *match_slots;
   92         int                     *matrix;
   93         union evdev_mt_slot     slots[];
   94 };
   95 
   96 static void     evdev_mt_send_st_compat(struct evdev_dev *);
   97 static void     evdev_mt_send_autorel(struct evdev_dev *);
   98 static void     evdev_mt_replay_events(struct evdev_dev *);
   99 
  100 static inline int
  101 ffc_slot(struct evdev_dev *evdev, slotset_t slots)
  102 {
  103         return (ffs(~slots & ((2U << MAXIMAL_MT_SLOT(evdev)) - 1)) - 1);
  104 }
  105 
  106 void
  107 evdev_mt_init(struct evdev_dev *evdev)
  108 {
  109         struct evdev_mt *mt;
  110         size_t size = offsetof(struct evdev_mt, slots);
  111         int slot, slots;
  112         bool type_a;
  113 
  114         type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
  115         if (type_a) {
  116                 /* Add events produced by MT type A to type B converter */
  117                 evdev_support_abs(evdev,
  118                     ABS_MT_SLOT, 0, MAX_MT_SLOTS - 1, 0, 0, 0);
  119                 evdev_support_abs(evdev,
  120                     ABS_MT_TRACKING_ID, -1, MAX_MT_SLOTS - 1, 0, 0, 0);
  121         }
  122 
  123         slots = MAXIMAL_MT_SLOT(evdev) + 1;
  124         size += sizeof(mt->slots[0]) * slots;
  125         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
  126                 size += sizeof(mt->match_slots[0]) * slots;
  127                 size += sizeof(mt->matrix[0]) * (slots + 6) * slots;
  128         }
  129 
  130         mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
  131         evdev->ev_mt = mt;
  132         mt->type_a = type_a;
  133 
  134         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
  135                 mt->match_slots = mt->slots + slots;
  136                 mt->matrix = (int *)(mt->match_slots + slots);
  137         }
  138 
  139         /* Initialize multitouch protocol type B states */
  140         for (slot = 0; slot < slots; slot++)
  141                 mt->slots[slot].id = -1;
  142 
  143         if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
  144                 evdev_support_abs(evdev,
  145                     ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0);
  146         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
  147                 evdev_support_mt_compat(evdev);
  148 }
  149 
  150 void
  151 evdev_mt_free(struct evdev_dev *evdev)
  152 {
  153         free(evdev->ev_mt, M_EVDEV);
  154 }
  155 
  156 void
  157 evdev_mt_sync_frame(struct evdev_dev *evdev)
  158 {
  159         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
  160                 evdev_mt_replay_events(evdev);
  161         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
  162                 evdev_mt_send_autorel(evdev);
  163         if (evdev->ev_report_opened &&
  164             bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
  165                 evdev_mt_send_st_compat(evdev);
  166         evdev->ev_mt->frame = 0;
  167 }
  168 
  169 static void
  170 evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
  171     union evdev_mt_slot *state)
  172 {
  173         int i;
  174         bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
  175 
  176         EVDEV_LOCK_ASSERT(evdev);
  177         MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)));
  178         MPASS(!type_a || state != NULL);
  179 
  180         if (!type_a) {
  181                 evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
  182                 if (state == NULL) {
  183                         evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
  184                         return;
  185                 }
  186         }
  187         bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
  188                 evdev_send_event(evdev, EV_ABS, i,
  189                     state->val[ABS_MT_INDEX(i)]);
  190         if (type_a)
  191                 evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
  192 }
  193 
  194 int
  195 evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
  196     union evdev_mt_slot *state)
  197 {
  198         struct evdev_mt *mt = evdev->ev_mt;
  199         bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
  200 
  201         if ((type_a || (mt != NULL && mt->type_a)) && state == NULL)
  202                 return (EINVAL);
  203         if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
  204                 return (EINVAL);
  205 
  206         EVDEV_ENTER(evdev);
  207         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) && mt->type_a) {
  208                 mt->match_slots[mt->match_slot] = *state;
  209                 evdev_mt_record_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
  210         } else if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
  211                 evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
  212                 if (state != NULL)
  213                         mt->match_slots[mt->match_slot] = *state;
  214                 else
  215                         evdev_mt_record_event(evdev, EV_ABS,
  216                             ABS_MT_TRACKING_ID, -1);
  217         } else
  218                 evdev_mt_send_slot(evdev, slot, state);
  219         EVDEV_EXIT(evdev);
  220 
  221         return (0);
  222 }
  223 
  224 /*
  225  * Find a minimum-weight matching for an m-by-n matrix.
  226  *
  227  * m must be greater than or equal to n. The size of the buffer must be
  228  * at least 3m + 3n.
  229  *
  230  * On return, the first m elements of the buffer contain the row-to-
  231  * column mappings, i.e., buffer[i] is the column index for row i, or -1
  232  * if there is no assignment for that row (which may happen if n < m).
  233  *
  234  * Wrong results because of overflows will not occur with input values
  235  * in the range of 0 to INT_MAX / 2 inclusive.
  236  *
  237  * The function applies the Dinic-Kronrod algorithm. It is not modern or
  238  * popular, but it seems to be a good choice for small matrices at least.
  239  * The original form of the algorithm is modified as follows: There is no
  240  * initial search for row minima, the initial assignments are in a
  241  * "virtual" column with the index -1 and zero values. This permits inputs
  242  * with n < m, and it simplifies the reassignments.
  243  */
  244 static void
  245 evdev_mt_matching(int *matrix, int m, int n, int *buffer)
  246 {
  247         int i, j, k, d, e, row, col, delta;
  248         int *p;
  249         int *r2c = buffer;      /* row-to-column assignments */
  250         int *red = r2c + m;     /* reduced values of the assignments */
  251         int *mc = red + m;      /* row-wise minimal elements of cs */
  252         int *cs = mc + m;       /* the column set */
  253         int *c2r = cs + n;      /* column-to-row assignments in cs */
  254         int *cd = c2r + n;      /* column deltas (reduction) */
  255 
  256         for (p = r2c; p < red; *p++ = -1) {}
  257         for (; p < mc; *p++ = 0) {}
  258         for (col = 0; col < n; col++) {
  259                 delta = INT_MAX;
  260                 for (i = 0, p = matrix + col; i < m; i++, p += n) {
  261                         d = *p - red[i];
  262                         if (d < delta || (d == delta && r2c[i] < 0)) {
  263                                 delta = d;
  264                                 row = i;
  265                         }
  266                 }
  267                 cd[col] = delta;
  268                 if (r2c[row] < 0) {
  269                         r2c[row] = col;
  270                         continue;
  271                 }
  272                 for (p = mc; p < cs; *p++ = col) {}
  273                 for (k = 0; (j = r2c[row]) >= 0;) {
  274                         cs[k++] = j;
  275                         c2r[j] = row;
  276                         mc[row] -= n;
  277                         delta = INT_MAX;
  278                         for (i = 0, p = matrix; i < m; i++, p += n)
  279                                 if (mc[i] >= 0) {
  280                                         d = p[mc[i]] - cd[mc[i]];
  281                                         e = p[j] - cd[j];
  282                                         if (e < d) {
  283                                                 d = e;
  284                                                 mc[i] = j;
  285                                         }
  286                                         d -= red[i];
  287                                         if (d < delta || (d == delta
  288                                             && r2c[i] < 0)) {
  289                                                 delta = d;
  290                                                 row = i;
  291                                         }
  292                                 }
  293                         cd[col] += delta;
  294                         for (i = 0; i < k; i++) {
  295                                 cd[cs[i]] += delta;
  296                                 red[c2r[cs[i]]] -= delta;
  297                         }
  298                 }
  299                 for (j = mc[row]; (r2c[row] = j) != col;) {
  300                         row = c2r[j];
  301                         j = mc[row] + n;
  302                 }
  303         }
  304 }
  305 
  306 /*
  307  * Assign tracking IDs to the points in the pt array.  The tracking ID
  308  * assignment pairs the points with points of the previous frame in
  309  * such a way that the sum of the squared distances is minimal.  Using
  310  * squares instead of simple distances favours assignments with more uniform
  311  * distances, and it is faster.
  312  * Set tracking id to -1 for unassigned (new) points.
  313  */
  314 void
  315 evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt,
  316     int size)
  317 {
  318         struct evdev_mt *mt = evdev->ev_mt;
  319         int i, j, m, n, dx, dy, slot, num_touches;
  320         int *p, *r2c, *c2r;
  321 
  322         EVDEV_LOCK_ASSERT(evdev);
  323         MPASS(mt->matrix != NULL);
  324         MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
  325 
  326         if (size == 0)
  327                 return;
  328 
  329         p = mt->matrix;
  330         num_touches = bitcount(mt->touches);
  331         if (num_touches >= size) {
  332                 FOREACHBIT(mt->touches, slot)
  333                         for (i = 0; i < size; i++) {
  334                                 dx = pt[i].x - mt->slots[slot].x;
  335                                 dy = pt[i].y - mt->slots[slot].y;
  336                                 *p++ = dx * dx + dy * dy;
  337                         }
  338                 m = num_touches;
  339                 n = size;
  340         } else {
  341                 for (i = 0; i < size; i++)
  342                         FOREACHBIT(mt->touches, slot) {
  343                                 dx = pt[i].x - mt->slots[slot].x;
  344                                 dy = pt[i].y - mt->slots[slot].y;
  345                                 *p++ = dx * dx + dy * dy;
  346                         }
  347                 m = size;
  348                 n = num_touches;
  349         }
  350         evdev_mt_matching(mt->matrix, m, n, p);
  351 
  352         r2c = p;
  353         c2r = p + m;
  354         for (i = 0; i < m; i++)
  355                 if ((j = r2c[i]) >= 0)
  356                         c2r[j] = i;
  357 
  358         p = (n == size ? c2r : r2c);
  359         for (i = 0; i < size; i++)
  360                 if (*p++ < 0)
  361                         pt[i].id = -1;
  362 
  363         p = (n == size ? r2c : c2r);
  364         FOREACHBIT(mt->touches, slot)
  365                 if ((i = *p++) >= 0)
  366                         pt[i].id = mt->tracking_ids[slot];
  367 }
  368 
  369 static void
  370 evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
  371 {
  372         struct evdev_mt *mt = evdev->ev_mt;
  373         union evdev_mt_slot *slot;
  374 
  375         EVDEV_LOCK_ASSERT(evdev);
  376         MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
  377 
  378         /*
  379          * While MT-matching assign tracking IDs of new contacts to be equal
  380          * to a slot number to make things simpler.
  381          */
  382         for (slot = pt; slot < pt + size; slot++) {
  383                 if (slot->id < 0)
  384                         slot->id = ffc_slot(evdev, mt->touches | mt->frame);
  385                 if (slot->id >= 0)
  386                         evdev_mt_send_slot(evdev, slot->id, slot);
  387         }
  388 }
  389 
  390 int
  391 evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
  392 {
  393         if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
  394                 return (EINVAL);
  395 
  396         EVDEV_ENTER(evdev);
  397         evdev_mt_send_frame(evdev, pt, size);
  398         EVDEV_EXIT(evdev);
  399 
  400         return (0);
  401 }
  402 
  403 bool
  404 evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
  405     int32_t value)
  406 {
  407         struct evdev_mt *mt = evdev->ev_mt;
  408 
  409         EVDEV_LOCK_ASSERT(evdev);
  410 
  411         switch (type) {
  412         case EV_SYN:
  413                 if (code == SYN_MT_REPORT) {
  414                         /* MT protocol type A support */
  415                         KASSERT(mt->type_a, ("Not a MT type A protocol"));
  416                         mt->match_frame |= 1U << mt->match_slot;
  417                         mt->match_slot++;
  418                         return (true);
  419                 }
  420                 break;
  421         case EV_ABS:
  422                 if (code == ABS_MT_SLOT) {
  423                         /* MT protocol type B support */
  424                         KASSERT(!mt->type_a, ("Not a MT type B protocol"));
  425                         KASSERT(value >= 0, ("Negative slot number"));
  426                         mt->match_slot = value;
  427                         mt->match_frame |= 1U << mt->match_slot;
  428                         return (true);
  429                 } else if (code == ABS_MT_TRACKING_ID) {
  430                         KASSERT(!mt->type_a, ("Not a MT type B protocol"));
  431                         if (value == -1)
  432                                 mt->match_frame &= ~(1U << mt->match_slot);
  433                         return (true);
  434                 } else if (ABS_IS_MT(code)) {
  435                         KASSERT(mt->match_slot >= 0, ("Negative slot"));
  436                         KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
  437                             ("Slot number too big"));
  438                         mt->match_slots[mt->match_slot].
  439                             val[ABS_MT_INDEX(code)] = value;
  440                         return (true);
  441                 }
  442                 break;
  443         default:
  444                 break;
  445         }
  446 
  447         return (false);
  448 }
  449 
  450 static void
  451 evdev_mt_replay_events(struct evdev_dev *evdev)
  452 {
  453         struct evdev_mt *mt = evdev->ev_mt;
  454         int slot, size = 0;
  455 
  456         EVDEV_LOCK_ASSERT(evdev);
  457 
  458         FOREACHBIT(mt->match_frame, slot) {
  459                 if (slot != size)
  460                         mt->match_slots[size] = mt->match_slots[slot];
  461                 size++;
  462         }
  463         evdev_mt_match_frame(evdev, mt->match_slots, size);
  464         evdev_mt_send_frame(evdev, mt->match_slots, size);
  465         mt->match_slot = 0;
  466         mt->match_frame = 0;
  467 }
  468 
  469 union evdev_mt_slot *
  470 evdev_mt_get_match_slots(struct evdev_dev *evdev)
  471 {
  472         return (evdev->ev_mt->match_slots);
  473 }
  474 
  475 int
  476 evdev_mt_get_last_slot(struct evdev_dev *evdev)
  477 {
  478         return (evdev->ev_mt->last_reported_slot);
  479 }
  480 
  481 void
  482 evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
  483 {
  484         struct evdev_mt *mt = evdev->ev_mt;
  485 
  486         MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
  487 
  488         mt->frame |= 1U << slot;
  489         mt->last_reported_slot = slot;
  490 }
  491 
  492 int32_t
  493 evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
  494 {
  495         struct evdev_mt *mt = evdev->ev_mt;
  496 
  497         MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
  498 
  499         return (mt->slots[slot].val[ABS_MT_INDEX(code)]);
  500 }
  501 
  502 void
  503 evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
  504     int32_t value)
  505 {
  506         struct evdev_mt *mt = evdev->ev_mt;
  507 
  508         MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
  509 
  510         if (code == ABS_MT_TRACKING_ID) {
  511                 if (value != -1)
  512                         mt->touches |= 1U << slot;
  513                 else
  514                         mt->touches &= ~(1U << slot);
  515         }
  516         mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
  517 }
  518 
  519 int
  520 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
  521 {
  522         struct evdev_mt *mt = evdev->ev_mt;
  523         int slot;
  524 
  525         KASSERT(!mt->type_a, ("Not a MT type B protocol"));
  526 
  527         /*
  528          * Ignore tracking_id if slot assignment is performed by evdev.
  529          * Events are written sequentially to temporary matching buffer.
  530          */
  531         if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
  532                 return (ffc_slot(evdev, mt->match_frame));
  533 
  534         FOREACHBIT(mt->touches, slot)
  535                 if (mt->tracking_ids[slot] == tracking_id)
  536                         return (slot);
  537         /*
  538          * Do not allow allocation of new slot in a place of just
  539          * released one within the same report.
  540          */
  541         return (ffc_slot(evdev, mt->touches | mt->frame));
  542 }
  543 
  544 int32_t
  545 evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
  546 {
  547         struct evdev_mt *mt = evdev->ev_mt;
  548         int32_t nid;
  549 
  550         if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
  551                 mt->tracking_ids[slot] = id;
  552                 return (id);
  553         }
  554 
  555         nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
  556         if (nid != -1) {
  557                 KASSERT(id == mt->tracking_ids[slot],
  558                     ("MT-slot tracking id has changed"));
  559                 return (nid);
  560         }
  561 
  562         mt->tracking_ids[slot] = id;
  563 again:
  564         nid = mt->tracking_id++;
  565         FOREACHBIT(mt->touches, slot)
  566                 if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
  567                         goto again;
  568 
  569         return (nid);
  570 }
  571 
  572 static inline int32_t
  573 evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
  574 {
  575         if (stmax != 0 && mtmax != mtmin) {
  576                 value = (value - mtmin) * stmax / (mtmax - mtmin);
  577                 value = MAX(MIN(value, stmax), 0);
  578         }
  579         return (value);
  580 }
  581 
  582 void
  583 evdev_support_mt_compat(struct evdev_dev *evdev)
  584 {
  585         struct input_absinfo *ai;
  586         int i;
  587 
  588         if (evdev->ev_absinfo == NULL)
  589                 return;
  590 
  591         evdev_support_event(evdev, EV_KEY);
  592         evdev_support_key(evdev, BTN_TOUCH);
  593 
  594         /* Touchscreens should not advertise tap tool capabilities */
  595         if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
  596                 evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
  597 
  598         /* Echo 0-th MT-slot as ST-slot */
  599         for (i = 0; i < nitems(evdev_mtstmap); i++) {
  600                 if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
  601                      bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
  602                         continue;
  603                 ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
  604                 evdev->ev_mt->mtst_events |= 1U << i;
  605                 if (evdev_mtstmap[i].max != 0)
  606                         evdev_support_abs(evdev, evdev_mtstmap[i].st,
  607                             0,
  608                             evdev_mtstmap[i].max,
  609                             0,
  610                             evdev_mt_normalize(
  611                               ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
  612                             0);
  613                 else
  614                         evdev_support_abs(evdev, evdev_mtstmap[i].st,
  615                             ai->minimum,
  616                             ai->maximum,
  617                             0,
  618                             ai->flat,
  619                             ai->resolution);
  620         }
  621 }
  622 
  623 static void
  624 evdev_mt_send_st_compat(struct evdev_dev *evdev)
  625 {
  626         struct evdev_mt *mt = evdev->ev_mt;
  627         int nfingers, i, st_slot;
  628 
  629         EVDEV_LOCK_ASSERT(evdev);
  630 
  631         nfingers = bitcount(mt->touches);
  632         evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
  633 
  634         /* Send first active MT-slot state as single touch report */
  635         st_slot = ffs(mt->touches) - 1;
  636         if (st_slot != -1)
  637                 FOREACHBIT(mt->mtst_events, i)
  638                         evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
  639                             evdev_mt_normalize(evdev_mt_get_value(evdev,
  640                               st_slot, evdev_mtstmap[i].mt),
  641                               evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
  642                               evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
  643                               evdev_mtstmap[i].max));
  644 
  645         /* Touchscreens should not report tool taps */
  646         if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
  647                 evdev_send_nfingers(evdev, nfingers);
  648 
  649         if (nfingers == 0)
  650                 evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0);
  651 }
  652 
  653 void
  654 evdev_push_mt_compat(struct evdev_dev *evdev)
  655 {
  656 
  657         EVDEV_ENTER(evdev);
  658         evdev_mt_send_st_compat(evdev);
  659         EVDEV_EXIT(evdev);
  660 }
  661 
  662 static void
  663 evdev_mt_send_autorel(struct evdev_dev *evdev)
  664 {
  665         struct evdev_mt *mt = evdev->ev_mt;
  666         int slot;
  667 
  668         EVDEV_LOCK_ASSERT(evdev);
  669         KASSERT(mt->match_frame == 0, ("Unmatched events exist"));
  670 
  671         FOREACHBIT(mt->touches & ~mt->frame, slot)
  672                 evdev_mt_send_slot(evdev, slot, NULL);
  673 }
  674 
  675 void
  676 evdev_mt_push_autorel(struct evdev_dev *evdev)
  677 {
  678         EVDEV_ENTER(evdev);
  679         evdev_mt_send_autorel(evdev);
  680         EVDEV_EXIT(evdev);
  681 }

Cache object: d71c2f47831e04a31c0ce0d83c3bb793


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.