Summary: Learning about Kindle, jailbreak, KUAL and linux events.
Table of contents (expand)
Table of Contents
- TL;DR
-
Timeline
- Part 1: Jailbreak with LanguageBreak
- Part 2: Persisting jailbreak - disabling OTA updates
- Part 3: Linkss and custom screensavers
- Part 4: Discovering KUAL extensions (including FileBrowser)
- Part 5: Learning about custom dashboards and retrieving images from the internet
- Part 6: SSH access
- Part 7: Learning about EIPS and FBInk (cols, rows, clearing screen, buffer)
- Part 8: Discovering lipc-set-prop commands and trying to refresh screen
- Part 9: Playing with events and interception
- Part 10: Compiling my first C program to grab the event device and intercept interactions
- Conclusions
- Resources
TL;DR
- Own a Kindle PaperWhite 3 and jailbroke it to:
- Run alternative readers
- Use custom screensaver images
- Remove ads
- Explored custom dashboards and KUAL extensions to display personalized information on the screen
- Solved touch input challenges by developing a method to read and block touch events interfering with the underlying framework
- Gained hands-on experience with:
- Kindle internals
- KUAL development
- Linux systems
- Cross-compilation
- Resources and source code are publicly available for others to build upon and learn from
Timeline
- Part 1: Jailbreak with LanguageBreak
- Part 2: Persisting jailbreak - disabling OTA updates
- Part 3: Linkss and custom screensavers
- Part 4: Discovering KUAL extensions (including FileBrowser)
- Part 5: Learning about custom dashboards and retrieving images from the internet
- Part 6: Image generation
- Part 6: SSH access
- Part 7: Learning about EIPS and FBInk (cols, rows, clearing screen, buffer)
- Part 8: Discovering lipc-set-prop commands and trying to refresh screen
- Part 9: Playing with events and interception
- Part 10: Compiling my first C program to grab the event device and intercept interactions
Part 1: Jailbreak with LanguageBreak
Check Kindle version. Mine was 5.16.2.1.1
Find proper jailbreak method. In my case it was LanguageBreak
Follow instructions on LanguageBreak.
Part 2: Persisting jailbreak - disabling OTA updates
Follow instructions on Hotfix - KindleModding
Follow instructions on Disable OTA - KindleModding
Follow instructions on Install KUAL - KindleModding
Part 3: Linkss and custom screensavers
Follow instructions on FW 5.x ScreenSavers Hack
Once done, place new images under "screensaver" folder. It will automatically convert them and use them as screensavers.
The bigger the images, the more time it will take to convert them. Conversion happens everytime the framework boots or Linkss detects new images.
To reduce image size and make it easier for conversion, we can convert the images on our computers before placing them inside the Kindle. For PW3, the images should be 1072×1448 8-bit grayscale PNGs, stripped of metadata, no virtual canvas, and optionally reduced to 16 grayscale levels.
magick image4.png \
-resize 1072x1448^ \
-gravity center \
-extent 1072x1448 \
-colorspace Gray \
-depth 8 \
-colors 16 \
-strip \
+repage \
output4.png
Non-PNG files will be discarded by the hack, and broken files or files in the wrong resolution will confuse the framework and trigger weird issues.
If you want to randomize the sequence in which your screensavers will be shown, create a blank file named "random" in the Linkss folder (right alongside the "auto" file), and then restart your Kindle. This will shuffle your screensavers around on each boot.
Part 4: Discovering KUAL extensions (including FileBrowser)
Turns out you can easily create your own KUAL extensions. It only needs a menu.json, config.xml and your script (in SH/ASH).
Good examples are:
With these, I learned to run simple scripts and that Kindle can run linux binaries if they are properly compiled for it (like Dropbear for SSH server and FileBrowser for the file browser).
Part 5: Learning about custom dashboards and retrieving images from the internet
Found out these two cool projects that generate a dashboard as an image and make the Kindle retrieve and display the image on a scheduled basis. These include information on how to enable/disable screensaver, put the Kindle to sleep to save power and many other small hacks.
They also use some pre-compiled binaries to calculate the next execution time based on a cronjob definition and a command line curl-like utility to fetch the images.
Part 6: SSH access
While playing with my own KUAL extension I found hard to debug the commands so I sought for a way of executing them and see the output in real time. At the beginning I was putting the output on a log file and had a menu item to print the contents of the log file. But after going back and forth a few times, I decided to give SSH a try. And God it was so easy now. Just run the SSH server and put yourself in the same network as your Kindle. Instant access to a root shell.
I used the previously mentioned KOSSH KUAL extension.
Part 7: Learning about EIPS and FBInk (cols, rows, clearing screen, buffer)
EIPS (Embedded Image Processing System) is the graphics and display system used in Kindle e-readers for rendering content on their e-ink screens. It’s a low-level framebuffer interface, meaning it gives direct access to the display memory so developers can draw pixels, lines, text, and images. Provides direct control over drawing, including fonts, bitmaps, and simple GUI elements and supports partial screen refreshes, which is important for e-ink to reduce flicker and improve update speed.
We can use it directly by calling eips in a terminal.
# Print "Hello Kindle" at column 10, row 5
eips 10 5 "Hello Kindle"
# Clears the current text buffer
eips -c
# Clears the buffer and forces a full screen refresh
eips -c -f
Notes:
- After clearing the screen, there is no way of asking it to redraw what was on the screen before. You have to trigger an action (like loading a new screen or printing new stuff to it)
- Clearing the screen doesn't "unload" the current application. If your Kindle supports touch events it will still detect and interact with the framework even if you don't see the UI
There is an alternative to EIPS called FBInk. Supposedly more flexible. I have not tried it yet.
Part 8: Discovering lipc-set-prop commands and trying to refresh screen
While researching ways of refreshing the current UI on the screen after clearing it, I found a way of interacting with the Kindle system using "lipc".
On a Kindle, LIPC stands for Linux Inter-Process Communication. It’s the proprietary IPC system Amazon uses to let Kindle processes talk to each other.
One can list all possible services and actions by running lipc-probe -l or lipc-probe -a com.lab126.appmgrd for a specific service.
Common Services to Probe
- com.lab126.winmgr: Controls the window manager, display modes, and screen refreshes.
- com.lab126.appmgrd: Manages application lifecycles, launching booklets (Home, Store, Reader), and navigation.
- com.lab126.powerd: Handles power states, sleep/wake events, and screensaver behavior.
- com.lab126.blanket: Manages system overlays like low battery warnings or USB mode screens.
- com.lab126.kaf: The Kindle Application Framework, useful for toggling display modes or calling the Java VM.
If you want to see events as they happen in real-time (such as when you press a button or a state changes), you can use lipc-wait-event -a *. This will output every system event broadcasted across the lipc bus.
I tried many things to make it refresh the screen. From simulating power key presses to forcing a change in screen orientation. None of it worked, but we've got a few cool commands:
# Rotate the screen (forces a redraw of the UI)
lipc-set-prop com.lab126.winmgr orientation 1
# Force a full display refresh via the window manager
lipc-set-prop com.lab126.winmgr epdcMode GC16
# Trigger a screen flash to force an E-ink refresh
lipc-set-prop com.lab126.winmgr liglFlash ""
# Force a repaint by setting the damage timeout to zero
lipc-set-prop -i com.lab126.winmgr extendAfterDamageTimeout 0
# Unload the UI overlay layer (used to force redraw)
lipc-set-prop com.lab126.blanket unload 1
# Reload the UI overlay layer (used to force redraw)
lipc-set-prop com.lab126.blanket load 1
# Keep the Kindle from entering sleep mode (Prevent Screensaver)
lipc-set-prop com.lab126.powerd preventScreenSaver 1
# Force a device restart
lipc-set-prop com.lab126.powerd deviceRestart 1
# Attempt to resubmit system events to refresh UI
lipc-set-prop com.lab126.powerd resubmit_events 1
# Launch or refresh the Kindle Home screen
lipc-set-prop com.lab126.appmgrd start app://com.lab126.booklet.home
# Launch the Kindle Reader booklet
lipc-set-prop com.lab126.appmgrd start app://com.lab126.booklet.reader
# Resume/Reload the currently active application
lipc-set-prop com.lab126.appmgrd goresult ""
# Hide the top status bar and bottom navigation (Chrome)
lipc-set-prop com.lab126.winmgr chromeState 0
# Enable book covers as screensavers
lipc-set-prop com.lab126.kindlecurator enableBookCover 1
# Shutdown the Kindle framework GUI
lipc-set-prop com.lab126.framework shutdown 1
# Toggle current display mode to force UI re-evaluation
lipc-set-prop com.lab126.kaf currentDisplayMode 0
# Force open the "Aa" font/layout menu to trigger a refresh
lipc-set-prop com.lab126.AaMenuApplication OpenAaDialog 1
# Force the whole UI tree to redraw (Fake Chrome Reconfigure)
lipc-set-prop com.lab126.kppchromebar configureChrome 1
Part 9: Playing with events and interception
Remember that clearing the screen doesn't "unload" the current application? If your Kindle supports touch events it will still detect and interact with the framework even if you don't see the UI. This was not good for any "application" or script I wanted to play on my Kindle. So I started another side quest to figure out how to read touch events, but most importantly intercept them.
Reading posts on mobileread forums I found out the events are registered under the block device /dev/input/eventX, as raw binary touch events. Tried several tools to inspect the values and ended up with evtest, which is a command line tool that can parse these events.
Great! I can not register every touch event. Touch down, touch up, scroll, slide, pinch, etc. But the framework was still detecting these touches and acting accordingly, for example launching books or apps while I was still playing with the touch system.
Asked a few AI chatbots and they told me I would have to grab exclusive access to the device by using EVIOCGRAB from a C program. Turns out modern implementations of evtest have this functionality embedded as the option --grab. But, kid you not, the existing evtest in the Kindle system doesnt have such option. So lets go and compile a new evtest!
Part 10: Compiling my first C program to grab the event device and intercept interactions
I found the source code of a modern implementation of evtest on Github, from a non official mirror of the FreeDesktop project. Its a very simple C program with very few standard library dependencies.
With a bit of help of the AI I found out the correct packages and commands to cross compile it for the ARM proccessor and current kernel of my Kindle. I had to edit the source code a little bit to make it compile cleanly as some structs were not fit to the standard libraries I was using for the cross compilation. But that was easy to spot and fix. You can see the final C file with the modifications on the respository attached to this post.
These are the commands I needed to cross compile this version of evtest:
apt-get install gcc-arm-linux-gnueabi libc6-dev-armel-cross
arm-linux-gnueabi-gcc -DKINDLE_PW3 -static -O2 -march=armv7-a -mfloat-abi=soft -o evtest evtest.c
Conclusions
With the new binary of evtest I managed to read and intercept the touch events so I could run my "app" on top of the current framework without having to launch a custom java applet.
The custom dashboard is now on pause as I am no longer sure if what I need can be actually generated directly on the Kindle or has to be a screenshot of a rendered complex HTML page.
Hope you enjoyed the whole write up and learned something new today. You can find the source code in this repository hosted on Github. Enjoy tinkering!