From 76b0c7eeeab0ca202addd3afb869ec444d935748 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 22 Sep 2016 10:10:27 -0600 Subject: [PATCH] Add wnohang, make PS/2 driver write input to display scheme, which then passes it to the shell --- Makefile | 6 +- arch/x86_64/src/paging/mapper.rs | 2 +- drivers/ps2d/src/keyboard.rs | 21 ++++-- drivers/ps2d/src/keymap.rs | 126 ++++++++++++++++--------------- drivers/vesad/src/main.rs | 70 ++++++++++++----- kernel/syscall/process.rs | 6 +- libstd | 2 +- programs/login/src/main.rs | 12 +-- syscall/src/flag.rs | 2 + 9 files changed, 151 insertions(+), 96 deletions(-) diff --git a/Makefile b/Makefile index 24a5cf8..60ee62d 100644 --- a/Makefile +++ b/Makefile @@ -24,12 +24,12 @@ all: $(KBUILD)/harddrive.bin clean: cargo clean cargo clean --manifest-path libstd/Cargo.toml - cargo clean --manifest-path init/Cargo.toml - cargo clean --manifest-path ion/Cargo.toml - cargo clean --manifest-path login/Cargo.toml cargo clean --manifest-path drivers/ps2d/Cargo.toml cargo clean --manifest-path drivers/pcid/Cargo.toml cargo clean --manifest-path drivers/vesad/Cargo.toml + cargo clean --manifest-path programs/init/Cargo.toml + cargo clean --manifest-path programs/ion/Cargo.toml + cargo clean --manifest-path programs/login/Cargo.toml cargo clean --manifest-path schemes/example/Cargo.toml rm -rf initfs/bin rm -rf build diff --git a/arch/x86_64/src/paging/mapper.rs b/arch/x86_64/src/paging/mapper.rs index 819efa9..cb4eccd 100644 --- a/arch/x86_64/src/paging/mapper.rs +++ b/arch/x86_64/src/paging/mapper.rs @@ -42,7 +42,7 @@ impl Mapper { /// Map a page to the next free frame pub fn map(&mut self, page: Page, flags: EntryFlags) { - let frame = allocate_frame().expect("out of memory"); + let frame = allocate_frame().expect("out of frames"); self.map_to(page, frame, flags) } diff --git a/drivers/ps2d/src/keyboard.rs b/drivers/ps2d/src/keyboard.rs index b0090a3..ec47030 100644 --- a/drivers/ps2d/src/keyboard.rs +++ b/drivers/ps2d/src/keyboard.rs @@ -5,9 +5,12 @@ use std::thread; use keymap; -pub fn keyboard() { +pub fn keyboard() { let mut file = File::open("irq:1").expect("ps2d: failed to open irq:1"); + let mut input = File::open("display:input").expect("ps2d: failed to open display:input"); + let mut lshift = false; + let mut rshift = false; loop { let mut irqs = [0; 8]; if file.read(&mut irqs).expect("ps2d: failed to read irq:1") >= mem::size_of::() { @@ -16,17 +19,25 @@ pub fn keyboard() { asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); } + file.write(&irqs).expect("ps2d: failed to write irq:1"); + let (scancode, pressed) = if data >= 0x80 { (data - 0x80, false) } else { (data, true) }; - if pressed { - print!("{}", keymap::get_char(scancode)); + if scancode == 0x2A { + lshift = pressed; + } else if scancode == 0x36 { + rshift = pressed; + } else if pressed { + let c = keymap::get_char(scancode, lshift || rshift); + if c != '\0' { + print!("{}", c); + input.write(&[c as u8]).expect("ps2d: failed to write input"); + } } - - file.write(&irqs).expect("ps2d: failed to write irq:1"); } else { thread::yield_now(); } diff --git a/drivers/ps2d/src/keymap.rs b/drivers/ps2d/src/keymap.rs index 699e3ad..0f7f634 100644 --- a/drivers/ps2d/src/keymap.rs +++ b/drivers/ps2d/src/keymap.rs @@ -1,67 +1,71 @@ -static ENGLISH: [[char; 3]; 58] = [ - ['\0', '\0', '\0'], - ['\x1B', '\x1B', '\x1B'], - ['1', '!', '1'], - ['2', '@', '2'], - ['3', '#', '3'], - ['4', '$', '4'], - ['5', '%', '5'], - ['6', '^', '6'], - ['7', '&', '7'], - ['8', '*', '8'], - ['9', '(', '9'], - ['0', ')', '0'], - ['-', '_', '-'], - ['=', '+', '='], - ['\0', '\0', '\0'], - ['\t', '\t', '\t'], - ['q', 'Q', 'q'], - ['w', 'W', 'w'], - ['e', 'E', 'e'], - ['r', 'R', 'r'], - ['t', 'T', 't'], - ['y', 'Y', 'y'], - ['u', 'U', 'u'], - ['i', 'I', 'i'], - ['o', 'O', 'o'], - ['p', 'P', 'p'], - ['[', '{', '['], - [']', '}', ']'], - ['\n', '\n', '\n'], - ['\0', '\0', '\0'], - ['a', 'A', 'a'], - ['s', 'S', 's'], - ['d', 'D', 'd'], - ['f', 'F', 'f'], - ['g', 'G', 'g'], - ['h', 'H', 'h'], - ['j', 'J', 'j'], - ['k', 'K', 'k'], - ['l', 'L', 'l'], - [';', ':', ';'], - ['\'', '"', '\''], - ['`', '~', '`'], - ['\0', '\0', '\0'], - ['\\', '|', '\\'], - ['z', 'Z', 'z'], - ['x', 'X', 'x'], - ['c', 'C', 'c'], - ['v', 'V', 'v'], - ['b', 'B', 'b'], - ['n', 'N', 'n'], - ['m', 'M', 'm'], - [',', '<', ','], - ['.', '>', '.'], - ['/', '?', '/'], - ['\0', '\0', '\0'], - ['\0', '\0', '\0'], - ['\0', '\0', '\0'], - [' ', ' ', ' '] +static ENGLISH: [[char; 2]; 58] = [ + ['\0', '\0'], + ['\x1B', '\x1B'], + ['1', '!'], + ['2', '@'], + ['3', '#'], + ['4', '$'], + ['5', '%'], + ['6', '^'], + ['7', '&'], + ['8', '*'], + ['9', '('], + ['0', ')'], + ['-', '_'], + ['=', '+'], + ['\x7F', '\x7F'], + ['\t', '\t'], + ['q', 'Q'], + ['w', 'W'], + ['e', 'E'], + ['r', 'R'], + ['t', 'T'], + ['y', 'Y'], + ['u', 'U'], + ['i', 'I'], + ['o', 'O'], + ['p', 'P'], + ['[', '{'], + [']', '}'], + ['\n', '\n'], + ['\0', '\0'], + ['a', 'A'], + ['s', 'S'], + ['d', 'D'], + ['f', 'F'], + ['g', 'G'], + ['h', 'H'], + ['j', 'J'], + ['k', 'K'], + ['l', 'L'], + [';', ':'], + ['\'', '"'], + ['`', '~'], + ['\0', '\0'], + ['\\', '|'], + ['z', 'Z'], + ['x', 'X'], + ['c', 'C'], + ['v', 'V'], + ['b', 'B'], + ['n', 'N'], + ['m', 'M'], + [',', '<'], + ['.', '>'], + ['/', '?'], + ['\0', '\0'], + ['\0', '\0'], + ['\0', '\0'], + [' ', ' '] ]; -pub fn get_char(scancode: u8) -> char { +pub fn get_char(scancode: u8, shift: bool) -> char { if let Some(c) = ENGLISH.get(scancode as usize) { - c[0] + if shift { + c[1] + } else { + c[0] + } } else { '\0' } diff --git a/drivers/vesad/src/main.rs b/drivers/vesad/src/main.rs index 7cbed6e..9e0aef9 100644 --- a/drivers/vesad/src/main.rs +++ b/drivers/vesad/src/main.rs @@ -8,6 +8,7 @@ extern crate ransid; extern crate syscall; use std::cell::RefCell; +use std::collections::VecDeque; use std::fs::File; use std::io::{Read, Write}; use std::{slice, thread}; @@ -24,32 +25,55 @@ pub mod primitive; struct DisplayScheme { console: RefCell, - display: RefCell + display: RefCell, + input: RefCell> } impl Scheme for DisplayScheme { - fn open(&self, _path: &[u8], _flags: usize) -> Result { - Ok(0) + fn open(&self, path: &[u8], _flags: usize) -> Result { + if path == b"input" { + Ok(1) + } else { + Ok(0) + } } - fn dup(&self, _id: usize) -> Result { - Ok(0) + fn dup(&self, id: usize) -> Result { + Ok(id) } fn fsync(&self, _id: usize) -> Result { Ok(0) } - fn write(&self, _id: usize, buf: &[u8]) -> Result { - let mut display = self.display.borrow_mut(); - self.console.borrow_mut().write(buf, |event| { - match event { - Event::Char { x, y, c, color, .. } => display.char(x * 8, y * 16, c, color.data), - Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data), - Event::Scroll { rows, color } => display.scroll(rows * 16, color.data) + fn read(&self, _id: usize, buf: &mut [u8]) -> Result { + let mut i = 0; + let mut input = self.input.borrow_mut(); + while i < buf.len() && ! input.is_empty() { + buf[i] = input.pop_front().unwrap(); + i += 1; + } + Ok(i) + } + + fn write(&self, id: usize, buf: &[u8]) -> Result { + if id == 1 { + let mut input = self.input.borrow_mut(); + for &b in buf.iter() { + input.push_back(b); } - }); - Ok(buf.len()) + Ok(buf.len()) + } else { + let mut display = self.display.borrow_mut(); + self.console.borrow_mut().write(buf, |event| { + match event { + Event::Char { x, y, c, color, .. } => display.char(x * 8, y * 16, c, color.data), + Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data), + Event::Scroll { rows, color } => display.scroll(rows * 16, color.data) + } + }); + Ok(buf.len()) + } } fn close(&self, _id: usize) -> Result { @@ -89,15 +113,27 @@ fn main() { display: RefCell::new(Display::new(width, height, unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } - )) + )), + input: RefCell::new(VecDeque::new()) }; + let mut blocked = VecDeque::new(); loop { let mut packet = Packet::default(); socket.read(&mut packet).expect("vesad: failed to read display scheme"); //println!("vesad: {:?}", packet); - scheme.handle(&mut packet); - socket.write(&packet).expect("vesad: failed to write display scheme"); + if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() { + blocked.push_back(packet); + } else { + scheme.handle(&mut packet); + socket.write(&packet).expect("vesad: failed to write display scheme"); + } + while ! scheme.input.borrow().is_empty() { + if let Some(mut packet) = blocked.pop_front() { + scheme.handle(&mut packet); + socket.write(&packet).expect("vesad: failed to write display scheme"); + } + } } }); } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 34d5751..b38aee6 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -18,7 +18,7 @@ use elf::{self, program_header}; use scheme; use syscall; use syscall::error::*; -use syscall::flag::{CLONE_VM, CLONE_FS, CLONE_FILES, MAP_WRITE, MAP_WRITE_COMBINE}; +use syscall::flag::{CLONE_VM, CLONE_FS, CLONE_FILES, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -594,7 +594,7 @@ pub fn sched_yield() -> Result { Ok(0) } -pub fn waitpid(pid: usize, status_ptr: usize, _options: usize) -> Result { +pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result { //TODO: Implement status_ptr and options loop { { @@ -616,6 +616,8 @@ pub fn waitpid(pid: usize, status_ptr: usize, _options: usize) -> Result if exited { let mut contexts = context::contexts_mut(); return contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid)); + } else if flags & WNOHANG == WNOHANG { + return Ok(0); } } diff --git a/libstd b/libstd index ae80aff..a5a6e9f 160000 --- a/libstd +++ b/libstd @@ -1 +1 @@ -Subproject commit ae80aff4d39b2d3a83f7d32bc95739e4e1169184 +Subproject commit a5a6e9fe349d80918d6fc233d23530c4bf3b4f96 diff --git a/programs/login/src/main.rs b/programs/login/src/main.rs index 043c0af..b885a6b 100644 --- a/programs/login/src/main.rs +++ b/programs/login/src/main.rs @@ -11,13 +11,13 @@ pub fn main() { let sh = args.next().expect("login: no sh provided"); let sh_args: Vec = args.collect(); - syscall::close(2); - syscall::close(1); - syscall::close(0); + let _ = syscall::close(2); + let _ = syscall::close(1); + let _ = syscall::close(0); - syscall::open(&tty, syscall::flag::O_RDWR); - syscall::open(&tty, syscall::flag::O_RDWR); - syscall::open(&tty, syscall::flag::O_RDWR); + let _ = syscall::open(&tty, syscall::flag::O_RDWR); + let _ = syscall::open(&tty, syscall::flag::O_RDWR); + let _ = syscall::open(&tty, syscall::flag::O_RDWR); thread::spawn(move || { loop { diff --git a/syscall/src/flag.rs b/syscall/src/flag.rs index 5351384..52db74c 100644 --- a/syscall/src/flag.rs +++ b/syscall/src/flag.rs @@ -41,3 +41,5 @@ pub const O_FSYNC: usize = 0x80; pub const O_CREAT: usize = 0x200; pub const O_TRUNC: usize = 0x400; pub const O_EXCL: usize = 0x800; + +pub const WNOHANG: usize = 1;