Skip to content

Framebuffer Overview

Can Selcik edited this page Mar 30, 2018 · 9 revisions

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;

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 at xochitl-reference/libqsgepaper.md 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.