goMarkableStream
I use this toy project to stream my remarkable 2 (firmware 2.5) on my laptop using the local wifi.
video/demo here
Quick start
You need ssh access to your remarkable
Download two files from the release page:
- the server "
Linux/Armv7
" for your remarkable
- the client for your laptop according to the couple
OS/arch
or build it yourself if you have the go toolchain installed on your machine.
The server
Copy the server on the remarkable and start it.
scp goMarkableStreamServer.arm remarkable:
ssh remarkable './goMarkableStreamServer.arm $(pidof xochitl)'
The client
Configuration
It is possible to tweak the configuration via environment variables:
Server
Env var |
Default |
Descri[ption |
RK_SERVER_BIND_ADDR |
:2000 |
the TCP listen address |
Client
Env var |
Default |
Descri[ption |
RK_CLIENT_BIND_ADDR |
:8080 |
the TCP listen address |
RK_SERVER_ADDR |
remarkabke:2000 |
the address of the remarkable |
How it works?
The server loop
- The server gets the address of the framebuffer in the memory space of the
xochitl
- The server launches a "ticketing system" to avoid congestion. The ticketing system is a channel that gets an event every 200ms.
- Then it exposes a gRPC function (with TLS and mutual authentication).
- The gRPC function waits for a "ticket" on the channel, and then grabs the data from the framebuffer.
- It packs the data into an
image
message encoded in protobuf and sends it to the consumer
The client loop
- The client creates an
MJPEG
stream and serves it over HTTP on the provided address
- The client dial server and sends its certificate, and add the compression header.
- Then it triggers a goroutine to get the
image
in a for loop.
- The image is then encoded into JPEG format and added to the MJPEG stream.
Security
The communication is using TLS. The client and the server owns an embedded certificate chain (with the CA). There are performing mutual authentication.
A new certificate chain is generated per build. Therefore, if you want restrict the access to your server to your client only, you must rebuild the tool yourself.
Manual build
Note: you need go > 1.16beta to build the tool because of the embedding mechanism for the certificate.
To build the tool manually, the easiest way is to use goreleaser
:
goreleaser --snapshot --skip-publish --rm-dist
To build the services manually:
go generate ./... # This generates the certificates
cd server && GOOS=linux GOARCH=arm GOARM=7 go build -o goStreamServer.arm
cd client && go build -o goStreamClient
Most of the information on how to hack the remarkable 2 comes from the reStream project See #28 for more info. All I did was to plumb the information to suit my own need.
Here is the recap:
- To get the remarkable version:
reMarkable: ~/ cat /usr/share/remarkable/update.conf
[General]
#REMARKABLE_RELEASE_APPID={98DA7DF2-4E3E-4744-9DE6-EC931886ABAB}
#SERVER=https://get-updates.cloud.remarkable.engineering/service/update2
#GROUP=Prod
#PLATFORM=reMarkable2
REMARKABLE_RELEASE_VERSION=2.5.0.27
- To find the location of the framebuffer pointer:
strace xochitl
...
563 openat(AT_FDCWD, "/dev/fb0", O_RDWR) = 5
564 ioctl(5, FBIOGET_FSCREENINFO, 0x7ee9d5f4) = 0
565 ioctl(5, FBIOGET_VSCREENINFO, 0x42f0ec) = 0
566 ioctl(5, FBIOPUT_VSCREENINFO, 0x42f0ec) = 0
Global framebuffer is located at 0x42f0ec-4 =0x42f0e8 (4387048 in decimal)
#!/bin/sh
pid=`pidof xochitl`
addr=`dd if=/proc/$pid/mem bs=1 count=4 skip=4387048 2>/dev/null | hexdump | awk '{print $3$2}'`
skipbytes=`printf "%d" $((16#$addr))`
dd if=/proc/$pid/mem bs=1 count=2628288 skip=$skipbytes > out.data
Note: 1404*1872 =2628288 is the size of the binary data to get
Acknowledgement
All the people in the reStream projet and specially
@ddvk and @raisjn