ultimatepp/bazaar/LinuxFrameBuffer/LinuxFrameBuffer.cpp
zbych 4844054f9a LinuxFrameBuffer: attempt to disable keys leakage to the console via virtual terminal API
git-svn-id: svn://ultimatepp.org/upp/trunk@14613 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-06-20 22:40:10 +00:00

183 lines
3.7 KiB
C++

#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
//#include <linux/kd.h>
#include <linux/vt.h>
#include "LinuxFrameBuffer.h"
using namespace Upp;
static int open_restricted(const char *path, int flags, void *user_data)
{
int fd = open(path, flags);
return fd < 0 ? -errno : fd;
}
static void close_restricted(int fd, void *user_data)
{
close(fd);
}
static const struct libinput_interface input_interface =
{
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};
LinuxFrameBuffer::~LinuxFrameBuffer()
{
Destroy();
}
bool LinuxFrameBuffer::Screen::Open(const char * device)
{
Close();
handle = open(device, O_RDWR);
if (handle < 0){
RLOG("Error opening device: '" << device << "': " << GetLastErrorMessage());
return false;
}
struct fb_var_screeninfo info;
if (ioctl(handle, FBIOGET_VSCREENINFO, &info) == 0){
resolution.cx = info.xres;
resolution.cy = info.yres;
bits_per_pixel = info.bits_per_pixel;
}
struct fb_fix_screeninfo finfo;
if (ioctl(handle, FBIOGET_FSCREENINFO, &finfo) == 0){
buff_len = finfo.smem_len;
}
buffer = (uint32 *)mmap(nullptr, buff_len, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
if (buffer == MAP_FAILED){
RLOG("Memory mapping error: " << GetLastErrorMessage());
return false;
}
image.Create(resolution);
painter.Create(image, MODE_ANTIALIASED);
sysdraw.SetTarget(&painter);
return true;
}
void LinuxFrameBuffer::Screen::Close()
{
if (buffer != nullptr){
munmap(buffer, buff_len);
buffer = nullptr;
}
if (handle >= 0){
close(handle);
handle = -1;
}
}
bool LinuxFrameBuffer::input_t::Open()
{
Close();
udev = udev_new();
if (udev == nullptr){
RLOG("udev_new error");
return false;
}
lib_inp = libinput_udev_create_context(&input_interface, nullptr, udev);
if (lib_inp == nullptr){
RLOG("libinput create context error");
return false;
}
libinput_udev_assign_seat(lib_inp, "seat0");
libinput_dispatch(lib_inp);
kb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (kb_ctx == nullptr){
RLOG("xkb context error");
return false;
}
kb_map = xkb_keymap_new_from_names(kb_ctx, nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (kb_map == nullptr){
RLOG("xkb map error");
return false;
}
kb_state = xkb_state_new(kb_map);
if (kb_state == nullptr){
RLOG("xkb state error");
return false;
}
return true;
}
void LinuxFrameBuffer::input_t::Close()
{
if (kb_state != nullptr){
xkb_state_unref(kb_state);
kb_state = nullptr;
}
if (kb_map != nullptr){
xkb_keymap_unref(kb_map);
kb_map = nullptr;
}
if (kb_ctx != nullptr){
xkb_context_unref(kb_ctx);
kb_ctx = nullptr;
}
if (lib_inp != nullptr){
libinput_unref(lib_inp);
lib_inp = nullptr;
}
if (udev != nullptr){
udev_unref(udev);
udev = nullptr;
}
}
void LinuxFrameBuffer::Destroy()
{
input.Close();
vt.Close();
screen.Close();
}
bool LinuxFrameBuffer::Create(const char * device)
{
Destroy();
if (!screen.Open(device)){
Destroy();
return false;
}
//vt.Open("/dev/tty3");
if (!input.Open()){
Destroy();
return false;
}
return true;
}