2 * uvtd - User-space VT daemon
4 * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Every virtual terminal forms a session inside of uvtd. Sessions are scheduled
29 * by the seat/session-scheduler and notified whenever they get active/inactive.
45 #include "uvtd_seat.h"
48 #define LOG_SUBSYSTEM "vt"
53 struct shl_hook *hook;
54 struct uvtd_session *session;
59 struct vt_mode vtmode;
63 static void vt_hup(struct uvtd_vt *vt)
65 struct uvt_vt_event ev;
67 memset(&ev, 0, sizeof(ev));
70 shl_hook_call(vt->hook, vt, &ev);
73 static int vt_session_event(struct uvtd_session *session, unsigned int event,
76 struct uvtd_vt *vt = data;
79 case UVTD_SESSION_UNREGISTER:
83 case UVTD_SESSION_ACTIVATE:
84 log_debug("activate %p", vt);
86 case UVTD_SESSION_DEACTIVATE:
87 log_debug("deactivate %p", vt);
94 int uvtd_vt_new(struct uvtd_vt **out, struct uvt_ctx *uctx, unsigned int id,
95 struct uvtd_seat *seat, bool is_legacy)
103 vt = malloc(sizeof(*vt));
107 memset(vt, 0, sizeof(*vt));
110 vt->is_legacy = is_legacy;
112 vt->kbmode = K_UNICODE;
113 vt->vtmode.mode = VT_AUTO;
115 ret = shl_hook_new(&vt->hook);
119 ret = uvtd_seat_register_session(seat, &vt->session, id,
120 vt_session_event, vt);
124 uvt_ctx_ref(vt->uctx);
129 shl_hook_free(vt->hook);
135 void uvtd_vt_ref(struct uvtd_vt *vt)
143 void uvtd_vt_unref(struct uvtd_vt *vt)
145 if (!vt || !vt->ref || --vt->ref)
148 uvtd_session_unregister(vt->session);
149 shl_hook_free(vt->hook);
150 uvt_ctx_unref(vt->uctx);
154 int uvtd_vt_register_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data)
159 return shl_hook_add_cast(vt->hook, cb, data, false);
162 void uvtd_vt_unregister_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data)
167 shl_hook_rm_cast(vt->hook, cb, data);
170 int uvtd_vt_read(struct uvtd_vt *vt, uint8_t *mem, size_t len)
175 int uvtd_vt_write(struct uvtd_vt *vt, const uint8_t *mem, size_t len)
180 unsigned int uvtd_vt_poll(struct uvtd_vt *vt)
182 return UVT_TTY_WRITE;
185 static int vt_ioctl_TCFLSH(void *data, unsigned long arg)
199 static int vt_ioctl_VT_ACTIVATE(void *data, unsigned long arg)
204 static int vt_ioctl_VT_WAITACTIVE(void *data, unsigned long arg)
209 static int vt_ioctl_VT_GETSTATE(void *data, struct vt_stat *arg)
214 static int vt_ioctl_VT_OPENQRY(void *data, unsigned int *arg)
219 static int vt_ioctl_VT_GETMODE(void *data, struct vt_mode *arg)
221 struct uvtd_vt *vt = data;
223 memcpy(arg, &vt->vtmode, sizeof(*arg));
227 static int vt_ioctl_VT_SETMODE(void *data, const struct vt_mode *arg,
230 struct uvtd_vt *vt = data;
232 /* TODO: implement waitv logic (hang on write if not active) */
238 if (arg->relsig > SIGRTMAX || arg->relsig < 0)
240 if (arg->acqsig > SIGRTMAX || arg->acqsig < 0)
245 if (arg->acqsig || arg->relsig)
256 memcpy(&vt->vtmode, arg, sizeof(*arg));
260 static int vt_ioctl_VT_RELDISP(void *data, unsigned long arg)
265 static int vt_ioctl_KDGETMODE(void *data, unsigned int *arg)
267 struct uvtd_vt *vt = data;
273 static int vt_ioctl_KDSETMODE(void *data, unsigned int arg)
275 struct uvtd_vt *vt = data;
293 static int vt_ioctl_KDGKBMODE(void *data, unsigned int *arg)
295 struct uvtd_vt *vt = data;
301 static int vt_ioctl_KDSKBMODE(void *data, unsigned int arg)
303 struct uvtd_vt *vt = data;
307 /* TODO: what does K_RAW do? */
314 /* TODO: do we need these? */
323 /* compatibility to UVT-VT ops */
325 static void vt_ref(void *vt)
330 static void vt_unref(void *vt)
335 static int vt_register_cb(void *vt, uvt_vt_cb cb, void *data)
337 return uvtd_vt_register_cb(vt, cb, data);
340 static void vt_unregister_cb(void *vt, uvt_vt_cb cb, void *data)
342 uvtd_vt_register_cb(vt, cb, data);
345 static int vt_read(void *vt, uint8_t *mem, size_t len)
347 return uvtd_vt_read(vt, mem, len);
350 static int vt_write(void *vt, const uint8_t *mem, size_t len)
352 return uvtd_vt_write(vt, mem, len);
355 static unsigned int vt_poll(void *vt)
357 return uvtd_vt_poll(vt);
360 struct uvt_vt_ops uvtd_vt_ops = {
363 .register_cb = vt_register_cb,
364 .unregister_cb = vt_unregister_cb,
369 .ioctl_TCFLSH = vt_ioctl_TCFLSH,
371 .ioctl_VT_ACTIVATE = vt_ioctl_VT_ACTIVATE,
372 .ioctl_VT_WAITACTIVE = vt_ioctl_VT_WAITACTIVE,
373 .ioctl_VT_GETSTATE = vt_ioctl_VT_GETSTATE,
374 .ioctl_VT_OPENQRY = vt_ioctl_VT_OPENQRY,
375 .ioctl_VT_GETMODE = vt_ioctl_VT_GETMODE,
376 .ioctl_VT_SETMODE = vt_ioctl_VT_SETMODE,
377 .ioctl_VT_RELDISP = vt_ioctl_VT_RELDISP,
378 .ioctl_KDGETMODE = vt_ioctl_KDGETMODE,
379 .ioctl_KDSETMODE = vt_ioctl_KDSETMODE,
380 .ioctl_KDGKBMODE = vt_ioctl_KDGKBMODE,
381 .ioctl_KDSKBMODE = vt_ioctl_KDSKBMODE,