about summary refs log tree commit diff
path: root/fakefbdev
diff options
context:
space:
mode:
authorMalte Voos <git@mal.tc>2024-04-03 18:12:50 +0200
committerMalte Voos <git@mal.tc>2024-04-03 18:12:50 +0200
commit6eaea5ca33cfaeea7a7fc9434e082ce1a9e0c6c5 (patch)
tree0f65ca7bb4c5a951f132b6ad53582dc7b5dcc12a /fakefbdev
downloadreMder-6eaea5ca33cfaeea7a7fc9434e082ce1a9e0c6c5.tar.gz
reMder-6eaea5ca33cfaeea7a7fc9434e082ce1a9e0c6c5.zip
init
Diffstat (limited to 'fakefbdev')
-rw-r--r--fakefbdev/FakeFBDev.cpp59
-rw-r--r--fakefbdev/IOCTL.cpp43
-rw-r--r--fakefbdev/IOCTL.h3
-rw-r--r--fakefbdev/Makefile5
-rw-r--r--fakefbdev/SharedBuffer.cpp46
-rw-r--r--fakefbdev/SharedBuffer.h38
-rw-r--r--fakefbdev/mxcfb.h201
7 files changed, 395 insertions, 0 deletions
diff --git a/fakefbdev/FakeFBDev.cpp b/fakefbdev/FakeFBDev.cpp
new file mode 100644
index 0000000..a37b0a0
--- /dev/null
+++ b/fakefbdev/FakeFBDev.cpp
@@ -0,0 +1,59 @@
+#include "IOCTL.h"
+#include "SharedBuffer.h"
+
+#include <cstring>
+#include <dlfcn.h>
+#include <string>
+#include <sys/types.h>
+#include <unistd.h>
+
+SharedFB fb(default_fb_name);
+
+extern "C" {
+
+int
+open64(const char* pathname, int flags, mode_t mode = 0) {
+  if (pathname == std::string("/dev/fb0")) {
+    return fb.fd;
+  }
+
+  static const auto func_open =
+    (int (*)(const char*, int, mode_t))dlsym(RTLD_NEXT, "open64");
+
+  return func_open(pathname, flags, mode);
+}
+
+int
+open(const char* pathname, int flags, mode_t mode = 0) {
+  if (pathname == std::string("/dev/fb0")) {
+    return fb.fd;
+  }
+
+  static const auto func_open =
+    (int (*)(const char*, int, mode_t))dlsym(RTLD_NEXT, "open");
+
+  return func_open(pathname, flags, mode);
+}
+
+int
+close(int fd) {
+  if (fd == fb.fd) {
+    return 0;
+  }
+
+  static const auto func_close = (int (*)(int))dlsym(RTLD_NEXT, "close");
+  return func_close(fd);
+}
+
+int
+ioctl(int fd, unsigned long request, char* ptr) {
+  if (fd == fb.fd) {
+    return handleIOCTL(request, ptr);
+  }
+
+  static auto func_ioctl =
+    (int (*)(int, unsigned long request, ...))dlsym(RTLD_NEXT, "ioctl");
+
+  return func_ioctl(fd, request, ptr);
+}
+}
diff --git a/fakefbdev/IOCTL.cpp b/fakefbdev/IOCTL.cpp
new file mode 100644
index 0000000..90e2583
--- /dev/null
+++ b/fakefbdev/IOCTL.cpp
@@ -0,0 +1,43 @@
+#include "IOCTL.h"
+#include "SharedBuffer.h"
+
+#include <cstring>
+#include <linux/ioctl.h>
+
+#include "mxcfb.h"
+
+int
+handleIOCTL(unsigned long request, char* ptr) {
+  if (request == FBIOGET_VSCREENINFO) {
+
+    fb_var_screeninfo* screeninfo = (fb_var_screeninfo*)ptr;
+    screeninfo->xres = fb_width;
+    screeninfo->yres = fb_height;
+    screeninfo->grayscale = 0;
+    screeninfo->bits_per_pixel = 8 * fb_pixel_size;
+    screeninfo->xres_virtual = fb_width;
+    screeninfo->yres_virtual = fb_height;
+
+    // set to RGB565
+    screeninfo->red.offset = 11;
+    screeninfo->red.length = 5;
+    screeninfo->green.offset = 5;
+    screeninfo->green.length = 6;
+    screeninfo->blue.offset = 0;
+    screeninfo->blue.length = 5;
+
+    return 0;
+  } else if (request == FBIOGET_FSCREENINFO) {
+
+    fb_fix_screeninfo* screeninfo = (fb_fix_screeninfo*)ptr;
+    screeninfo->smem_len = fb_size;
+    screeninfo->smem_start = (unsigned long)0x1000;
+    screeninfo->line_length = fb_width * fb_pixel_size;
+    constexpr char fb_id[] = "mxcfb";
+    std::memcpy(screeninfo->id, fb_id, sizeof(fb_id));
+
+    return 0;
+  } else {
+    return 0;
+  }
+}
diff --git a/fakefbdev/IOCTL.h b/fakefbdev/IOCTL.h
new file mode 100644
index 0000000..423531a
--- /dev/null
+++ b/fakefbdev/IOCTL.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int handleIOCTL(unsigned long request, char* ptr);
diff --git a/fakefbdev/Makefile b/fakefbdev/Makefile
new file mode 100644
index 0000000..516802f
--- /dev/null
+++ b/fakefbdev/Makefile
@@ -0,0 +1,5 @@
+libfakefbdev.so:
+	$(CXX) -fPIC FakeFBDev.cpp IOCTL.cpp SharedBuffer.cpp -shared -o libfakefbdev.so
+
+install:
+	install -Dm755 libfakefbdev.so $(DESTDIR)/lib/libfakefbdev.so
diff --git a/fakefbdev/SharedBuffer.cpp b/fakefbdev/SharedBuffer.cpp
new file mode 100644
index 0000000..fbc3121
--- /dev/null
+++ b/fakefbdev/SharedBuffer.cpp
@@ -0,0 +1,46 @@
+#include "SharedBuffer.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+SharedFB::SharedFB(const char* path) : fd(shm_open(path, O_RDWR, 0755)) {
+  if (fd == -1) {
+    fd = shm_open(path, O_RDWR | O_CREAT, 0755);
+  }
+
+  if (fd < 0) {
+    perror("Can't open shm");
+    return;
+  }
+
+  ftruncate(fd, fb_size);
+  mem = (uint16_t*)mmap(nullptr, fb_size, PROT_WRITE, MAP_SHARED, fd, 0);
+}
+
+SharedFB::~SharedFB() {
+  if (mem != nullptr) {
+    munmap(mem, fb_size);
+  }
+}
+
+SharedFB::SharedFB(SharedFB&& other) noexcept : fd(other.fd), mem(other.mem) {
+  other.fd = -1;
+  other.mem = nullptr;
+}
+
+SharedFB&
+SharedFB::operator=(SharedFB&& other) noexcept {
+  // TODO: release
+  this->fd = other.fd;
+  this->mem = other.mem;
+
+  other.fd = -1;
+  other.mem = nullptr;
+
+  return *this;
+}
diff --git a/fakefbdev/SharedBuffer.h b/fakefbdev/SharedBuffer.h
new file mode 100644
index 0000000..8c96668
--- /dev/null
+++ b/fakefbdev/SharedBuffer.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <cstdint>
+
+constexpr int fb_width = 1404;
+constexpr int fb_height = 1872;
+constexpr int fb_pixel_size = sizeof(uint16_t);
+
+// this is the number of bytes that xochitl mmaps() from the framebuffer.
+// MIGHT CHANGE BETWEEN XOCHITL VERSIONS!
+// the below value was extracted from xochitl 3.10.2.2063.
+//
+// to figure out this value, decompile xochitl using ghidra and
+// - search for the string "Error writing variable information"
+// - this string should be used in a call to perror() which is contained
+//   in the if-part of a branch
+// - look for the corresponding else-branch: the first statement should be
+//   a call to mmap() with the below size.
+// (of course, these instruction might become outdated if remarkable folks
+// rewrite this part of xochitl :/)
+constexpr int fb_size = 0x17bd800;
+
+constexpr auto default_fb_name = "/rm2fb.01";
+
+// TODO: use unistdpp
+struct SharedFB {
+  int fd = -1;
+  uint16_t* mem = nullptr;
+
+  SharedFB(const char* path);
+  ~SharedFB();
+
+  SharedFB(const SharedFB& other) = delete;
+  SharedFB& operator=(const SharedFB& other) = delete;
+
+  SharedFB(SharedFB&& other) noexcept;
+  SharedFB& operator=(SharedFB&& other) noexcept;
+};
diff --git a/fakefbdev/mxcfb.h b/fakefbdev/mxcfb.h
new file mode 100644
index 0000000..3e05795
--- /dev/null
+++ b/fakefbdev/mxcfb.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. All Rights Reserved
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * @file uapi/linux/mxcfb.h
+ *
+ * @brief Global header file for the MXC frame buffer
+ *
+ * @ingroup Framebuffer
+ */
+#ifndef __ASM_ARCH_MXCFB_H__
+#define __ASM_ARCH_MXCFB_H__
+
+#include <linux/ioctl.h>
+#include <linux/fb.h>
+
+#define FB_SYNC_OE_LOW_ACT	0x80000000
+#define FB_SYNC_CLK_LAT_FALL	0x40000000
+#define FB_SYNC_DATA_INVERT	0x20000000
+#define FB_SYNC_CLK_IDLE_EN	0x10000000
+#define FB_SYNC_SHARP_MODE	0x08000000
+#define FB_SYNC_SWAP_RGB	0x04000000
+#define FB_ACCEL_TRIPLE_FLAG	0x00000000
+#define FB_ACCEL_DOUBLE_FLAG	0x00000001
+
+struct mxcfb_gbl_alpha {
+	int enable;
+	int alpha;
+};
+
+struct mxcfb_loc_alpha {
+	int enable;
+	int alpha_in_pixel;
+	unsigned long alpha_phy_addr0;
+	unsigned long alpha_phy_addr1;
+};
+
+struct mxcfb_color_key {
+	int enable;
+	__u32 color_key;
+};
+
+struct mxcfb_pos {
+	__u16 x;
+	__u16 y;
+};
+
+struct mxcfb_gamma {
+	int enable;
+	int constk[16];
+	int slopek[16];
+};
+
+struct mxcfb_gpu_split_fmt {
+	struct fb_var_screeninfo var;
+	unsigned long offset;
+};
+
+struct mxcfb_rect {
+	__u32 top;
+	__u32 left;
+	__u32 width;
+	__u32 height;
+};
+
+#define GRAYSCALE_8BIT				0x1
+#define GRAYSCALE_8BIT_INVERTED			0x2
+#define GRAYSCALE_4BIT                          0x3
+#define GRAYSCALE_4BIT_INVERTED                 0x4
+
+#define AUTO_UPDATE_MODE_REGION_MODE		0
+#define AUTO_UPDATE_MODE_AUTOMATIC_MODE		1
+
+#define UPDATE_SCHEME_SNAPSHOT			0
+#define UPDATE_SCHEME_QUEUE			1
+#define UPDATE_SCHEME_QUEUE_AND_MERGE		2
+
+#define UPDATE_MODE_PARTIAL			0x0
+#define UPDATE_MODE_FULL			0x1
+
+#define WAVEFORM_MODE_GLR16			4
+#define WAVEFORM_MODE_GLD16			5
+#define WAVEFORM_MODE_AUTO			257
+
+#define TEMP_USE_AMBIENT			0x1000
+
+#define EPDC_FLAG_ENABLE_INVERSION		0x01
+#define EPDC_FLAG_FORCE_MONOCHROME		0x02
+#define EPDC_FLAG_USE_CMAP			0x04
+#define EPDC_FLAG_USE_ALT_BUFFER		0x100
+#define EPDC_FLAG_TEST_COLLISION		0x200
+#define EPDC_FLAG_GROUP_UPDATE			0x400
+#define EPDC_FLAG_USE_DITHERING_Y1		0x2000
+#define EPDC_FLAG_USE_DITHERING_Y4		0x4000
+#define EPDC_FLAG_USE_REGAL				0x8000
+
+enum mxcfb_dithering_mode {
+	EPDC_FLAG_USE_DITHERING_PASSTHROUGH = 0x0,
+	EPDC_FLAG_USE_DITHERING_FLOYD_STEINBERG,
+	EPDC_FLAG_USE_DITHERING_ATKINSON,
+	EPDC_FLAG_USE_DITHERING_ORDERED,
+	EPDC_FLAG_USE_DITHERING_QUANT_ONLY,
+	EPDC_FLAG_USE_DITHERING_MAX,
+};
+
+#define FB_POWERDOWN_DISABLE			-1
+#define FB_TEMP_AUTO_UPDATE_DISABLE		-1
+
+struct mxcfb_alt_buffer_data {
+	__u32 phys_addr;
+	__u32 width;	/* width of entire buffer */
+	__u32 height;	/* height of entire buffer */
+	struct mxcfb_rect alt_update_region;	/* region within buffer to update */
+};
+
+struct mxcfb_update_data {
+	struct mxcfb_rect update_region;
+	__u32 waveform_mode;
+	__u32 update_mode;
+	__u32 update_marker;
+	int temp;
+	unsigned int flags;
+	int dither_mode;
+	int quant_bit;
+	struct mxcfb_alt_buffer_data alt_buffer_data;
+};
+
+struct mxcfb_update_marker_data {
+	__u32 update_marker;
+	__u32 collision_test;
+};
+
+/*
+ * Structure used to define waveform modes for driver
+ * Needed for driver to perform auto-waveform selection
+ */
+struct mxcfb_waveform_modes {
+	int mode_init;
+	int mode_du;
+	int mode_gc4;
+	int mode_gc8;
+	int mode_gc16;
+	int mode_gc32;
+};
+
+/*
+ * Structure used to define a 5*3 matrix of parameters for
+ * setting IPU DP CSC module related to this framebuffer.
+ */
+struct mxcfb_csc_matrix {
+	int param[5][3];
+};
+
+#define MXCFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
+#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
+#define MXCFB_SET_CLR_KEY       _IOW('F', 0x22, struct mxcfb_color_key)
+#define MXCFB_SET_OVERLAY_POS   _IOWR('F', 0x24, struct mxcfb_pos)
+#define MXCFB_GET_FB_IPU_CHAN 	_IOR('F', 0x25, u_int32_t)
+#define MXCFB_SET_LOC_ALPHA     _IOWR('F', 0x26, struct mxcfb_loc_alpha)
+#define MXCFB_SET_LOC_ALP_BUF    _IOW('F', 0x27, unsigned long)
+#define MXCFB_SET_GAMMA	       _IOW('F', 0x28, struct mxcfb_gamma)
+#define MXCFB_GET_FB_IPU_DI 	_IOR('F', 0x29, u_int32_t)
+#define MXCFB_GET_DIFMT	       _IOR('F', 0x2A, u_int32_t)
+#define MXCFB_GET_FB_BLANK     _IOR('F', 0x2B, u_int32_t)
+#define MXCFB_SET_DIFMT		_IOW('F', 0x2C, u_int32_t)
+#define MXCFB_CSC_UPDATE	_IOW('F', 0x2D, struct mxcfb_csc_matrix)
+#define MXCFB_SET_GPU_SPLIT_FMT	_IOW('F', 0x2F, struct mxcfb_gpu_split_fmt)
+#define MXCFB_SET_PREFETCH	_IOW('F', 0x30, int)
+#define MXCFB_GET_PREFETCH	_IOR('F', 0x31, int)
+
+/* IOCTLs for E-ink panel updates */
+#define MXCFB_SET_WAVEFORM_MODES	_IOW('F', 0x2B, struct mxcfb_waveform_modes)
+#define MXCFB_SET_TEMPERATURE		_IOW('F', 0x2C, int32_t)
+#define MXCFB_SET_AUTO_UPDATE_MODE	_IOW('F', 0x2D, __u32)
+#define MXCFB_SEND_UPDATE		_IOW('F', 0x2E, struct mxcfb_update_data)
+#define MXCFB_WAIT_FOR_UPDATE_COMPLETE	_IOWR('F', 0x2F, struct mxcfb_update_marker_data)
+#define MXCFB_SET_PWRDOWN_DELAY		_IOW('F', 0x30, int32_t)
+#define MXCFB_GET_PWRDOWN_DELAY		_IOR('F', 0x31, int32_t)
+#define MXCFB_SET_UPDATE_SCHEME		_IOW('F', 0x32, __u32)
+#define MXCFB_GET_WORK_BUFFER		_IOWR('F', 0x34, unsigned long)
+#define MXCFB_SET_TEMP_AUTO_UPDATE_PERIOD      _IOW('F', 0x36, int32_t)
+#define MXCFB_DISABLE_EPDC_ACCESS	_IO('F', 0x35)
+#define MXCFB_ENABLE_EPDC_ACCESS	_IO('F', 0x36)
+#endif