Init
This commit is contained in:
commit
12b41e011d
12 changed files with 829 additions and 0 deletions
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# This file is for zig-specific build artifacts.
|
||||
# If you have OS-specific or editor-specific files to ignore,
|
||||
# such as *.swp or .DS_Store, put those in your global
|
||||
# ~/.gitignore and put this in your ~/.gitconfig:
|
||||
#
|
||||
# [core]
|
||||
# excludesfile = ~/.gitignore
|
||||
#
|
||||
# Cheers!
|
||||
# -andrewrk
|
||||
|
||||
.zig-cache/
|
||||
zig-out/
|
||||
/release/
|
||||
/debug/
|
||||
/build/
|
||||
/build-*/
|
||||
/docgen_tmp/
|
||||
|
||||
# Although this was renamed to .zig-cache, let's leave it here for a few
|
||||
# releases to make it less annoying to work with multiple branches.
|
||||
zig-cache/
|
41
build.zig
Normal file
41
build.zig
Normal file
|
@ -0,0 +1,41 @@
|
|||
const std = @import("std");
|
||||
|
||||
const kindle_target_query: std.Target.Query = .{
|
||||
.cpu_arch = .arm,
|
||||
.cpu_model = std.Target.Query.CpuModel{
|
||||
.explicit = &std.Target.arm.cpu.cortex_a8,
|
||||
},
|
||||
.abi = .gnueabihf,
|
||||
.os_tag = .linux,
|
||||
.glibc_version = std.SemanticVersion.parse("2.12.0") catch unreachable,
|
||||
.dynamic_linker = std.Target.DynamicLinker.init("/lib/ld-linux.so.3"),
|
||||
};
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const kindle_target = b.resolveTargetQuery(kindle_target_query);
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const libkindle_sys = buildLibkindleSys(b, kindle_target, optimize);
|
||||
b.installArtifact(libkindle_sys);
|
||||
|
||||
const lib_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/root.zig"),
|
||||
.target = kindle_target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
lib_mod.linkLibrary(libkindle_sys);
|
||||
}
|
||||
|
||||
fn buildLibkindleSys(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile {
|
||||
const getauxval_backport_dep = b.dependency("getauxval_backport", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.elf64 = false,
|
||||
});
|
||||
const libgetauxval_backport = getauxval_backport_dep.artifact("getauxval_backport");
|
||||
|
||||
const libkindle_sys = @import("libs/kindle_sys.zig").create(b, target, optimize);
|
||||
libkindle_sys.linkLibrary(libgetauxval_backport);
|
||||
|
||||
return libkindle_sys;
|
||||
}
|
17
build.zig.zon
Normal file
17
build.zig.zon
Normal file
|
@ -0,0 +1,17 @@
|
|||
.{
|
||||
.name = .kindle,
|
||||
.version = "0.0.0",
|
||||
.fingerprint = 0x276419b66ac24917,
|
||||
.minimum_zig_version = "0.14.0",
|
||||
.dependencies = .{
|
||||
.getauxval_backport = .{
|
||||
.url = "git+https://git.dergrimm.net/dergrimm/getauxval-backport#e1a7e24c5cb9c42a9dbea5997bb03c2565f3f164",
|
||||
.hash = "getauxval_backport-0.0.0-3FxplIwLAAAnSp0CfvCJmoYOjptZYCuz8d-fTRILQEct",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
},
|
||||
}
|
21
kindle/backports/fortify.c
Normal file
21
kindle/backports/fortify.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void __attribute__((noreturn)) __fortify_fail(const char *msg) {
|
||||
fprintf(stderr, "*** <unknown> ***: %s terminated\n", msg);
|
||||
abort();
|
||||
}
|
||||
|
||||
void __attribute__((noreturn)) __chk_fail(void) {
|
||||
__fortify_fail("buffer overflow detected");
|
||||
}
|
||||
|
||||
long int __fdelt_chk(long int d) {
|
||||
if (d >= FD_SETSIZE) {
|
||||
__chk_fail();
|
||||
}
|
||||
|
||||
return d / __NFDBITS;
|
||||
}
|
1
kindle/sysroot/lib/libc.so
Symbolic link
1
kindle/sysroot/lib/libc.so
Symbolic link
|
@ -0,0 +1 @@
|
|||
./libc.so.6
|
BIN
kindle/sysroot/lib/libc.so.6
Executable file
BIN
kindle/sysroot/lib/libc.so.6
Executable file
Binary file not shown.
489
kindle/sysroot/usr/include/einkfb.h
Normal file
489
kindle/sysroot/usr/include/einkfb.h
Normal file
|
@ -0,0 +1,489 @@
|
|||
// NOTE: Upstream kernels available here:
|
||||
// https://www.amazon.com/gp/help/customer/display.html?nodeId=200203720
|
||||
|
||||
#ifndef _EINKFB_H
|
||||
#define _EINKFB_H
|
||||
|
||||
#include <asm-generic/ioctl.h>
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define EINK_1BPP 1
|
||||
#define EINK_2BPP 2
|
||||
#define EINK_4BPP 4
|
||||
#define EINK_8BPP 8
|
||||
#define EINK_BPP_MAX EINK_8BPP
|
||||
|
||||
#define EINK_WHITE 0x00 // For whacking all the pixels in a...
|
||||
#define EINK_BLACK 0xFF // ...byte (8, 4, 2, or 1) at once.
|
||||
|
||||
// Replace EINK_WHITE & EINK_BLACK with the following macros.
|
||||
//
|
||||
#define eink_white(b) EINK_WHITE
|
||||
#define eink_black(b) EINK_BLACK
|
||||
|
||||
// For pixels (at bytes at a time) other than white/black, the following holds.
|
||||
//
|
||||
#define eink_pixels(b, p) (p)
|
||||
|
||||
#define EINK_ORIENT_LANDSCAPE 1
|
||||
#define EINK_ORIENT_PORTRAIT 0
|
||||
|
||||
#define BPP_SIZE(r, b) (((r) * (b)) / 8)
|
||||
#define BPP_MAX(b) (1 << (b))
|
||||
|
||||
#define U_IN_RANGE(n, m, M) \
|
||||
((((n) == 0) && ((m) == 0)) || (((n) > (m)) && ((n) <= (M))))
|
||||
#define IN_RANGE(n, m, M) (((n) >= (m)) && ((n) <= (M)))
|
||||
|
||||
#define ORIENTATION(x, y) \
|
||||
(((y) > (x)) ? EINK_ORIENT_PORTRAIT : EINK_ORIENT_LANDSCAPE)
|
||||
|
||||
struct raw_image_t {
|
||||
int xres, // image's width, in pixels
|
||||
yres, // image's height
|
||||
bpp; // image's pixel (bit) depth
|
||||
|
||||
uint8_t start[]; // actual start of image
|
||||
};
|
||||
typedef struct raw_image_t raw_image_t;
|
||||
|
||||
struct image_t {
|
||||
int xres, // image's visual width, in pixels
|
||||
xlen, // image's actual width, used for rowbyte & memory size calculations
|
||||
yres, // image's height
|
||||
bpp; // image's pixel (bit) depth
|
||||
|
||||
uint8_t *start; // pointer to start of image
|
||||
};
|
||||
typedef struct image_t image_t;
|
||||
|
||||
#define INIT_IMAGE_T() {0, 0, 0, 0, NULL}
|
||||
|
||||
enum splash_screen_type {
|
||||
// Simple (non-composite) splash screens.
|
||||
//
|
||||
// splash_screen_powering_off = 0, // Deprecated.
|
||||
// splash_screen_powering_on, // Deprecated.
|
||||
|
||||
// splash_screen_powering_off_wireless, // Deprecated.
|
||||
// splash_screen_powering_on_wireless, // Deprecated.
|
||||
|
||||
// splash_screen_exit, // Deprecated.
|
||||
splash_screen_logo = 5,
|
||||
|
||||
// splash_screen_usb_internal, // Deprecated.
|
||||
// splash_screen_usb_external, // Deprecated.
|
||||
// splash_screen_usb, // Deprecated.
|
||||
|
||||
// splash_screen_sleep, // Deprecated.
|
||||
// splash_screen_update, // Deprecated.
|
||||
|
||||
// num_splash_screens, // Deprecated.
|
||||
|
||||
// Composite splash screens & messages.
|
||||
//
|
||||
// splash_screen_drivemode_0, // Deprecated.
|
||||
// splash_screen_drivemode_1, // Deprecated.
|
||||
// splash_screen_drivemode_2, // Deprecated.
|
||||
// splash_screen_drivemode_3, // Deprecated.
|
||||
|
||||
splash_screen_power_off_clear_screen =
|
||||
16, // Message: clear screen and power down controller.
|
||||
// splash_screen_screen_saver_picture, // Deprecated.
|
||||
|
||||
splash_screen_shim_picture = 18, // Message: shim wants a picture displayed.
|
||||
|
||||
splash_screen_lowbatt, // Picture: Not composite, post-legacy ordering (Mario
|
||||
// only).
|
||||
splash_screen_reboot, // Picture: Composite (not used on Fiona).
|
||||
|
||||
splash_screen_update_initial, // Composite software-update screens.
|
||||
splash_screen_update_success, //
|
||||
splash_screen_update_failure, //
|
||||
splash_screen_update_failure_no_wait, //
|
||||
|
||||
splash_screen_repair_needed, // More composite screens.
|
||||
splash_screen_boot, //
|
||||
|
||||
splash_screen_invalid = -1
|
||||
};
|
||||
typedef enum splash_screen_type splash_screen_type;
|
||||
|
||||
// Alias some of the legacy enumerations for Mario.
|
||||
//
|
||||
#define splash_screen_usb_recovery_util \
|
||||
((splash_screen_type)8) // splash_screen_usb
|
||||
|
||||
struct power_override_t {
|
||||
unsigned int cmd;
|
||||
unsigned long arg;
|
||||
};
|
||||
typedef struct power_override_t power_override_t;
|
||||
|
||||
enum fx_type {
|
||||
// Deprecated from the HAL, but still supported by the Shim.
|
||||
//
|
||||
fx_mask = 11, // Only for use with update_area_t's non-NULL buffer which_fx.
|
||||
fx_buf_is_mask = 14, // Same as fx_mask, but doesn't require a doubling (i.e.,
|
||||
// the buffer & mask are the same).
|
||||
|
||||
fx_none = -1, // No legacy-FX to apply.
|
||||
|
||||
// Screen-update FX, supported by HAL.
|
||||
//
|
||||
fx_flash =
|
||||
20, // Only for use with update_area_t (for faking a flashing update).
|
||||
fx_invert = 21, // Only for use with update_area_t (only inverts output data).
|
||||
|
||||
fx_update_partial = 0, // Higher-speed, lower-fidelity update at bit depth's
|
||||
// number of grays (aka non-flashing).
|
||||
fx_update_full = 1, // Higher-fidelity, lower speed update at bit depth's
|
||||
// number of grays (aka flashing).
|
||||
|
||||
fx_update_fast =
|
||||
2, // Sacrifices all fidelity for speed (will be non-flashing).
|
||||
fx_update_slow = 3, // Sacrifices any speed for fidelity (will be flashing).
|
||||
|
||||
fx_buffer_load =
|
||||
99, // Just load the hardware buffer; don't update the display.
|
||||
fx_buffer_display_partial =
|
||||
100, // Display whatever's in the hardware's buffer, non-flashing style.
|
||||
fx_buffer_display_full =
|
||||
101 // Display whatever's in the hardware's buffer, flashing style.
|
||||
};
|
||||
typedef enum fx_type fx_type;
|
||||
|
||||
// The only valid legacy-FX types for area updates are fx_mask and
|
||||
// fx_buf_is_mask.
|
||||
//
|
||||
#define UPDATE_AREA_FX(f) ((fx_mask == (f)) || (fx_buf_is_mask == (f)))
|
||||
|
||||
// Fast page turns consists of both fast updates to begin with, which are low
|
||||
// fidelity, and then a slow update at the end of the fast-update sequence to
|
||||
// restore fidelity to the display.
|
||||
//
|
||||
#define UPDATE_FAST_PAGE_TURN(f) \
|
||||
((fx_update_fast == (f)) || (fx_update_slow == (f)))
|
||||
|
||||
// The default ("none") for area updates is partial (non-flashing); full
|
||||
// (flashing) updates are for FX and such (i.e., explicit completion is
|
||||
// desired).
|
||||
//
|
||||
#define UPDATE_AREA_PART(f) \
|
||||
((fx_none == (f)) || (fx_buffer_display_partial == (f)) || \
|
||||
(fx_update_partial == (f)) || (fx_update_fast == (f)))
|
||||
|
||||
#define UPDATE_AREA_FULL(f) \
|
||||
(UPDATE_AREA_FX(f) || (fx_buffer_display_full == (f)) || \
|
||||
(fx_update_full == (f)) || (fx_update_slow == (f)))
|
||||
|
||||
#define UPDATE_AREA_MODE(f) \
|
||||
(UPDATE_AREA_FULL(f) ? fx_update_full : fx_update_partial)
|
||||
|
||||
// For use with the FBIO_EINK_UPDATE_DISPLAY ioctl.
|
||||
//
|
||||
#define UPDATE_PART(f) \
|
||||
((fx_buffer_display_partial == (f)) || (fx_update_partial == (f)) || \
|
||||
(fx_update_fast == (f)))
|
||||
|
||||
#define UPDATE_FULL(f) \
|
||||
((fx_buffer_display_full == (f)) || (fx_update_full == (f)) || \
|
||||
(fx_update_slow == (f)))
|
||||
|
||||
#define UPDATE_MODE(f) (UPDATE_FULL(f) ? fx_update_full : fx_update_partial)
|
||||
|
||||
#define UPDATE_MODE_BUFFER(f) \
|
||||
((fx_buffer_load == (f)) || (fx_buffer_display_partial == (f)) || \
|
||||
(fx_buffer_display_full == (f)))
|
||||
|
||||
#define SKIP_BUFFERS_EQUAL(f, c) \
|
||||
(UPDATE_MODE_BUFFER(f) || (fx_update_slow == (f)) || (contrast_off != (c)))
|
||||
|
||||
struct rect_t {
|
||||
// Note: The bottom-right (x2, y2) coordinate is actually such that (x2 - x1)
|
||||
// and (y2 - y1)
|
||||
// are xres and yres, respectively, when normally xres and yres would
|
||||
// be (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
|
||||
//
|
||||
int x1, y1, x2, y2;
|
||||
};
|
||||
typedef struct rect_t rect_t;
|
||||
|
||||
#define INIT_RECT_T() {0, 0, 0, 0}
|
||||
#define MAX_EXCLUDE_RECTS 8
|
||||
|
||||
struct fx_t {
|
||||
fx_type update_mode, // Screen-update FX: fx_update_full | fx_update_partial.
|
||||
which_fx; // Shim (legacy) FX.
|
||||
|
||||
int num_exclude_rects; // 0..MAX_EXCLUDE_RECTS.
|
||||
rect_t exclude_rects[MAX_EXCLUDE_RECTS];
|
||||
};
|
||||
typedef struct fx_t fx_t;
|
||||
|
||||
#define INIT_FX_T() \
|
||||
{ \
|
||||
fx_update_partial, fx_none, 0, { \
|
||||
INIT_RECT_T(), INIT_RECT_T(), INIT_RECT_T(), INIT_RECT_T(), \
|
||||
INIT_RECT_T(), INIT_RECT_T(), INIT_RECT_T(), INIT_RECT_T() \
|
||||
} \
|
||||
}
|
||||
|
||||
struct update_area_t {
|
||||
// Note: The bottom-right (x2, y2) coordinate is actually such that (x2 - x1)
|
||||
// and (y2 - y1)
|
||||
// are xres and yres, respectively, when normally xres and yres would
|
||||
// be (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
|
||||
//
|
||||
int x1, y1, // Top-left...
|
||||
x2, y2; // ...bottom-right.
|
||||
|
||||
fx_type which_fx; // FX to use.
|
||||
|
||||
uint8_t *buffer; // If NULL, extract from framebuffer, top-left to
|
||||
// bottom-right, by rowbytes.
|
||||
};
|
||||
typedef struct update_area_t update_area_t;
|
||||
|
||||
#define INIT_UPDATE_AREA_T() {0, 0, 0, 0, fx_none, NULL}
|
||||
|
||||
struct progressbar_xy_t {
|
||||
int x, y; // Top-left corner of progressbar's position (ignores x for now).
|
||||
};
|
||||
typedef struct progressbar_xy_t progressbar_xy_t;
|
||||
|
||||
enum screen_saver_t { screen_saver_invalid = 0, screen_saver_valid };
|
||||
typedef enum screen_saver_t screen_saver_t;
|
||||
|
||||
enum orientation_t {
|
||||
orientation_portrait,
|
||||
orientation_portrait_upside_down,
|
||||
orientation_landscape,
|
||||
orientation_landscape_upside_down
|
||||
};
|
||||
typedef enum orientation_t orientation_t;
|
||||
|
||||
#define num_orientations (orientation_landscape_upside_down + 1)
|
||||
|
||||
#define ORIENTATION_PORTRAIT(o) \
|
||||
((orientation_portrait == (o)) || (orientation_portrait_upside_down == (o)))
|
||||
|
||||
#define ORIENTATION_LANDSCAPE(o) \
|
||||
((orientation_landscape == (o)) || (orientation_landscape_upside_down == (o)))
|
||||
|
||||
#define ORIENTATION_SAME(o1, o2) \
|
||||
((ORIENTATION_PORTRAIT(o1) && ORIENTATION_PORTRAIT(o2)) || \
|
||||
(ORIENTATION_LANDSCAPE(o1) && ORIENTATION_LANDSCAPE(o2)))
|
||||
|
||||
enum einkfb_events_t {
|
||||
einkfb_event_update_display = 0, // FBIO_EINK_UPDATE_DISPLAY
|
||||
einkfb_event_update_display_area, // FBIO_EINK_UPDATE_DISPLAY_AREA
|
||||
|
||||
einkfb_event_blank_display, // FBIOBLANK (fb.h)
|
||||
einkfb_event_rotate_display, // FBIO_EINK_SET_DISPLAY_ORIENTATION
|
||||
|
||||
einkfb_event_null = -1
|
||||
};
|
||||
typedef enum einkfb_events_t einkfb_events_t;
|
||||
|
||||
struct einkfb_event_t {
|
||||
einkfb_events_t
|
||||
event; // Not all einkfb_events_t use all of the einkfb_event_t fields.
|
||||
|
||||
fx_type update_mode; // Screen-update FX: fx_update_full | fx_update_partial.
|
||||
|
||||
// Note: The bottom-right (x2, y2) coordinate is actually such that (x2 - x1)
|
||||
// and (y2 - y1)
|
||||
// are xres and yres, respectively, when normally xres and yres would
|
||||
// be (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
|
||||
//
|
||||
int x1, y1, // Top-left...
|
||||
x2, y2; // ...bottom-right.
|
||||
|
||||
orientation_t orientation; // Display rotated into this orientation.
|
||||
};
|
||||
typedef struct einkfb_event_t einkfb_event_t;
|
||||
|
||||
enum reboot_behavior_t {
|
||||
reboot_screen_asis,
|
||||
reboot_screen_clear,
|
||||
reboot_screen_splash
|
||||
};
|
||||
typedef enum reboot_behavior_t reboot_behavior_t;
|
||||
|
||||
enum progressbar_badge_t {
|
||||
progressbar_badge_success,
|
||||
progressbar_badge_failure,
|
||||
|
||||
progressbar_badge_none
|
||||
};
|
||||
typedef enum progressbar_badge_t progressbar_badge_t;
|
||||
|
||||
enum sleep_behavior_t {
|
||||
sleep_behavior_allow_sleep,
|
||||
sleep_behavior_prevent_sleep
|
||||
};
|
||||
typedef enum sleep_behavior_t sleep_behavior_t;
|
||||
|
||||
enum contrast_t {
|
||||
contrast_off,
|
||||
|
||||
contrast_light,
|
||||
contrast_medium,
|
||||
contrast_dark,
|
||||
|
||||
contrast_lighter,
|
||||
contrast_lightest,
|
||||
|
||||
contrast_darker,
|
||||
contrast_darkest
|
||||
};
|
||||
typedef enum contrast_t contrast_t;
|
||||
|
||||
#define EINK_FRAME_BUFFER "/dev/fb/0"
|
||||
|
||||
#define SIZEOF_EINK_EVENT sizeof(einkfb_event_t)
|
||||
#define EINK_EVENTS "/dev/misc/eink_events"
|
||||
|
||||
#define EINK_ROTATE_FILE "/sys/devices/platform/eink_fb.0/send_fake_rotate"
|
||||
#define EINK_ROTATE_FILE_LEN 1
|
||||
#define ORIENT_PORTRAIT orientation_portrait
|
||||
#define ORIENT_PORTRAIT_UPSIDE_DOWN orientation_portrait_upside_down
|
||||
#define ORIENT_LANDSCAPE orientation_landscape
|
||||
#define ORIENT_LANDSCAPE_UPSIDE_DOWN orientation_landscape_upside_down
|
||||
#define ORIENT_ASIS (-1)
|
||||
|
||||
#define EINK_USID_FILE "/var/local/eink/usid"
|
||||
|
||||
#define EINK_CLEAR_SCREEN 0
|
||||
#define EINK_CLEAR_BUFFER 1
|
||||
#define EINK_CLEAR_SCREEN_NOT_BUFFER 2
|
||||
|
||||
#define FBIO_EINK_SCREEN_CLEAR FBIO_EINK_CLEAR_SCREEN, EINK_CLEAR_SCREEN
|
||||
#define FBIO_EINK_BUFFER_CLEAR FBIO_EINK_CLEAR_SCREEN, EINK_CLEAR_BUFFER
|
||||
#define FBIO_EINK_SCREEN_CLEAR_ONLY \
|
||||
FBIO_EINK_CLEAR_SCREEN, EINK_CLEAR_SCREEN_NOT_BUFFER
|
||||
|
||||
#define FBIO_MIN_SCREEN splash_screen_powering_off
|
||||
#define FBIO_MAX_SCREEN num_splash_screens
|
||||
#define FBIO_SCREEN_IN_RANGE(s) \
|
||||
((FBIO_MIN_SCREEN <= (s)) && (FBIO_MAX_SCREEN > (s)))
|
||||
|
||||
#define FBIO_MAGIC_NUMBER 'F'
|
||||
|
||||
// Implemented in the eInk HAL.
|
||||
//
|
||||
#define FBIO_EINK_UPDATE_DISPLAY \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xdb) // 0x46db (fx_type)
|
||||
#define FBIO_EINK_UPDATE_DISPLAY_AREA \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xdd) // 0x46dd (update_area_t *)
|
||||
|
||||
#define FBIO_EINK_RESTORE_DISPLAY \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xef) // 0x46ef (UPDATE_MODE(fx_type))
|
||||
|
||||
#define FBIO_EINK_SET_REBOOT_BEHAVIOR \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xe9) // 0x46e9 (reboot_behavior_t)
|
||||
#define FBIO_EINK_GET_REBOOT_BEHAVIOR \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xed) // 0x46ed (reboot_behavior_t *)
|
||||
|
||||
#define FBIO_EINK_SET_DISPLAY_ORIENTATION \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf0) // 0x46f0 (orientation_t)
|
||||
#define FBIO_EINK_GET_DISPLAY_ORIENTATION \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf1) // 0x46f1 (orientation_t *)
|
||||
|
||||
#define FBIO_EINK_SET_SLEEP_BEHAVIOR \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf2) // 0x46f2 (sleep_behavior_t)
|
||||
#define FBIO_EINK_GET_SLEEP_BEHAVIOR \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf3) // 0x46f3 (sleep_behavior_t *)
|
||||
|
||||
#define FBIO_EINK_SET_CONTRAST \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf5) // 0x46f5 (contrast_t)
|
||||
|
||||
// Implemented in the eInk Shim.
|
||||
//
|
||||
#define FBIO_EINK_UPDATE_DISPLAY_FX \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xe4) // 0x46e4 (fx_t *)
|
||||
#define FBIO_EINK_SPLASH_SCREEN \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xdc) // 0x46dc (splash_screen_type)
|
||||
#define FBIO_EINK_SPLASH_SCREEN_SLEEP \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xe0) // 0x46e0 (splash_screen_type)
|
||||
#define FBIO_EINK_OFF_CLEAR_SCREEN \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xdf) // 0x46df (no args)
|
||||
#define FBIO_EINK_CLEAR_SCREEN \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xe1) // 0x46e1 (EINK_CLEAR_SCREEN || EINK_CLEAR_BUFFER
|
||||
// || EINK_CLEAR_SCREEN_NOT_BUFFER)
|
||||
#define FBIO_EINK_POWER_OVERRIDE \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xe3) // 0x46e3 (power_override_t *)
|
||||
|
||||
#define FBIO_EINK_PROGRESSBAR \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xea) // 0x46ea (int: 0..100 -> draw progressbar ||
|
||||
// !(0..100) -> clear progressbar)
|
||||
#define FBIO_EINK_PROGRESSBAR_SET_XY \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xeb) // 0x46eb (progressbar_xy_t *)
|
||||
#define FBIO_EINK_PROGRESSBAR_BADGE \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xec) // 0x46ec (progressbar_badge_t);
|
||||
#define FBIO_EINK_PROGRESSBAR_BACKGROUND \
|
||||
_IO(FBIO_MAGIC_NUMBER, 0xf4) // 0x46f4 (int: EINKFB_WHITE || EINKFB_BLACK)
|
||||
|
||||
#define IS_UPDATE_DISPLAY_CMD(c) \
|
||||
((FBIO_EINK_UPDATE_DISPLAY == (c)) || \
|
||||
(FBIO_EINK_UPDATE_DISPLAY_FX == (c)) || \
|
||||
(FBIO_EINK_UPDATE_DISPLAY_AREA == (c)) || \
|
||||
(FBIO_EINK_RESTORE_DISPLAY == (c)) || (FBIO_EINK_CLEAR_SCREEN == (c)))
|
||||
|
||||
#define IS_PROGRESSBAR_CMD(c) \
|
||||
((FBIO_EINK_PROGRESSBAR == (c)) || (FBIO_EINK_PROGRESSBAR_SET_XY == (c)) || \
|
||||
(FBIO_EINK_PROGRESSBAR_BADGE == (c)) || \
|
||||
(FBIO_EINK_PROGRESSBAR_BACKGROUND == (c)))
|
||||
|
||||
// Deprecated from the HAL & Shim.
|
||||
//
|
||||
// #define FBIO_EINK_UPDATE_DISPLAY_ASYNC _IO(FBIO_MAGIC_NUMBER, 0xde) //
|
||||
// 0x46de (fx_type: fx_update_full || fx_update_partial) #define
|
||||
// FBIO_EINK_FAKE_PNLCD _IO(FBIO_MAGIC_NUMBER, 0xe8) // 0x46e8
|
||||
// (char *)
|
||||
|
||||
// For use with /proc/eink_fb/update_display.
|
||||
//
|
||||
#define PROC_EINK_UPDATE_DISPLAY_CLS 0 // FBIO_EINK_CLEAR_SCREEN
|
||||
#define PROC_EINK_UPDATE_DISPLAY_PART \
|
||||
1 // FBIO_EINK_UPDATE_DISPLAY(fx_update_partial)
|
||||
#define PROC_EINK_UPDATE_DISPLAY_FULL \
|
||||
2 // FBIO_EINK_UPDATE_DISPLAY(fx_update_full)
|
||||
#define PROC_EINK_UPDATE_DISPLAY_AREA 3 // FBIO_EINK_UPDATE_DISPLAY_AREA
|
||||
// #define PROC_EINK_UPDATE_DISPLAY_REST 4 // FBIO_EINK_RESTORE_SCREEN
|
||||
#define PROC_EINK_UPDATE_DISPLAY_SCRN 5 // FBIO_EINK_SPLASH_SCREEN
|
||||
#define PROC_EINK_UPDATE_DISPLAY_OVRD 6 // FBIO_EINK_FPOW_OVERRIDE
|
||||
#define PROC_EINK_UPDATE_DISPLAY_FX 7 // FBIO_EINK_UPDATE_DISPLAY_FX
|
||||
// #define PROC_EINK_UPDATE_DISPLAY_SYNC 8 // FBIO_EINK_SYNC_BUFFERS
|
||||
// #define PROC_EINK_UPDATE_DISPLAY_PNLCD 9 // FBIO_EINK_FAKE_PNLCD
|
||||
#define PROC_EINK_SET_REBOOT_BEHAVIOR 10 // FBIO_EINK_SET_REBOOT_BEHAVIOR
|
||||
#define PROC_EINK_SET_PROGRESSBAR_XY 11 // FBIO_EINK_PROGRESSBAR_SET_XY
|
||||
#define PROC_EINK_UPDATE_DISPLAY_SCRN_SLP 12 // FBIO_EINK_SPLASH_SCREEN_SLEEP
|
||||
#define PROC_EINK_PROGRESSBAR_BADGE 13 // FBIO_EINK_PROGRESSBAR_BADGE
|
||||
#define PROC_EINK_SET_DISPLAY_ORIENTATION \
|
||||
14 // FBIO_EINK_SET_DISPLAY_ORIENTATION
|
||||
#define PROC_EINK_RESTORE_DISPLAY 15 // FBIO_EINK_RESTORE_DISPLAY
|
||||
#define PROC_EINK_SET_SLEEP_BEHAVIOR 16 // FBIO_EINK_SET_SLEEP_BEHAVIOR
|
||||
#define PROC_EINK_PROGRESSBAR_BACKGROUND 17 // FBIO_EINK_PROGRESSBAR_BACKGROUND
|
||||
#define PROC_EINK_UPDATE_DISPLAY_WHICH 18 // FBIO_EINK_UPDATE_DISPLAY
|
||||
#define PROC_EINK_SET_CONTRAST 19 // FBIO_EINK_SET_CONTRAST
|
||||
|
||||
// #define PROC_EINK_FAKE_PNLCD_TEST 100 // Programmatically drive
|
||||
// FBIO_EINK_FAKE_PNLCD (not implemented).
|
||||
#define PROC_EINK_GRAYSCALE_TEST \
|
||||
101 // Fills display with white-to-black ramp at current bit depth.
|
||||
|
||||
// Inter-module/inter-driver eink ioctl access.
|
||||
//
|
||||
extern int fiona_eink_ioctl_stub(unsigned int cmd, unsigned long arg);
|
||||
|
||||
#define eink_sys_ioctl(cmd, arg) \
|
||||
(get_fb_ioctl() \
|
||||
? (*get_fb_ioctl())((unsigned int)cmd, (unsigned long)arg) \
|
||||
: fiona_eink_ioctl_stub((unsigned int)cmd, (unsigned long)arg))
|
||||
|
||||
#endif // _EINKFB_H
|
21
libs/kindle_sys.zig
Normal file
21
libs/kindle_sys.zig
Normal file
|
@ -0,0 +1,21 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn create(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile {
|
||||
const lib = b.addStaticLibrary(.{
|
||||
.name = "kindle_sys",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
lib.addCSourceFile(.{
|
||||
.file = b.path("kindle/backports/fortify.c"),
|
||||
});
|
||||
|
||||
lib.addLibraryPath(b.path("kindle/sysroot/lib"));
|
||||
lib.linkSystemLibrary2("c", .{ .preferred_link_mode = .dynamic });
|
||||
|
||||
lib.addIncludePath(b.path("kindle/sysroot/usr/include"));
|
||||
lib.installHeadersDirectory(b.path("kindle/sysroot/usr/include"), "", .{});
|
||||
|
||||
return lib;
|
||||
}
|
125
src/eink/fb.zig
Normal file
125
src/eink/fb.zig
Normal file
|
@ -0,0 +1,125 @@
|
|||
const std = @import("std");
|
||||
|
||||
const sys = @import("sys.zig");
|
||||
|
||||
pub const FramebufferError = error{
|
||||
BppUnsupported,
|
||||
};
|
||||
|
||||
pub const Framebuffer = struct {
|
||||
const Self = @This();
|
||||
|
||||
file: std.fs.File,
|
||||
data: []align(std.mem.page_size) u8,
|
||||
|
||||
xres: u32,
|
||||
yres: u32,
|
||||
bits_per_pixel: u32,
|
||||
|
||||
/// Extracted from `eips` binary
|
||||
fn checkBppSupported(bpp: c_uint) bool {
|
||||
return (bpp <= 8) and
|
||||
((@as(c_uint, 0x68800000) << @truncate(bpp)) >> ((@sizeOf(c_uint) * 8) - 1)) == 1;
|
||||
}
|
||||
|
||||
pub fn open(path: []const u8) !Self {
|
||||
const file = try std.fs.cwd().openFile(path, .{
|
||||
.mode = .read_write,
|
||||
});
|
||||
|
||||
const vinfo = try sys.vscreeninfo(file.handle);
|
||||
if (!checkBppSupported(vinfo.bits_per_pixel)) {
|
||||
return FramebufferError.BppUnsupported;
|
||||
}
|
||||
|
||||
const data = try sys.mmap_fb(file.handle, vinfo);
|
||||
|
||||
return .{
|
||||
.file = file,
|
||||
.data = data,
|
||||
.xres = vinfo.xres,
|
||||
.yres = vinfo.yres,
|
||||
.bits_per_pixel = vinfo.bits_per_pixel,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
std.posix.munmap(self.data);
|
||||
self.file.close();
|
||||
}
|
||||
|
||||
pub fn fill(self: *Self, color: u8) void {
|
||||
@memset(self.data, color);
|
||||
}
|
||||
|
||||
pub fn fillLine(self: *Self, y: u32, color: u8) void {
|
||||
if (y >= self.yres)
|
||||
return;
|
||||
|
||||
const buf = self.data[self.offset(0, y)..self.offset(self.xres, y)];
|
||||
@memset(buf, color);
|
||||
}
|
||||
|
||||
pub fn fillLineVar(self: *Self, y: u32, x_start: u32, x_end: u32, color: u8) void {
|
||||
if (y >= self.yres or
|
||||
x_start > x_end or
|
||||
x_start >= self.xres)
|
||||
return;
|
||||
|
||||
if (x_start == x_end) {
|
||||
self.set(x_start, y, color);
|
||||
return;
|
||||
}
|
||||
|
||||
const safe_x_end = @min(x_end, self.xres);
|
||||
const buf = self.data[self.offset(x_start, y)..self.offset(safe_x_end, y)];
|
||||
@memset(buf, color);
|
||||
}
|
||||
|
||||
pub fn fillArea(self: *Self, region: sys.Region, color: u8) void {
|
||||
if (region.top >= self.yres or
|
||||
region.left >= self.xres or
|
||||
region.width == 0 or
|
||||
region.height == 0)
|
||||
return;
|
||||
|
||||
const y_end = @min(region.top + region.height + 1, self.yres);
|
||||
const x_end = @min(region.left + region.width + 1, self.xres);
|
||||
|
||||
for (region.top..y_end) |y| {
|
||||
const buf = self.data[self.offset(region.left, y)..self.offset(x_end, y)];
|
||||
@memset(buf, color);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(self: *Self) !void {
|
||||
try sys.clear_screen(self.file.handle);
|
||||
self.fill(0x00);
|
||||
}
|
||||
|
||||
pub fn update(self: *const Self, update_mode: sys.UpdateMode) !void {
|
||||
try sys.update_display(self.file.handle, update_mode);
|
||||
}
|
||||
|
||||
pub fn updateArea(self: *const Self, region: sys.Region, update_mode: sys.UpdateMode) !void {
|
||||
if (region.width == self.xres and region.height == self.yres) {
|
||||
try sys.update_display(self.file.handle, update_mode);
|
||||
} else {
|
||||
try sys.update_display_area(self.file.handle, region, update_mode);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn offset(self: *const Self, x: usize, y: usize) usize {
|
||||
return y * self.xres + x;
|
||||
}
|
||||
|
||||
pub fn get(self: *const Self, x: usize, y: usize) u8 {
|
||||
return self.data[self.offset(x, y)];
|
||||
}
|
||||
|
||||
pub fn set(self: *Self, x: usize, y: usize, color: u8) void {
|
||||
if (x < self.xres and y < self.yres) {
|
||||
self.data[self.offset(x, y)] = color;
|
||||
}
|
||||
}
|
||||
};
|
1
src/eink/root.zig
Normal file
1
src/eink/root.zig
Normal file
|
@ -0,0 +1 @@
|
|||
pub const fb = @import("fb.zig");
|
90
src/eink/sys.zig
Normal file
90
src/eink/sys.zig
Normal file
|
@ -0,0 +1,90 @@
|
|||
const std = @import("std");
|
||||
|
||||
const c = @cImport({
|
||||
@cInclude("linux/fb.h");
|
||||
@cInclude("einkfb.h");
|
||||
});
|
||||
|
||||
fn handleErrno(rc: usize) std.posix.UnexpectedError!void {
|
||||
const err = std.posix.errno(rc);
|
||||
if (err != .SUCCESS)
|
||||
return std.posix.unexpectedErrno(err);
|
||||
}
|
||||
|
||||
pub fn vscreeninfo(fd: std.posix.fd_t) std.posix.UnexpectedError!c.fb_var_screeninfo {
|
||||
var vinfo: c.fb_var_screeninfo = undefined;
|
||||
try handleErrno(
|
||||
std.os.linux.ioctl(fd, c.FBIOGET_VSCREENINFO, @intFromPtr(&vinfo)),
|
||||
);
|
||||
|
||||
return vinfo;
|
||||
}
|
||||
|
||||
pub fn mmap_fb(fd: std.posix.fd_t, vinfo: c.fb_var_screeninfo) ![]align(std.mem.page_size) u8 {
|
||||
const data_size: usize = vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel / 8);
|
||||
const data = try std.posix.mmap(
|
||||
null,
|
||||
data_size,
|
||||
std.posix.PROT.READ | std.posix.PROT.WRITE,
|
||||
.{
|
||||
.TYPE = .SHARED,
|
||||
.LOCKED = false,
|
||||
},
|
||||
fd,
|
||||
0,
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
pub fn clear_screen(fd: std.posix.fd_t) std.posix.UnexpectedError!void {
|
||||
try handleErrno(
|
||||
std.os.linux.ioctl(fd, c.FBIO_EINK_CLEAR_SCREEN, c.EINK_CLEAR_SCREEN),
|
||||
);
|
||||
}
|
||||
|
||||
pub const UpdateMode = enum {
|
||||
full,
|
||||
partial,
|
||||
|
||||
fn toFxType(self: UpdateMode) c.fx_type {
|
||||
switch (self) {
|
||||
.full => return c.fx_update_full,
|
||||
.partial => return c.fx_update_partial,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn update_display(fd: std.posix.fd_t, update_mode: UpdateMode) std.posix.UnexpectedError!void {
|
||||
const fx = update_mode.toFxType();
|
||||
|
||||
try handleErrno(
|
||||
std.os.linux.ioctl(fd, c.FBIO_EINK_UPDATE_DISPLAY, @intCast(fx)),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn Rect(comptime T: type) type {
|
||||
return struct {
|
||||
top: T,
|
||||
left: T,
|
||||
width: T,
|
||||
height: T,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Region = Rect(u32);
|
||||
|
||||
pub fn update_display_area(fd: std.posix.fd_t, region: Region, update_mode: UpdateMode) std.posix.UnexpectedError!void {
|
||||
const area: c.update_area_t = .{
|
||||
.x1 = @intCast(region.left),
|
||||
.y1 = @intCast(region.top),
|
||||
.x2 = @intCast(region.left + region.width),
|
||||
.y2 = @intCast(region.top + region.height),
|
||||
.which_fx = update_mode.toFxType(),
|
||||
.buffer = 0,
|
||||
};
|
||||
|
||||
try handleErrno(
|
||||
std.os.linux.ioctl(fd, c.FBIO_EINK_UPDATE_DISPLAY_AREA, @intFromPtr(&area)),
|
||||
);
|
||||
}
|
1
src/root.zig
Normal file
1
src/root.zig
Normal file
|
@ -0,0 +1 @@
|
|||
pub const eink = @import("eink/root.zig");
|
Loading…
Reference in a new issue