Add set_off_screen ioctl

This commit is contained in:
2025-06-08 17:11:51 +02:00
commit 983008b01f
4 changed files with 572 additions and 0 deletions

79
src/main.rs Normal file
View File

@ -0,0 +1,79 @@
use clap::Parser;
use eyre::{Context, ensure, eyre};
use nix::ioctl_write_ptr;
use std::{
fs::File,
io::Read,
os::fd::AsRawFd,
path::{Path, PathBuf},
};
#[derive(Parser)]
struct Opt {
/// Path to the image-blob.
pub path: PathBuf,
}
const SCREEN_W: usize = 1404;
const SCREEN_H: usize = 1872;
const BITS_PER_PIXEL: usize = 4;
const FILE_SIZE: usize = SCREEN_W * SCREEN_H * BITS_PER_PIXEL / 8;
// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
// #define DRM_IOCTL_ROCKCHIP_EBC_OFF_SCREEN DRM_IOWR(DRM_COMMAND_BASE + 0x01, struct drm_rockchip_ebc_off_screen)
#[repr(C)]
struct DrmRockchipEbcOffScreen {
info1: u64,
ptr_screen_content: *const u8,
}
const DRM_IOCTL_BASE: u8 = b'd';
const DRM_COMMAND_BASE: u8 = 0x40;
const ROCKCHIP_EBC_FILE: &str = "/dev/dri/by-path/platform-fdec0000.ebc-card";
ioctl_write_ptr!(
set_off_screen,
DRM_IOCTL_BASE,
DRM_COMMAND_BASE + 1,
DrmRockchipEbcOffScreen
);
fn main() -> eyre::Result<()> {
let opt = Opt::parse();
color_eyre::install()?;
let image =
read_file(&opt.path).wrap_err_with(|| eyre!("Failed to read file at {:?}", opt.path))?;
let set_off_screen_data = DrmRockchipEbcOffScreen {
info1: 0, // TODO: what is this?
ptr_screen_content: image.as_ptr(),
};
let driver_file = File::options()
.write(true)
.open(ROCKCHIP_EBC_FILE)
.wrap_err_with(|| eyre!("Failed to open rockchip ebc file at {ROCKCHIP_EBC_FILE:?}"))?;
unsafe { set_off_screen(driver_file.as_raw_fd(), &set_off_screen_data) }
.wrap_err("ioctl error")?;
Ok(())
}
fn read_file(path: &Path) -> eyre::Result<Vec<u8>> {
let mut file = File::open(path)?;
let mut buf = vec![0u8; FILE_SIZE];
file.read_exact(&mut buf[..])
.wrap_err_with(|| eyre!("Expected a raw image file, of exactly {FILE_SIZE} bytes"))?;
// Try to read a single byte. If n != 0, it means the file was larger than FILE_SIZE
let n = file.read(&mut [0u8])?;
ensure!(n == 0, "File must be exacly {FILE_SIZE} bytes long");
Ok(buf)
}