This page aims to provide guidance on how to port KOReader to other platforms.
There are mainly two modules that you need to take care of: input and output.
After you finish these two, KOReader should have no problem running on your platform.
Feel free to open issues in our issue tracker if you need further help on this topic :)
Current mxcfb eInk devices
KOReader uses the Linux framebuffer to control eInk devices, so the output module for mxcfb (i.e., those based on Freescale/NXP hardware) devices is
Most common bitdepths are supported, although no devices should actually be using anything other than 8bpp, 16bpp and 32bpp.
For 8bpp, we assume the grayscale palette is NOT inverted.
At 32bpp, we generally assume the pixel format is BGRA, and we honor Alpha, despite it being effectively ignored by the display (see Kobos).
At 16bpp, we assume the pixel format is RGB565.
For obvious performance reasons, we prefer 8bpp, and we will attempt to enforce that on devices which are not natively running at that depth (i.e., on Kobos).
As explained below, the same considerations should be kept in mind regarding the effective 16c palette of eInk screens.
When we're in control of the data, we attempt to always use "perfect" in-palette colors (c.f., the COLOR constants in the BlitBuffer module).
Otherwise, when there'd be signficiant gain in doing so (i.e., when displaying mainly image content), we attempt to make use of dithering, ideally offloaded to the hardware when supported.
The actual framebuffer content is then refreshed (i.e., displayed) via device-specific ioctls, making the best effort in using device-specific capabilities, whether that be optimized waveform modes, hardware dithering or hardware inversion.
Legacy einkfb eInk devices
KOReader uses the Linux framebuffer to control eInk devices, so the output module for legacy einkfb devices is
Following are the framebuffers that
framebuffer_einkfb.lua currently supports:
- 4bpp framebuffer (palette is always inverted)
- 16c 8bpp framebuffer (inverted grayscale palette)
For 4bpp framebuffers, it means every pixel is represented with 4 bits, so we have 2 pixels in 1 byte.
That also effectively limits the palette to 16 colors.
The inverted part means that every pixel's color value is flipped (
For example, two pixels
0xF0 will be flipped to
0x0F, before being packed to accomodate the framebuffer's pixel format (here, into a single byte).
For 8bpp framebuffers, it means each pixel is instead stored in 1 byte, making addressing much simpler.
The effective color palette of the display is still limited to 16 shades of gray: it will do a decimating quantization pass on its own on refresh.
So, while a black pixel will indeed be
0x00, any color value <
0x11 (the next effective shade of gray in the palette) will be displayed as pure black, too.
If the palette is expected to be inverted, then all the bits are flipped in the same way as done on a 4bpp framebuffer.
In practice, this is always the case.
The actual framebuffer content is then refreshed (i.e., displayed) via device-specific ioctls.
All the intermediary buffers are handled in a pixel format that matches the output module in use as closely as possible.
The magic happens in
base/ffi/blitbuffer.lua, with some help from the LinuxFB frontend to the output modules.
Note that on most devices, a C version is used instead for more consistent performance.
Which version is more easily readable to a newcomer is up for debate, so, don't hesitate to cross-reference ;).
Feature-parity should be complete, with the exception of 4bpp support in the C version.
If you need a bit of guidance, you can also take a look at FBInk, and/or ping @NiLuJe on gitter.
We have an
input.c module in koreader-base that reads input events from Linux's input system and passes it on to the Lua frontend.
Basically, you don't need to change that module because it should support most of the events.
For this part, the file you have to hack on is
Firstly, you need to tell which input device to open on KOReader start. All the input devices are opened in
Next, you might need to define
Input:eventAdjustHook() function in
We use this hook function to translate events into a format that KOReader understands.
You can look at the KindleTouch initialization code for a real-world example.
For some Kobo devices (Mini, Touch, Glo and Aura HD) the function
Input:eventAdjustHook() was skipped and the functions
Input:handleTypeBTouchEv() were changed to accomodate for the single touch protocol.
For the Kobo Aura (and others with the same kernel quirks) with multitouch support, an extra function
Input:handlePhoenixTouchEv() was added.
Linux supports two kinds of Multi-touch protocols:
Currently, KOReader supports gesture detection of protocol B, so if your device sends out protocol A, you need to make a variant of function
Input:handlePhoenixTouchEv()) and simulate protocol B.
You are also welcome to send a PR that adds protocol A support to KOReader.
More information on Linux's input system: