2016-09-21 05:52:45 +02:00
|
|
|
#![feature(alloc)]
|
|
|
|
#![feature(asm)]
|
|
|
|
#![feature(heap_api)]
|
2016-09-21 20:18:48 +02:00
|
|
|
#![feature(question_mark)]
|
2016-09-21 05:52:45 +02:00
|
|
|
|
|
|
|
extern crate alloc;
|
2016-09-21 20:18:48 +02:00
|
|
|
extern crate ransid;
|
2016-09-21 05:52:45 +02:00
|
|
|
extern crate syscall;
|
|
|
|
|
2016-09-21 20:18:48 +02:00
|
|
|
use std::cell::RefCell;
|
2016-09-29 21:17:19 +02:00
|
|
|
use std::collections::{BTreeSet, VecDeque};
|
2016-09-21 05:52:45 +02:00
|
|
|
use std::fs::File;
|
2016-09-21 20:18:48 +02:00
|
|
|
use std::io::{Read, Write};
|
2016-09-22 16:43:22 +02:00
|
|
|
use std::{slice, thread};
|
2016-09-21 20:18:48 +02:00
|
|
|
use ransid::{Console, Event};
|
2016-09-24 01:54:39 +02:00
|
|
|
use syscall::{physmap, physunmap, Packet, Result, Scheme, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE};
|
2016-09-21 05:52:45 +02:00
|
|
|
|
|
|
|
use display::Display;
|
|
|
|
use mode_info::VBEModeInfo;
|
2016-09-22 16:43:22 +02:00
|
|
|
use primitive::fast_set64;
|
2016-09-21 05:52:45 +02:00
|
|
|
|
|
|
|
pub mod display;
|
|
|
|
pub mod mode_info;
|
|
|
|
pub mod primitive;
|
|
|
|
|
2016-09-21 20:18:48 +02:00
|
|
|
struct DisplayScheme {
|
|
|
|
console: RefCell<Console>,
|
2016-09-22 18:10:27 +02:00
|
|
|
display: RefCell<Display>,
|
2016-09-29 21:17:19 +02:00
|
|
|
changed: RefCell<BTreeSet<usize>>,
|
2016-09-24 01:54:39 +02:00
|
|
|
input: RefCell<VecDeque<u8>>,
|
2016-09-28 23:17:37 +02:00
|
|
|
cooked: RefCell<VecDeque<u8>>,
|
2016-09-24 01:54:39 +02:00
|
|
|
requested: RefCell<usize>
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
|
|
|
|
2016-09-29 21:17:19 +02:00
|
|
|
impl DisplayScheme {
|
|
|
|
fn event(&self, event: Event) {
|
|
|
|
let mut display = self.display.borrow_mut();
|
|
|
|
let mut changed = self.changed.borrow_mut();
|
|
|
|
|
|
|
|
match event {
|
|
|
|
Event::Char { x, y, c, color, bold, .. } => {
|
|
|
|
display.char(x * 8, y * 16, c, color.data, bold, false);
|
|
|
|
changed.insert(y);
|
|
|
|
},
|
|
|
|
Event::Rect { x, y, w, h, color } => {
|
|
|
|
display.rect(x * 8, y * 16, w * 8, h * 16, color.data);
|
|
|
|
for y2 in y..y + h {
|
|
|
|
changed.insert(y2);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Event::Scroll { rows, color } => {
|
|
|
|
display.scroll(rows * 16, color.data);
|
|
|
|
for y in 0..display.height/16 {
|
|
|
|
changed.insert(y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn sync(&self) {
|
|
|
|
let mut display = self.display.borrow_mut();
|
|
|
|
let mut changed = self.changed.borrow_mut();
|
|
|
|
|
|
|
|
let width = display.width;
|
|
|
|
for change in changed.iter() {
|
|
|
|
display.sync(0, change * 16, width, 16);
|
|
|
|
}
|
|
|
|
changed.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-21 20:18:48 +02:00
|
|
|
impl Scheme for DisplayScheme {
|
2016-09-22 18:10:27 +02:00
|
|
|
fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
|
|
|
|
if path == b"input" {
|
|
|
|
Ok(1)
|
|
|
|
} else {
|
|
|
|
Ok(0)
|
|
|
|
}
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
|
|
|
|
2016-09-22 18:10:27 +02:00
|
|
|
fn dup(&self, id: usize) -> Result<usize> {
|
|
|
|
Ok(id)
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 23:47:53 +02:00
|
|
|
fn fevent(&self, _id: usize, flags: usize) -> Result<usize> {
|
2016-09-24 01:54:39 +02:00
|
|
|
*self.requested.borrow_mut() = flags;
|
2016-09-23 23:47:53 +02:00
|
|
|
println!("fevent {:X}", flags);
|
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
|
2016-09-29 21:17:19 +02:00
|
|
|
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
|
|
|
let path_str = if id == 1 {
|
|
|
|
format!("display:input")
|
|
|
|
} else {
|
|
|
|
let console = self.console.borrow();
|
|
|
|
format!("display:{}/{}", console.w, console.h)
|
|
|
|
};
|
|
|
|
|
|
|
|
let path = path_str.as_bytes();
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
while i < buf.len() && i < path.len() {
|
|
|
|
buf[i] = path[i];
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fsync(&self, id: usize) -> Result<usize> {
|
|
|
|
if id == 1 {
|
|
|
|
|
|
|
|
} else {
|
|
|
|
self.sync();
|
|
|
|
}
|
|
|
|
|
2016-09-22 16:43:22 +02:00
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
|
2016-09-22 18:10:27 +02:00
|
|
|
fn read(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
|
|
|
|
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<usize> {
|
|
|
|
if id == 1 {
|
2016-09-28 23:17:37 +02:00
|
|
|
if self.console.borrow().raw_mode {
|
|
|
|
for &b in buf.iter() {
|
|
|
|
self.input.borrow_mut().push_back(b);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for &b in buf.iter() {
|
|
|
|
match b {
|
|
|
|
b'\x08' | b'\x7F' => {
|
2016-09-29 21:17:19 +02:00
|
|
|
if let Some(_c) = self.cooked.borrow_mut().pop_back() {
|
2016-09-28 23:17:37 +02:00
|
|
|
self.write(0, b"\x08")?;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
b'\n' | b'\r' => {
|
|
|
|
self.cooked.borrow_mut().push_back(b);
|
|
|
|
while let Some(c) = self.cooked.borrow_mut().pop_front() {
|
|
|
|
self.input.borrow_mut().push_back(c);
|
|
|
|
}
|
|
|
|
self.write(0, b"\n")?;
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
self.cooked.borrow_mut().push_back(b);
|
|
|
|
self.write(0, &[b])?;
|
|
|
|
}
|
2016-09-28 23:04:15 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
2016-09-22 18:10:27 +02:00
|
|
|
Ok(buf.len())
|
|
|
|
} else {
|
2016-09-23 01:11:42 +02:00
|
|
|
let mut console = self.console.borrow_mut();
|
2016-09-28 20:19:30 +02:00
|
|
|
if console.cursor && console.x < console.w && console.y < console.h {
|
2016-09-29 21:17:19 +02:00
|
|
|
self.event(Event::Rect {
|
|
|
|
x: console.x,
|
|
|
|
y: console.y,
|
|
|
|
w: 1,
|
|
|
|
h: 1,
|
|
|
|
color: console.background
|
|
|
|
});
|
2016-09-23 01:11:42 +02:00
|
|
|
}
|
|
|
|
console.write(buf, |event| {
|
2016-09-29 21:17:19 +02:00
|
|
|
self.event(event);
|
2016-09-22 18:10:27 +02:00
|
|
|
});
|
2016-09-28 20:19:30 +02:00
|
|
|
if console.cursor && console.x < console.w && console.y < console.h {
|
2016-09-29 21:17:19 +02:00
|
|
|
self.event(Event::Rect {
|
|
|
|
x: console.x,
|
|
|
|
y: console.y,
|
|
|
|
w: 1,
|
|
|
|
h: 1,
|
|
|
|
color: console.foreground
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if ! console.raw_mode {
|
|
|
|
self.sync();
|
2016-09-23 01:11:42 +02:00
|
|
|
}
|
2016-09-22 18:10:27 +02:00
|
|
|
Ok(buf.len())
|
|
|
|
}
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
|
|
|
|
2016-09-22 16:43:22 +02:00
|
|
|
fn close(&self, _id: usize) -> Result<usize> {
|
2016-09-21 20:18:48 +02:00
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-21 05:52:45 +02:00
|
|
|
fn main() {
|
|
|
|
let width;
|
|
|
|
let height;
|
|
|
|
let physbaseptr;
|
|
|
|
|
|
|
|
{
|
|
|
|
let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) };
|
|
|
|
|
|
|
|
width = mode_info.xresolution as usize;
|
|
|
|
height = mode_info.yresolution as usize;
|
|
|
|
physbaseptr = mode_info.physbaseptr as usize;
|
|
|
|
|
|
|
|
unsafe { let _ = physunmap(mode_info as *const _ as usize); }
|
|
|
|
}
|
|
|
|
|
|
|
|
if physbaseptr > 0 {
|
|
|
|
thread::spawn(move || {
|
2016-09-21 05:56:40 +02:00
|
|
|
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
|
2016-09-21 20:18:48 +02:00
|
|
|
|
2016-09-21 05:52:45 +02:00
|
|
|
let size = width * height;
|
|
|
|
|
|
|
|
let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
|
|
|
|
unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };
|
|
|
|
|
|
|
|
let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
|
|
|
|
unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
|
|
|
|
|
2016-09-21 20:18:48 +02:00
|
|
|
let scheme = DisplayScheme {
|
|
|
|
console: RefCell::new(Console::new(width/8, height/16)),
|
|
|
|
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) }
|
2016-09-22 18:10:27 +02:00
|
|
|
)),
|
2016-09-29 21:17:19 +02:00
|
|
|
changed: RefCell::new(BTreeSet::new()),
|
2016-09-24 01:54:39 +02:00
|
|
|
input: RefCell::new(VecDeque::new()),
|
2016-09-28 23:17:37 +02:00
|
|
|
cooked: RefCell::new(VecDeque::new()),
|
2016-09-24 01:54:39 +02:00
|
|
|
requested: RefCell::new(0)
|
2016-09-21 20:18:48 +02:00
|
|
|
};
|
2016-09-21 05:52:45 +02:00
|
|
|
|
2016-09-22 18:10:27 +02:00
|
|
|
let mut blocked = VecDeque::new();
|
2016-09-21 20:18:48 +02:00
|
|
|
loop {
|
|
|
|
let mut packet = Packet::default();
|
2016-09-22 16:43:22 +02:00
|
|
|
socket.read(&mut packet).expect("vesad: failed to read display scheme");
|
2016-09-21 20:18:48 +02:00
|
|
|
//println!("vesad: {:?}", packet);
|
2016-09-24 01:54:39 +02:00
|
|
|
|
|
|
|
// If it is a read packet, and there is no data, block it. Otherwise, handle packet
|
2016-09-22 18:10:27 +02:00
|
|
|
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");
|
|
|
|
}
|
2016-09-24 01:54:39 +02:00
|
|
|
|
|
|
|
// If there are blocked readers, and data is available, handle them
|
2016-09-22 18:10:27 +02:00
|
|
|
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");
|
2016-09-24 01:54:39 +02:00
|
|
|
} else {
|
|
|
|
break;
|
2016-09-22 18:10:27 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-24 01:54:39 +02:00
|
|
|
|
|
|
|
// If there are requested events, and data is available, send a notification
|
|
|
|
if ! scheme.input.borrow().is_empty() && *scheme.requested.borrow() & EVENT_READ == EVENT_READ {
|
|
|
|
let event_packet = Packet {
|
|
|
|
id: 0,
|
|
|
|
a: syscall::number::SYS_FEVENT,
|
|
|
|
b: 0,
|
|
|
|
c: EVENT_READ,
|
|
|
|
d: scheme.input.borrow().len()
|
|
|
|
};
|
|
|
|
socket.write(&event_packet).expect("vesad: failed to write display scheme");
|
|
|
|
}
|
2016-09-21 20:18:48 +02:00
|
|
|
}
|
2016-09-21 05:52:45 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|