Files
kmscon/src/uterm.h
T
David Herrmann 4ceb557ecb kmscon: run only on VT-less seats in listen-mode
If we run in listen mode, we are supposed to take over a seat. If a seat
supports VTs (like kernel VTs or kmscon cdev fake VTs) we assume that
there is some manager for these VTs (the one who created them). Therefore,
there is no need to run kmscon in listen mode on these seats. Instead, you
should run kmscon in default mode on these seats.

We enforce this limitation because if the VT-master on those seats dies
and causes a HUP, they have no way to notify us when they startup again.
Therefore, this kind of setup is broken. Furthermore, no-one would every
want such setups.

Instead use the startup mechanism of the VT/seat-manager to start kmscon
in default mode on those seats.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
2012-12-06 14:18:57 +01:00

428 lines
14 KiB
C

/*
* uterm - Linux User-Space Terminal
*
* Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Linux User-Space Terminal
* Historically, terminals were implemented in kernel-space on linux. With the
* development of KMS and the linux input-API it is now possible to implement
* all we need in user-space. This allows to disable the in-kernel CONFIG_VT and
* similar options and reduce the kernel-overhead.
* This library provides an API to implement terminals in user-space. This is
* not limited to classic text-terminals but rather to all kind of applications
* that need graphical output (with OpenGL) or direct keyboard/mouse/etc. input
* from the kernel.
*/
#ifndef UTERM_UTERM_H
#define UTERM_UTERM_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include "eloop.h"
/*
* Video Control
* Linux provides 2 famous ways to access the video hardware: fbdev and drm
* fbdev is the older one of both and is simply a mmap() of the framebuffer into
* main memory. It does not allow 3D acceleration and if you need 2D
* acceleration you should use libraries like cairo to draw into the framebuffer
* provided by this library.
* DRM is the new approach which provides 3D acceleration with mesa. It allows
* much more configuration as fbdev and is the recommended way to access video
* hardware on modern computers.
* Modern mesa provides 3D acceleration on fbdev, too. This is used in systems
* like Android. This will allow us to provide an fbdev backend here.
*
* Famous linux graphics systems like X.Org/X11 or Wayland use fbdev or DRM
* internally to access the video hardware. This API allows low-level access to
* fbdev and DRM without the need of X.Org/X11 or Wayland. If VT support is
* enabled in your kernel, each application can run on a different VT. For
* instance, X.Org may run on VT-7, Wayland on VT-8, your application on VT-9
* and default consoles on VT-1 to VT-6. You can switch between them with
* ctrl-alt-F1-F12.
* If VT support is not available (very unlikely) you need other ways to switch
* between applications.
*
* The main object by this API is uterm_video. This object attaches to a single
* graphics card via DRM or on a single frambuffer via fbdev. Many DRM drivers
* also provide an fbdev driver so you must go sure not to write to both
* simulatneously. Use "UTERM_VIDEO_DRM" to scan for DRM devices. Otherwise,
* fbdev is used. DRM is the recommended way. Use fbdev only on embedded devices
* which do not come with an DRM driver.
* The uterm_video object scans for graphic-cards and connected displays. Each
* display is represented as a uterm_display object. The uterm_video object is
* hotplug-capable so it reports if a display is connected or disconnected.
* Each uterm_display object can be activated/deactivated independently of the
* other displays. To draw to a display you need to create a uterm_screen object
* and add your display to the screen. The screen object allows to spread a
* single screen onto multiple displays. Currently, the uterm_screen object
* allows only one display per screen but we may extend this in the future.
*
* If you are using fbdev, you *must* correctly destroy your uterm_video object
* and also call uterm_video_segfault() if you abnormally abort your
* application. Otherwise your video device remains in undefined state and other
* applications might not display correctly.
* If you use DRM, the same operations are recommended but not required as the
* kernel can correctly reset video devices on its own.
*/
struct uterm_mode;
struct uterm_display;
struct uterm_video;
enum uterm_display_state {
UTERM_DISPLAY_ACTIVE,
UTERM_DISPLAY_ASLEEP,
UTERM_DISPLAY_INACTIVE,
UTERM_DISPLAY_GONE,
};
enum uterm_display_dpms {
UTERM_DPMS_ON,
UTERM_DPMS_STANDBY,
UTERM_DPMS_SUSPEND,
UTERM_DPMS_OFF,
UTERM_DPMS_UNKNOWN,
};
enum uterm_video_type {
UTERM_VIDEO_DRM,
UTERM_VIDEO_DUMB,
UTERM_VIDEO_FBDEV,
};
enum uterm_video_action {
UTERM_WAKE_UP,
UTERM_SLEEP,
UTERM_NEW,
UTERM_GONE,
};
struct uterm_video_hotplug {
struct uterm_display *display;
int action;
};
enum uterm_display_action {
UTERM_PAGE_FLIP,
};
struct uterm_display_event {
int action;
};
enum uterm_video_format {
UTERM_FORMAT_GREY,
UTERM_FORMAT_XRGB32,
};
struct uterm_video_buffer {
unsigned int width;
unsigned int height;
unsigned int stride;
unsigned int format;
uint8_t *data;
};
struct uterm_video_blend_req {
const struct uterm_video_buffer *buf;
unsigned int x;
unsigned int y;
uint8_t fr;
uint8_t fg;
uint8_t fb;
uint8_t br;
uint8_t bg;
uint8_t bb;
};
typedef void (*uterm_video_cb) (struct uterm_video *video,
struct uterm_video_hotplug *arg,
void *data);
typedef void (*uterm_display_cb) (struct uterm_display *disp,
struct uterm_display_event *arg,
void *data);
/* misc */
const char *uterm_dpms_to_name(int dpms);
bool uterm_video_available(unsigned int type);
/* display modes interface */
void uterm_mode_ref(struct uterm_mode *mode);
void uterm_mode_unref(struct uterm_mode *mode);
struct uterm_mode *uterm_mode_next(struct uterm_mode *mode);
const char *uterm_mode_get_name(const struct uterm_mode *mode);
unsigned int uterm_mode_get_width(const struct uterm_mode *mode);
unsigned int uterm_mode_get_height(const struct uterm_mode *mode);
/* display interface */
void uterm_display_ref(struct uterm_display *disp);
void uterm_display_unref(struct uterm_display *disp);
struct uterm_display *uterm_display_next(struct uterm_display *disp);
int uterm_display_register_cb(struct uterm_display *disp, uterm_display_cb cb,
void *data);
void uterm_display_unregister_cb(struct uterm_display *disp,
uterm_display_cb cb, void *data);
struct uterm_mode *uterm_display_get_modes(struct uterm_display *disp);
struct uterm_mode *uterm_display_get_current(struct uterm_display *disp);
struct uterm_mode *uterm_display_get_default(struct uterm_display *disp);
int uterm_display_get_state(struct uterm_display *disp);
int uterm_display_activate(struct uterm_display *disp, struct uterm_mode *mode);
void uterm_display_deactivate(struct uterm_display *disp);
int uterm_display_set_dpms(struct uterm_display *disp, int state);
int uterm_display_get_dpms(const struct uterm_display *disp);
int uterm_display_use(struct uterm_display *disp);
int uterm_display_swap(struct uterm_display *disp);
bool uterm_display_is_swapping(struct uterm_display *disp);
int uterm_display_fill(struct uterm_display *disp,
uint8_t r, uint8_t g, uint8_t b,
unsigned int x, unsigned int y,
unsigned int width, unsigned int height);
int uterm_display_blit(struct uterm_display *disp,
const struct uterm_video_buffer *buf,
unsigned int x, unsigned int y);
int uterm_display_fake_blend(struct uterm_display *disp,
const struct uterm_video_buffer *buf,
unsigned int x, unsigned int y,
uint8_t fr, uint8_t fg, uint8_t fb,
uint8_t br, uint8_t bg, uint8_t bb);
int uterm_display_fake_blendv(struct uterm_display *disp,
const struct uterm_video_blend_req *req,
size_t num);
/* video interface */
int uterm_video_new(struct uterm_video **out,
struct ev_eloop *eloop,
unsigned int type,
const char *node);
void uterm_video_ref(struct uterm_video *video);
void uterm_video_unref(struct uterm_video *video);
void uterm_video_segfault(struct uterm_video *video);
int uterm_video_use(struct uterm_video *video);
struct uterm_display *uterm_video_get_displays(struct uterm_video *video);
int uterm_video_register_cb(struct uterm_video *video, uterm_video_cb cb,
void *data);
void uterm_video_unregister_cb(struct uterm_video *video, uterm_video_cb cb,
void *data);
void uterm_video_sleep(struct uterm_video *video);
int uterm_video_wake_up(struct uterm_video *video);
bool uterm_video_is_awake(struct uterm_video *video);
void uterm_video_poll(struct uterm_video *video);
/*
* Input Devices
* This input object can combine multiple linux input devices into a single
* device and notifies the application about events. It has several different
* keyboard backends so the full XKB feature set is available.
*/
struct uterm_input;
/* keep in sync with shl_xkb_mods */
enum uterm_input_modifier {
UTERM_SHIFT_MASK = (1 << 0),
UTERM_LOCK_MASK = (1 << 1),
UTERM_CONTROL_MASK = (1 << 2),
UTERM_ALT_MASK = (1 << 3),
UTERM_LOGO_MASK = (1 << 4),
};
/* keep in sync with TSM_VTE_INVALID */
#define UTERM_INPUT_INVALID 0xffffffff
struct uterm_input_event {
bool handled; /* user-controlled, default is false */
uint16_t keycode; /* linux keycode - KEY_* - linux/input.h */
uint32_t ascii; /* ascii keysym for @keycode */
unsigned int mods; /* active modifiers - uterm_modifier mask */
unsigned int num_syms; /* number of keysyms */
uint32_t *keysyms; /* XKB-common keysym-array - XKB_KEY_* */
uint32_t *codepoints; /* ucs4 unicode value or UTERM_INPUT_INVALID */
};
#define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods))
typedef void (*uterm_input_cb) (struct uterm_input *input,
struct uterm_input_event *ev,
void *data);
int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop,
const char *model,
const char *layout,
const char *variant,
const char *options,
unsigned int repeat_delay,
unsigned int repeat_rate);
void uterm_input_ref(struct uterm_input *input);
void uterm_input_unref(struct uterm_input *input);
void uterm_input_add_dev(struct uterm_input *input, const char *node);
void uterm_input_remove_dev(struct uterm_input *input, const char *node);
int uterm_input_register_cb(struct uterm_input *input,
uterm_input_cb cb,
void *data);
void uterm_input_unregister_cb(struct uterm_input *input,
uterm_input_cb cb,
void *data);
void uterm_input_sleep(struct uterm_input *input);
void uterm_input_wake_up(struct uterm_input *input);
bool uterm_input_is_awake(struct uterm_input *input);
void uterm_input_keysym_to_string(struct uterm_input *input,
uint32_t keysym, char *str, size_t size);
int uterm_input_string_to_keysym(struct uterm_input *input, const char *n,
uint32_t *out);
/*
* Virtual Terminals
* Virtual terminals allow controlling multiple virtual terminals on one real
* terminal. It is multi-seat capable and fully asynchronous.
*/
struct uterm_vt;
struct uterm_vt_master;
enum uterm_vt_action {
UTERM_VT_ACTIVATE,
UTERM_VT_DEACTIVATE,
UTERM_VT_HUP,
};
enum uterm_vt_flags {
UTERM_VT_FORCE = 0x01,
};
struct uterm_vt_event {
unsigned int action;
unsigned int flags;
int target;
};
enum uterm_vt_type {
UTERM_VT_REAL = 0x01,
UTERM_VT_FAKE = 0x02,
};
typedef int (*uterm_vt_cb) (struct uterm_vt *vt, struct uterm_vt_event *ev,
void *data);
int uterm_vt_master_new(struct uterm_vt_master **out,
struct ev_eloop *eloop);
void uterm_vt_master_ref(struct uterm_vt_master *vtm);
void uterm_vt_master_unref(struct uterm_vt_master *vtm);
int uterm_vt_master_activate_all(struct uterm_vt_master *vtm);
int uterm_vt_master_deactivate_all(struct uterm_vt_master *vtm);
int uterm_vt_allocate(struct uterm_vt_master *vt, struct uterm_vt **out,
unsigned int allowed_types,
const char *seat, struct uterm_input *input,
const char *vt_name, uterm_vt_cb cb, void *data);
void uterm_vt_deallocate(struct uterm_vt *vt);
void uterm_vt_ref(struct uterm_vt *vt);
void uterm_vt_unref(struct uterm_vt *vt);
int uterm_vt_activate(struct uterm_vt *vt);
int uterm_vt_deactivate(struct uterm_vt *vt);
void uterm_vt_retry(struct uterm_vt *vt);
unsigned int uterm_vt_get_type(struct uterm_vt *vt);
/*
* System Monitor
* This watches the system for new seats, graphics devices or other devices that
* are used by terminals.
*/
struct uterm_monitor;
struct uterm_monitor_seat;
struct uterm_monitor_dev;
enum uterm_monitor_event_type {
UTERM_MONITOR_NEW_SEAT,
UTERM_MONITOR_FREE_SEAT,
UTERM_MONITOR_NEW_DEV,
UTERM_MONITOR_FREE_DEV,
UTERM_MONITOR_HOTPLUG_DEV,
};
enum uterm_monitor_dev_type {
UTERM_MONITOR_DRM,
UTERM_MONITOR_FBDEV,
UTERM_MONITOR_INPUT,
};
enum uterm_monitor_dev_flag {
UTERM_MONITOR_DRM_BACKED = 0x01,
UTERM_MONITOR_PRIMARY = 0x02,
UTERM_MONITOR_AUX = 0x04,
};
struct uterm_monitor_event {
unsigned int type;
struct uterm_monitor_seat *seat;
const char *seat_name;
void *seat_data;
struct uterm_monitor_dev *dev;
unsigned int dev_type;
unsigned int dev_flags;
const char *dev_node;
void *dev_data;
};
typedef void (*uterm_monitor_cb) (struct uterm_monitor *mon,
struct uterm_monitor_event *event,
void *data);
int uterm_monitor_new(struct uterm_monitor **out,
struct ev_eloop *eloop,
uterm_monitor_cb cb,
void *data);
void uterm_monitor_ref(struct uterm_monitor *mon);
void uterm_monitor_unref(struct uterm_monitor *mon);
void uterm_monitor_scan(struct uterm_monitor *mon);
void uterm_monitor_set_seat_data(struct uterm_monitor_seat *seat, void *data);
void uterm_monitor_set_dev_data(struct uterm_monitor_dev *dev, void *data);
#endif /* UTERM_UTERM_H */