tty_core.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. use core::{fmt::Debug, sync::atomic::AtomicBool};
  2. use alloc::{string::String, sync::Arc, vec::Vec};
  3. use system_error::SystemError;
  4. use crate::{
  5. libs::{
  6. rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
  7. spinlock::{SpinLock, SpinLockGuard},
  8. wait_queue::EventWaitQueue,
  9. },
  10. mm::VirtAddr,
  11. net::event_poll::EPollEventType,
  12. process::Pid,
  13. syscall::user_access::UserBufferWriter,
  14. };
  15. use super::{
  16. termios::{ControlMode, PosixTermios, Termios, TtySetTermiosOpt, WindowSize},
  17. tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
  18. tty_ldisc::{
  19. ntty::{NTtyData, NTtyLinediscipline},
  20. TtyLineDiscipline,
  21. },
  22. tty_port::TtyPort,
  23. virtual_terminal::{virtual_console::VirtualConsoleData, VIRT_CONSOLES},
  24. };
  25. #[derive(Debug)]
  26. pub struct TtyCore {
  27. core: TtyCoreData,
  28. /// 线路规程函数集
  29. line_discipline: Arc<dyn TtyLineDiscipline>,
  30. }
  31. impl TtyCore {
  32. pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
  33. let name = driver.tty_line_name(index);
  34. let termios = driver.init_termios();
  35. let core = TtyCoreData {
  36. tty_driver: driver,
  37. termios: RwLock::new(termios),
  38. name,
  39. flags: RwLock::new(TtyFlag::empty()),
  40. count: RwLock::new(0),
  41. window_size: RwLock::new(WindowSize::default()),
  42. read_wq: EventWaitQueue::new(),
  43. write_wq: EventWaitQueue::new(),
  44. port: RwLock::new(None),
  45. index,
  46. ctrl: SpinLock::new(TtyContorlInfo::default()),
  47. closing: AtomicBool::new(false),
  48. flow: SpinLock::new(TtyFlowState::default()),
  49. };
  50. return Arc::new(Self {
  51. core,
  52. line_discipline: Arc::new(NTtyLinediscipline {
  53. data: SpinLock::new(NTtyData::new()),
  54. }),
  55. });
  56. }
  57. #[inline]
  58. pub fn core(&self) -> &TtyCoreData {
  59. return &self.core;
  60. }
  61. #[inline]
  62. pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
  63. self.line_discipline.clone()
  64. }
  65. pub fn reopen(&self) -> Result<(), SystemError> {
  66. let tty_core = self.core();
  67. let driver = tty_core.driver();
  68. if driver.tty_driver_type() == TtyDriverType::Pty
  69. && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster
  70. {
  71. return Err(SystemError::EIO);
  72. }
  73. // if *tty_core.count.read() == 0 {
  74. // return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
  75. // }
  76. // TODO 判断flags
  77. tty_core.add_count();
  78. Ok(())
  79. }
  80. #[inline]
  81. pub fn set_port(&self, port: Arc<dyn TtyPort>) {
  82. *self.core.port.write() = Some(port);
  83. }
  84. pub fn tty_start(&self) {
  85. let mut flow = self.core.flow.lock_irqsave();
  86. if !flow.stopped || flow.tco_stopped {
  87. return;
  88. }
  89. flow.stopped = false;
  90. let _ = self.start(self.core());
  91. self.tty_wakeup();
  92. }
  93. pub fn tty_stop(&self) {
  94. let mut flow = self.core.flow.lock_irqsave();
  95. if flow.stopped {
  96. return;
  97. }
  98. flow.stopped = true;
  99. let _ = self.stop(self.core());
  100. }
  101. pub fn tty_wakeup(&self) {
  102. if self.core.flags.read().contains(TtyFlag::DO_WRITE_WAKEUP) {
  103. let _ = self.ldisc().write_wakeup(self.core());
  104. }
  105. self.core()
  106. .write_wq
  107. .wakeup(EPollEventType::EPOLLOUT.bits() as u64);
  108. }
  109. pub fn tty_mode_ioctl(
  110. &self,
  111. tty: Arc<TtyCore>,
  112. cmd: u32,
  113. arg: usize,
  114. ) -> Result<usize, SystemError> {
  115. match cmd {
  116. TtyIoctlCmd::TCGETS => {
  117. let termios = PosixTermios::from_kernel_termios(self.core.termios().clone());
  118. let mut user_writer = UserBufferWriter::new(
  119. VirtAddr::new(arg).as_ptr::<PosixTermios>(),
  120. core::mem::size_of::<PosixTermios>(),
  121. true,
  122. )?;
  123. user_writer.copy_one_to_user(&termios, 0)?;
  124. return Ok(0);
  125. }
  126. TtyIoctlCmd::TCSETSW => {
  127. return self.core_set_termios(
  128. tty,
  129. VirtAddr::new(arg),
  130. TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_OLD,
  131. );
  132. }
  133. _ => {
  134. return Err(SystemError::ENOIOCTLCMD);
  135. }
  136. }
  137. }
  138. pub fn core_set_termios(
  139. &self,
  140. tty: Arc<TtyCore>,
  141. arg: VirtAddr,
  142. opt: TtySetTermiosOpt,
  143. ) -> Result<usize, SystemError> {
  144. let tmp_termios = self.core().termios().clone();
  145. if opt.contains(TtySetTermiosOpt::TERMIOS_TERMIO) {
  146. todo!()
  147. } else {
  148. let mut user_writer = UserBufferWriter::new(
  149. arg.as_ptr::<PosixTermios>(),
  150. core::mem::size_of::<PosixTermios>(),
  151. true,
  152. )?;
  153. user_writer.copy_one_to_user(&tmp_termios, 0)?;
  154. }
  155. if opt.contains(TtySetTermiosOpt::TERMIOS_FLUSH) {
  156. let ld = self.ldisc();
  157. let _ = ld.flush_buffer(tty.clone());
  158. }
  159. if opt.contains(TtySetTermiosOpt::TERMIOS_WAIT) {
  160. // TODO
  161. }
  162. self.set_termios_next(tty, tmp_termios)?;
  163. Ok(0)
  164. }
  165. pub fn set_termios_next(
  166. &self,
  167. tty: Arc<TtyCore>,
  168. new_termios: Termios,
  169. ) -> Result<(), SystemError> {
  170. let mut termios = self.core().termios_write();
  171. let old_termios = termios.clone();
  172. *termios = new_termios;
  173. let tmp = termios.control_mode;
  174. termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
  175. let ret = self.set_termios(tty.clone(), old_termios);
  176. if ret.is_err() {
  177. termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
  178. termios.control_mode |= old_termios.control_mode
  179. & !(ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL);
  180. termios.input_speed = old_termios.input_speed;
  181. termios.output_speed = old_termios.output_speed;
  182. }
  183. drop(termios);
  184. let ld = self.ldisc();
  185. ld.set_termios(tty, Some(old_termios))?;
  186. Ok(())
  187. }
  188. }
  189. #[derive(Debug)]
  190. pub struct TtyContorlInfo {
  191. /// 前台进程pid
  192. pub session: Option<Pid>,
  193. /// 前台进程组id
  194. pub pgid: Option<Pid>,
  195. /// packet模式下使用,目前未用到
  196. pub pktstatus: u8,
  197. pub packet: bool,
  198. }
  199. impl Default for TtyContorlInfo {
  200. fn default() -> Self {
  201. Self {
  202. session: None,
  203. pgid: None,
  204. pktstatus: Default::default(),
  205. packet: Default::default(),
  206. }
  207. }
  208. }
  209. #[derive(Debug, Default)]
  210. pub struct TtyCoreWriteData {
  211. /// 写缓冲区
  212. pub write_buf: Vec<u8>,
  213. /// 写入数量
  214. pub write_cnt: usize,
  215. }
  216. #[derive(Debug, Default)]
  217. pub struct TtyFlowState {
  218. /// 表示流控是否被停止
  219. pub stopped: bool,
  220. /// 表示 TCO(Transmit Continuous Operation)流控是否被停止
  221. pub tco_stopped: bool,
  222. }
  223. #[derive(Debug)]
  224. pub struct TtyCoreData {
  225. tty_driver: Arc<TtyDriver>,
  226. termios: RwLock<Termios>,
  227. name: String,
  228. flags: RwLock<TtyFlag>,
  229. /// 在初始化时即确定不会更改,所以这里不用加锁
  230. index: usize,
  231. count: RwLock<usize>,
  232. /// 窗口大小
  233. window_size: RwLock<WindowSize>,
  234. /// 读等待队列
  235. read_wq: EventWaitQueue,
  236. /// 写等待队列
  237. write_wq: EventWaitQueue,
  238. /// 端口
  239. port: RwLock<Option<Arc<dyn TtyPort>>>,
  240. /// 前台进程
  241. ctrl: SpinLock<TtyContorlInfo>,
  242. /// 是否正在关闭
  243. closing: AtomicBool,
  244. /// 流控状态
  245. flow: SpinLock<TtyFlowState>,
  246. }
  247. impl TtyCoreData {
  248. #[inline]
  249. pub fn driver(&self) -> Arc<TtyDriver> {
  250. self.tty_driver.clone()
  251. }
  252. #[inline]
  253. pub fn flow_irqsave(&self) -> SpinLockGuard<TtyFlowState> {
  254. self.flow.lock_irqsave()
  255. }
  256. #[inline]
  257. pub fn port(&self) -> Option<Arc<dyn TtyPort>> {
  258. self.port.read().clone()
  259. }
  260. #[inline]
  261. pub fn index(&self) -> usize {
  262. self.index
  263. }
  264. #[inline]
  265. pub fn name(&self) -> String {
  266. self.name.clone()
  267. }
  268. #[inline]
  269. pub fn flags(&self) -> TtyFlag {
  270. self.flags.read().clone()
  271. }
  272. #[inline]
  273. pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
  274. self.termios.read()
  275. }
  276. #[inline]
  277. pub fn termios_write(&self) -> RwLockWriteGuard<Termios> {
  278. self.termios.write()
  279. }
  280. #[inline]
  281. pub fn set_termios(&self, termios: Termios) {
  282. let mut termios_guard = self.termios.write();
  283. *termios_guard = termios;
  284. }
  285. #[inline]
  286. pub fn add_count(&self) {
  287. let mut guard = self.count.write();
  288. *guard += 1;
  289. }
  290. #[inline]
  291. pub fn read_wq(&self) -> &EventWaitQueue {
  292. &self.read_wq
  293. }
  294. #[inline]
  295. pub fn write_wq(&self) -> &EventWaitQueue {
  296. &self.write_wq
  297. }
  298. #[inline]
  299. pub fn contorl_info_irqsave(&self) -> SpinLockGuard<TtyContorlInfo> {
  300. self.ctrl.lock_irqsave()
  301. }
  302. #[inline]
  303. pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<WindowSize> {
  304. self.window_size.upgradeable_read()
  305. }
  306. #[inline]
  307. pub fn window_size(&self) -> RwLockReadGuard<WindowSize> {
  308. self.window_size.read()
  309. }
  310. #[inline]
  311. pub fn is_closing(&self) -> bool {
  312. self.closing.load(core::sync::atomic::Ordering::SeqCst)
  313. }
  314. #[inline]
  315. pub fn vc_data_irqsave(&self) -> SpinLockGuard<VirtualConsoleData> {
  316. VIRT_CONSOLES[self.index].lock_irqsave()
  317. }
  318. }
  319. /// TTY 核心接口,不同的tty需要各自实现这个trait
  320. pub trait TtyCoreFuncs: Debug + Send + Sync {}
  321. impl TtyOperation for TtyCore {
  322. #[inline]
  323. fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
  324. return self.core().tty_driver.driver_funcs().open(tty);
  325. }
  326. #[inline]
  327. fn write_room(&self, tty: &TtyCoreData) -> usize {
  328. return self.core().tty_driver.driver_funcs().write_room(tty);
  329. }
  330. #[inline]
  331. fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
  332. return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
  333. }
  334. #[inline]
  335. fn flush_chars(&self, tty: &TtyCoreData) {
  336. self.core().tty_driver.driver_funcs().flush_chars(tty);
  337. }
  338. #[inline]
  339. fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
  340. return self.core().tty_driver.driver_funcs().put_char(tty, ch);
  341. }
  342. #[inline]
  343. fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
  344. return self.core().tty_driver.driver_funcs().install(driver, tty);
  345. }
  346. #[inline]
  347. fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
  348. return self.core().tty_driver.driver_funcs().start(tty);
  349. }
  350. #[inline]
  351. fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
  352. return self.core().tty_driver.driver_funcs().stop(tty);
  353. }
  354. #[inline]
  355. fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
  356. return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg);
  357. }
  358. #[inline]
  359. fn chars_in_buffer(&self) -> usize {
  360. return self.core().tty_driver.driver_funcs().chars_in_buffer();
  361. }
  362. #[inline]
  363. fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> {
  364. return self
  365. .core()
  366. .tty_driver
  367. .driver_funcs()
  368. .set_termios(tty, old_termios);
  369. }
  370. }
  371. bitflags! {
  372. pub struct TtyFlag: u32 {
  373. /// 终端被节流
  374. const THROTTLED = 1 << 0;
  375. /// 终端输入输出错误状态
  376. const IO_ERROR = 1 << 1;
  377. /// 终端的其他一方已关闭
  378. const OTHER_CLOSED = 1 << 2;
  379. /// 终端处于独占状态
  380. const EXCLUSIVE = 1 << 3;
  381. /// 终端执行写唤醒操作
  382. const DO_WRITE_WAKEUP = 1 << 5;
  383. /// 终端线路驱动程序已打开
  384. const LDISC_OPEN = 1 << 11;
  385. /// 终端伪终端设备已锁定
  386. const PTY_LOCK = 1 << 16;
  387. /// 终端禁用写分裂操作
  388. const NO_WRITE_SPLIT = 1 << 17;
  389. /// 终端挂断(挂起)状态
  390. const HUPPED = 1 << 18;
  391. /// 终端正在挂断(挂起)
  392. const HUPPING = 1 << 19;
  393. /// 终端线路驱动程序正在更改
  394. const LDISC_CHANGING = 1 << 20;
  395. /// 终端线路驱动程序已停止
  396. const LDISC_HALTED = 1 << 22;
  397. }
  398. }
  399. #[derive(Debug, PartialEq)]
  400. pub enum EchoOperation {
  401. /// 开始特殊操作。
  402. Start,
  403. /// 向后移动光标列。
  404. MoveBackCol,
  405. /// 设置规范模式下的列位置。
  406. SetCanonCol,
  407. /// 擦除制表符。
  408. EraseTab,
  409. Undefined(u8),
  410. }
  411. impl EchoOperation {
  412. pub fn from_u8(num: u8) -> EchoOperation {
  413. match num {
  414. 0xff => Self::Start,
  415. 0x80 => Self::MoveBackCol,
  416. 0x81 => Self::SetCanonCol,
  417. 0x82 => Self::EraseTab,
  418. _ => Self::Undefined(num),
  419. }
  420. }
  421. pub fn to_u8(&self) -> u8 {
  422. match *self {
  423. EchoOperation::Start => 0xff,
  424. EchoOperation::MoveBackCol => 0x80,
  425. EchoOperation::SetCanonCol => 0x81,
  426. EchoOperation::EraseTab => 0x82,
  427. EchoOperation::Undefined(num) => num,
  428. }
  429. }
  430. }
  431. pub struct TtyIoctlCmd;
  432. #[allow(dead_code)]
  433. impl TtyIoctlCmd {
  434. /// 获取终端参数
  435. pub const TCGETS: u32 = 0x5401;
  436. /// 设置终端参数
  437. pub const TCSETS: u32 = 0x5402;
  438. /// 设置终端参数并等待所有输出完成
  439. pub const TCSETSW: u32 = 0x5403;
  440. /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
  441. pub const TCSETSF: u32 = 0x5404;
  442. /// 获取终端参数
  443. pub const TCGETA: u32 = 0x5405;
  444. /// 设置终端参数
  445. pub const TCSETA: u32 = 0x5406;
  446. /// 设置终端参数并等待所有输出完成
  447. pub const TCSETAW: u32 = 0x5407;
  448. /// 设置终端参数并且等待所有输出完成,但在这之前将终端清空
  449. pub const TCSETAF: u32 = 0x5408;
  450. /// 发送零字节,等待所有输出完成
  451. pub const TCSBRK: u32 = 0x5409;
  452. /// 控制终端的流控
  453. pub const TCXONC: u32 = 0x540A;
  454. /// 刷新输入/输出缓冲区或者丢弃输入缓冲区
  455. pub const TCFLSH: u32 = 0x540B;
  456. /// 设置设备为独占模式
  457. pub const TIOCEXCL: u32 = 0x540C;
  458. /// 设置设备为非独占模式
  459. pub const TIOCNXCL: u32 = 0x540D;
  460. /// 设置当前进程的控制终端
  461. pub const TIOCSCTTY: u32 = 0x540E;
  462. /// 获取前台进程组
  463. pub const TIOCGPGRP: u32 = 0x540F;
  464. ///设置前台进程组
  465. pub const TIOCSPGRP: u32 = 0x5410;
  466. /// 获取输出队列的字节数
  467. pub const TIOCOUTQ: u32 = 0x5411;
  468. /// 模拟从终端输入字符
  469. pub const TIOCSTI: u32 = 0x5412;
  470. /// 获取窗口大小
  471. pub const TIOCGWINSZ: u32 = 0x5413;
  472. /// 设置窗口大小
  473. pub const TIOCSWINSZ: u32 = 0x5414;
  474. /// 获取终端控制信号的状态
  475. pub const TIOCMGET: u32 = 0x5415;
  476. /// 设置终端控制信号的位
  477. pub const TIOCMBIS: u32 = 0x5416;
  478. /// 清除终端控制信号的位
  479. pub const TIOCMBIC: u32 = 0x5417;
  480. /// 设置终端控制信号的状态
  481. pub const TIOCMSET: u32 = 0x5418;
  482. /// 获取软件载波状态
  483. pub const TIOCGSOFTCAR: u32 = 0x5419;
  484. /// 设置软件载波状态
  485. pub const TIOCSSOFTCAR: u32 = 0x541A;
  486. /// 获取输入队列的字节数
  487. pub const FIONREAD: u32 = 0x541B;
  488. /// Linux 特有命令
  489. pub const TIOCLINUX: u32 = 0x541C;
  490. /// 获取控制台设备
  491. pub const TIOCCONS: u32 = 0x541D;
  492. /// 获取串行设备参数
  493. pub const TIOCGSERIAL: u32 = 0x541E;
  494. /// 设置串行设备参数
  495. pub const TIOCSSERIAL: u32 = 0x541F;
  496. /// 设置套接字的报文模式
  497. pub const TIOCPKT: u32 = 0x5420;
  498. /// 设置非阻塞 I/O
  499. pub const FIONBIO: u32 = 0x5421;
  500. /// 清除控制终端
  501. pub const TIOCNOTTY: u32 = 0x5422;
  502. /// 设置终端线路驱动器
  503. pub const TIOCSETD: u32 = 0x5423;
  504. /// 获取终端线路驱动器
  505. pub const TIOCGETD: u32 = 0x5424;
  506. /// 发送终止条件
  507. pub const TCSBRKP: u32 = 0x5425;
  508. /// 开始发送零比特
  509. pub const TIOCSBRK: u32 = 0x5427;
  510. /// 停止发送零比特
  511. pub const TIOCCBRK: u32 = 0x5428;
  512. /// Return the session ID of FD
  513. pub const TIOCGSID: u32 = 0x5429;
  514. }