use std::io::{stdin, Read, Write}; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::{cell::RefCell, convert::Infallible, fs::File, process::Command, time::Duration}; use embedded_graphics_core::{pixelcolor::Rgb888, prelude::*}; use embedded_graphics_simulator::{ OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; use embedded_term::Console; use libc::{self, winsize}; use mio::{unix::EventedFd, Events, Poll, PollOpt, Ready, Token}; use pty::fork::Fork; use termios::{cfmakeraw, tcsetattr, Termios, TCSANOW}; const DISPLAY_SIZE: Size = Size::new(800, 600); fn main() { let fork = Fork::from_ptmx().unwrap(); if let Ok(mut master) = fork.is_parent() { env_logger::init(); let display = SimulatorDisplay::::new(DISPLAY_SIZE); let display = RefCell::new(display); let mut console = Console::on_frame_buffer(DisplayWrapper(&display)); let poll = Poll::new().unwrap(); poll.register( &EventedFd(&master.as_raw_fd()), Token(0), Ready::readable(), PollOpt::edge(), ) .unwrap(); // set to raw mode let fd = stdin().as_raw_fd(); let mut termios = Termios::from_fd(fd).unwrap(); cfmakeraw(&mut termios); tcsetattr(fd, TCSANOW, &termios).unwrap(); let ws = winsize { ws_row: console.rows() as libc::c_ushort, ws_col: console.columns() as libc::c_ushort, ws_xpixel: DISPLAY_SIZE.width as libc::c_ushort, ws_ypixel: DISPLAY_SIZE.height as libc::c_ushort, }; let res = unsafe { libc::ioctl(master.as_raw_fd(), libc::TIOCSWINSZ, &ws as *const _) }; if res < 0 { panic!( "ioctl TIOCSWINSZ failed: {}", std::io::Error::last_os_error() ); } let mut stdin = unsafe { File::from_raw_fd(fd) }; poll.register( &EventedFd(&fd), Token(1), Ready::readable(), PollOpt::edge(), ) .unwrap(); let mut events = Events::with_capacity(1024); let output_settings = OutputSettingsBuilder::new().build(); let mut window = Window::new("Example", &output_settings); loop { poll.poll(&mut events, Some(Duration::from_millis(10))) .unwrap(); let mut buffer = [0u8; 10240]; for event in events.iter() { match event.token() { Token(0) => { let len = master.read(&mut buffer).unwrap(); for c in &buffer[..len] { console.write_byte(*c); } } Token(1) => { let len = stdin.read(&mut buffer).unwrap(); master.write_all(&buffer[..len]).unwrap(); } _ => unreachable!(), } } while let Some(byte) = console.pop_report() { master.write_all(&[byte]).unwrap(); } window.update(&display.borrow_mut()); if window.events().any(|e| e == SimulatorEvent::Quit) { break; } } } else { let mut args = std::env::args_os(); args.next(); // skip myself let name = args.next().unwrap(); Command::new(name) .args(args) .status() .expect("could not execute program"); } } struct DisplayWrapper<'a>(&'a RefCell>); impl DrawTarget for DisplayWrapper<'_> { type Color = Rgb888; type Error = Infallible; fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> where I: IntoIterator>, { self.0.borrow_mut().draw_iter(pixels) } } impl OriginDimensions for DisplayWrapper<'_> { fn size(&self) -> Size { self.0.borrow().size() } }