]> git.proxmox.com Git - systemd.git/blob - src/libsystemd-terminal/idev.h
Imported Upstream version 222
[systemd.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 <xkbcommon/xkbcommon.h>
32 #include "sd-bus.h"
33 #include "sd-event.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);