1 use core::fmt::Debug; 2 3 use alloc::sync::{Arc, Weak}; 4 use kdepends::thingbuf::mpsc; 5 use system_error::SystemError; 6 7 use crate::libs::spinlock::{SpinLock, SpinLockGuard}; 8 9 use super::tty_core::TtyCore; 10 11 const TTY_PORT_BUFSIZE: usize = 4096; 12 13 #[allow(dead_code)] 14 #[derive(Debug)] 15 pub struct TtyPortData { 16 flags: i32, 17 iflags: TtyPortState, 18 sender: mpsc::Sender<u8>, 19 receiver: mpsc::Receiver<u8>, 20 tty: Weak<TtyCore>, 21 /// 内部tty,即与port直接相连的 22 internal_tty: Weak<TtyCore>, 23 } 24 25 impl Default for TtyPortData { 26 fn default() -> Self { 27 Self::new() 28 } 29 } 30 31 impl TtyPortData { 32 pub fn new() -> Self { 33 let (sender, receiver) = mpsc::channel::<u8>(TTY_PORT_BUFSIZE); 34 Self { 35 flags: 0, 36 iflags: TtyPortState::Initialized, 37 sender, 38 receiver, 39 tty: Weak::new(), 40 internal_tty: Weak::new(), 41 } 42 } 43 44 pub fn internal_tty(&self) -> Option<Arc<TtyCore>> { 45 self.internal_tty.upgrade() 46 } 47 48 pub fn tty(&self) -> Option<Arc<TtyCore>> { 49 self.tty.upgrade() 50 } 51 } 52 53 #[allow(dead_code)] 54 #[derive(Debug, PartialEq, Clone, Copy)] 55 pub enum TtyPortState { 56 Initialized, 57 Suspended, 58 Active, 59 CtsFlow, 60 CheckCD, 61 KOPENED, 62 } 63 64 pub trait TtyPort: Sync + Send + Debug { 65 fn port_data(&self) -> SpinLockGuard<TtyPortData>; 66 67 /// 获取Port的状态 68 fn state(&self) -> TtyPortState { 69 self.port_data().iflags 70 } 71 72 /// 为port设置tty 73 fn setup_internal_tty(&self, tty: Weak<TtyCore>) { 74 self.port_data().internal_tty = tty; 75 } 76 77 /// 作为客户端的tty ports接收数据 78 fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> { 79 let tty = self.port_data().internal_tty().unwrap(); 80 81 let ld = tty.ldisc(); 82 83 let ret = ld.receive_buf2(tty.clone(), buf, None, count); 84 if ret.is_err() && ret.clone().unwrap_err() == SystemError::ENOSYS { 85 return ld.receive_buf(tty, buf, None, count); 86 } 87 88 ret 89 } 90 } 91 92 #[derive(Debug)] 93 pub struct DefaultTtyPort { 94 port_data: SpinLock<TtyPortData>, 95 } 96 97 impl DefaultTtyPort { 98 pub fn new() -> Self { 99 Self { 100 port_data: SpinLock::new(TtyPortData::new()), 101 } 102 } 103 } 104 105 impl TtyPort for DefaultTtyPort { 106 fn port_data(&self) -> SpinLockGuard<TtyPortData> { 107 self.port_data.lock_irqsave() 108 } 109 } 110