Skip to content

Commit 45347f7

Browse files
authored
reMarkable port (koreader#1023)
* reMarkable port Mostly based on the sony-prstux port * remarkable: no longer using lj-wpaclient * remarkable: add simple button listener launcher Assumes the koreader systemd unit is installed correctly. Launch koreader when the middle (home) button is held for 3 seconds. Inspired by https://github.com/dixonary/button-capture-reMarkable but significantly simpler. * remarkable: include fbink & fbdepth * remarkable: add fake event generation USB Plug/Unplug, charge status change. Seems to take a minute or two from USB Unplug to the battery state changing to discharging in sysfs. * remarkable: switch to remarkable toolchain Rather than reusing kobo toolchain. Built from koxtoolchain. * Reorder some lists alphabetically * remarkable: strip fbdepth As on Kobo
1 parent 76bdfd3 commit 45347f7

11 files changed

+563
-8
lines changed

Makefile

+12-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ all: $(OUTPUT_DIR)/libs $(if $(ANDROID),,$(LUAJIT)) \
2929
$(if $(or $(DARWIN),$(WIN32),$(ANDROID),$(UBUNTUTOUCH),$(APPIMAGE)),,$(OUTPUT_DIR)/dropbear) \
3030
$(if $(or $(KINDLE),$(KOBO),$(CERVANTES)),$(OUTPUT_DIR)/sftp-server,) \
3131
$(if $(or $(DARWIN),$(WIN32)),,$(OUTPUT_DIR)/tar) \
32-
$(if $(or $(KINDLE),$(KOBO),$(CERVANTES)),$(OUTPUT_DIR)/fbink,) \
32+
$(if $(or $(CERVANTES),$(KINDLE),$(KOBO),$(REMARKABLE)),$(OUTPUT_DIR)/fbink,) \
33+
$(if $(REMARKABLE),$(OUTPUT_DIR)/button-listen,) \
3334
$(SQLITE_LIB) \
3435
$(LUA_LJ_SQLITE) $(OUTPUT_DIR)/common/xsys.lua
3536
ifndef EMULATE_READER
@@ -41,8 +42,9 @@ ifndef KODEBUG
4142
$(if $(or $(DARWIN),$(WIN32),$(ANDROID),$(UBUNTUTOUCH),$(APPIMAGE)),,$(OUTPUT_DIR)/dropbear) \
4243
$(if $(or $(KINDLE),$(KOBO),$(CERVANTES)),$(OUTPUT_DIR)/sftp-server,) \
4344
$(if $(or $(KINDLE),$(KOBO)),$(OUTPUT_DIR)/scp,) \
44-
$(if $(or $(KINDLE),$(KOBO),$(CERVANTES)),$(OUTPUT_DIR)/fbink,) \
45-
$(if $(KOBO),$(OUTPUT_DIR)/fbdepth,) \
45+
$(if $(or $(CERVANTES),$(KINDLE),$(KOBO),$(REMARKABLE)),$(OUTPUT_DIR)/fbink,) \
46+
$(if $(REMARKABLE),$(OUTPUT_DIR)/button-listen,) \
47+
$(if $(or $(KOBO),$(REMARKABLE)),$(OUTPUT_DIR)/fbdepth,) \
4648
$(if $(ANDROID),,$(LUAJIT)) \
4749
$(OUTPUT_DIR)/libs/$(if $(WIN32),*.dll,*.so*)" ;\
4850
$(STRIP) --strip-unneeded $${STRIP_FILES} ;\
@@ -95,7 +97,7 @@ libs: \
9597
$(OUTPUT_DIR)/libs/libkoreader-input.so: input/*.c input/*.h $(if $(KINDLE),$(POPEN_NOSHELL_LIB),)
9698
@echo "Building koreader input module..."
9799
$(CC) $(DYNLIB_CFLAGS) -I$(POPEN_NOSHELL_DIR) -I./input \
98-
$(if $(KOBO),-DKOBO,) $(if $(KINDLE),-DKINDLE,) $(if $(POCKETBOOK),-DPOCKETBOOK,) $(if $(SONY_PRSTUX),-DSONY_PRSTUX,) $(if $(CERVANTES),-DCERVANTES,)\
100+
$(if $(CERVANTES),-DCERVANTES,) $(if $(KOBO),-DKOBO,) $(if $(KINDLE),-DKINDLE,) $(if $(POCKETBOOK),-DPOCKETBOOK,) $(if $(REMARKABLE),-DREMARKABLE,) $(if $(SONY_PRSTUX),-DSONY_PRSTUX,)\
99101
-o $@ \
100102
input/input.c \
101103
$(if $(KINDLE),$(POPEN_NOSHELL_LIB),) \
@@ -201,6 +203,12 @@ ffi/lodepng_h.lua: ffi-cdecl/lodepng_decl.c $(LODEPNG_DIR)
201203
# include all third party libs
202204
include Makefile.third
203205

206+
# ===========================================================================
207+
# very simple "launcher" for koreader on the remarkable
208+
209+
$(OUTPUT_DIR)/button-listen: button-listen.c
210+
$(CC) $(CFLAGS) -o $@ $^
211+
204212
# ===========================================================================
205213
# the attachment extraction tool:
206214

Makefile.defs

+6
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ else ifeq ($(TARGET), pocketbook)
147147
export PATH:=$(POCKETBOOK_TOOLCHAIN)/bin:$(PATH)
148148
export SYSROOT=$(POCKETBOOK_TOOLCHAIN)/arm-obreey-linux-gnueabi/sysroot
149149
endif
150+
else ifeq ($(TARGET), remarkable)
151+
CHOST?=arm-remarkable-linux-gnueabihf
152+
export REMARKABLE=1
150153
else ifeq ($(TARGET), sony-prstux)
151154
CHOST?=arm-linux-gnueabihf
152155
export SONY_PRSTUX=1
@@ -393,6 +396,9 @@ else ifeq ($(TARGET), android)
393396
ARM_ARCH+=-mfloat-abi=softfp
394397
export ac_cv_type_in_port_t=yes
395398
endif
399+
else ifeq ($(TARGET), remarkable)
400+
ARM_ARCH:=$(ARMV7_A9_ARCH)
401+
ARM_ARCH+=-mfloat-abi=hard
396402
else ifeq ($(TARGET), sony-prstux)
397403
ARM_ARCH:=$(ARMV7_A8_ARCH)
398404
ARM_ARCH+=-mfloat-abi=hard

Makefile.third

+3
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ $(OUTPUT_DIR)/fbink: $(THIRDPARTY_DIR)/fbink/*.*
492492
ifdef KOBO
493493
cp $(FBINK_DIR)/fbdepth $(OUTPUT_DIR)/
494494
endif
495+
ifdef REMARKABLE
496+
cp $(FBINK_DIR)/fbdepth $(OUTPUT_DIR)/
497+
endif
495498

496499
# ===========================================================================
497500
# common lua library for networking

button-listen.c

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <linux/input.h>
2+
#include <stdio.h>
3+
#include <time.h>
4+
#include <stdlib.h>
5+
6+
static double timeval_diff(struct timeval const* start, struct timeval const* end)
7+
{
8+
double s = (double)end->tv_sec - (double)start->tv_sec;
9+
double us = (double)end->tv_usec - (double)start->tv_usec;
10+
return s + (us / 1e6);
11+
}
12+
13+
int main(int argc, char** argv)
14+
{
15+
FILE* evf = fopen("/dev/input/event2", "rb");
16+
if(!evf) {
17+
fprintf(stderr, "Could not open /dev/input/event2\n");
18+
return 1;
19+
}
20+
21+
struct input_event ev;
22+
struct timeval press_stamp = {0};
23+
while(1) {
24+
size_t sz = fread(&ev, sizeof(ev), 1, evf);
25+
if(sz == 0) {
26+
return 1;
27+
}
28+
if(ev.type == EV_KEY && ev.code == KEY_HOME) {
29+
if(ev.value == 0) { /* keyrelease */
30+
double t = timeval_diff(&press_stamp, &ev.time);
31+
/* hold home (middle) button for 3 seconds to start koreader */
32+
if(t >= 3.0) {
33+
system("systemctl start koreader");
34+
}
35+
}
36+
else if(ev.value == 1) { /* keypress */
37+
press_stamp = ev.time;
38+
}
39+
}
40+
}
41+
}

