xref: /DragonOS/kernel/src/driver/tty/termios.rs (revision a8753f8fffb992e4d3bbd21eda431081b395af6b)
1 use super::tty_ldisc::LineDisciplineType;
2 
3 /// ## 窗口大小
4 #[repr(C)]
5 #[derive(Debug, Clone, Copy, PartialEq)]
6 pub struct WindowSize {
7     /// 行
8     pub row: u16,
9     /// 列
10     pub col: u16,
11     /// x方向像素数
12     pub xpixel: u16,
13     /// y方向像素数
14     pub ypixel: u16,
15 }
16 
17 impl WindowSize {
18     pub const DEFAULT: WindowSize = WindowSize::new(24, 80, 1, 1);
19     pub const fn new(row: u16, col: u16, xpixel: u16, ypixel: u16) -> Self {
20         Self {
21             row,
22             col,
23             xpixel,
24             ypixel,
25         }
26     }
27 }
28 
29 impl Default for WindowSize {
30     fn default() -> Self {
31         Self::DEFAULT
32     }
33 }
34 
35 #[derive(Debug, Clone, Copy)]
36 pub struct Termios {
37     pub input_mode: InputMode,
38     pub output_mode: OutputMode,
39     pub control_mode: ControlMode,
40     pub local_mode: LocalMode,
41     pub control_characters: [u8; CONTORL_CHARACTER_NUM],
42     pub line: LineDisciplineType,
43     pub input_speed: u32,
44     pub output_speed: u32,
45 }
46 
47 #[derive(Clone, Copy, Default)]
48 pub struct PosixTermios {
49     pub c_iflag: u32,
50     pub c_oflag: u32,
51     pub c_cflag: u32,
52     pub c_lflag: u32,
53     pub c_cc: [u8; CONTORL_CHARACTER_NUM],
54     pub c_line: u8,
55     pub c_ispeed: u32,
56     pub c_ospeed: u32,
57 }
58 
59 impl PosixTermios {
60     pub fn from_kernel_termios(termios: Termios) -> Self {
61         Self {
62             c_iflag: termios.input_mode.bits,
63             c_oflag: termios.output_mode.bits,
64             c_cflag: termios.control_mode.bits,
65             c_lflag: termios.local_mode.bits,
66             c_cc: termios.control_characters,
67             c_line: termios.line as u8,
68             c_ispeed: termios.input_speed,
69             c_ospeed: termios.output_speed,
70         }
71     }
72 
73     pub fn to_kernel_termios(self) -> Termios {
74         // TODO:这里没有考虑非规范模式
75         Termios {
76             input_mode: InputMode::from_bits_truncate(self.c_iflag),
77             output_mode: OutputMode::from_bits_truncate(self.c_oflag),
78             control_mode: ControlMode::from_bits_truncate(self.c_cflag),
79             local_mode: LocalMode::from_bits_truncate(self.c_lflag),
80             control_characters: self.c_cc,
81             line: LineDisciplineType::from_line(self.c_line),
82             input_speed: self.c_ispeed,
83             output_speed: self.c_ospeed,
84         }
85     }
86 }
87 
88 pub const INIT_CONTORL_CHARACTERS: [u8; CONTORL_CHARACTER_NUM] = [
89     b'C' - 0x40,  // VINTR
90     b'\\' - 0x40, // VQUIT
91     0o177,        // VERASE
92     b'U' - 0x40,  // VKILL
93     b'D' - 0x40,  // VEOF
94     1,            // VMIN
95     0,            // VEOL
96     0,            // VTIME
97     0,            // VEOL2
98     0,            // VSWTC
99     b'W' - 0x40,  // VWERASE
100     b'R' - 0x40,  // VREPRINT
101     b'Z' - 0x40,  // VSUSP
102     b'Q' - 0x40,  // VSTART
103     b'S' - 0x40,  // VSTOP
104     b'V' - 0x40,  // VLNEXT
105     b'O' - 0x40,  // VDISCARD
106     0,
107     0,
108 ];
109 
110 // pub const INIT_CONTORL_CHARACTERS: [u8; CONTORL_CHARACTER_NUM] = {
111 //     let mut chs: [u8; CONTORL_CHARACTER_NUM] = Default::default();
112 //     chs[ControlCharIndex::VINTR] = b'C' - 0x40;
113 //     chs[ControlCharIndex::VQUIT] = b'\\' - 0x40;
114 //     chs[ControlCharIndex::VERASE] = 0o177;
115 //     chs[ControlCharIndex::VKILL] = b'U' - 0x40;
116 //     chs[ControlCharIndex::VEOF] = b'D' - 0x40;
117 //     chs[ControlCharIndex::VSTART] = b'Q' - 0x40;
118 //     chs[ControlCharIndex::VSTOP] = b'S' - 0x40;
119 //     chs[ControlCharIndex::VSUSP] = b'Z' - 0x40;
120 //     chs[ControlCharIndex::VREPRINT] = b'R' - 0x40;
121 //     chs[ControlCharIndex::VDISCARD] = b'O' - 0x40;
122 //     chs[ControlCharIndex::VWERASE] = b'W' - 0x40;
123 //     chs[ControlCharIndex::VLNEXT] = b'V' - 0x40;
124 //     // chs[ContorlCharIndex::VDSUSP] = b'Y'  - 0x40;
125 //     chs[ControlCharIndex::VMIN] = 1;
126 //     return chs;
127 // };
128 
129 lazy_static! {
130     pub static ref TTY_STD_TERMIOS: Termios = {
131         Termios {
132             input_mode: InputMode::ICRNL | InputMode::IXON,
133             output_mode: OutputMode::OPOST | OutputMode::ONLCR,
134             control_mode: ControlMode::B38400
135                 | ControlMode::CREAD
136                 | ControlMode::HUPCL
137                 | ControlMode::CS8,
138             local_mode: LocalMode::ISIG
139                 | LocalMode::ICANON
140                 | LocalMode::ECHO
141                 | LocalMode::ECHOE
142                 | LocalMode::ECHOK
143                 | LocalMode::ECHOCTL
144                 | LocalMode::ECHOKE
145                 | LocalMode::IEXTEN,
146             control_characters: INIT_CONTORL_CHARACTERS,
147             line: LineDisciplineType::NTty,
148             input_speed: 38400,
149             output_speed: 38400,
150         }
151     };
152 }
153 
154 pub const CONTORL_CHARACTER_NUM: usize = 19;
155 
156 bitflags! {
157     /// termios输入特性
158     pub struct InputMode: u32 {
159         /// 如果设置了该标志,表示启用软件流控制。
160         const IXON = 0x0400;
161         /// 如果设置了该标志,表示启用输入流控制。
162         const IXOFF = 0x1000;
163         /// Map Uppercase to Lowercase on Input 将大写转换为小写
164         /// 表示不区分大小写
165         const IUCLC = 0x0200;
166         /// 如果设置了该标志,表示当输入队列满时,产生一个响铃信号。
167         const IMAXBEL = 0x2000;
168         /// 如果设置了该标志,表示输入数据被视为 UTF-8 编码。
169         const IUTF8 = 0x4000;
170 
171         /// 忽略中断信号
172         const IGNBRK	= 0x001;
173         /// 检测到中断信号时生成中断(产生中断信号)
174         const BRKINT	= 0x002;
175         /// 忽略具有奇偶校验错误的字符
176         const IGNPAR	= 0x004;
177         /// 在检测到奇偶校验错误或帧错误时,将字符以 \377 标记
178         const PARMRK	= 0x008;
179         /// 启用输入奇偶校验检查
180         const INPCK	= 0x010;
181         /// 从输入字符中剥离第 8 位,即只保留低 7 位
182         const ISTRIP	= 0x020;
183         /// 表示将输入的换行符 (\n) 映射为回车符 (\r)
184         const INLCR	= 0x040;
185         /// 表示忽略回车符 (\r)
186         const IGNCR	= 0x080;
187         /// 表示将输入的回车符 (\r) 映射为换行符 (\n)
188         const ICRNL	= 0x100;
189         /// 表示在输入被停止(Ctrl-S)后,任何字符的输入都将重新启动输入
190         const IXANY	= 0x800;
191     }
192 
193     /// termios输出特性
194     pub struct OutputMode: u32 {
195         /// 在输出时将换行符替换\r\n
196         const ONLCR	= 0x00004;
197         /// Map Lowercase to Uppercase on Output 输出字符时将小写字母映射为大写字母
198         const OLCUC	= 0x00002;
199 
200         /// 与NL协同 配置换行符的处理方式
201         const NLDLY	= 0x00100;
202         const   NL0	= 0x00000;  // 不延迟换行
203         const   NL1	= 0x00100;  // 延迟换行(输出回车后等待一段时间再输出换行)
204 
205         /// 配置水平制表符的处理方式
206         const TABDLY = 0x01800;
207         const  TAB0 = 0x00000;  // 不延迟水平制表符
208         const  TAB1 = 0x00800;  // 在输出水平制表符时,延迟到下一个设置的水平制表符位置
209         const  TAB2 = 0x01000;  // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置
210         const  TAB3 = 0x01800;  // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用
211         const XTABS = 0x01800;
212 
213         /// 配置回车符的处理方式
214         const CRDLY	= 0x00600;
215         const   CR0	= 0x00000;  // 不延迟回车
216         const   CR1	= 0x02000;  //  延迟回车(输出回车后等待一段时间再输出换行)
217         const   CR2	= 0x04000;  // CR2 和 CR3保留,暂未使用
218         const   CR3	= 0x06000;
219 
220         /// 配置换页符(form feed)的处理方式
221         const FFDLY	= 0x08000;
222         const   FF0	= 0x00000;  // 不延迟换页
223         const   FF1	= 0x08000;  // 延迟换页
224 
225         /// 配置退格符(backspace)的处理方式
226         const BSDLY	= 0x02000;
227         const   BS0	= 0x00000;  // 不延迟退格
228         const   BS1	= 0x02000;  // 延迟退格
229 
230         /// 配置垂直制表符(vertical tab)的处理方式
231         const VTDLY	= 0x04000;
232         const   VT0	= 0x00000;  // 不延迟垂直制表符
233         const   VT1	= 0x04000;  // 延迟垂直制表符
234 
235         /// 表示执行输出处理,即启用输出处理函数
236         const OPOST	= 0x01;
237         /// 表示将输出的回车符 (\r) 映射为换行符 (\n)
238         const OCRNL	= 0x08;
239         /// 表示在输出时,如果光标在第 0 列,则不输出回车符 (\r)
240         const ONOCR	= 0x10;
241         /// 表示将回车符 (\r) 映射为换行符 (\n)
242         const ONLRET	= 0x20;
243         /// 表示使用填充字符进行延迟。这个填充字符的默认值是空格。
244         const OFILL	= 0x40;
245         /// 表示使用删除字符 (DEL, \177) 作为填充字符
246         const OFDEL	= 0x80;
247     }
248 
249     /// 配置终端设备的基本特性和控制参数
250     pub struct ControlMode: u32 {
251         /// Baud Rate Mask 指定波特率的掩码
252         const CBAUD		= 0x0000100f;
253         /// Extra Baud Bits 指定更高的波特率位
254         const CBAUDEX	= 0x00001000;
255         /// Custom Baud Rate 指定自定义波特率 如果设置了 BOTHER,则通过以下位来设置自定义的波特率值
256         const BOTHER	= 0x00001000;
257 
258         /* Common CBAUD rates */
259         const     B0	= 0x00000000;	/* hang up */
260         const    B50	= 0x00000001;
261         const    B75	= 0x00000002;
262         const   B110	= 0x00000003;
263         const   B134	= 0x00000004;
264         const   B150	= 0x00000005;
265         const   B200	= 0x00000006;
266         const   B300	= 0x00000007;
267         const   B600	= 0x00000008;
268         const  B1200	= 0x00000009;
269         const  B1800	= 0x0000000a;
270         const  B2400	= 0x0000000b;
271         const  B4800	= 0x0000000c;
272         const  B9600	= 0x0000000d;
273         const B19200	= 0x0000000e;
274         const B38400	= 0x0000000f;
275 
276         const     B57600 = 0x00001001;
277         const    B115200 = 0x00001002;
278         const    B230400 = 0x00001003;
279         const    B460800 = 0x00001004;
280         const    B500000 = 0x00001005;
281         const    B576000 = 0x00001006;
282         const    B921600 = 0x00001007;
283         const   B1000000 = 0x00001008;
284         const   B1152000 = 0x00001009;
285         const   B1500000 = 0x0000100a;
286         const   B2000000 = 0x0000100b;
287         const   B2500000 = 0x0000100c;
288         const   B3000000 = 0x0000100d;
289         const   B3500000 = 0x0000100e;
290         const   B4000000 = 0x0000100f;
291 
292         /// 指定字符大小的掩码 以下位为特定字符大小
293         const CSIZE		= 0x00000030;
294         const   CS5		= 0x00000000;
295         const   CS6		= 0x00000010;
296         const   CS7		= 0x00000020;
297         const   CS8		= 0x00000030;
298 
299         /// Stop Bit Select 表示使用两个停止位;否则,表示使用一个停止位
300         const CSTOPB	= 0x00000040;
301         /// 表示启用接收器。如果未设置,则禁用接收器。
302         const CREAD		= 0x00000080;
303         /// 表示启用奇偶校验。如果未设置,则禁用奇偶校验。
304         const PARENB	= 0x00000100;
305         /// 表示启用奇校验。如果未设置,则表示启用偶校验。
306         const PARODD	= 0x00000200;
307         /// 表示在终端设备被关闭时挂断线路(执行挂断操作)
308         const HUPCL		= 0x00000400;
309         /// 表示忽略调制解调器的状态(DCD、DSR、CTS 等)
310         const CLOCAL	= 0x00000800;
311         /// 指定输入波特率的掩码
312         const CIBAUD	= 0x100f0000;
313 
314         const ADDRB = 0x20000000;
315     }
316 
317     /// 配置终端设备的本地模式(local mode)或控制输入处理的行为
318     pub struct LocalMode: u32 {
319         /// 启用中断字符(Ctrl-C、Ctrl-Z)
320         const ISIG	 = 0x00001;
321         /// 表示启用规范模式,即启用行缓冲和回显。在规范模式下,输入被缓冲,并且只有在输入回车符时才会传递给应用程序。
322         const ICANON = 0x00002;
323         /// 表示启用大写模式,即输入输出都将被转换为大写。
324         const XCASE	 = 0x00004;
325         /// 表示启用回显(显示用户输入的字符)
326         const ECHO	 = 0x00008;
327         /// 表示在回显时将擦除的字符用 backspace 和空格字符显示。
328         const ECHOE	 = 0x00010;
329         /// 表示在回显时将换行符后的字符用空格字符显示。
330         const ECHOK	 = 0x00020;
331         /// 表示在回显时将换行符显示为换行和回车符。
332         const ECHONL = 0x00040;
333         /// 表示在收到中断(Ctrl-C)和退出(Ctrl-\)字符后,不清空输入和输出缓冲区。
334         const NOFLSH = 0x00080;
335         /// 表示在后台进程尝试写入终端时,发送停止信号(Ctrl-S)
336         const TOSTOP = 0x00100;
337         /// 表示在回显时,显示控制字符为 ^ 加字符。
338         const ECHOCTL= 0x00200;
339         /// 表示在回显时显示带有 # 的换行符(为了与 echo -n 命令兼容)。
340         const ECHOPRT= 0x00400;
341         /// 表示在回显时将 KILL 字符(Ctrl-U)用空格字符显示。
342         const ECHOKE = 0x00800;
343         /// 表示输出正在被冲刷(flush),通常是由于输入/输出流的状态变化。
344         const FLUSHO = 0x01000;
345         /// 表示在规范模式下,存在需要重新打印的字符。
346         const PENDIN = 0x04000;
347         /// 表示启用实现定义的输入处理。
348         const IEXTEN = 0x08000;
349         /// 表示启用扩展的处理函数
350         const EXTPROC= 0x10000;
351     }
352 
353     pub struct TtySetTermiosOpt: u8 {
354         const TERMIOS_FLUSH	=1;
355         const TERMIOS_WAIT	=2;
356         const TERMIOS_TERMIO	=4;
357         const TERMIOS_OLD	=8;
358     }
359 }
360 
361 /// 对应termios中控制字符的索引
362 pub struct ControlCharIndex;
363 #[allow(dead_code)]
364 impl ControlCharIndex {
365     pub const DISABLE_CHAR: u8 = b'\0';
366     /// 中断信号
367     pub const VINTR: usize = 0;
368     /// 退出信号
369     pub const VQUIT: usize = 1;
370     /// 退格
371     pub const VERASE: usize = 2;
372     /// 终止输入信号
373     pub const VKILL: usize = 3;
374     /// 文件结束信号 \0?
375     pub const VEOF: usize = 4;
376     /// 指定非规范模式下的最小字符数
377     pub const VMIN: usize = 5;
378     /// 换行符
379     pub const VEOL: usize = 6;
380     /// 指定非规范模式下的超时时间
381     pub const VTIME: usize = 7;
382     /// 换行符
383     pub const VEOL2: usize = 8;
384     /// 未使用,保留
385     pub const VSWTC: usize = 9;
386     /// 擦除前一个单词
387     pub const VWERASE: usize = 10;
388     /// 重新打印整行
389     pub const VREPRINT: usize = 11;
390     /// 挂起信号
391     pub const VSUSP: usize = 12;
392     /// 启动输出信号
393     pub const VSTART: usize = 13;
394     /// 停止输出信号
395     pub const VSTOP: usize = 14;
396     /// 将下一个字符视为字面值,而不是特殊字符
397     pub const VLNEXT: usize = 15;
398     /// 对应于字符丢弃信号,用于丢弃当前输入的行
399     pub const VDISCARD: usize = 16;
400 }
401