开发者生态
morning
越狱 Kindle 上的 Rust(和 Slint)
2026-05-27
1 阅读
homarp
.. / rust-on-kindle 发布于:2026 年 5 月 26 日 Rust(和 Slint)在越狱的 Kindle 上。我最近越狱了我的第七代 Kindle Paperwhite。虽然我的动机可能应该是“摆脱亚马逊潮湿而紧绷的束缚”,但事实是我想要一种将它用作床头柜上的时钟的方法。我找到了这个项目,并认为我可以对代码进行一些调整。效果很好。但当我打开门时,我开始考虑是否能让 Rust 也能在 Kindle 上工作。也许我可以用它做更多有用的事情?由于我最近再次开始摆弄家庭助理和智能设备,因此针对某些功能的仪表板的想法可能是一个有趣的项目。虽然可能有很多非常好的项目,但我还没有做过任何一个。告诉程序员已经有一个库可以做 X 就像告诉歌曲作者已经有一首关于爱情的歌曲一样。 -Pete Cordell 为 Kindle 交叉编译 Rust 经过一番研究,我发现我需要针对 ARMv7 和 musl libc。我之前曾在 ARM 机器上涉足过 Rust,并且从痛苦的经历中知道,让 Rust 编译工具链在如此低功耗的设备上工作是不可能的。幸运的是,有一些很棒的交叉编译工具。颇具讽刺意味的是,我交叉编译 Rust 的首选是cargo-zigbuild。 Zig 编译器附带了内置的 musl libc 源代码和标头,适用于所有支持的体系结构。它还有自己的链接器,因此 zig cc 可以充当任何主机上任何 musl 目标的完整交叉编译工具链。针对 Kindle 进行编译变得非常简单: * 安装 Zig * 安装 Cargo-zigbuild * Cargo Zigbuild --release --target Armv7-unknown-linux-musleabihf 在 Kindle 上获取 shell 访问权限 当我的 hello-world-app 准备就绪并构建完成后,我需要一种方法将其放在 Kindle 上并运行它。虽然我可能可以使用在越狱过程中安装的 KUAL,但我还希望能够查看标准输出来验证我的应用程序是否确实有效。经过一番挖掘,我发现 USBNetwork 工具允许通过 USB 或 Wifi 设置对设备的 SSH 访问。为了方便起见,我在 sshconfig 中添加了一个条目并复制了我的公钥。注意:ssh-copy-id 对我不起作用,我必须将我的 .pub 文件添加到 Kindle 上的 /mnt/us/usbnet/etc/authorized_keys 中。你好世界!现在怎么办?通过 shell 访问,我能够确认我的交叉编译工具链确实有效,“Hello,World!”正如预期的那样出现了。但是通过 SSH 打印到标准输出的程序在 Kindle 上没有多大帮助。随着 Rust 的成熟,不少 GUI 库如雨后春笋般涌现。就我个人而言,我只有 Slint 的经验,所以这就是我所达到的目的。我可以让它在 Kindle 上运行吗?根据我在 Raspberry Pi 上运行 Slint 的经验,我知道 ARMv7 平台是开箱即用的。缺失的链接将输出到电子墨水屏幕并从触摸面板输入。我们有视觉! Slint 支持各种渲染器和后端,包括一个方便且轻量级的软件渲染器,基本上适用于任何东西。通过提供实现 process_line() 的 LineBufferProvider,我们能够获取一行一行的光栅化视觉输出,将其转换为灰度并将其写入帧缓冲区,在我的 Kindle 上,它只是 /dev/fb0 中的一个文件,我们有内存映射。有时我喜欢“一切皆文件”的 Linux 哲学。现在唯一要做的就是通知驾驶员刷新显示器,这就是电子墨水的工作原理。这是通过 libc crate 和 ioctl() (输入/输出控制)完成的。我们传入要刷新的脏区域,这是由 Slint 内部轻松提供的。触摸我这里,触摸我那里 屏幕上有像素,难题的另一半是让触摸面板与 Slint 对话。 “一切都是文件”的口号再次拯救了我们:触摸控制器显示为 /dev/input/event1 ,我们可以从中 read() 。每次读取都会返回一个内核直接写入缓冲区的结构:时间戳、事件类型、代码和值。没有解析,没有协议,只有我们必须匹配的内存布局。 Kindle 使用 Linux 内核的多点触控协议类型 B ,这意味着事件以“X 坐标现在是这个”、“Y 坐标现在是那个”、“跟踪 ID 现在是这个”的流形式到达,然后是一个 SYNC_REPORT 事件,表示“好吧,该批次已完成,您现在可以对其进行操作”。因此,随着事件的到来,我们会累积最新的 X、Y 和跟踪 ID,并在每个 SYNC_REPORT 上计算出要分派给 Slint 的内容。跟踪 ID 为 -1 表示手指抬起,成为 PointerReleased 。否则,触地后的第一个同步将变为 PointerPressed ,任何后续同步将变为 PointerMoved 。斯林特处理剩下的事情。它确实有效!经过大量调试无可见输出、屏幕不刷新、双刷新闪烁、触摸输入不注册