-
Notifications
You must be signed in to change notification settings - Fork 56
Framebuffer Overview
Current framebuffer can be dumped into a PNG with:
ssh [email protected] "cat /dev/fb0" | \
convert -depth 16 -size 1408x1872+0 gray:- png:/tmp/frame.png
Looks like the latest version of ImageMagick has changed the command line parameters for the gray16_le
pixel format so here is the alternative for the command above using ffmpeg
instead of convert
:
ssh [email protected] "cat /dev/fb0" | \
ffmpeg -vcodec rawvideo \
-f rawvideo \
-pix_fmt gray16le \
-s 1408,1872 \
-i - \
-vframes 1
-f image2
-vcodec mjpeg /tmp/frame.jpg
The pixel format for the framebuffer is rgb565_le
due to the following:
red : offset = 11, length =5, msb_right = 0
green : offset = 5, length =6, msb_right = 0
blue : offset = 0, length =5, msb_right = 0
transp : offset = 0, length =0, msb_right = 0
However, given the nature of the display, it can be thought as gray16_le
.
This is what it looks like when interpreted as gray16_le
:
And as rgb565_le
:
Remarkable Paper Tablet has an undocumented API for partial refreshes on its eInk display, which is what's behind its magic that disappears when custom Qt applications are used to draw on the screen, even using the toolchain provided by Remarkable.
The xochitl
program opens /dev/fb0
, which always ends up being the FD=3
. It then writes to this FD when it wants to update the screen and uses primarily the following ioctl
call in order to perform its partial updates when the user draws on the device (0x4048462e
is the PARTIAL_UPDATE_MAGIC
, and the next argument is a pointer to mxcfb_update_data
):
What is particularly interesting here is that 0x4048462e
also happens to be Kindle's MXCFB_SEND_UPDATE
magic. Something to keep in mind.
typedef struct {
uint32_t top; // 0x0000
uint32_t left; // 0x0000
uint32_t width; // 0x0258 = 600
uint32_t height; // 0x0320 = 800
} mxcfb_rect;
typedef struct {
mxcfb_rect update_region;
uint32_t waveform_mode; // 0x0002 = WAVEFORM_MODE_GC16
uint32_t update_mode; // 0x0000 = UPDATE_MODE_PARTIAL
uint32_t update_marker; // 0x002a
int temp; // 0x1001 = TEMP_USE_PAPYRUS
uint flags; // 0x0000
void* alt_buffer_data; // must not used when flags is 0
...
} mxcfb_update_data;
ioctl(3, 0x4048462e, 0x7ea2d290{
updateRegion: x: 0
y: 0
width: 1404
height: 1872
waveformMode: 3,
updateMode: 0
updateMarker: 46
temp: 4096
flags: 0000
alt_buffer_data: 0x300f30
...
}) == 0
The xochitl
program is statically linked with the QsgEpaperPlugin
which can be found in this repository with the filename libqsgepaper.a
. These implementations contained within that library, however, are not used in the PoC as they are not yet fully explored and entirely undocumented. What is used instead is skipping what libqsgepaper
can achieve with its undocumented portions listed here and instead gaining lower level access to the hardware.
However, looking at the function signatures and the analysis so far, it looks like the PoC actually has gotten them right (EPFrameBuffer::WaveformMode, EPFrameBuffer::UpdateMode
in EPFramebuffer::sendUpdate
, returning a uint32_t refresh_marker
that is referred to as an updateCounter
in epframebuffer.o
). The list of prototypes can be found at the end of this page.
Additionally take a look at the /usr/bin/remarkable-test
program. It definitely offers interesting insights into the device.