Skip to content

Add EPD waveform controller for Nook Glowlight 4 Plus (bnrv1300)#597

Open
backcountrymountains wants to merge 1 commit into
koreader:masterfrom
backcountrymountains:nook-gl4plus-epd
Open

Add EPD waveform controller for Nook Glowlight 4 Plus (bnrv1300)#597
backcountrymountains wants to merge 1 commit into
koreader:masterfrom
backcountrymountains:nook-gl4plus-epd

Conversation

@backcountrymountains

@backcountrymountains backcountrymountains commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

The Nook Glowlight 4 Plus (bnrv1300) uses an AllWinner "Emperor" platform that is architecturally distinct from the GL4/4e (Freescale NTX). This PR splits it into its own DeviceInfo ID and adds a dedicated EPD controller that enables GC16 waveform without root or a Magisk module.

  • DeviceInfo.kt: split bnrv1300 from the NOOK_GL4 group into NOOK_GL4PLUS
  • EPDFactory.kt: route NOOK_GL4PLUS to NookEmperorEPDController instead of NGL4EPDController
  • NookEmperorEPDController.kt: new controller using ViewRootImpl.setRefreshMode via reflection
  • TestActivity.kt: add "Nook GL4 Plus" entry to the EInk test driver map (per @hugleo's request in Add lights support for Nook Glowlight 4 Plus (bnrv1300) #592)

How it works

B&N's Android 8.1 firmware adds setRefreshMode(int) directly to ViewRootImpl. The controller reaches it via reflection and the call routes through SurfaceFlinger → HWC (hwcomposer.virgo.so) → hwc_set_layer_refresh_modelayer->refreshMode/dev/disp ioctl. Because HWC reads layer->refreshMode during composition, the waveform is applied to the correct (incoming) buffer.

Fallback order if reflection fails:

  1. ViewRootImpl.setRefreshMode — B&N Android 8.1 (preferred, confirmed working)
  2. SurfaceControl.setRefreshMode via mSurfaceControl field — AOSP Android 10+
  3. sysfs force_update_mode write — last resort, requires Magisk epd_gc16 module

Testing

Confirmed on a Nook Glowlight 4 Plus running B&N Android 8.1 (bnrv1300):

  • ViewRootImpl.setRefreshMode path active on launch (logged)
  • GC16 (mode=0x4) confirmed in kernel dmesg (mode=0x200004) on full-page refreshes
  • No root, no Magisk module, no ADB setup required — works on a stock rooted device with Magisk module disabled

No setup required

Unlike some EPD drivers, this controller needs no ADB properties, no appops grants, and no Magisk modules. No wiki page is needed.

🤖 Generated with Claude Code


This change is Reviewable

The GL4 Plus (bnrv1300) uses an AllWinner "Emperor" platform that is
architecturally distinct from the GL4/4e (Freescale NTX). Split it into
its own DeviceInfo ID and wire it to a dedicated EPD controller.

NookEmperorEPDController uses ViewRootImpl.setRefreshMode(int) via
reflection — a B&N-specific addition to their Android 8.1 framework.
The call routes through SurfaceFlinger → HWC (hwcomposer.virgo.so) →
hwc_set_layer_refresh_mode → layer->refreshMode → /dev/disp ioctl.
Because HWC reads layer->refreshMode during composition, the waveform
is applied to the correct (incoming) buffer, not the currently-displayed
one.

GC16 (mode 0x4) confirmed working on device: kernel dmesg shows
mode=0x200004 on full-page refreshes. No root or Magisk module required.

Fallback order:
  1. ViewRootImpl.setRefreshMode (B&N Android 8.1)
  2. SurfaceControl.setRefreshMode via mSurfaceControl (AOSP Android 10+)
  3. sysfs force_update_mode write (requires Magisk epd_gc16 module)

Note: this PR overlaps with koreader#592 on DeviceInfo.kt (same bnrv1300 split)
and on EPDFactory.kt (koreader#592 adds NOOK_GL4PLUS to the NGL4 group; this PR
gives it a dedicated controller instead). Should be merged after koreader#592 or

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@backcountrymountains

Copy link
Copy Markdown
Contributor Author

Rebased onto master after #592 merged and resolved conflicts:

  • DeviceInfo.kt: only a comment-text conflict; kept the more descriptive (AllWinner "Emperor" platform) wording.
  • EPDFactory.kt: Add lights support for Nook Glowlight 4 Plus (bnrv1300) #592 had placed NOOK_GL4PLUS in the NGL4 group; removed it from there since this PR gives it a dedicated NookEmperorEPDController case.

Also fixed all Codacy "Unnecessary long whitespace" warnings in NookEmperorEPDController.kt — aligned = in the const val block, aligned = in the single-expression override fun bodies, and an extra space before ?: in surfaceControlSetMode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant