1extern crate alloc;
7use crate::arch::Trapframe;
8use crate::device::char::{CharDevice, TtyControl};
9use crate::device::events::{DeviceEvent, DeviceEventListener, InputEvent};
10use crate::device::manager::DeviceManager;
11use crate::device::{Device, DeviceCapability, DeviceType};
12use crate::late_initcall;
13use crate::object::capability::selectable::{
14 ReadyInterest, ReadySet, SelectWaitOutcome, Selectable,
15};
16use crate::object::capability::{ControlOps, MemoryMappingOps};
17use crate::sync::waker::Waker;
18use crate::task::mytask;
19use crate::timer::{TimerHandler, add_timer, cancel_timer, get_tick};
20use alloc::collections::VecDeque;
21use alloc::sync::Arc;
22use core::any::Any;
23use core::sync::atomic::{AtomicBool, AtomicU16, Ordering};
24use spin::Mutex;
25
26pub mod tty_ctl {
29 pub const SCTL_TTY_SET_ECHO: u32 = 0x5354_0001;
31 pub const SCTL_TTY_GET_ECHO: u32 = 0x5354_0002;
32 pub const SCTL_TTY_SET_CANONICAL: u32 = 0x5354_0003;
33 pub const SCTL_TTY_GET_CANONICAL: u32 = 0x5354_0004;
34 pub const SCTL_TTY_SET_WINSIZE: u32 = 0x5354_0005;
36 pub const SCTL_TTY_GET_WINSIZE: u32 = 0x5354_0006;
38 pub const SCTL_TTY_SET_READ_POLICY: u32 = 0x5354_0007;
41 pub const SCTL_TTY_GET_READ_POLICY: u32 = 0x5354_0008;
43 pub const SCTL_TTY_FLUSH_INPUT: u32 = 0x5354_0009;
45 pub const SCTL_TTY_SET_DEBUG: u32 = 0x5354_000A;
47 pub const SCTL_TTY_GET_DEBUG: u32 = 0x5354_000B;
49 pub const SCTL_TTY_SET_KBMODE: u32 = 0x5354_000C;
51 pub const SCTL_TTY_GET_KBMODE: u32 = 0x5354_000D;
53}
54use tty_ctl::*;
55
56static TTY_CAPS: [DeviceCapability; 1] = [DeviceCapability::Tty];
58
59fn init_tty_subsystem() {
61 let result = try_init_tty_subsystem();
62 if let Err(e) = result {
63 crate::early_println!("Failed to initialize TTY subsystem: {}", e);
64 }
65}
66
67fn try_init_tty_subsystem() -> Result<(), &'static str> {
68 let device_manager = DeviceManager::get_manager();
69
70 let devices_count = device_manager.get_devices_count();
72 let mut serial_device_id: Option<usize> = None;
73 for id in 1..=devices_count {
74 if let Some(dev) = device_manager.get_device(id) {
75 if dev.device_type() == DeviceType::Char
76 && dev.capabilities().contains(&DeviceCapability::Serial)
77 && !dev.capabilities().contains(&DeviceCapability::Tty)
78 {
79 serial_device_id = Some(id);
80 break;
81 }
82 }
83 }
84
85 let uart_device_id =
86 serial_device_id.ok_or("No Serial-capable char device found for TTY initialization")?;
87
88 let tty_device = Arc::new(TtyDevice::new("tty0", uart_device_id));
90 let uart_device = device_manager
91 .get_device(uart_device_id)
92 .ok_or("UART device not found")?;
93
94 if let Some(ec) = uart_device.as_event_capable() {
96 let weak_tty = Arc::downgrade(&tty_device);
97 ec.register_event_listener(weak_tty);
98 crate::early_println!("TTY registered as UART event listener");
99 }
100
101 let _tty_id =
103 device_manager.register_device_with_name(alloc::string::String::from("tty0"), tty_device);
104
105 crate::early_println!("TTY subsystem initialized successfully");
106 Ok(())
107}
108
109late_initcall!(init_tty_subsystem);
110
111pub struct TtyDevice {
116 name: &'static str,
117 uart_device_id: usize,
118
119 input_buffer: Arc<Mutex<VecDeque<u8>>>,
121
122 input_waker: Waker,
124
125 canonical_mode: AtomicBool,
127 echo_enabled: AtomicBool,
128
129 read_min_ready_bytes: AtomicU16,
131 read_timeout_ms: AtomicU16,
132
133 winsize_cols: Mutex<u16>,
135 winsize_rows: Mutex<u16>,
136 debug_enabled: AtomicBool,
138
139 kb_mode: core::sync::atomic::AtomicU8,
141
142 esc_state: Mutex<u8>,
145 nonblocking: AtomicBool,
147}
148
149impl TtyDevice {
150 pub fn new(name: &'static str, uart_device_id: usize) -> Self {
151 Self {
152 name,
153 uart_device_id,
154 input_buffer: Arc::new(Mutex::new(VecDeque::new())),
155 input_waker: Waker::new_interruptible("tty_input"),
156 canonical_mode: AtomicBool::new(true),
157 echo_enabled: AtomicBool::new(true),
158 read_min_ready_bytes: AtomicU16::new(1),
159 read_timeout_ms: AtomicU16::new(0),
160 winsize_cols: Mutex::new(80),
161 winsize_rows: Mutex::new(25),
162 debug_enabled: AtomicBool::new(false),
164 kb_mode: core::sync::atomic::AtomicU8::new(0),
165 esc_state: Mutex::new(0),
166 nonblocking: AtomicBool::new(false),
167 }
168 }
169
170 pub fn wait_until_readable(&self, trapframe: &mut Trapframe) {
173 loop {
174 if self.can_read() {
175 return;
176 }
177 if let Some(task) = mytask() {
178 self.input_waker.wait(task.get_id(), trapframe);
179 } else {
180 return;
182 }
183 }
184 }
185
186 pub fn wake_input(&self) {
189 self.input_waker.wake_all();
190 }
191
192 pub fn wait_until_readable_with_timeout_ticks(
195 &self,
196 trapframe: &mut Trapframe,
197 ticks: u64,
198 ) -> bool {
199 if self.can_read() {
200 return false;
201 }
202 if ticks == 0 {
203 return true;
204 }
205
206 struct TtyTimeoutHandler {
207 tty_ptr: *const TtyDevice,
208 }
209 unsafe impl Send for TtyTimeoutHandler {}
210 unsafe impl Sync for TtyTimeoutHandler {}
211 impl TimerHandler for TtyTimeoutHandler {
212 fn on_timer_expired(self: Arc<Self>, _context: usize) {
213 unsafe {
214 (*self.tty_ptr).wake_input();
215 }
216 }
217 }
218
219 let deadline = get_tick().saturating_add(ticks);
220 let handler: Arc<dyn TimerHandler> = Arc::new(TtyTimeoutHandler {
221 tty_ptr: self as *const TtyDevice,
222 });
223 let timer_id = add_timer(deadline, &handler, 0);
224
225 if let Some(task) = mytask() {
226 self.input_waker.wait(task.get_id(), trapframe);
227 }
228
229 cancel_timer(timer_id);
231 if self.can_read() { false } else { true }
232 }
233
234 pub fn input_len(&self) -> usize {
236 self.input_buffer.lock().len()
237 }
238
239 pub fn is_read_ready_for_select(&self) -> bool {
243 if self.canonical_mode.load(Ordering::Relaxed) {
244 let g = self.input_buffer.lock();
245 return g.iter().any(|&b| b == b'\n');
246 }
247
248 let min_ready = self.read_min_ready_bytes.load(Ordering::Relaxed) as usize;
249 let kb_mode = self.kb_mode.load(Ordering::Relaxed);
250
251 if min_ready == 0 {
254 return true;
255 }
256
257 if kb_mode == 2 {
258 let g = self.input_buffer.lock();
259 let available = g.len();
260 if let Some(&first) = g.front() {
261 if first == 0xE0 {
262 if available < 2 {
263 return false;
264 }
265 return available >= min_ready;
266 }
267 } else {
268 return false;
269 }
270 available >= min_ready
271 } else {
272 let available = self.input_len();
273 available >= min_ready
274 }
275 }
276
277 fn handle_input_byte(&self, byte: u8) {
281 if self.debug_enabled.load(Ordering::Relaxed) {
282 crate::println!(
283 "[TTY] RX byte=0x{:02x} '{}' canonical={} size={}",
284 byte,
285 if byte.is_ascii_graphic() || byte == b' ' {
286 byte as char
287 } else {
288 '.'
289 },
290 self.canonical_mode.load(Ordering::Relaxed),
291 self.input_buffer.lock().len()
292 );
293 }
294 if self.canonical_mode.load(Ordering::Relaxed) {
296 match byte {
297 0x08 | 0x7F => {
299 let mut input_buffer = self.input_buffer.lock();
300 if input_buffer.pop_back().is_some()
301 && self.echo_enabled.load(Ordering::Relaxed)
302 {
303 self.echo_backspace();
304 }
305 }
306 b'\r' | b'\n' => {
308 if self.echo_enabled.load(Ordering::Relaxed) {
309 self.echo_char(b'\r');
310 self.echo_char(b'\n');
311 }
312 let mut input_buffer = self.input_buffer.lock();
313 input_buffer.push_back(b'\n');
314 drop(input_buffer);
315 self.input_waker.wake_all();
316 }
317 0x03 => {
319 if self.echo_enabled.load(Ordering::Relaxed) {
320 self.echo_char('^' as u8);
321 self.echo_char('C' as u8);
322 self.echo_char('\r' as u8);
323 self.echo_char('\n' as u8);
324 }
325 }
326 0x1A => {
328 }
330 byte => {
332 if self.echo_enabled.load(Ordering::Relaxed) {
333 self.echo_char(byte);
334 }
335 let mut input_buffer = self.input_buffer.lock();
336 input_buffer.push_back(byte);
337 drop(input_buffer);
338 if !self.canonical_mode.load(Ordering::Relaxed) {
339 self.input_waker.wake_all();
340 }
341 }
342 }
343 } else {
344 let kb_mode = self.kb_mode.load(Ordering::Relaxed);
346 if kb_mode == 0 {
347 let mut input_buffer = self.input_buffer.lock();
349 input_buffer.push_back(byte);
350 drop(input_buffer);
351 self.input_waker.wake_all();
352 } else if kb_mode == 1 {
353 fn ascii_to_linux_keycode(b: u8) -> Option<u8> {
355 match b {
356 b'1' => Some(2),
357 b'2' => Some(3),
358 b'3' => Some(4),
359 b'4' => Some(5),
360 b'5' => Some(6),
361 b'6' => Some(7),
362 b'7' => Some(8),
363 b'8' => Some(9),
364 b'9' => Some(10),
365 b'0' => Some(11),
366 b'-' => Some(12),
367 b'=' => Some(13),
368 0x08 | 0x7F => Some(14), b'\t' => Some(15),
370 b'q' => Some(16),
371 b'w' => Some(17),
372 b'e' => Some(18),
373 b'r' => Some(19),
374 b't' => Some(20),
375 b'y' => Some(21),
376 b'u' => Some(22),
377 b'i' => Some(23),
378 b'o' => Some(24),
379 b'p' => Some(25),
380 b'[' => Some(26),
381 b']' => Some(27),
382 b'\n' | b'\r' => Some(28),
383 b'a' => Some(30),
384 b's' => Some(31),
385 b'd' => Some(32),
386 b'f' => Some(33),
387 b'g' => Some(34),
388 b'h' => Some(35),
389 b'j' => Some(36),
390 b'k' => Some(37),
391 b'l' => Some(38),
392 b';' => Some(39),
393 b'\'' => Some(40),
394 b'`' => Some(41),
395 b'\\' => Some(43),
396 b'z' => Some(44),
397 b'x' => Some(45),
398 b'c' => Some(46),
399 b'v' => Some(47),
400 b'b' => Some(48),
401 b'n' => Some(49),
402 b'm' => Some(50),
403 b',' => Some(51),
404 b'.' => Some(52),
405 b'/' => Some(53),
406 b' ' => Some(57),
407 b'A'..=b'Z' => Some(30 + (b.to_ascii_lowercase() - b'a') as u8),
409 _ => None,
410 }
411 }
412 fn push_keycode_press_release(dev: &TtyDevice, code: u8) {
413 let mut input_buffer = dev.input_buffer.lock();
414 input_buffer.push_back(code);
415 input_buffer.push_back(code | 0x80); drop(input_buffer);
417 dev.input_waker.wake_all();
418 }
419 let mut handled_escape = false;
421 {
422 let mut st = self.esc_state.lock();
423 match (*st, byte) {
424 (0, 0x1B) => {
425 *st = 1;
426 handled_escape = true;
427 }
428 (1, b'[') => {
429 *st = 2;
430 handled_escape = true;
431 }
432 (1, b'O') => {
433 *st = 3;
434 handled_escape = true;
435 }
436 (2, b'A') => {
438 *st = 0;
439 handled_escape = true;
440 push_keycode_press_release(self, 103);
441 } (2, b'B') => {
443 *st = 0;
444 handled_escape = true;
445 push_keycode_press_release(self, 108);
446 } (2, b'C') => {
448 *st = 0;
449 handled_escape = true;
450 push_keycode_press_release(self, 106);
451 } (2, b'D') => {
453 *st = 0;
454 handled_escape = true;
455 push_keycode_press_release(self, 105);
456 } (3, b'H') => {
459 *st = 0;
460 handled_escape = true;
461 push_keycode_press_release(self, 103);
462 }
463 (3, b'P') => {
464 *st = 0;
465 handled_escape = true;
466 push_keycode_press_release(self, 108);
467 }
468 (3, b'M') => {
469 *st = 0;
470 handled_escape = true;
471 push_keycode_press_release(self, 106);
472 }
473 (3, b'K') => {
474 *st = 0;
475 handled_escape = true;
476 push_keycode_press_release(self, 105);
477 }
478 (2, b'H') => {
480 *st = 0;
481 handled_escape = true;
482 push_keycode_press_release(self, 102);
483 } (2, b'F') => {
485 *st = 0;
486 handled_escape = true;
487 push_keycode_press_release(self, 107);
488 } (3, b'F') => {
491 *st = 0;
492 handled_escape = true;
493 push_keycode_press_release(self, 107);
494 }
495 (2, b'2') => {
497 *st = 4;
498 handled_escape = true;
499 } (2, b'3') => {
501 *st = 5;
502 handled_escape = true;
503 } (2, b'5') => {
505 *st = 6;
506 handled_escape = true;
507 } (2, b'6') => {
509 *st = 7;
510 handled_escape = true;
511 } (4, b'~') => {
513 *st = 0;
514 handled_escape = true;
515 push_keycode_press_release(self, 110);
516 } (5, b'~') => {
518 *st = 0;
519 handled_escape = true;
520 push_keycode_press_release(self, 111);
521 } (6, b'~') => {
523 *st = 0;
524 handled_escape = true;
525 push_keycode_press_release(self, 104);
526 } (7, b'~') => {
528 *st = 0;
529 handled_escape = true;
530 push_keycode_press_release(self, 109);
531 } (1, _) | (2, _) | (3, _) => {
533 *st = 0;
534 }
535 _ => {}
536 }
537 }
538 if !handled_escape {
539 if let Some(code) = ascii_to_linux_keycode(byte) {
540 push_keycode_press_release(self, code);
541 }
542 }
543 } else {
544 fn ascii_to_set1_scancode(b: u8) -> Option<u8> {
546 match b {
547 b'1' => Some(2),
548 b'2' => Some(3),
549 b'3' => Some(4),
550 b'4' => Some(5),
551 b'5' => Some(6),
552 b'6' => Some(7),
553 b'7' => Some(8),
554 b'8' => Some(9),
555 b'9' => Some(10),
556 b'0' => Some(11),
557 b'-' => Some(12),
558 b'=' => Some(13),
559 0x08 | 0x7F => Some(14),
560 b'\t' => Some(15),
561 b'q' => Some(16),
562 b'w' => Some(17),
563 b'e' => Some(18),
564 b'r' => Some(19),
565 b't' => Some(20),
566 b'y' => Some(21),
567 b'u' => Some(22),
568 b'i' => Some(23),
569 b'o' => Some(24),
570 b'p' => Some(25),
571 b'[' => Some(26),
572 b']' => Some(27),
573 b'\n' | b'\r' => Some(28),
574 b'a' => Some(30),
575 b's' => Some(31),
576 b'd' => Some(32),
577 b'f' => Some(33),
578 b'g' => Some(34),
579 b'h' => Some(35),
580 b'j' => Some(36),
581 b'k' => Some(37),
582 b'l' => Some(38),
583 b';' => Some(39),
584 b'\'' => Some(40),
585 b'`' => Some(41),
586 b'\\' => Some(43),
587 b'z' => Some(44),
588 b'x' => Some(45),
589 b'c' => Some(46),
590 b'v' => Some(47),
591 b'b' => Some(48),
592 b'n' => Some(49),
593 b'm' => Some(50),
594 b',' => Some(51),
595 b'.' => Some(52),
596 b'/' => Some(53),
597 b' ' => Some(57),
598 b'A'..=b'Z' => Some(30 + (b.to_ascii_lowercase() - b'a') as u8),
599 _ => None,
600 }
601 }
602 fn push_scancode_press_release(dev: &TtyDevice, code: u8, extended: bool) {
603 let mut input_buffer = dev.input_buffer.lock();
604 if extended {
606 input_buffer.push_back(0xE0);
607 }
608 input_buffer.push_back(code);
609 if extended {
611 input_buffer.push_back(0xE0);
612 }
613 input_buffer.push_back(code | 0x80);
614 drop(input_buffer);
615 dev.input_waker.wake_all();
616 }
617 let mut handled_escape = false;
618 {
619 let mut st = self.esc_state.lock();
620 match (*st, byte) {
621 (0, 0x1B) => {
622 *st = 1;
623 handled_escape = true;
624 }
625 (1, b'[') => {
626 *st = 2;
627 handled_escape = true;
628 }
629 (1, b'O') => {
630 *st = 3;
631 handled_escape = true;
632 }
633 (2, b'A') => {
635 *st = 0;
636 handled_escape = true;
637 push_scancode_press_release(self, 0x48, true);
638 } (2, b'B') => {
640 *st = 0;
641 handled_escape = true;
642 push_scancode_press_release(self, 0x50, true);
643 } (2, b'C') => {
645 *st = 0;
646 handled_escape = true;
647 push_scancode_press_release(self, 0x4D, true);
648 } (2, b'D') => {
650 *st = 0;
651 handled_escape = true;
652 push_scancode_press_release(self, 0x4B, true);
653 } (3, b'H') => {
656 *st = 0;
657 handled_escape = true;
658 push_scancode_press_release(self, 0x48, true);
659 } (3, b'P') => {
661 *st = 0;
662 handled_escape = true;
663 push_scancode_press_release(self, 0x50, true);
664 } (3, b'M') => {
666 *st = 0;
667 handled_escape = true;
668 push_scancode_press_release(self, 0x4D, true);
669 } (3, b'K') => {
671 *st = 0;
672 handled_escape = true;
673 push_scancode_press_release(self, 0x4B, true);
674 } (2, b'H') => {
677 *st = 0;
678 handled_escape = true;
679 push_scancode_press_release(self, 0x47, true);
680 } (2, b'F') => {
682 *st = 0;
683 handled_escape = true;
684 push_scancode_press_release(self, 0x4F, true);
685 } (3, b'F') => {
688 *st = 0;
689 handled_escape = true;
690 push_scancode_press_release(self, 0x4F, true);
691 }
692 (2, b'2') => {
694 *st = 4;
695 handled_escape = true;
696 } (2, b'3') => {
698 *st = 5;
699 handled_escape = true;
700 } (2, b'5') => {
702 *st = 6;
703 handled_escape = true;
704 } (2, b'6') => {
706 *st = 7;
707 handled_escape = true;
708 } (4, b'~') => {
710 *st = 0;
711 handled_escape = true;
712 push_scancode_press_release(self, 0x52, true);
713 } (5, b'~') => {
715 *st = 0;
716 handled_escape = true;
717 push_scancode_press_release(self, 0x53, true);
718 } (6, b'~') => {
720 *st = 0;
721 handled_escape = true;
722 push_scancode_press_release(self, 0x49, true);
723 } (7, b'~') => {
725 *st = 0;
726 handled_escape = true;
727 push_scancode_press_release(self, 0x51, true);
728 } (1, _) | (2, _) | (3, _) => {
730 *st = 0;
732 }
733 _ => {}
734 }
735 }
736 if !handled_escape {
737 if let Some(code) = ascii_to_set1_scancode(byte) {
738 let mut input_buffer = self.input_buffer.lock();
740 input_buffer.push_back(code);
741 input_buffer.push_back(code | 0x80);
742 drop(input_buffer);
743 self.input_waker.wake_all();
744 }
745 }
746 }
747 }
748 }
749
750 fn echo_char(&self, byte: u8) {
752 let device_manager = DeviceManager::get_manager();
754 if let Some(uart_device) = device_manager.get_device(self.uart_device_id) {
755 if let Some(char_device) = uart_device.as_char_device() {
757 let _ = char_device.write_byte(byte);
758 }
759 }
760 }
761
762 fn echo_backspace(&self) {
764 self.echo_char(0x08);
766 self.echo_char(b' ');
767 self.echo_char(0x08);
768 }
769}
770
771impl Selectable for TtyDevice {
772 fn current_ready(&self, interest: ReadyInterest) -> ReadySet {
773 let mut set = ReadySet::none();
774 if interest.read {
775 set.read = self.is_read_ready_for_select();
776 }
777 if interest.write {
778 set.write = true;
780 }
781 if interest.except {
782 set.except = false;
783 }
784 set
785 }
786
787 fn wait_until_ready(
788 &self,
789 interest: ReadyInterest,
790 trapframe: &mut crate::arch::Trapframe,
791 timeout_ticks: Option<u64>,
792 ) -> SelectWaitOutcome {
793 if interest.read {
795 match timeout_ticks {
796 Some(ticks) => {
797 let timed_out = self.wait_until_readable_with_timeout_ticks(trapframe, ticks);
798 if timed_out {
799 SelectWaitOutcome::TimedOut
800 } else {
801 SelectWaitOutcome::Ready
802 }
803 }
804 None => {
805 self.wait_until_readable(trapframe);
806 SelectWaitOutcome::Ready
807 }
808 }
809 } else {
810 SelectWaitOutcome::Ready
811 }
812 }
813
814 fn set_nonblocking(&self, enabled: bool) {
815 crate::println!("[TTY] set_nonblocking: {}", enabled);
816 self.nonblocking.store(enabled, Ordering::Relaxed);
817 }
818
819 fn is_nonblocking(&self) -> bool {
820 self.nonblocking.load(Ordering::Relaxed)
821 }
822}
823
824impl TtyControl for TtyDevice {
825 fn set_echo(&self, enabled: bool) {
826 self.echo_enabled.store(enabled, Ordering::Relaxed);
827 }
828 fn is_echo_enabled(&self) -> bool {
829 self.echo_enabled.load(Ordering::Relaxed)
830 }
831
832 fn set_canonical(&self, enabled: bool) {
833 self.canonical_mode.store(enabled, Ordering::Relaxed);
834 }
835 fn is_canonical(&self) -> bool {
836 self.canonical_mode.load(Ordering::Relaxed)
837 }
838
839 fn set_winsize(&self, cols: u16, rows: u16) {
840 *self.winsize_cols.lock() = cols;
841 *self.winsize_rows.lock() = rows;
842 }
843 fn get_winsize(&self) -> (u16, u16) {
844 (*self.winsize_cols.lock(), *self.winsize_rows.lock())
845 }
846}
847
848impl DeviceEventListener for TtyDevice {
849 fn on_device_event(&self, event: &dyn DeviceEvent) {
850 if let Some(input_event) = event.as_any().downcast_ref::<InputEvent>() {
851 self.handle_input_byte(input_event.data);
852 }
853 }
854
855 fn interested_in(&self, event_type: &str) -> bool {
856 event_type == "input"
857 }
858}
859
860impl MemoryMappingOps for TtyDevice {
861 fn get_mapping_info(
862 &self,
863 _offset: usize,
864 _length: usize,
865 ) -> Result<(usize, usize, bool), &'static str> {
866 Err("Memory mapping not supported by TTY device")
867 }
868
869 fn on_mapped(&self, _vaddr: usize, _paddr: usize, _length: usize, _offset: usize) {
870 }
872
873 fn on_unmapped(&self, _vaddr: usize, _length: usize) {
874 }
876
877 fn supports_mmap(&self) -> bool {
878 false
879 }
880}
881
882impl Device for TtyDevice {
883 fn device_type(&self) -> DeviceType {
884 DeviceType::Char
885 }
886
887 fn name(&self) -> &'static str {
888 self.name
889 }
890
891 fn as_any(&self) -> &dyn Any {
892 self
893 }
894
895 fn as_any_mut(&mut self) -> &mut dyn Any {
896 self
897 }
898
899 fn as_char_device(&self) -> Option<&dyn CharDevice> {
900 Some(self)
901 }
902
903 fn capabilities(&self) -> &'static [DeviceCapability] {
904 &TTY_CAPS
905 }
906}
907
908impl CharDevice for TtyDevice {
909 fn read(&self, buffer: &mut [u8]) -> usize {
910 if buffer.is_empty() {
911 return 0;
912 }
913
914 let min_ready = self.read_min_ready_bytes.load(Ordering::Relaxed) as usize;
916 let canonical = self.canonical_mode.load(Ordering::Relaxed);
917
918 let copy_out = |buf: &mut [u8], until_newline: bool| -> usize {
920 let mut bytes = 0;
921 let mut guard = self.input_buffer.lock();
922 if until_newline {
923 if let Some(pos) = guard.iter().position(|&b| b == b'\n') {
925 let take = core::cmp::min(pos + 1, buf.len());
927 for i in 0..take {
928 if let Some(b) = guard.pop_front() {
929 buf[i] = b;
930 bytes += 1;
931 } else {
932 break;
933 }
934 }
935 }
936 } else {
937 while bytes < buf.len() {
938 if let Some(b) = guard.pop_front() {
939 buf[bytes] = b;
940 bytes += 1;
941 } else {
942 break;
943 }
944 }
945 }
946 bytes
947 };
948
949 if canonical {
951 loop {
952 {
954 let has_newline = {
955 let g = self.input_buffer.lock();
956 g.iter().any(|&b| b == b'\n')
957 };
958 if has_newline {
959 return copy_out(buffer, true);
960 }
961 }
962 if self.nonblocking.load(Ordering::Relaxed) {
964 return 0; }
966 if let Some(task) = mytask() {
967 self.input_waker.wait(task.get_id(), task.get_trapframe());
968 } else {
969 return 0;
971 }
972 }
973 }
974
975 if min_ready == 0 {
977 let kb_mode = self.kb_mode.load(Ordering::Relaxed);
980 if kb_mode == 2 {
981 let mut guard = self.input_buffer.lock();
982 if let Some(&first) = guard.front() {
983 if first == 0xE0 {
984 if guard.len() >= 2 && buffer.len() >= 2 {
985 let b0 = guard.pop_front().unwrap();
986 let b1 = guard.pop_front().unwrap();
987 drop(guard);
988 buffer[0] = b0;
989 buffer[1] = b1;
990 return 2;
991 }
992 }
993 }
994 drop(guard);
995 }
996 return copy_out(buffer, false);
997 }
998
999 loop {
1000 let kb_mode = self.kb_mode.load(Ordering::Relaxed);
1001 if kb_mode == 2 {
1002 let (need_pair, have_pair) = {
1004 let g = self.input_buffer.lock();
1005 let head_is_e0 = g.front().map(|b| *b == 0xE0).unwrap_or(false);
1006 let have = g.len() >= 2;
1007 (head_is_e0 && buffer.len() >= 2, have)
1008 };
1009 if need_pair && !have_pair {
1010 if self.nonblocking.load(Ordering::Relaxed) {
1011 return 0;
1012 }
1013 if let Some(task) = mytask() {
1014 self.input_waker.wait(task.get_id(), task.get_trapframe());
1015 continue;
1016 } else {
1017 return 0;
1018 }
1019 }
1020 }
1021
1022 let available = { self.input_buffer.lock().len() };
1023 if available >= core::cmp::min(min_ready as usize, buffer.len()) {
1024 let kb_mode = self.kb_mode.load(Ordering::Relaxed);
1026 if kb_mode == 2 {
1027 let mut guard = self.input_buffer.lock();
1028 if let Some(&first) = guard.front() {
1029 if first == 0xE0 && guard.len() >= 2 && buffer.len() >= 2 {
1030 let b0 = guard.pop_front().unwrap();
1031 let b1 = guard.pop_front().unwrap();
1032 drop(guard);
1033 buffer[0] = b0;
1034 buffer[1] = b1;
1035 return 2;
1036 }
1037 }
1038 drop(guard);
1039 }
1040 return copy_out(buffer, false);
1041 }
1042 if self.nonblocking.load(Ordering::Relaxed) {
1044 return 0;
1045 }
1046 if let Some(task) = mytask() {
1047 self.input_waker.wait(task.get_id(), task.get_trapframe());
1048 } else {
1049 return 0;
1050 }
1051 }
1052 }
1053 fn read_byte(&self) -> Option<u8> {
1054 loop {
1056 let mut input_buffer = self.input_buffer.lock();
1057 if let Some(byte) = input_buffer.pop_front() {
1058 return Some(byte);
1059 }
1060 drop(input_buffer);
1061
1062 if let Some(task) = mytask() {
1064 self.input_waker.wait(task.get_id(), task.get_trapframe());
1067
1068 continue;
1070 } else {
1071 return None;
1073 }
1074 }
1075 }
1076
1077 fn write_byte(&self, byte: u8) -> Result<(), &'static str> {
1078 let device_manager = DeviceManager::get_manager();
1080 if let Some(uart_device) = device_manager.get_device(self.uart_device_id) {
1081 if let Some(char_device) = uart_device.as_char_device() {
1083 if byte == b'\n' {
1085 char_device.write_byte(b'\r')?;
1086 char_device.write_byte(b'\n')?;
1087 } else {
1088 char_device.write_byte(byte)?;
1089 }
1090 return Ok(());
1091 }
1092 }
1093 Err("UART device not available")
1094 }
1095
1096 fn can_read(&self) -> bool {
1097 let input_buffer = self.input_buffer.lock();
1098 !input_buffer.is_empty()
1099 }
1100
1101 fn can_write(&self) -> bool {
1102 let device_manager = DeviceManager::get_manager();
1104 if let Some(dev) = device_manager.get_device(self.uart_device_id) {
1105 if let Some(cdev) = dev.as_char_device() {
1106 return cdev.can_write();
1107 }
1108 }
1109 false
1110 }
1111}
1112
1113impl ControlOps for TtyDevice {
1114 fn control(&self, command: u32, arg: usize) -> Result<i32, &'static str> {
1116 match command {
1117 SCTL_TTY_SET_ECHO => {
1118 self.set_echo(arg != 0);
1119 Ok(0)
1120 }
1121 SCTL_TTY_GET_ECHO => Ok(self.is_echo_enabled() as i32),
1122 SCTL_TTY_SET_CANONICAL => {
1123 self.set_canonical(arg != 0);
1124 Ok(0)
1125 }
1126 SCTL_TTY_GET_CANONICAL => Ok(self.is_canonical() as i32),
1127 SCTL_TTY_SET_WINSIZE => {
1128 let cols = ((arg >> 16) & 0xFFFF) as u16;
1129 let rows = (arg & 0xFFFF) as u16;
1130 self.set_winsize(cols, rows);
1131 Ok(0)
1132 }
1133 SCTL_TTY_GET_WINSIZE => {
1134 let (cols, rows) = self.get_winsize();
1135 let packed = ((cols as u32) << 16) | (rows as u32);
1136 Ok(packed as i32)
1137 }
1138 SCTL_TTY_SET_READ_POLICY => {
1139 let min_ready = (arg & 0xFFFF) as u16;
1140 let timeout_ms = ((arg >> 16) & 0xFFFF) as u16;
1141 self.read_min_ready_bytes
1142 .store(min_ready, Ordering::Relaxed);
1143 self.read_timeout_ms.store(timeout_ms, Ordering::Relaxed);
1144 Ok(0)
1145 }
1146 SCTL_TTY_GET_READ_POLICY => {
1147 let min_ready = self.read_min_ready_bytes.load(Ordering::Relaxed) as u32;
1148 let timeout_ms = self.read_timeout_ms.load(Ordering::Relaxed) as u32;
1149 let packed = (timeout_ms << 16) | min_ready;
1150 Ok(packed as i32)
1151 }
1152 SCTL_TTY_FLUSH_INPUT => {
1153 let mut g = self.input_buffer.lock();
1154 g.clear();
1155 Ok(0)
1156 }
1157 SCTL_TTY_SET_DEBUG => {
1158 self.debug_enabled.store(arg != 0, Ordering::Relaxed);
1159 Ok(0)
1160 }
1161 SCTL_TTY_GET_DEBUG => Ok(self.debug_enabled.load(Ordering::Relaxed) as i32),
1162 SCTL_TTY_SET_KBMODE => {
1163 let v = (arg & 0xFF) as u8;
1164 self.kb_mode.store(v, Ordering::Relaxed);
1165 Ok(0)
1166 }
1167 SCTL_TTY_GET_KBMODE => Ok(self.kb_mode.load(Ordering::Relaxed) as i32),
1168 _ => Err("Unsupported control command for TTY device"),
1169 }
1170 }
1171}