use std::{
fs::{File, OpenOptions},
io::{Read, Write},
os::fd::AsFd,
path::Path,
};
use nix::poll::{PollFd, PollFlags, PollTimeout, poll};
use tracing::debug;
use super::{PrinterConnection, printer_connection::sealed::ConnectionImpl};
use crate::error::KernelError;
pub struct KernelConnection {
handle: File,
}
impl KernelConnection {
pub fn open<P>(path: P) -> Result<Self, KernelError>
where
P: AsRef<Path>,
{
debug!("Opening kernel connection to the printer...");
let handle = OpenOptions::new().read(true).write(true).open(path)?;
debug!("Successfully opened kernel device!");
Ok(Self { handle })
}
}
impl PrinterConnection for KernelConnection {}
impl ConnectionImpl for KernelConnection {
type Error = KernelError;
fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
let bytes_written = self.handle.write(data)?;
if bytes_written != data.len() {
return Err(KernelError::IncompleteWrite);
}
Ok(())
}
fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
let mut pollfds = [PollFd::new(self.handle.as_fd(), PollFlags::POLLIN)];
let nready = poll(&mut pollfds, PollTimeout::ZERO).unwrap_or(0);
if nready == 0 {
return Ok(0);
}
let bytes_read = self.handle.read(buffer)?;
Ok(bytes_read)
}
}