Skip to content

Commit a5028f7

Browse files
Move commands into own modules.
1 parent 5f01d19 commit a5028f7

File tree

6 files changed

+318
-292
lines changed

6 files changed

+318
-292
lines changed

src/commands/config.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! Configuration related commands for Neotron OS
2+
3+
use crate::{config, println, Ctx};
4+
5+
/// Called when the "config" command is executed.
6+
pub fn command(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &mut Ctx) {
7+
let command = args.get(0).cloned().unwrap_or("print");
8+
match command {
9+
"reset" => match config::Config::load() {
10+
Ok(new_config) => {
11+
ctx.config = new_config;
12+
println!("Loaded OK.");
13+
}
14+
Err(e) => {
15+
println!("Error loading; {}", e);
16+
}
17+
},
18+
"save" => match ctx.config.save() {
19+
Ok(_) => {
20+
println!("Saved OK.");
21+
}
22+
Err(e) => {
23+
println!("Error saving: {}", e);
24+
}
25+
},
26+
"vga" => match args.get(1).cloned() {
27+
Some("on") => {
28+
ctx.config.set_vga_console(true);
29+
println!("VGA now on");
30+
}
31+
Some("off") => {
32+
ctx.config.set_vga_console(false);
33+
println!("VGA now off");
34+
}
35+
_ => {
36+
println!("Give on or off as argument");
37+
}
38+
},
39+
"serial" => match (args.get(1).cloned(), args.get(1).map(|s| s.parse::<u32>())) {
40+
(_, Some(Ok(baud))) => {
41+
println!("Turning serial console on at {} bps", baud);
42+
ctx.config.set_serial_console_on(baud);
43+
}
44+
(Some("off"), _) => {
45+
println!("Turning serial console off");
46+
ctx.config.set_serial_console_off();
47+
}
48+
_ => {
49+
println!("Give off or an integer as argument");
50+
}
51+
},
52+
"print" => {
53+
println!("VGA : {}", ctx.config.get_vga_console());
54+
match ctx.config.get_serial_console() {
55+
None => {
56+
println!("Serial: off");
57+
}
58+
Some((_port, config)) => {
59+
println!("Serial: {} bps", config.data_rate_bps);
60+
}
61+
}
62+
}
63+
_ => {
64+
println!("config print - print the config");
65+
println!("config help - print this help text");
66+
println!("config reset - load config from BIOS store");
67+
println!("config save - save config to BIOS store");
68+
println!("config vga on - turn VGA on");
69+
println!("config vga off - turn VGA off");
70+
println!("config serial off - turn serial console off");
71+
println!("config serial <baud> - turn serial console on with given baud rate");
72+
}
73+
}
74+
}

src/commands/hardware.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! Hardware related commands for Neotron OS
2+
3+
use crate::{bios, println, Ctx, API};
4+
5+
/// Called when the "lshw" command is executed.
6+
pub fn lshw(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
7+
let api = API.get();
8+
let mut found = false;
9+
10+
println!("Memory regions:");
11+
for region_idx in 0..=255u8 {
12+
if let bios::Option::Some(region) = (api.memory_get_region)(region_idx) {
13+
println!(" {}: {}", region_idx, region);
14+
found = true;
15+
}
16+
}
17+
if !found {
18+
println!(" None");
19+
}
20+
21+
println!();
22+
found = false;
23+
24+
println!("Serial Devices:");
25+
for dev_idx in 0..=255u8 {
26+
if let bios::Option::Some(device_info) = (api.serial_get_info)(dev_idx) {
27+
println!(" {}: {:?}", dev_idx, device_info);
28+
found = true;
29+
}
30+
}
31+
if !found {
32+
println!(" None");
33+
}
34+
35+
println!();
36+
found = false;
37+
38+
println!("Block Devices:");
39+
for dev_idx in 0..=255u8 {
40+
if let bios::Option::Some(device_info) = (api.block_dev_get_info)(dev_idx) {
41+
println!(" {}: {:?}", dev_idx, device_info);
42+
found = true;
43+
}
44+
}
45+
if !found {
46+
println!(" None");
47+
}
48+
49+
println!();
50+
found = false;
51+
52+
println!("I2C Buses:");
53+
for dev_idx in 0..=255u8 {
54+
if let bios::Option::Some(device_info) = (api.i2c_bus_get_info)(dev_idx) {
55+
println!(" {}: {:?}", dev_idx, device_info);
56+
found = true;
57+
}
58+
}
59+
if !found {
60+
println!(" None");
61+
}
62+
63+
println!();
64+
found = false;
65+
66+
println!("Neotron Bus Devices:");
67+
for dev_idx in 0..=255u8 {
68+
if let bios::Option::Some(device_info) = (api.bus_get_info)(dev_idx) {
69+
println!(" {}: {:?}", dev_idx, device_info);
70+
found = true;
71+
}
72+
}
73+
if !found {
74+
println!(" None");
75+
}
76+
77+
println!();
78+
found = false;
79+
80+
println!("Audio Mixers:");
81+
for dev_idx in 0..=255u8 {
82+
if let bios::Option::Some(device_info) = (api.audio_mixer_channel_get_info)(dev_idx) {
83+
println!(" {}: {:?}", dev_idx, device_info);
84+
found = true;
85+
}
86+
}
87+
if !found {
88+
println!(" None");
89+
}
90+
}