ffi-cdecl/include/mxcfb-remarkable.h

+267
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*
2+
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc. All Rights Reserved
3+
*/
4+
5+
/*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along
17+
* with this program; if not, write to the Free Software Foundation, Inc.,
18+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*/
20+
21+
/* Original source:
22+
* https://github.com/reMarkable/linux/blob/zero-gravitas/include/uapi/linux/mxcfb.h
23+
* Waveform modes constants originally from libremarkable:
24+
* https://github.com/canselcik/libremarkable
25+
* Then later cleaned up thanks to the official SDK:
26+
* https://remarkable.engineering/
27+
*/
28+
29+
/*
30+
* @file uapi/linux/mxcfb.h
31+
*
32+
* @brief Global header file for the MXC frame buffer
33+
*
34+
* @ingroup Framebuffer
35+
*/
36+
#ifndef __ASM_ARCH_MXCFB_H__
37+
#define __ASM_ARCH_MXCFB_H__
38+
39+
#include <linux/fb.h>
40+
41+
#define FB_SYNC_OE_LOW_ACT 0x80000000
42+
#define FB_SYNC_CLK_LAT_FALL 0x40000000
43+
#define FB_SYNC_DATA_INVERT 0x20000000
44+
#define FB_SYNC_CLK_IDLE_EN 0x10000000
45+
#define FB_SYNC_SHARP_MODE 0x08000000
46+
#define FB_SYNC_SWAP_RGB 0x04000000
47+
#define FB_ACCEL_TRIPLE_FLAG 0x00000000
48+
#define FB_ACCEL_DOUBLE_FLAG 0x00000001
49+
50+
struct mxcfb_gbl_alpha {
51+
int enable;
52+
int alpha;
53+
};
54+
55+
struct mxcfb_loc_alpha {
56+
int enable;
57+
int alpha_in_pixel;
58+
unsigned long alpha_phy_addr0;
59+
unsigned long alpha_phy_addr1;
60+
};
61+
62+
struct mxcfb_color_key {
63+
int enable;
64+
__u32 color_key;
65+
};
66+
67+
struct mxcfb_pos {
68+
__u16 x;
69+
__u16 y;
70+
};
71+
72+
struct mxcfb_gamma {
73+
int enable;
74+
int constk[16];
75+
int slopek[16];
76+
};
77+
78+
struct mxcfb_gpu_split_fmt {
79+
struct fb_var_screeninfo var;
80+
unsigned long offset;
81+
};
82+
83+
struct mxcfb_rect {
84+
__u32 top;
85+
__u32 left;
86+
__u32 width;
87+
__u32 height;
88+
};
89+
90+
#define GRAYSCALE_8BIT 0x1
91+
#define GRAYSCALE_8BIT_INVERTED 0x2
92+
#define GRAYSCALE_4BIT 0x3
93+
#define GRAYSCALE_4BIT_INVERTED 0x4
94+
95+
#define AUTO_UPDATE_MODE_REGION_MODE 0
96+
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1
97+
98+
#define UPDATE_SCHEME_SNAPSHOT 0
99+
#define UPDATE_SCHEME_QUEUE 1
100+
#define UPDATE_SCHEME_QUEUE_AND_MERGE 2
101+
102+
#define UPDATE_MODE_PARTIAL 0x0
103+
#define UPDATE_MODE_FULL 0x1
104+
105+
// Findings courtesy of libremarkable
106+
/*
107+
// c.f., https://github.com/canselcik/libremarkable/blob/67ff7ea3926319a6d33a216a2b8c1f679916aa3c/src/framebuffer/common.rs#L338
108+
// NOTE: Those constant names seem to be inspired from https://github.com/fread-ink/inkwave
109+
// (which was itself built around Kindle waveforms, which is why some of those names will look familiar if you check mxcfb-kindle.h ;)).
110+
// NOTE: Also added relevant enum names from libqsgepaper.a (it's part of the official SDK) as inline comments (AFAICT, here be dragons!).
111+
// NOTE: Speaking of inkwave, it seems to confirm that the firmware blob only ships 5 different waveform modes, so I'd trust EPFrameBuffer::WaveformMode ;).
112+
// Still, it was designed with Kindle firmware blobs in mind, so, take that with a grain of salt nonetheless.
113+
#define WAVEFORM_MODE_INIT 0 // EPFrameBuffer::WaveformMode::Initialize EPFrameBuffer::Waveform::INIT
114+
#define WAVEFORM_MODE_DU 1 // EPFrameBuffer::WaveformMode::Mono EPFrameBuffer::Waveform::DU
115+
#define WAVEFORM_MODE_GC16 2 // EPFrameBuffer::WaveformMode::HighQualityGrayscale EPFrameBuffer::Waveform::GC16
116+
#define WAVEFORM_MODE_GC16_FAST 3 // EPFrameBuffer::WaveformMode::Grayscale EPFrameBuffer::Waveform::GL16
117+
118+
#define WAVEFORM_MODE_GL16_FAST 6 // EPFrameBuffer::Waveform::A2
119+
#define WAVEFORM_MODE_DU4 7 // EPFrameBuffer::Waveform::DU4
120+
#define WAVEFORM_MODE_REAGL 8 // EPFrameBuffer::WaveformMode::Highlight EPFrameBuffer::Waveform::UNKNOWN
121+
#define WAVEFORM_MODE_REAGLD 9 // EPFrameBuffer::Waveform::INIT2
122+
#define WAVEFORM_MODE_GL4 0xA
123+
#define WAVEFORM_MODE_GL16_INV 0xB
124+
125+
// NOTE: Those leftover constants from the upstream kernel sources are *extremely* confusingly named.
126+
// libremarkable tests & comments hinted that this one was actually A2, which we've also confirmed.
127+
#define WAVEFORM_MODE_GLR16 4 // EPFrameBuffer::Waveform::GLR16
128+
#define WAVEFORM_MODE_A2 WAVEFORM_MODE_GLR16
129+
// NOTE: Which would actually make this GL16 (purely by virtue of GL16 *usually* being A2 + 1)?
130+
// Practical tests have yielded weird results, but with a weirdness consistent with GL16_FAST at least ^^.
131+
#define WAVEFORM_MODE_GLD16 5 // EPFrameBuffer::Waveform::GLD16
132+
#define WAVEFORM_MODE_GL16 WAVEFORM_MODE_GLD16
133+
// NOTE: That one can't be bogus, because it's actually used by the driver to check for obviously invalid modes ;).
134+
// Also, it's consistent with other platforms.
135+
// Speaking of other platforms, usually, GLR16 == REAGL & GLD16 == REAGLD ;).
136+
#define WAVEFORM_MODE_AUTO 257
137+
*/
138+
139+
// Let's honor <epframebuffer.h> instead, it's slightly less confusing ;).
140+
// c.f., https://github.com/NiLuJe/FBInk/pull/41#issuecomment-579579351
141+
#define WAVEFORM_MODE_INIT 0
142+
#define WAVEFORM_MODE_DU 1
143+
#define WAVEFORM_MODE_GC16 2
144+
#define WAVEFORM_MODE_GL16 3
145+
// NOTE: Here be dragons!
146+
// xochitl itself will never use any of those, and despite what's detailed in <epframebuffer.h>,
147+
// testing on production devices reveals that no-one really should either, actually ;).
148+
// c.f., https://github.com/NiLuJe/FBInk/pull/41#issuecomment-580926264
149+
/*
150+
#define WAVEFORM_MODE_GLR16 4
151+
#define WAVEFORM_MODE_GLD16 5
152+
#define WAVEFORM_MODE_A2 6
153+
#define WAVEFORM_MODE_DU4 7
154+
#define WAVEFORM_MODE_UNKNOWN 8
155+
#define WAVEFORM_MODE_INIT2 9
156+
*/
157+
// NOTE: The only thing we can salvage is what's quite likely actually A2, according both to testing,
158+
// and poking at the binary firmware blob.
159+
#define WAVEFORM_MODE_A2 4
160+
161+
#define WAVEFORM_MODE_AUTO 257
162+
163+
#define TEMP_USE_AMBIENT 0x1000
164+
165+
// Again, pilfered from libremarkable ;).
166+
// In practice, only appears to be used in conjunction w/ DU
167+
// (c.f., https://github.com/NiLuJe/FBInk/pull/41#issuecomment-579424194)
168+
#define TEMP_USE_REMARKABLE 0x0018
169+
170+
#define EPDC_FLAG_ENABLE_INVERSION 0x01
171+
#define EPDC_FLAG_FORCE_MONOCHROME 0x02
172+
#define EPDC_FLAG_USE_CMAP 0x04
173+
#define EPDC_FLAG_USE_ALT_BUFFER 0x100
174+
#define EPDC_FLAG_TEST_COLLISION 0x200
175+
#define EPDC_FLAG_GROUP_UPDATE 0x400
176+
#define EPDC_FLAG_USE_DITHERING_Y1 0x2000
177+
#define EPDC_FLAG_USE_DITHERING_Y4 0x4000
178+
#define EPDC_FLAG_USE_REGAL 0x8000
179+
180+
enum mxcfb_dithering_mode {
181+
EPDC_FLAG_USE_DITHERING_PASSTHROUGH = 0x0,
182+
EPDC_FLAG_USE_DITHERING_FLOYD_STEINBERG,
183+
EPDC_FLAG_USE_DITHERING_ATKINSON,
184+
EPDC_FLAG_USE_DITHERING_ORDERED,
185+
EPDC_FLAG_USE_DITHERING_QUANT_ONLY,
186+
EPDC_FLAG_USE_DITHERING_MAX,
187+
};
188+
189+
#define FB_POWERDOWN_DISABLE -1
190+
#define FB_TEMP_AUTO_UPDATE_DISABLE -1
191+
192+
struct mxcfb_alt_buffer_data {
193+
__u32 phys_addr;
194+
__u32 width; /* width of entire buffer */
195+
__u32 height; /* height of entire buffer */
196+
struct mxcfb_rect alt_update_region; /* region within buffer to update */
197+
};
198+
199+
struct mxcfb_update_data {
200+
struct mxcfb_rect update_region;
201+
__u32 waveform_mode;
202+
__u32 update_mode;
203+
__u32 update_marker;
204+
int temp;
205+
unsigned int flags;
206+
int dither_mode;
207+
int quant_bit;
208+
struct mxcfb_alt_buffer_data alt_buffer_data;
209+
};
210+
211+
struct mxcfb_update_marker_data {
212+
__u32 update_marker;
213+
__u32 collision_test;
214+
};
215+
216+
/*
217+
* Structure used to define waveform modes for driver
218+
* Needed for driver to perform auto-waveform selection
219+
*/
220+
struct mxcfb_waveform_modes {
221+
int mode_init;
222+
int mode_du;
223+
int mode_gc4;
224+
int mode_gc8;
225+
int mode_gc16;
226+
int mode_gc32;
227+
};
228+
229+
/*
230+
* Structure used to define a 5*3 matrix of parameters for
231+
* setting IPU DP CSC module related to this framebuffer.
232+
*/
233+
struct mxcfb_csc_matrix {
234+
int param[5][3];
235+
};
236+
237+
#define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
238+
#define MXCFB_SET_GBL_ALPHA _IOW('F', 0x21, struct mxcfb_gbl_alpha)
239+
#define MXCFB_SET_CLR_KEY _IOW('F', 0x22, struct mxcfb_color_key)
240+
#define MXCFB_SET_OVERLAY_POS _IOWR('F', 0x24, struct mxcfb_pos)
241+
#define MXCFB_GET_FB_IPU_CHAN _IOR('F', 0x25, u_int32_t)
242+
#define MXCFB_SET_LOC_ALPHA _IOWR('F', 0x26, struct mxcfb_loc_alpha)
243+
#define MXCFB_SET_LOC_ALP_BUF _IOW('F', 0x27, unsigned long)
244+
#define MXCFB_SET_GAMMA _IOW('F', 0x28, struct mxcfb_gamma)
245+
#define MXCFB_GET_FB_IPU_DI _IOR('F', 0x29, u_int32_t)
246+
#define MXCFB_GET_DIFMT _IOR('F', 0x2A, u_int32_t)
247+
#define MXCFB_GET_FB_BLANK _IOR('F', 0x2B, u_int32_t)
248+
#define MXCFB_SET_DIFMT _IOW('F', 0x2C, u_int32_t)
249+
#define MXCFB_CSC_UPDATE _IOW('F', 0x2D, struct mxcfb_csc_matrix)
250+
#define MXCFB_SET_GPU_SPLIT_FMT _IOW('F', 0x2F, struct mxcfb_gpu_split_fmt)
251+
#define MXCFB_SET_PREFETCH _IOW('F', 0x30, int)
252+
#define MXCFB_GET_PREFETCH _IOR('F', 0x31, int)
253+
254+
/* IOCTLs for E-ink panel updates */
255+
#define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes)
256+
#define MXCFB_SET_TEMPERATURE _IOW('F', 0x2C, int32_t)
257+
#define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, __u32)
258+
#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data)
259+
#define MXCFB_WAIT_FOR_UPDATE_COMPLETE _IOWR('F', 0x2F, struct mxcfb_update_marker_data)
260+
#define MXCFB_SET_PWRDOWN_DELAY _IOW('F', 0x30, int32_t)
261+
#define MXCFB_GET_PWRDOWN_DELAY _IOR('F', 0x31, int32_t)
262+
#define MXCFB_SET_UPDATE_SCHEME _IOW('F', 0x32, __u32)
263+
#define MXCFB_GET_WORK_BUFFER _IOWR('F', 0x34, unsigned long)
264+
#define MXCFB_SET_TEMP_AUTO_UPDATE_PERIOD _IOW('F', 0x36, int32_t)
265+
#define MXCFB_DISABLE_EPDC_ACCESS _IO('F', 0x35)
266+
#define MXCFB_ENABLE_EPDC_ACCESS _IO('F', 0x36)
267+
#endif

0 commit comments

Comments
 (0)