ddvk / remarkable2-framebuffer

remarkable2 framebuffer reversing
MIT License
283 stars 22 forks source link

usage document for rm2fb #11

Closed raisjn closed 3 years ago

raisjn commented 4 years ago

rm2fb is a server/client model for communicating with the framebuffer on the rM2.

building and running

  1. source rM toolchain
  2. run qmake in top level directory
  3. run make in top level directory
  4. server binary is now in src/server/
  5. copy server binary to rM2 and run with LD_PRELOAD=librm2fb.so remarkable-shutdown

how rm2fb works

server

the server of rm2fb (librm2fb.so) injects itself into the remarkable-shutdown binary using LD_PRELOAD and starts its own server. librm2fb then creates a piece of shared memory (/dev/shm/swtfb*) and starts a message queue. librm2fb then uses shared memory and messages coming over the message queue to tell SWTCON what to draw to screen. the SWTCON is the software thread that is driving the display.

clients

clients interact with the server through IPC. instead of opening /dev/fb0 as their framebuffer, they use /dev/shm/swtfb* as their framebuffer's memory. instead of sending the mxcfb_update ioctl, specifying where to redraw on screen, they send the same struct through a message queue to the librm2fb server.

how to write an IPC client for rm2fb

relevant system APIS: shm_open, msgget, msgsnd

see ipc.cpp for the reference implementation

  1. use shm_open to open /swtfb.01 as the framebuffer and mmap it into memory. it has a fixed size of 1404x1872xsizeof(uint16_t) and expects rgb565 content (like the original rM1 does)

  2. open the Sys V message queue with ID 0x2257c using msgget for writing as queue_fd

  3. define an envelope struct that contains two members: long mtype and mxcfb_update_data. mtype must be non-zero

struct swtfb_update_data {
  long mtype;
  mxcfb_update_data update;
}
  1. instead of calling ioctl(fb_fd, MXCFB_SEND_UPDATE, update_data), use:
    swtfb_update_data swtfb_update = swtfb_update_data { 1, update_data };
    msgsnd(queue_fd, &swtfb_update, sizeof(swtfb_update), 0)

EDIT: 11/6/20: swtfb_update_data is defined to be an envelope around mxcfb_update_data instead of being an augmented mxcfb_update_data

pgaskin commented 4 years ago

An interesting extension to this (since this appears to be quite close to the direct API) would be another LD_PRELOAD shim to hook the open, close, mmap, ioctl, and other related syscalls to allow using normal applications which use the framebuffer directly to work without modification.

LinusCDE commented 4 years ago

As for the location of the documentation, I'm not sure either where to put it.
Some ideas:

EDIT: It would probably be an interesting route to create a dedicated documentation repo and have a readthedocs site for it. Though that would basicially be the unofficial wiki all over and we should try to first update that instead.

raisjn commented 4 years ago

@pgaskin I really like this idea, would make things much easier

pgaskin commented 4 years ago

Another idea for apps which don't support LD_PRELOAD: mount a custom FUSE filesystem on /dev/fb0 which forwards to rm2fb. This would have a slightly larger performance impact, but it would work on all apps without modification. The code would be around the same length as the LD_PRELOAD shim.

Note that I've never tried doing something like this, so this is purely theoretical.