diff options
Diffstat (limited to 'src/libsystemd-terminal/modeset.c')
-rw-r--r-- | src/libsystemd-terminal/modeset.c | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/src/libsystemd-terminal/modeset.c b/src/libsystemd-terminal/modeset.c deleted file mode 100644 index 790a244772..0000000000 --- a/src/libsystemd-terminal/modeset.c +++ /dev/null @@ -1,482 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -/* - * Modeset Testing - * The modeset tool attaches to the session of the caller and shows a - * test-pattern on all displays of this session. It is meant as debugging tool - * for the grdev infrastructure. - */ - -#include <drm_fourcc.h> -#include <errno.h> -#include <getopt.h> -#include <linux/kd.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <termios.h> -#include <unistd.h> -#include "sd-bus.h" -#include "sd-event.h" -#include "sd-login.h" -#include "build.h" -#include "macro.h" -#include "random-util.h" -#include "signal-util.h" -#include "util.h" -#include "grdev.h" -#include "sysview.h" - -typedef struct Modeset Modeset; - -struct Modeset { - char *session; - char *seat; - sd_event *event; - sd_bus *bus; - sd_event_source *exit_src; - sysview_context *sysview; - grdev_context *grdev; - grdev_session *grdev_session; - - uint8_t r, g, b; - bool r_up, g_up, b_up; - - bool my_tty : 1; - bool managed : 1; -}; - -static int modeset_exit_fn(sd_event_source *source, void *userdata) { - Modeset *m = userdata; - - if (m->grdev_session) - grdev_session_restore(m->grdev_session); - - return 0; -} - -static Modeset *modeset_free(Modeset *m) { - if (!m) - return NULL; - - m->grdev_session = grdev_session_free(m->grdev_session); - m->grdev = grdev_context_unref(m->grdev); - m->sysview = sysview_context_free(m->sysview); - m->exit_src = sd_event_source_unref(m->exit_src); - m->bus = sd_bus_unref(m->bus); - m->event = sd_event_unref(m->event); - free(m->seat); - free(m->session); - free(m); - - return NULL; -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(Modeset*, modeset_free); - -static bool is_my_tty(const char *session) { - unsigned int vtnr; - struct stat st; - long mode; - int r; - - /* Using logind's Controller API is highly fragile if there is already - * a session controller running. If it is registered as controller - * itself, TakeControl will simply fail. But if its a legacy controller - * that does not use logind's controller API, we must never register - * our own controller. Otherwise, we really mess up the VT. Therefore, - * only run in managed mode if there's no-one else. Furthermore, never - * try to access graphics devices if there's someone else. Unlike input - * devices, graphics devies cannot be shared easily. */ - - if (!isatty(1)) - return false; - - if (!session) - return false; - - r = sd_session_get_vt(session, &vtnr); - if (r < 0 || vtnr < 1 || vtnr > 63) - return false; - - mode = 0; - r = ioctl(1, KDGETMODE, &mode); - if (r < 0 || mode != KD_TEXT) - return false; - - r = fstat(1, &st); - if (r < 0 || minor(st.st_rdev) != vtnr) - return false; - - return true; -} - -static int modeset_new(Modeset **out) { - _cleanup_(modeset_freep) Modeset *m = NULL; - int r; - - assert(out); - - m = new0(Modeset, 1); - if (!m) - return log_oom(); - - r = sd_pid_get_session(getpid(), &m->session); - if (r < 0) - return log_error_errno(r, "Cannot retrieve logind session: %m"); - - r = sd_session_get_seat(m->session, &m->seat); - if (r < 0) - return log_error_errno(r, "Cannot retrieve seat of logind session: %m"); - - m->my_tty = is_my_tty(m->session); - m->managed = m->my_tty && geteuid() > 0; - - m->r = rand() % 0xff; - m->g = rand() % 0xff; - m->b = rand() % 0xff; - m->r_up = m->g_up = m->b_up = true; - - r = sd_event_default(&m->event); - if (r < 0) - return r; - - r = sd_bus_open_system(&m->bus); - if (r < 0) - return r; - - r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL); - if (r < 0) - return r; - - r = sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1); - if (r < 0) - return r; - - r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); - if (r < 0) - return r; - - r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); - if (r < 0) - return r; - - r = sd_event_add_exit(m->event, &m->exit_src, modeset_exit_fn, m); - if (r < 0) - return r; - - /* schedule before sd-bus close */ - r = sd_event_source_set_priority(m->exit_src, -10); - if (r < 0) - return r; - - r = sysview_context_new(&m->sysview, - SYSVIEW_CONTEXT_SCAN_LOGIND | - SYSVIEW_CONTEXT_SCAN_DRM, - m->event, - m->bus, - NULL); - if (r < 0) - return r; - - r = grdev_context_new(&m->grdev, m->event, m->bus); - if (r < 0) - return r; - - *out = m; - m = NULL; - return 0; -} - -static uint8_t next_color(bool *up, uint8_t cur, unsigned int mod) { - uint8_t next; - - /* generate smoothly morphing colors */ - - next = cur + (*up ? 1 : -1) * (rand() % mod); - if ((*up && next < cur) || (!*up && next > cur)) { - *up = !*up; - next = cur; - } - - return next; -} - -static void modeset_draw(Modeset *m, const grdev_display_target *t) { - uint32_t j, k, *b; - uint8_t *l; - - assert(t->back->format == DRM_FORMAT_XRGB8888 || t->back->format == DRM_FORMAT_ARGB8888); - assert(!t->rotate); - assert(!t->flip); - - l = t->back->maps[0]; - for (j = 0; j < t->height; ++j) { - for (k = 0; k < t->width; ++k) { - b = (uint32_t*)l; - b[k] = (0xff << 24) | (m->r << 16) | (m->g << 8) | m->b; - } - - l += t->back->strides[0]; - } -} - -static void modeset_render(Modeset *m, grdev_display *d) { - const grdev_display_target *t; - - m->r = next_color(&m->r_up, m->r, 4); - m->g = next_color(&m->g_up, m->g, 3); - m->b = next_color(&m->b_up, m->b, 2); - - GRDEV_DISPLAY_FOREACH_TARGET(d, t) { - modeset_draw(m, t); - grdev_display_flip_target(d, t); - } - - grdev_session_commit(m->grdev_session); -} - -static void modeset_grdev_fn(grdev_session *session, void *userdata, grdev_event *ev) { - Modeset *m = userdata; - - switch (ev->type) { - case GRDEV_EVENT_DISPLAY_ADD: - grdev_display_enable(ev->display_add.display); - break; - case GRDEV_EVENT_DISPLAY_REMOVE: - break; - case GRDEV_EVENT_DISPLAY_CHANGE: - break; - case GRDEV_EVENT_DISPLAY_FRAME: - modeset_render(m, ev->display_frame.display); - break; - } -} - -static int modeset_sysview_fn(sysview_context *c, void *userdata, sysview_event *ev) { - unsigned int flags, type; - Modeset *m = userdata; - sysview_device *d; - const char *name; - int r; - - switch (ev->type) { - case SYSVIEW_EVENT_SESSION_FILTER: - if (streq_ptr(m->session, ev->session_filter.id)) - return 1; - - break; - case SYSVIEW_EVENT_SESSION_ADD: - assert(!m->grdev_session); - - name = sysview_session_get_name(ev->session_add.session); - flags = 0; - - if (m->managed) - flags |= GRDEV_SESSION_MANAGED; - - r = grdev_session_new(&m->grdev_session, - m->grdev, - flags, - name, - modeset_grdev_fn, - m); - if (r < 0) - return log_error_errno(r, "Cannot create grdev session: %m"); - - if (m->managed) { - r = sysview_session_take_control(ev->session_add.session); - if (r < 0) - return log_error_errno(r, "Cannot request session control: %m"); - } - - grdev_session_enable(m->grdev_session); - - break; - case SYSVIEW_EVENT_SESSION_REMOVE: - if (!m->grdev_session) - return 0; - - grdev_session_restore(m->grdev_session); - grdev_session_disable(m->grdev_session); - m->grdev_session = grdev_session_free(m->grdev_session); - if (sd_event_get_exit_code(m->event, &r) == -ENODATA) - sd_event_exit(m->event, 0); - break; - case SYSVIEW_EVENT_SESSION_ATTACH: - d = ev->session_attach.device; - type = sysview_device_get_type(d); - if (type == SYSVIEW_DEVICE_DRM) - grdev_session_add_drm(m->grdev_session, sysview_device_get_ud(d)); - - break; - case SYSVIEW_EVENT_SESSION_DETACH: - d = ev->session_detach.device; - type = sysview_device_get_type(d); - if (type == SYSVIEW_DEVICE_DRM) - grdev_session_remove_drm(m->grdev_session, sysview_device_get_ud(d)); - - break; - case SYSVIEW_EVENT_SESSION_REFRESH: - d = ev->session_refresh.device; - type = sysview_device_get_type(d); - if (type == SYSVIEW_DEVICE_DRM) - grdev_session_hotplug_drm(m->grdev_session, ev->session_refresh.ud); - - break; - case SYSVIEW_EVENT_SESSION_CONTROL: - r = ev->session_control.error; - if (r < 0) - return log_error_errno(r, "Cannot acquire session control: %m"); - - r = ioctl(1, KDSKBMODE, K_UNICODE); - if (r < 0) - return log_error_errno(errno, "Cannot set K_UNICODE on stdout: %m"); - - break; - } - - return 0; -} - -static int modeset_run(Modeset *m) { - struct termios in_attr, saved_attr; - int r; - - assert(m); - - if (!m->my_tty) { - log_warning("You need to run this program on a free VT"); - return -EACCES; - } - - if (!m->managed && geteuid() > 0) - log_warning("You run in unmanaged mode without being root. This is likely to fail.."); - - printf("modeset - Show test pattern on selected graphics devices\n" - " Running on seat '%s' in user-session '%s'\n" - " Exit by pressing ^C\n\n", - m->seat ? : "seat0", m->session ? : "<none>"); - - r = sysview_context_start(m->sysview, modeset_sysview_fn, m); - if (r < 0) - goto out; - - r = tcgetattr(0, &in_attr); - if (r < 0) { - r = -errno; - goto out; - } - - saved_attr = in_attr; - in_attr.c_lflag &= ~ECHO; - - r = tcsetattr(0, TCSANOW, &in_attr); - if (r < 0) { - r = -errno; - goto out; - } - - r = sd_event_loop(m->event); - tcsetattr(0, TCSANOW, &saved_attr); - printf("exiting..\n"); - -out: - sysview_context_stop(m->sysview); - return r; -} - -static int help(void) { - printf("%s [OPTIONS...]\n\n" - "Show test pattern on all selected graphics devices.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - , program_invocation_short_name); - - return 0; -} - -static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - }; - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - {}, - }; - int c; - - assert(argc >= 0); - assert(argv); - - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) - switch (c) { - case 'h': - help(); - return 0; - - case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; - - case '?': - return -EINVAL; - - default: - assert_not_reached("Unhandled option"); - } - - if (argc > optind) { - log_error("Too many arguments"); - return -EINVAL; - } - - return 1; -} - -int main(int argc, char *argv[]) { - _cleanup_(modeset_freep) Modeset *m = NULL; - int r; - - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - initialize_srand(); - - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; - - r = modeset_new(&m); - if (r < 0) - goto finish; - - r = modeset_run(m); - -finish: - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} |