src/commands/input.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! Input related commands for Neotron OS
2+
3+
use crate::{bios, println, Ctx, API};
4+
5+
/// Called when the "kbtest" command is executed.
6+
pub fn kbtest(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], ctx: &mut Ctx) {
7+
let api = API.get();
8+
loop {
9+
match (api.hid_get_event)() {
10+
bios::Result::Ok(bios::Option::Some(bios::hid::HidEvent::KeyPress(code))) => {
11+
let pckb_ev = pc_keyboard::KeyEvent {
12+
code,
13+
state: pc_keyboard::KeyState::Down,
14+
};
15+
if let Some(ev) = ctx.keyboard.process_keyevent(pckb_ev) {
16+
println!("Code={code:?} State=Down Decoded={ev:?}");
17+
} else {
18+
println!("Code={code:?} State=Down Decoded=None");
19+
}
20+
if code == pc_keyboard::KeyCode::Escape {
21+
break;
22+
}
23+
}
24+
bios::Result::Ok(bios::Option::Some(bios::hid::HidEvent::KeyRelease(code))) => {
25+
let pckb_ev = pc_keyboard::KeyEvent {
26+
code,
27+
state: pc_keyboard::KeyState::Up,
28+
};
29+
if let Some(ev) = ctx.keyboard.process_keyevent(pckb_ev) {
30+
println!("Code={code:?} State=Up Decoded={ev:?}");
31+
} else {
32+
println!("Code={code:?} State=Up Decoded=None");
33+
}
34+
}
35+
bios::Result::Ok(bios::Option::Some(bios::hid::HidEvent::MouseInput(_ignore))) => {}
36+
bios::Result::Ok(bios::Option::None) => {
37+
// Do nothing
38+
}
39+
bios::Result::Err(e) => {
40+
println!("Failed to get HID events: {:?}", e);
41+
}
42+
}
43+
}
44+
}

src/commands/mod.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//! Commands for Neotron OS
2+
//!
3+
//! Defines the top-level menu, and the commands it can call.
4+
5+
pub use super::Ctx;
6+
7+
mod config;
8+
mod hardware;
9+
mod input;
10+
mod screen;
11+
12+
pub static OS_MENU: menu::Menu<Ctx> = menu::Menu {
13+
label: "root",
14+
items: &[
15+
&menu::Item {
16+
item_type: menu::ItemType::Callback {
17+
function: hardware::lshw,
18+
parameters: &[],
19+
},
20+
command: "lshw",
21+
help: Some("List all the hardware"),
22+
},
23+
&menu::Item {
24+
item_type: menu::ItemType::Callback {
25+
function: screen::clear,
26+
parameters: &[],
27+
},
28+
command: "clear",
29+
help: Some("Clear the screen"),
30+
},
31+
&menu::Item {
32+
item_type: menu::ItemType::Callback {
33+
function: screen::fill,
34+
parameters: &[],
35+
},
36+
command: "fill",
37+
help: Some("Fill the screen with characters"),
38+
},
39+
&menu::Item {
40+
item_type: menu::ItemType::Callback {
41+
function: config::command,
42+
parameters: &[
43+
menu::Parameter::Optional {
44+
parameter_name: "command",
45+
help: Some("Which operation to perform (try help)"),
46+
},
47+
menu::Parameter::Optional {
48+
parameter_name: "value",
49+
help: Some("new value for the setting"),
50+
},
51+
],
52+
},
53+
command: "config",
54+
help: Some("Handle non-volatile OS configuration"),
55+
},
56+
&menu::Item {
57+
item_type: menu::ItemType::Callback {
58+
function: input::kbtest,
59+
parameters: &[],
60+
},
61+
command: "kbtest",
62+
help: Some("Test the keyboard (press ESC to quit)"),
63+
},
64+
],
65+
entry: None,
66+
exit: None,
67+
};

src/commands/screen.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//! Screen-related commands for Neotron OS
2+
3+
use crate::{print, println, Ctx, API, VGA_CONSOLE};
4+
5+
/// Called when the "clear" command is executed.
6+
pub fn clear(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
7+
if let Some(ref mut console) = unsafe { &mut VGA_CONSOLE } {
8+
console.clear();
9+
}
10+
}
11+
12+
/// Called when the "fill" command is executed.
13+
pub fn fill(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
14+
if let Some(ref mut console) = unsafe { &mut VGA_CONSOLE } {
15+
console.clear();
16+
}
17+
let api = API.get();
18+
let mode = (api.video_get_mode)();
19+
let (Some(width), Some(height)) = (mode.text_width(), mode.text_height()) else {
20+
println!("Unable to get console size");
21+
return;
22+
};
23+
// A range of printable ASCII compatible characters
24+
let mut char_cycle = (' '..='~').cycle();
25+
// Scroll two screen fulls
26+
for _row in 0..height * 2 {
27+
for _col in 0..width {
28+
print!("{}", char_cycle.next().unwrap());
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)