#![allow(non_camel_case_types)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
use std::default::Default;
use std::os::unix::io::AsRawFd;
#[derive(Debug)]
pub struct ErrnoError {
pub errno: i32,
pub message: String,
}
impl ErrnoError {
fn new() -> Self {
let errno = unsafe { *libc::__errno_location() };
let message_c = unsafe { std::ffi::CStr::from_ptr(libc::strerror(errno)) };
let message = String::from(message_c.to_str().unwrap());
Self { errno, message }
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct PixelLayoutChannel {
pub offset: u32,
pub length: u32,
pub msb_right: bool,
}
impl From<fb_bitfield> for PixelLayoutChannel {
fn from(bitfield: fb_bitfield) -> Self {
Self {
offset: bitfield.offset,
length: bitfield.length,
msb_right: bitfield.msb_right != 0,
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct PixelLayout {
pub red: PixelLayoutChannel,
pub green: PixelLayoutChannel,
pub blue: PixelLayoutChannel,
pub alpha: PixelLayoutChannel,
}
#[derive(Default, Clone)]
pub struct VarScreeninfo {
internal: fb_var_screeninfo,
}
impl VarScreeninfo {
pub fn size_in_pixels(&self) -> (u32, u32) {
(self.internal.xres, self.internal.yres)
}
pub fn size_in_mm(&self) -> (u32, u32) {
(self.internal.width, self.internal.height)
}
pub fn bytes_per_pixel(&self) -> u32 {
self.internal.bits_per_pixel / 8
}
pub fn pixel_layout(&self) -> PixelLayout {
PixelLayout {
red: PixelLayoutChannel::from(self.internal.red),
green: PixelLayoutChannel::from(self.internal.green),
blue: PixelLayoutChannel::from(self.internal.blue),
alpha: PixelLayoutChannel::from(self.internal.transp),
}
}
pub fn set_bytes_per_pixel(&mut self, value: u32) {
self.internal.bits_per_pixel = value * 8;
}
pub fn virtual_size(&self) -> (u32, u32) {
(self.internal.xres_virtual, self.internal.yres_virtual)
}
pub fn set_virtual_size(&mut self, width: u32, height: u32) {
self.internal.xres_virtual = width;
self.internal.yres_virtual = height;
}
pub fn offset(&self) -> (u32, u32) {
(self.internal.xoffset, self.internal.yoffset)
}
pub fn set_offset(&mut self, x: u32, y: u32) {
self.internal.xoffset = x;
self.internal.yoffset = y;
}
pub fn activate_now(&mut self) {
self.internal.activate = FB_ACTIVATE_NOW;
}
}
#[derive(Default, Clone)]
pub struct FixScreeninfo {
internal: fb_fix_screeninfo,
}
impl FixScreeninfo {
pub fn id(&self) -> String {
let c_string = unsafe { std::ffi::CStr::from_ptr(self.internal.id.as_ptr()) };
String::from(c_string.to_str().unwrap())
}
}
pub fn get_vscreeninfo(file: &impl AsRawFd) -> Result<VarScreeninfo, ErrnoError> {
let mut vinfo: fb_var_screeninfo = Default::default();
match unsafe {
libc::ioctl(file.as_raw_fd(), FBIOGET_VSCREENINFO as _, &mut vinfo)
} {
-1 => Err(ErrnoError::new()),
_ => Ok(VarScreeninfo { internal: vinfo })
}
}
pub fn put_vscreeninfo(file: &impl AsRawFd, var_screeninfo: &mut VarScreeninfo) -> Result<(), ErrnoError> {
let mut vinfo = var_screeninfo.internal;
match unsafe {
libc::ioctl(file.as_raw_fd(), FBIOPUT_VSCREENINFO as _, &mut vinfo)
} {
-1 => Err(ErrnoError::new()),
_ => Ok(())
}
}
pub fn get_fscreeninfo(file: &impl AsRawFd) -> Result<FixScreeninfo, ErrnoError> {
let mut finfo: fb_fix_screeninfo = Default::default();
match unsafe {
libc::ioctl(file.as_raw_fd(), FBIOGET_FSCREENINFO as _, &mut finfo)
} {
-1 => Err(ErrnoError::new()),
_ => Ok(FixScreeninfo { internal: finfo })
}
}
#[derive(Debug, Clone)]
pub enum BlankingLevel {
Unblank,
Normal,
VsyncSuspend,
HsyncSuspend,
Powerdown,
}
impl BlankingLevel {
fn to_ulong(&self) -> std::os::raw::c_ulong {
match self {
BlankingLevel::Unblank => FB_BLANK_UNBLANK,
BlankingLevel::Normal => FB_BLANK_NORMAL,
BlankingLevel::VsyncSuspend => FB_BLANK_VSYNC_SUSPEND,
BlankingLevel::HsyncSuspend => FB_BLANK_HSYNC_SUSPEND,
BlankingLevel::Powerdown => FB_BLANK_POWERDOWN,
}.into()
}
}
pub fn blank(file: &impl AsRawFd, level: BlankingLevel) -> Result<(), ErrnoError> {
match unsafe {
libc::ioctl(file.as_raw_fd(), FBIOBLANK as _, level.to_ulong())
} {
-1 => Err(ErrnoError::new()),
_ => Ok(())
}
}
#[derive(Copy, Clone)]
pub enum TerminalMode {
Text,
Graphics,
}
impl TerminalMode {
fn to_ulong(&self) -> std::os::raw::c_ulong {
match self {
TerminalMode::Text => KD_TEXT,
TerminalMode::Graphics => KD_GRAPHICS,
}.into()
}
}
pub fn set_terminal_mode(tty: &impl AsRawFd, mode: TerminalMode) -> Result<(), ErrnoError> {
match unsafe {
libc::ioctl(tty.as_raw_fd(), KDSETMODE as _, mode.to_ulong())
} {
-1 => Err(ErrnoError::new()),
_ => Ok(())
}
}