Add a dummy Console device
This commit is contained in:
		
							parent
							
								
									9f06e2f1a5
								
							
						
					
					
						commit
						7a46d7d993
					
				|  | @ -0,0 +1,136 @@ | |||
| /* | ||||
|  * SPDX-License-Identifier: BlueOak-1.0.0 | ||||
|  */ | ||||
| 
 | ||||
| #![allow(dead_code)] | ||||
| 
 | ||||
| use core::fmt; | ||||
| 
 | ||||
| /// A trait that must be implemented by devices that are candidates for the
 | ||||
| /// global console.
 | ||||
| #[allow(unused_variables)] | ||||
| pub trait ConsoleOps { | ||||
|     fn putc(&self, c: char) {} | ||||
|     fn puts(&self, string: &str) {} | ||||
|     fn getc(&self) -> char { | ||||
|         ' ' | ||||
|     } | ||||
|     fn flush(&self) {} | ||||
| } | ||||
| 
 | ||||
| /// A dummy console that just ignores its inputs.
 | ||||
| pub struct NullConsole; | ||||
| impl Drop for NullConsole { | ||||
|     fn drop(&mut self) {} | ||||
| } | ||||
| impl ConsoleOps for NullConsole {} | ||||
| 
 | ||||
| /// Possible outputs which the console can store.
 | ||||
| pub enum Output { | ||||
|     None(NullConsole), | ||||
| } | ||||
| 
 | ||||
| /// Generate boilerplate for converting into one of Output enum values
 | ||||
| macro output_from($name:ty, $optname:ident) { | ||||
|     impl From<$name> for Output { | ||||
|         fn from(instance: $name) -> Self { | ||||
|             Output::$optname(instance) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| output_from!(NullConsole, None); | ||||
| pub struct Console { | ||||
|     output: Output, | ||||
| } | ||||
| 
 | ||||
| impl Default for Console { | ||||
|     fn default() -> Self { | ||||
|         Console { | ||||
|             output: (NullConsole {}).into(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Console { | ||||
|     pub const fn new() -> Console { | ||||
|         Console { | ||||
|             output: Output::None(NullConsole {}), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[inline(always)] | ||||
|     fn current_ptr(&self) -> &dyn ConsoleOps { | ||||
|         match &self.output { | ||||
|             Output::None(i) => i, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Overwrite the current output. The old output will go out of scope and
 | ||||
|     /// it's Drop function will be called.
 | ||||
|     pub fn replace_with(&mut self, x: Output) { | ||||
|         self.current_ptr().flush(); | ||||
| 
 | ||||
|         self.output = x; | ||||
|     } | ||||
| 
 | ||||
|     /// A command prompt.
 | ||||
|     pub fn command_prompt<'a>(&self, buf: &'a mut [u8]) -> &'a [u8] { | ||||
|         self.puts("\n$> "); | ||||
| 
 | ||||
|         let mut i = 0; | ||||
|         let mut input; | ||||
|         loop { | ||||
|             input = self.getc(); | ||||
| 
 | ||||
|             if input == '\n' { | ||||
|                 self.puts("\n"); // do \r\n output
 | ||||
|                 return &buf[..i]; | ||||
|             } else { | ||||
|                 if i < buf.len() { | ||||
|                     buf[i] = input as u8; | ||||
|                     i += 1; | ||||
|                 } else { | ||||
|                     return &buf[..i]; | ||||
|                 } | ||||
| 
 | ||||
|                 self.putc(input); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Drop for Console { | ||||
|     fn drop(&mut self) {} | ||||
| } | ||||
| 
 | ||||
| /// Dispatch the respective function to the currently stored output device.
 | ||||
| impl ConsoleOps for Console { | ||||
|     fn putc(&self, c: char) { | ||||
|         self.current_ptr().putc(c); | ||||
|     } | ||||
| 
 | ||||
|     fn puts(&self, string: &str) { | ||||
|         self.current_ptr().puts(string); | ||||
|     } | ||||
| 
 | ||||
|     fn getc(&self) -> char { | ||||
|         self.current_ptr().getc() | ||||
|     } | ||||
| 
 | ||||
|     fn flush(&self) { | ||||
|         self.current_ptr().flush() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Implementing this trait enables usage of the format_args! macros, which in
 | ||||
| /// turn are used to implement the kernel's print! and println! macros.
 | ||||
| ///
 | ||||
| /// See src/macros.rs.
 | ||||
| impl fmt::Write for Console { | ||||
|     fn write_str(&mut self, s: &str) -> fmt::Result { | ||||
|         self.current_ptr().puts(s); | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| /* | ||||
|  * SPDX-License-Identifier: BlueOak-1.0.0 | ||||
|  */ | ||||
| pub mod console; | ||||
| 
 | ||||
| pub use console::{Console, ConsoleOps}; | ||||
|  | @ -31,6 +31,7 @@ extern crate rlibc; // To enable linking memory intrinsics. | |||
| #[macro_use] | ||||
| pub mod arch; | ||||
| pub use arch::*; | ||||
| mod devices; | ||||
| mod macros; | ||||
| mod mm; | ||||
| mod panic; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue