chiark / gitweb /
0e846179e6093c061cb9cde2b7ca0704cbdf4901
[elogind.git] / src / libsystemd-terminal / idev.h
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 /*
23  * IDev
24  */
25
26 #pragma once
27
28 #include <libudev.h>
29 #include <linux/input.h>
30 #include <stdbool.h>
31 #include <systemd/sd-bus.h>
32 #include <systemd/sd-event.h>
33 #include <xkbcommon/xkbcommon.h>
34
35 typedef struct idev_data                idev_data;
36 typedef struct idev_data_evdev          idev_data_evdev;
37 typedef struct idev_data_keyboard       idev_data_keyboard;
38
39 typedef struct idev_event               idev_event;
40 typedef struct idev_device              idev_device;
41 typedef struct idev_session             idev_session;
42 typedef struct idev_context             idev_context;
43
44 /*
45  * Types
46  */
47
48 enum {
49         IDEV_ELEMENT_EVDEV,
50         IDEV_ELEMENT_CNT
51 };
52
53 enum {
54         IDEV_DEVICE_KEYBOARD,
55         IDEV_DEVICE_CNT
56 };
57
58 /*
59  * Evdev Elements
60  */
61
62 struct idev_data_evdev {
63         struct input_event event;
64 };
65
66 /*
67  * Keyboard Devices
68  */
69
70 struct xkb_state;
71
72 enum {
73         IDEV_KBDMOD_IDX_SHIFT,
74         IDEV_KBDMOD_IDX_CTRL,
75         IDEV_KBDMOD_IDX_ALT,
76         IDEV_KBDMOD_IDX_LINUX,
77         IDEV_KBDMOD_IDX_CAPS,
78         IDEV_KBDMOD_CNT,
79
80         IDEV_KBDMOD_SHIFT               = 1 << IDEV_KBDMOD_IDX_SHIFT,
81         IDEV_KBDMOD_CTRL                = 1 << IDEV_KBDMOD_IDX_CTRL,
82         IDEV_KBDMOD_ALT                 = 1 << IDEV_KBDMOD_IDX_ALT,
83         IDEV_KBDMOD_LINUX               = 1 << IDEV_KBDMOD_IDX_LINUX,
84         IDEV_KBDMOD_CAPS                = 1 << IDEV_KBDMOD_IDX_CAPS,
85 };
86
87 enum {
88         IDEV_KBDLED_IDX_NUM,
89         IDEV_KBDLED_IDX_CAPS,
90         IDEV_KBDLED_IDX_SCROLL,
91         IDEV_KBDLED_CNT,
92
93         IDEV_KBDLED_NUM                 = 1 << IDEV_KBDLED_IDX_NUM,
94         IDEV_KBDLED_CAPS                = 1 << IDEV_KBDLED_IDX_CAPS,
95         IDEV_KBDLED_SCROLL              = 1 << IDEV_KBDLED_IDX_SCROLL,
96 };
97
98 struct idev_data_keyboard {
99         struct xkb_state *xkb_state;
100         int8_t ascii;
101         uint8_t value;
102         uint16_t keycode;
103         uint32_t mods;
104         uint32_t consumed_mods;
105         uint32_t n_syms;
106         uint32_t *keysyms;
107         uint32_t *codepoints;
108 };
109
110 static inline bool idev_kbdmatch(idev_data_keyboard *kdata,
111                                  uint32_t mods, uint32_t n_syms,
112                                  const uint32_t *syms) {
113         const uint32_t significant = IDEV_KBDMOD_SHIFT |
114                                      IDEV_KBDMOD_CTRL |
115                                      IDEV_KBDMOD_ALT |
116                                      IDEV_KBDMOD_LINUX;
117         uint32_t real;
118
119         if (n_syms != kdata->n_syms)
120                 return false;
121
122         real = kdata->mods & ~kdata->consumed_mods & significant;
123         if (real != mods)
124                 return false;
125
126         return !memcmp(syms, kdata->keysyms, n_syms * sizeof(*syms));
127 }
128
129 #define IDEV_KBDMATCH(_kdata, _mods, _sym) \
130         idev_kbdmatch((_kdata), (_mods), 1, (const uint32_t[]){ (_sym) })
131
132 /*
133  * Data Packets
134  */
135
136 enum {
137         IDEV_DATA_RESYNC,
138         IDEV_DATA_EVDEV,
139         IDEV_DATA_KEYBOARD,
140         IDEV_DATA_CNT
141 };
142
143 struct idev_data {
144         unsigned int type;
145         bool resync : 1;
146
147         union {
148                 idev_data_evdev evdev;
149                 idev_data_keyboard keyboard;
150         };
151 };
152
153 /*
154  * Events
155  */
156
157 enum {
158         IDEV_EVENT_DEVICE_ADD,
159         IDEV_EVENT_DEVICE_REMOVE,
160         IDEV_EVENT_DEVICE_DATA,
161         IDEV_EVENT_CNT
162 };
163
164 struct idev_event {
165         unsigned int type;
166         union {
167                 struct {
168                         idev_device *device;
169                 } device_add, device_remove;
170
171                 struct {
172                         idev_device *device;
173                         idev_data data;
174                 } device_data;
175         };
176 };
177
178 typedef int (*idev_event_fn) (idev_session *s, void *userdata, idev_event *ev);
179
180 /*
181  * Devices
182  */
183
184 void idev_device_enable(idev_device *d);
185 void idev_device_disable(idev_device *d);
186
187 /*
188  * Sessions
189  */
190
191 enum {
192         IDEV_SESSION_CUSTOM                     = (1 << 0),
193         IDEV_SESSION_MANAGED                    = (1 << 1),
194 };
195
196 int idev_session_new(idev_session **out,
197                      idev_context *c,
198                      unsigned int flags,
199                      const char *name,
200                      idev_event_fn event_fn,
201                      void *userdata);
202 idev_session *idev_session_free(idev_session *s);
203
204 DEFINE_TRIVIAL_CLEANUP_FUNC(idev_session*, idev_session_free);
205
206 bool idev_session_is_enabled(idev_session *s);
207 void idev_session_enable(idev_session *s);
208 void idev_session_disable(idev_session *s);
209
210 int idev_session_add_evdev(idev_session *s, struct udev_device *ud);
211 int idev_session_remove_evdev(idev_session *s, struct udev_device *ud);
212
213 /*
214  * Contexts
215  */
216
217 int idev_context_new(idev_context **out, sd_event *event, sd_bus *sysbus);
218 idev_context *idev_context_ref(idev_context *c);
219 idev_context *idev_context_unref(idev_context *c);
220
221 DEFINE_TRIVIAL_CLEANUP_FUNC(idev_context*, idev_context_unref);