17
17
18
18
use core:: sync:: atomic:: { AtomicU32 , Ordering } ;
19
19
20
+ use aero_syscall as libc;
20
21
use aero_syscall:: { Termios , WinSize } ;
22
+
21
23
use alloc:: collections:: BTreeMap ;
22
24
use alloc:: string:: ToString ;
23
25
use alloc:: sync:: { Arc , Weak } ;
@@ -26,6 +28,7 @@ use spin::{Once, RwLock};
26
28
27
29
use uapi:: pty:: * ;
28
30
31
+ use crate :: arch:: user_copy:: UserRef ;
29
32
use crate :: fs:: cache:: * ;
30
33
use crate :: fs:: devfs:: DEV_FILESYSTEM ;
31
34
use crate :: fs:: inode:: { DirEntry , FileType , INodeInterface , PollFlags } ;
@@ -45,6 +48,55 @@ lazy_static::lazy_static! {
45
48
static PTS_FS : Once < Arc < PtsFs > > = Once :: new ( ) ;
46
49
static PTY_ID : AtomicU32 = AtomicU32 :: new ( 0 ) ;
47
50
51
+ #[ derive( Debug , Ioctl ) ]
52
+ pub enum TermiosCmd {
53
+ /// Get window size.
54
+ #[ command( libc:: TIOCGWINSZ ) ]
55
+ GetWinSize ( UserRef < WinSize > ) ,
56
+
57
+ /// Set window size.
58
+ #[ command( libc:: TIOCSWINSZ ) ]
59
+ SetWinSize ( UserRef < WinSize > ) ,
60
+
61
+ /// Get the current serial port settings.
62
+ ///
63
+ /// Equivalent to `tcgetattr(fd, argp)`.
64
+ #[ command( libc:: TCGETS ) ]
65
+ TcGets ( UserRef < Termios > ) ,
66
+
67
+ /// Allow the output buffer to drain, discard pending input, and set the current serial
68
+ /// port settings.
69
+ ///
70
+ /// Equivalent to `tcsetattr(fd, TCSAFLUSH, argp)`.
71
+ #[ command( libc:: TCSETSF ) ]
72
+ TcSetsf ( UserRef < Termios > ) ,
73
+
74
+ /// Allow the output buffer to drain, and set the current serial port settings.
75
+ ///
76
+ /// Equivalent to `tcsetattr(fd, TCSADRAIN, argp)`.
77
+ #[ command( libc:: TCSETSW ) ]
78
+ TcSetsw ( UserRef < Termios > ) ,
79
+
80
+ /// Make the given terminal the controlling terminal of the calling process. The calling
81
+ /// process must be a session leader and not have a controlling terminal already. For this
82
+ /// case, arg should be specified as zero.
83
+ ///
84
+ /// If this terminal is already the controlling terminal of a different session group, then the
85
+ /// ioctl fails with EPERM, unless the caller has the CAP_SYS_ADMIN capability and arg equals
86
+ /// 1, in which case the terminal is stolen, and all processes that had it as controlling
87
+ /// terminal lose it.
88
+ // FIXME: argument usize
89
+ #[ command( libc:: TIOCSCTTY ) ]
90
+ SetCtrlTerm ,
91
+
92
+ /// Get the process group ID of the foreground process group on this terminal.
93
+ ///
94
+ /// When successful, equivalent to `*argp = tcgetpgrp(fd)`.
95
+ // FIXME: argument usize
96
+ #[ command( libc:: TIOCGPGRP ) ]
97
+ GetProcGroupId ,
98
+ }
99
+
48
100
struct Master {
49
101
id : u32 ,
50
102
wq : WaitQueue ,
@@ -65,6 +117,16 @@ impl Master {
65
117
discipline : LineDiscipline :: new ( ) ,
66
118
}
67
119
}
120
+
121
+ #[ inline]
122
+ fn set_window_size ( & self , size : WinSize ) {
123
+ * self . window_size . lock_irq ( ) = size;
124
+ }
125
+
126
+ #[ inline]
127
+ fn get_window_size ( & self ) -> WinSize {
128
+ * self . window_size . lock_irq ( )
129
+ }
68
130
}
69
131
70
132
impl INodeInterface for Master {
@@ -180,58 +242,29 @@ impl INodeInterface for Slave {
180
242
}
181
243
182
244
fn ioctl ( & self , command : usize , arg : usize ) -> fs:: Result < usize > {
183
- match command {
184
- aero_syscall:: TIOCGWINSZ => {
185
- let winsize = VirtAddr :: new ( arg as u64 ) . read_mut :: < WinSize > ( ) ?;
186
- * winsize = * self . master . window_size . lock_irq ( ) ;
187
-
188
- Ok ( 0 )
189
- }
190
-
191
- aero_syscall:: TIOCSWINSZ => {
192
- * self . master . window_size . lock_irq ( ) = * VirtAddr :: new ( arg as u64 ) . read_mut ( ) ?;
193
- Ok ( 0 )
194
- }
195
-
196
- aero_syscall:: TCGETS => {
197
- let termios = VirtAddr :: new ( arg as u64 ) . read_mut :: < Termios > ( ) ?;
198
- * termios = self . master . discipline . termios ( ) ;
199
-
200
- Ok ( 0 )
201
- }
202
-
203
- aero_syscall:: TCSETSF => {
204
- let termios = VirtAddr :: new ( arg as u64 ) . read_mut :: < Termios > ( ) ?;
205
- self . master . discipline . set_termios ( termios. clone ( ) ) ;
206
-
207
- Ok ( 0 )
208
- }
209
-
210
- aero_syscall:: TCSETSW => {
245
+ match TermiosCmd :: from_command_arg ( command, arg) {
246
+ TermiosCmd :: GetWinSize ( mut size) => * size = self . master . get_window_size ( ) ,
247
+ TermiosCmd :: SetWinSize ( size) => self . master . set_window_size ( * size) ,
248
+ TermiosCmd :: TcGets ( mut termios) => * termios = self . master . discipline . termios ( ) ,
249
+ TermiosCmd :: TcSetsf ( termios) => self . master . discipline . set_termios ( * termios) ,
250
+ TermiosCmd :: TcSetsw ( termios) => {
211
251
// TODO: Allow the output buffer to drain and then set the current serial port
212
252
// settings.
213
- //
214
- // Equivalent to tcsetattr(fd, TCSADRAIN, argp).
215
- let termios = VirtAddr :: new ( arg as u64 ) . read_mut :: < Termios > ( ) ?;
216
- self . master . discipline . set_termios ( termios. clone ( ) ) ;
217
-
218
- Ok ( 0 )
253
+ self . master . discipline . set_termios ( * termios)
219
254
}
220
255
221
- aero_syscall :: TIOCSCTTY => {
256
+ TermiosCmd :: SetCtrlTerm => {
222
257
let current_task = scheduler:: get_scheduler ( ) . current_task ( ) ;
223
258
assert ! ( current_task. is_session_leader( ) ) ;
224
259
225
260
current_task. attach ( self . sref ( ) ) ;
226
- Ok ( 0 )
227
261
}
228
262
229
- // TIOCGPGRP - Get the process group ID of the foreground process group on this
230
- // terminal.
231
- 0x540f => Err ( FileSystemError :: NotSupported ) ,
232
-
233
- _ => panic ! ( "pty: unknown ioctl: {command}" ) ,
263
+ // FIXME: the following ioctls are not implemented.
264
+ TermiosCmd :: GetProcGroupId => return Err ( FileSystemError :: NotSupported ) ,
234
265
}
266
+
267
+ Ok ( 0 )
235
268
}
236
269
237
270
fn poll ( & self , table : Option < & mut fs:: inode:: PollTable > ) -> fs:: Result < PollFlags > {
@@ -250,9 +283,7 @@ impl INodeInterface for Slave {
250
283
}
251
284
252
285
fn read_at ( & self , _offset : usize , buffer : & mut [ u8 ] ) -> fs:: Result < usize > {
253
- let x = self . master . discipline . read ( buffer) ?;
254
- dbg ! ( core:: str :: from_utf8( & buffer[ ..x] ) ) ;
255
- Ok ( x)
286
+ Ok ( self . master . discipline . read ( buffer) ?)
256
287
}
257
288
258
289
fn write_at ( & self , _offset : usize , buffer : & [ u8 ] ) -> fs:: Result < usize > {
0 commit comments