← All posts

· 4 min read

TagMod: open-sourcing my hacked ereader software

I turned a broken-touchscreen e-reader into a one-button Kindle with an always-on dashboard. Now the code is open source.

I have several Tagus (Onyx e-readers running Android 4.4) with broken touchscreens. Fixing the touch doesn’t make financial sense, but the e-ink panel and hardware work perfectly. So I turned them into something else: an e-reader you drive entirely with a single button, and while it sleeps it shows a dashboard with my agenda, tasks, Umami analytics, server status and weather.

Today I’m releasing it as open source.

The problem

A Tagus without a touchscreen is a paperweight. Android expects you to touch the screen for everything: picking a book, turning pages, going back. Without touch, there’s no way to use it.

The solution was writing a C daemon that hijacks the power button and turns press patterns into keyboard events. The Android system never sees the real button. The daemon interprets:

Gesture Library Reading
Tap next item next page
Double tap previous previous page
Hold 0.8-3s, release open back to library
Hold 3s sleep (shows panel) sleep

The dashboard

While the e-reader is asleep, the screen doesn’t turn off: it shows a TRMNL-style panel with useful information. The daemon has a kernel timer (CLOCK_REALTIME_ALARM) that wakes the device from deep suspend every hour, updates the panel and puts it back to sleep. The frontlight stays off during the whole cycle, so the room stays dark.

What the panel shows:

  • Header: weekday, date, battery level
  • Agenda: upcoming calendar events (from a server with iCal)
  • Tasks: pending items with due dates (Markdown or Todoist)
  • Current book: the last book opened
  • Analytics: visitors, sessions, pageviews, average time (self-hosted Umami), 7-day chart, top events
  • Server monitor: heartbeat checks every hour, 24h bars, weekly uptime, incident history
  • Weather: hourly and weekly forecast (Open-Meteo, no API key needed)

Everything is painted with Canvas in Java onto a 758x1024 bitmap that SurfaceFlinger uses as the sleep image. No Android views, no WebView. The panel is shown in the cover image of this post.

How it works under the hood

The project has four independent pieces:

powerkeyd (C) — the root daemon. Grabs exclusive ownership of /dev/input/event0 (the power button) and emits synthetic keyboard events to other input devices. It runs inside the boot image ramdisk, so it starts before Android. It also listens on an abstract Unix socket (@tagmod) so the launcher can request panel refreshes, kernel wakelocks and scheduled updates.

Launcher APK (Java, API 19) — no Gradle, no external dependencies. One-button library with frontlight control. PanelService collects data with PanelSource (weather, server feed, Umami, battery, services), paints it with PanelRenderer and writes the bitmap. StatusTracker is the uptime monitor. Umami is the analytics client. Http forces TLS 1.2 and bundles current root CAs because the Android 4.4 trust store is expired.

tagmod-server (Python) — optional backend for a VPS. Exposes GET /feed.json with Bearer auth. Combines ICS calendar events (with recurrence expansion) and tasks from a Markdown file or the Todoist API. Each source has its own cache; if one fails, it serves the last good copy.

Boot image and art — Python scripts to pack/unpack Android v0 boot images, inject TagMod files into the ramdisk, patch init.rc and default.prop (ro.secure=0 for adb root), and replace the bootloader logo in the resource partition.

Current status and what’s missing

What works, verified on the device:

  • One-button control, library, frontlight 150-255
  • Full dashboard with all the blocks described above
  • Scheduled refresh from deep suspend
  • One-script deployment: deploy/flash.sh install
  • Onyx services disabled (status bar, bookstore, OTA)
  • WiFi configurable via script

What hasn’t been tested yet:

  • Page turning with the button in AlReader (I don’t have FB2/MOBI on the device)
  • The server isn’t deployed in production (I use file:///sdcard/TagMod/feed.json locally with test data)

Why open source

The code works and is tested on real hardware. An e-ink e-reader is a fantastic device for an always-on dashboard without draining battery, and the software to do it shouldn’t stay on my hard drive.

The pieces are independent. The C daemon is generic (any Rockchip with Android 4.4+). The launcher is vanilla Java. The server is standard Python. If you have an old Android e-reader lying around, you can probably adapt it.

The repo documentation includes guides for porting to other devices (Kindle, Kobo, generic), using it as an e-ink dashboard, and firmware modding.

The code is at github.com/IgnacioLD/tagmod under the MIT license.

Drafted with AI, edited by hand. I publish it when it sounds like me.