tty_core.rs 20 KB

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