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_private.h

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) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
    3  * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 
   30 #ifndef _DEV_EVDEV_EVDEV_PRIVATE_H
   31 #define _DEV_EVDEV_EVDEV_PRIVATE_H
   32 
   33 #include <sys/bitstring.h>
   34 #include <sys/ck.h>
   35 #include <sys/epoch.h>
   36 #include <sys/kbio.h>
   37 #include <sys/lock.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mutex.h>
   40 #include <sys/queue.h>
   41 #include <sys/selinfo.h>
   42 #include <sys/sx.h>
   43 #include <sys/sysctl.h>
   44 
   45 #include <dev/evdev/evdev.h>
   46 #include <dev/evdev/input.h>
   47 #include <dev/kbd/kbdreg.h>
   48 
   49 #define NAMELEN         80
   50 
   51 /*
   52  * bitstr_t implementation must be identical to one found in EVIOCG*
   53  * libevdev ioctls. Our bitstring(3) API is compatible since r299090.
   54  */
   55 _Static_assert(sizeof(bitstr_t) == sizeof(unsigned long),
   56     "bitstr_t size mismatch");
   57 
   58 MALLOC_DECLARE(M_EVDEV);
   59 
   60 struct evdev_client;
   61 struct evdev_mt;
   62 
   63 #define CURRENT_MT_SLOT(evdev)  ((evdev)->ev_absinfo[ABS_MT_SLOT].value)
   64 #define MAXIMAL_MT_SLOT(evdev)  ((evdev)->ev_absinfo[ABS_MT_SLOT].maximum)
   65 
   66 enum evdev_key_events
   67 {
   68         KEY_EVENT_UP,
   69         KEY_EVENT_DOWN,
   70         KEY_EVENT_REPEAT
   71 };
   72 
   73 /* evdev clock IDs in Linux semantic */
   74 enum evdev_clock_id
   75 {
   76         EV_CLOCK_REALTIME = 0,  /* UTC clock */
   77         EV_CLOCK_MONOTONIC,     /* monotonic, stops on suspend */
   78         EV_CLOCK_BOOTTIME       /* monotonic, suspend-awared */
   79 };
   80 
   81 /*
   82  * Locking.
   83  *
   84  * Internal  evdev structures are protected with next locks:
   85  * State lock           (s) - Internal state. The data it protects is changed
   86  *                            by incoming evdev events and some ioctls.
   87  * Client list epoch    (l) - Read access to client list.
   88  * Client list lock     (l) - Write access to client list.
   89  * Client queue locks   (q) - One lock per client to serialize access to data
   90  *                            available through character device node.
   91  *
   92  * Depending on evdev_register_() suffix evdev can run in following modes:
   93  * 1. Internal epoch. evdev_register(). All locks are internal.
   94  * 2. External epoch. Evdev expects to be run under input epoch entered by
   95  *    parent driver. The mode is enabled with EVDEV_FLAG_EXT_EPOCH flag.
   96  * 3. External mutex. evdev_register_mtx(). Evdev uses mutex provided by parent
   97  *    driver as both "State lock" and "Client list lock". This mode is
   98  *    deprecated as it causes ev_open and ev_close handlers to be called with
   99  *    parent driver mutex taken.
  100  */
  101 #define INPUT_EPOCH     global_epoch_preempt
  102 
  103 enum evdev_lock_type
  104 {
  105         EV_LOCK_INTERNAL = 0,   /* Internal epoch */
  106         EV_LOCK_MTX,            /* Driver`s mutex */
  107         EV_LOCK_EXT_EPOCH,      /* External epoch */
  108 };
  109 
  110 struct evdev_dev
  111 {
  112         char                    ev_name[NAMELEN];
  113         char                    ev_shortname[NAMELEN];
  114         char                    ev_serial[NAMELEN];
  115         struct cdev *           ev_cdev;
  116         int                     ev_unit;
  117         enum evdev_lock_type    ev_lock_type;
  118         struct mtx *            ev_state_lock;  /* State lock */
  119         struct mtx              ev_mtx;         /* Internal state lock */
  120         struct sx               ev_list_lock;   /* Client list lock */
  121         struct input_id         ev_id;
  122         struct evdev_client *   ev_grabber;                     /* (s) */
  123         size_t                  ev_report_size;
  124 
  125         /* Supported features: */
  126         bitstr_t                bit_decl(ev_prop_flags, INPUT_PROP_CNT);
  127         bitstr_t                bit_decl(ev_type_flags, EV_CNT);
  128         bitstr_t                bit_decl(ev_key_flags, KEY_CNT);
  129         bitstr_t                bit_decl(ev_rel_flags, REL_CNT);
  130         bitstr_t                bit_decl(ev_abs_flags, ABS_CNT);
  131         bitstr_t                bit_decl(ev_msc_flags, MSC_CNT);
  132         bitstr_t                bit_decl(ev_led_flags, LED_CNT);
  133         bitstr_t                bit_decl(ev_snd_flags, SND_CNT);
  134         bitstr_t                bit_decl(ev_sw_flags, SW_CNT);
  135         struct input_absinfo *  ev_absinfo;                     /* (s) */
  136         bitstr_t                bit_decl(ev_flags, EVDEV_FLAG_CNT);
  137 
  138         /* Repeat parameters & callout: */
  139         int                     ev_rep[REP_CNT];                /* (s) */
  140         struct callout          ev_rep_callout;                 /* (s) */
  141         uint16_t                ev_rep_key;                     /* (s) */
  142 
  143         /* State: */
  144         bitstr_t                bit_decl(ev_key_states, KEY_CNT); /* (s) */
  145         bitstr_t                bit_decl(ev_led_states, LED_CNT); /* (s) */
  146         bitstr_t                bit_decl(ev_snd_states, SND_CNT); /* (s) */
  147         bitstr_t                bit_decl(ev_sw_states, SW_CNT); /* (s) */
  148         bool                    ev_report_opened;               /* (s) */
  149 
  150         /* KDB state: */
  151         bool                    ev_kdb_active;
  152         bitstr_t                bit_decl(ev_kdb_led_states, LED_CNT);
  153 
  154         /* Multitouch protocol type B state: */
  155         struct evdev_mt *       ev_mt;                          /* (s) */
  156 
  157         /* Counters: */
  158         uint64_t                ev_event_count;                 /* (s) */
  159         uint64_t                ev_report_count;                /* (s) */
  160 
  161         /* Parent driver callbacks: */
  162         const struct evdev_methods * ev_methods;
  163         void *                  ev_softc;
  164 
  165         /* Sysctl: */
  166         struct sysctl_ctx_list  ev_sysctl_ctx;
  167 
  168         LIST_ENTRY(evdev_dev) ev_link;
  169         CK_SLIST_HEAD(, evdev_client) ev_clients;               /* (l) */
  170 };
  171 
  172 #define SYSTEM_CONSOLE_LOCK     &Giant
  173 
  174 #define EVDEV_LOCK(evdev)               mtx_lock((evdev)->ev_state_lock)
  175 #define EVDEV_UNLOCK(evdev)             mtx_unlock((evdev)->ev_state_lock)
  176 #define EVDEV_LOCK_ASSERT(evdev)        do {                            \
  177         if ((evdev)->ev_state_lock != SYSTEM_CONSOLE_LOCK)              \
  178                 mtx_assert((evdev)->ev_state_lock, MA_OWNED);           \
  179 } while (0)
  180 #define EVDEV_ENTER(evdev)      do {                                    \
  181         if ((evdev)->ev_lock_type != EV_LOCK_MTX)                       \
  182                 EVDEV_LOCK(evdev);                                      \
  183         else                                                            \
  184                 EVDEV_LOCK_ASSERT(evdev);                               \
  185 } while (0)
  186 #define EVDEV_EXIT(evdev)       do {                                    \
  187         if ((evdev)->ev_lock_type != EV_LOCK_MTX)                       \
  188                 EVDEV_UNLOCK(evdev);                                    \
  189 } while (0)
  190 
  191 #define EVDEV_LIST_LOCK(evdev)  do {                                    \
  192         if ((evdev)->ev_lock_type == EV_LOCK_MTX)                       \
  193                 EVDEV_LOCK(evdev);                                      \
  194         else                                                            \
  195                 sx_xlock(&(evdev)->ev_list_lock);                       \
  196 } while (0)
  197 #define EVDEV_LIST_UNLOCK(evdev)        do {                            \
  198         if ((evdev)->ev_lock_type == EV_LOCK_MTX)                       \
  199                 EVDEV_UNLOCK(evdev);                                    \
  200         else                                                            \
  201                 sx_unlock(&(evdev)->ev_list_lock);                      \
  202 } while (0)
  203 #define EVDEV_LIST_LOCK_ASSERT(evdev)   do {                            \
  204         if ((evdev)->ev_lock_type == EV_LOCK_MTX)                       \
  205                 EVDEV_LOCK_ASSERT(evdev);                               \
  206         else                                                            \
  207                 sx_assert(&(evdev)->ev_list_lock, MA_OWNED);            \
  208 } while (0)
  209 static inline int
  210 EVDEV_LIST_LOCK_SIG(struct evdev_dev *evdev)
  211 {
  212         if (evdev->ev_lock_type == EV_LOCK_MTX) {
  213                 EVDEV_LOCK(evdev);
  214                 return (0);
  215         }
  216         return (sx_xlock_sig(&evdev->ev_list_lock));
  217 }
  218 
  219 struct evdev_client
  220 {
  221         struct evdev_dev *      ec_evdev;
  222         struct mtx              ec_buffer_mtx;  /* Client queue lock */
  223         size_t                  ec_buffer_size;
  224         size_t                  ec_buffer_head;         /* (q) */
  225         size_t                  ec_buffer_tail;         /* (q) */
  226         size_t                  ec_buffer_ready;        /* (q) */
  227         enum evdev_clock_id     ec_clock_id;
  228         struct selinfo          ec_selp;                /* (q) */
  229         struct sigio *          ec_sigio;
  230         bool                    ec_async;               /* (q) */
  231         bool                    ec_revoked;             /* (l) */
  232         bool                    ec_blocked;             /* (q) */
  233         bool                    ec_selected;            /* (q) */
  234 
  235         CK_SLIST_ENTRY(evdev_client) ec_link;           /* (l) */
  236 
  237         struct input_event      ec_buffer[];            /* (q) */
  238 };
  239 
  240 #define EVDEV_CLIENT_LOCKQ(client)      mtx_lock(&(client)->ec_buffer_mtx)
  241 #define EVDEV_CLIENT_UNLOCKQ(client)    mtx_unlock(&(client)->ec_buffer_mtx)
  242 #define EVDEV_CLIENT_LOCKQ_ASSERT(client) \
  243     mtx_assert(&(client)->ec_buffer_mtx, MA_OWNED)
  244 #define EVDEV_CLIENT_EMPTYQ(client) \
  245     ((client)->ec_buffer_head == (client)->ec_buffer_ready)
  246 #define EVDEV_CLIENT_SIZEQ(client) \
  247     (((client)->ec_buffer_ready + (client)->ec_buffer_size - \
  248       (client)->ec_buffer_head) % (client)->ec_buffer_size)
  249 
  250 /* bitstring(3) helper */
  251 static inline void
  252 bit_change(bitstr_t *bitstr, int bit, int value)
  253 {
  254         if (value)
  255                 bit_set(bitstr, bit);
  256         else
  257                 bit_clear(bitstr, bit);
  258 }
  259 
  260 /* Input device interface: */
  261 void evdev_send_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
  262 int evdev_inject_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
  263 int evdev_cdev_create(struct evdev_dev *);
  264 int evdev_cdev_destroy(struct evdev_dev *);
  265 bool evdev_event_supported(struct evdev_dev *, uint16_t);
  266 void evdev_set_abs_bit(struct evdev_dev *, uint16_t);
  267 void evdev_set_absinfo(struct evdev_dev *, uint16_t, struct input_absinfo *);
  268 void evdev_restore_after_kdb(struct evdev_dev *);
  269 
  270 /* Client interface: */
  271 int evdev_register_client(struct evdev_dev *, struct evdev_client *);
  272 void evdev_dispose_client(struct evdev_dev *, struct evdev_client *);
  273 int evdev_grab_client(struct evdev_dev *, struct evdev_client *);
  274 int evdev_release_client(struct evdev_dev *, struct evdev_client *);
  275 void evdev_client_push(struct evdev_client *, uint16_t, uint16_t, int32_t);
  276 void evdev_notify_event(struct evdev_client *);
  277 void evdev_revoke_client(struct evdev_client *);
  278 
  279 /* Multitouch related functions: */
  280 void evdev_mt_init(struct evdev_dev *);
  281 void evdev_mt_free(struct evdev_dev *);
  282 void evdev_mt_sync_frame(struct evdev_dev *);
  283 int evdev_mt_get_last_slot(struct evdev_dev *);
  284 void evdev_mt_set_last_slot(struct evdev_dev *, int);
  285 int32_t evdev_mt_get_value(struct evdev_dev *, int, int16_t);
  286 void evdev_mt_set_value(struct evdev_dev *, int, int16_t, int32_t);
  287 int32_t evdev_mt_reassign_id(struct evdev_dev *, int, int32_t);
  288 bool evdev_mt_record_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
  289 
  290 /* Utility functions: */
  291 void evdev_client_dumpqueue(struct evdev_client *);
  292 void evdev_send_nfingers(struct evdev_dev *, int);
  293 
  294 #endif  /* _DEV_EVDEV_EVDEV_PRIVATE_H */

Cache object: 459ca8857a55efb91efad58efbef8b0b


[ 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.