chardev.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. use super::{
  2. block::make_device,
  3. console::get_console,
  4. constants::{EEXIST, EIO},
  5. task::{ProcessList, Thread},
  6. terminal::Terminal,
  7. vfs::{
  8. file::{File, TerminalFile},
  9. DevId,
  10. },
  11. };
  12. use crate::{io::Buffer, prelude::*};
  13. use alloc::{
  14. boxed::Box,
  15. collections::btree_map::{BTreeMap, Entry},
  16. sync::Arc,
  17. };
  18. use eonix_sync::AsProof as _;
  19. pub trait VirtualCharDevice: Send + Sync {
  20. fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize>;
  21. fn write(&self, data: &[u8]) -> KResult<usize>;
  22. }
  23. pub enum CharDeviceType {
  24. Terminal(Arc<Terminal>),
  25. Virtual(Box<dyn VirtualCharDevice>),
  26. }
  27. #[allow(dead_code)]
  28. pub struct CharDevice {
  29. name: Arc<str>,
  30. device: CharDeviceType,
  31. }
  32. static CHAR_DEVICES: Spin<BTreeMap<DevId, Arc<CharDevice>>> = Spin::new(BTreeMap::new());
  33. impl CharDevice {
  34. pub fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  35. match &self.device {
  36. CharDeviceType::Terminal(terminal) => terminal.read(buffer),
  37. CharDeviceType::Virtual(device) => device.read(buffer),
  38. }
  39. }
  40. pub fn write(&self, data: &[u8]) -> KResult<usize> {
  41. match &self.device {
  42. CharDeviceType::Virtual(device) => device.write(data),
  43. CharDeviceType::Terminal(terminal) => {
  44. for &ch in data.iter() {
  45. terminal.show_char(ch);
  46. }
  47. Ok(data.len())
  48. }
  49. }
  50. }
  51. pub fn get(devid: DevId) -> Option<Arc<CharDevice>> {
  52. CHAR_DEVICES.lock().get(&devid).cloned()
  53. }
  54. pub fn register(devid: DevId, name: Arc<str>, device: CharDeviceType) -> KResult<()> {
  55. match CHAR_DEVICES.lock().entry(devid) {
  56. Entry::Vacant(entry) => {
  57. entry.insert(Arc::new(CharDevice { name, device }));
  58. Ok(())
  59. }
  60. Entry::Occupied(_) => Err(EEXIST),
  61. }
  62. }
  63. pub fn open(self: &Arc<Self>) -> KResult<Arc<File>> {
  64. Ok(match &self.device {
  65. CharDeviceType::Terminal(terminal) => {
  66. let procs = ProcessList::get().read();
  67. let current = Thread::current();
  68. let session = current.process.session(procs.prove());
  69. // We only set the control terminal if the process is the session leader.
  70. if session.sid == Thread::current().process.pid {
  71. // Silently fail if we can't set the control terminal.
  72. dont_check!(session.set_control_terminal(&terminal, false, procs.prove()));
  73. }
  74. TerminalFile::new(terminal.clone())
  75. }
  76. CharDeviceType::Virtual(_) => Arc::new(File::CharDev(self.clone())),
  77. })
  78. }
  79. }
  80. struct NullDevice;
  81. impl VirtualCharDevice for NullDevice {
  82. fn read(&self, _buffer: &mut dyn Buffer) -> KResult<usize> {
  83. Ok(0)
  84. }
  85. fn write(&self, _data: &[u8]) -> KResult<usize> {
  86. Ok(_data.len())
  87. }
  88. }
  89. struct ZeroDevice;
  90. impl VirtualCharDevice for ZeroDevice {
  91. fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  92. // TODO: Copy from empty page.
  93. while let false = buffer.fill(&[0; 16])?.should_stop() {}
  94. Ok(buffer.wrote())
  95. }
  96. fn write(&self, _data: &[u8]) -> KResult<usize> {
  97. Ok(_data.len())
  98. }
  99. }
  100. struct ConsoleDevice;
  101. impl VirtualCharDevice for ConsoleDevice {
  102. fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  103. let console_terminal = get_console().ok_or(EIO)?;
  104. console_terminal.read(buffer)
  105. }
  106. fn write(&self, data: &[u8]) -> KResult<usize> {
  107. let console_terminal = get_console().ok_or(EIO)?;
  108. for &ch in data.iter() {
  109. console_terminal.show_char(ch);
  110. }
  111. Ok(data.len())
  112. }
  113. }
  114. impl CharDevice {
  115. pub fn init() -> KResult<()> {
  116. Self::register(
  117. make_device(1, 3),
  118. Arc::from("null"),
  119. CharDeviceType::Virtual(Box::new(NullDevice)),
  120. )?;
  121. Self::register(
  122. make_device(1, 5),
  123. Arc::from("zero"),
  124. CharDeviceType::Virtual(Box::new(ZeroDevice)),
  125. )?;
  126. Self::register(
  127. make_device(5, 1),
  128. Arc::from("console"),
  129. CharDeviceType::Virtual(Box::new(ConsoleDevice)),
  130. )?;
  131. Ok(())
  132. }
  133. }