Lines Matching +full:master +full:- +full:side

1 // SPDX-License-Identifier: GPL-2.0
5 * Added support for a Unix98-style ptmx device.
6 * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
49 if (tty->driver->subtype == PTY_TYPE_MASTER) in pty_close()
50 WARN_ON(tty->count > 1); in pty_close()
54 if (tty->count > 2) in pty_close()
57 set_bit(TTY_IO_ERROR, &tty->flags); in pty_close()
58 wake_up_interruptible(&tty->read_wait); in pty_close()
59 wake_up_interruptible(&tty->write_wait); in pty_close()
60 spin_lock_irq(&tty->ctrl.lock); in pty_close()
61 tty->ctrl.packet = false; in pty_close()
62 spin_unlock_irq(&tty->ctrl.lock); in pty_close()
63 /* Review - krefs on tty_link ?? */ in pty_close()
64 if (!tty->link) in pty_close()
66 set_bit(TTY_OTHER_CLOSED, &tty->link->flags); in pty_close()
67 wake_up_interruptible(&tty->link->read_wait); in pty_close()
68 wake_up_interruptible(&tty->link->write_wait); in pty_close()
69 if (tty->driver->subtype == PTY_TYPE_MASTER) { in pty_close()
70 set_bit(TTY_OTHER_CLOSED, &tty->flags); in pty_close()
72 if (tty->driver == ptm_driver) { in pty_close()
74 if (tty->link->driver_data) in pty_close()
75 devpts_pty_kill(tty->link->driver_data); in pty_close()
79 tty_vhangup(tty->link); in pty_close()
95 tty_wakeup(tty->link); in pty_unthrottle()
96 set_bit(TTY_THROTTLED, &tty->flags); in pty_unthrottle()
100 * pty_write - write to a pty
108 * the other side of the pty/tty pair.
113 struct tty_struct *to = tty->link; in pty_write()
116 if (tty->flow.stopped) in pty_write()
120 spin_lock_irqsave(&to->port->lock, flags); in pty_write()
122 c = tty_insert_flip_string(to->port, buf, c); in pty_write()
123 spin_unlock_irqrestore(&to->port->lock, flags); in pty_write()
126 tty_flip_buffer_push(to->port); in pty_write()
132 * pty_write_room - write space
141 if (tty->flow.stopped) in pty_write_room()
143 return tty_buffer_space_avail(tty->link->port); in pty_write_room()
152 return -EFAULT; in pty_set_lock()
154 set_bit(TTY_PTY_LOCK, &tty->flags); in pty_set_lock()
156 clear_bit(TTY_PTY_LOCK, &tty->flags); in pty_set_lock()
162 int locked = test_bit(TTY_PTY_LOCK, &tty->flags); in pty_get_lock()
173 return -EFAULT; in pty_set_pktmode()
175 spin_lock_irq(&tty->ctrl.lock); in pty_set_pktmode()
177 if (!tty->ctrl.packet) { in pty_set_pktmode()
178 tty->link->ctrl.pktstatus = 0; in pty_set_pktmode()
180 tty->ctrl.packet = true; in pty_set_pktmode()
183 tty->ctrl.packet = false; in pty_set_pktmode()
184 spin_unlock_irq(&tty->ctrl.lock); in pty_set_pktmode()
192 int pktmode = tty->ctrl.packet; in pty_get_pktmode()
203 return -EINVAL; in pty_signal()
205 if (tty->link) { in pty_signal()
206 pgrp = tty_get_pgrp(tty->link); in pty_signal()
216 struct tty_struct *to = tty->link; in pty_flush_buffer()
222 if (to->ctrl.packet) { in pty_flush_buffer()
223 spin_lock_irq(&tty->ctrl.lock); in pty_flush_buffer()
224 tty->ctrl.pktstatus |= TIOCPKT_FLUSHWRITE; in pty_flush_buffer()
225 wake_up_interruptible(&to->read_wait); in pty_flush_buffer()
226 spin_unlock_irq(&tty->ctrl.lock); in pty_flush_buffer()
232 if (!tty || !tty->link) in pty_open()
233 return -ENODEV; in pty_open()
235 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) in pty_open()
237 if (test_bit(TTY_PTY_LOCK, &tty->link->flags)) in pty_open()
239 if (tty->driver->subtype == PTY_TYPE_SLAVE && tty->link->count != 1) in pty_open()
242 clear_bit(TTY_IO_ERROR, &tty->flags); in pty_open()
243 clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); in pty_open()
244 set_bit(TTY_THROTTLED, &tty->flags); in pty_open()
248 set_bit(TTY_IO_ERROR, &tty->flags); in pty_open()
249 return -EIO; in pty_open()
256 if (tty->link && tty->link->ctrl.packet) { in pty_set_termios()
257 int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); in pty_set_termios()
258 int old_flow = ((old_termios->c_iflag & IXON) && in pty_set_termios()
259 (old_termios->c_cc[VSTOP] == '\023') && in pty_set_termios()
260 (old_termios->c_cc[VSTART] == '\021')); in pty_set_termios()
265 spin_lock_irq(&tty->ctrl.lock); in pty_set_termios()
267 tty->ctrl.pktstatus &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); in pty_set_termios()
269 tty->ctrl.pktstatus |= TIOCPKT_DOSTOP; in pty_set_termios()
271 tty->ctrl.pktstatus |= TIOCPKT_NOSTOP; in pty_set_termios()
274 tty->ctrl.pktstatus |= TIOCPKT_IOCTL; in pty_set_termios()
275 spin_unlock_irq(&tty->ctrl.lock); in pty_set_termios()
276 wake_up_interruptible(&tty->link->read_wait); in pty_set_termios()
280 tty->termios.c_cflag &= ~(CSIZE | PARENB); in pty_set_termios()
281 tty->termios.c_cflag |= (CS8 | CREAD); in pty_set_termios()
285 * pty_resize - resize event
296 struct tty_struct *pty = tty->link; in pty_resize()
298 /* For a PTY we need to lock the tty side */ in pty_resize()
299 mutex_lock(&tty->winsize_mutex); in pty_resize()
300 if (!memcmp(ws, &tty->winsize, sizeof(*ws))) in pty_resize()
315 tty->winsize = *ws; in pty_resize()
316 pty->winsize = *ws; /* Never used so will go away soon */ in pty_resize()
318 mutex_unlock(&tty->winsize_mutex); in pty_resize()
323 * pty_start - start() handler
324 * pty_stop - stop() handler
325 * @tty: tty being flow-controlled
327 * Propagates the TIOCPKT status to the master pty.
329 * NB: only the master pty can be in packet mode so only the slave
336 if (tty->link && tty->link->ctrl.packet) { in pty_start()
337 spin_lock_irqsave(&tty->ctrl.lock, flags); in pty_start()
338 tty->ctrl.pktstatus &= ~TIOCPKT_STOP; in pty_start()
339 tty->ctrl.pktstatus |= TIOCPKT_START; in pty_start()
340 spin_unlock_irqrestore(&tty->ctrl.lock, flags); in pty_start()
341 wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); in pty_start()
349 if (tty->link && tty->link->ctrl.packet) { in pty_stop()
350 spin_lock_irqsave(&tty->ctrl.lock, flags); in pty_stop()
351 tty->ctrl.pktstatus &= ~TIOCPKT_START; in pty_stop()
352 tty->ctrl.pktstatus |= TIOCPKT_STOP; in pty_stop()
353 spin_unlock_irqrestore(&tty->ctrl.lock, flags); in pty_stop()
354 wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); in pty_stop()
359 * pty_common_install - set up the pty pair
374 int idx = tty->index; in pty_common_install()
375 int retval = -ENOMEM; in pty_common_install()
377 /* Opening the slave first has always returned -EIO */ in pty_common_install()
378 if (driver->subtype != PTY_TYPE_MASTER) in pty_common_install()
379 return -EIO; in pty_common_install()
385 if (!try_module_get(driver->other->owner)) { in pty_common_install()
389 o_tty = alloc_tty_struct(driver->other, idx); in pty_common_install()
394 lockdep_set_subclass(&o_tty->termios_rwsem, TTY_LOCK_SLAVE); in pty_common_install()
402 driver->other->ttys[idx] = o_tty; in pty_common_install()
403 driver->ttys[idx] = tty; in pty_common_install()
405 memset(&tty->termios_locked, 0, sizeof(tty->termios_locked)); in pty_common_install()
406 tty->termios = driver->init_termios; in pty_common_install()
407 memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked)); in pty_common_install()
408 o_tty->termios = driver->other->init_termios; in pty_common_install()
414 tty_driver_kref_get(driver->other); in pty_common_install()
416 tty->link = o_tty; in pty_common_install()
417 o_tty->link = tty; in pty_common_install()
422 o_tty->port = ports[0]; in pty_common_install()
423 tty->port = ports[1]; in pty_common_install()
424 o_tty->port->itty = o_tty; in pty_common_install()
426 tty_buffer_set_lock_subclass(o_tty->port); in pty_common_install()
429 tty->count++; in pty_common_install()
430 o_tty->count++; in pty_common_install()
434 module_put(driver->other->owner); in pty_common_install()
443 tty_port_put(tty->port); in pty_cleanup()
456 struct tty_struct *pair = tty->link; in pty_remove()
458 driver->ttys[tty->index] = NULL; in pty_remove()
460 pair->driver->ttys[pair->index] = NULL; in pty_remove()
475 case TIOCSIG: /* Send signal to other side of pty */ in pty_bsd_ioctl()
478 return -EINVAL; in pty_bsd_ioctl()
480 return -ENOIOCTLCMD; in pty_bsd_ioctl()
488 * PTY ioctls don't require any special translation between 32-bit and in pty_bsd_compat_ioctl()
489 * 64-bit userspace, they are already compatible. in pty_bsd_compat_ioctl()
505 * The master side of a pty can do TIOCSPTLCK and thus
560 pty_driver->driver_name = "pty_master"; in legacy_pty_init()
561 pty_driver->name = "pty"; in legacy_pty_init()
562 pty_driver->major = PTY_MASTER_MAJOR; in legacy_pty_init()
563 pty_driver->minor_start = 0; in legacy_pty_init()
564 pty_driver->type = TTY_DRIVER_TYPE_PTY; in legacy_pty_init()
565 pty_driver->subtype = PTY_TYPE_MASTER; in legacy_pty_init()
566 pty_driver->init_termios = tty_std_termios; in legacy_pty_init()
567 pty_driver->init_termios.c_iflag = 0; in legacy_pty_init()
568 pty_driver->init_termios.c_oflag = 0; in legacy_pty_init()
569 pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; in legacy_pty_init()
570 pty_driver->init_termios.c_lflag = 0; in legacy_pty_init()
571 pty_driver->init_termios.c_ispeed = 38400; in legacy_pty_init()
572 pty_driver->init_termios.c_ospeed = 38400; in legacy_pty_init()
573 pty_driver->other = pty_slave_driver; in legacy_pty_init()
576 pty_slave_driver->driver_name = "pty_slave"; in legacy_pty_init()
577 pty_slave_driver->name = "ttyp"; in legacy_pty_init()
578 pty_slave_driver->major = PTY_SLAVE_MAJOR; in legacy_pty_init()
579 pty_slave_driver->minor_start = 0; in legacy_pty_init()
580 pty_slave_driver->type = TTY_DRIVER_TYPE_PTY; in legacy_pty_init()
581 pty_slave_driver->subtype = PTY_TYPE_SLAVE; in legacy_pty_init()
582 pty_slave_driver->init_termios = tty_std_termios; in legacy_pty_init()
583 pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; in legacy_pty_init()
584 pty_slave_driver->init_termios.c_ispeed = 38400; in legacy_pty_init()
585 pty_slave_driver->init_termios.c_ospeed = 38400; in legacy_pty_init()
586 pty_slave_driver->other = pty_driver; in legacy_pty_init()
603 * ptm_open_peer - open the peer of a pty
604 * @master: the open struct file of the ptmx device node
605 * @tty: the master of the pty being opened
609 * (where they have the master fd and cannot access or trust the mount
612 int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags) in ptm_open_peer() argument
616 int retval = -EINVAL; in ptm_open_peer()
619 if (tty->driver != ptm_driver) in ptm_open_peer()
620 return -EIO; in ptm_open_peer()
629 path.mnt = devpts_mntget(master, tty->driver_data); in ptm_open_peer()
634 path.dentry = tty->link->driver_data; in ptm_open_peer()
665 return put_user(tty->index, (unsigned int __user *)arg); in pty_unix98_ioctl()
666 case TIOCSIG: /* Send signal to other side of pty */ in pty_unix98_ioctl()
670 return -ENOIOCTLCMD; in pty_unix98_ioctl()
678 * PTY ioctls don't require any special translation between 32-bit and in pty_unix98_compat_ioctl()
679 * 64-bit userspace, they are already compatible. in pty_unix98_compat_ioctl()
689 * ptm_unix98_lookup - find a pty master
694 * Look up a pty master device. Called under the tty_mutex for now.
701 /* Master must be open via /dev/ptmx */ in ptm_unix98_lookup()
702 return ERR_PTR(-EIO); in ptm_unix98_lookup()
706 * pts_unix98_lookup - find a pty slave
711 * Look up a pty master device. Called under the tty_mutex for now.
721 tty = devpts_get_priv(file->f_path.dentry); in pts_unix98_lookup()
723 /* Master must be open before slave */ in pts_unix98_lookup()
725 return ERR_PTR(-EIO); in pts_unix98_lookup()
739 if (tty->driver->subtype == PTY_TYPE_MASTER) in pty_unix98_remove()
740 fsi = tty->driver_data; in pty_unix98_remove()
742 fsi = tty->link->driver_data; in pty_unix98_remove()
745 devpts_kill_index(fsi, tty->index); in pty_unix98_remove()
752 seq_printf(m, "tty-index:\t%d\n", tty->index); in pty_show_fdinfo()
789 * ptmx_open - open a unix 98 pty master
793 * Allocate a unix98 pty master device from the ptmx driver.
795 * Locking: tty_mutex protects the init_dev work. tty->count should
811 filp->f_mode |= FMODE_NONOTIFY; in ptmx_open()
847 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ in ptmx_open()
848 tty->driver_data = fsi; in ptmx_open()
852 dentry = devpts_pty_new(fsi, index, tty->link); in ptmx_open()
857 tty->link->driver_data = dentry; in ptmx_open()
859 retval = ptm_driver->ops->open(tty, filp); in ptmx_open()
863 tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); in ptmx_open()
869 // This will also put-ref the fsi in ptmx_open()
902 ptm_driver->driver_name = "pty_master"; in unix98_pty_init()
903 ptm_driver->name = "ptm"; in unix98_pty_init()
904 ptm_driver->major = UNIX98_PTY_MASTER_MAJOR; in unix98_pty_init()
905 ptm_driver->minor_start = 0; in unix98_pty_init()
906 ptm_driver->type = TTY_DRIVER_TYPE_PTY; in unix98_pty_init()
907 ptm_driver->subtype = PTY_TYPE_MASTER; in unix98_pty_init()
908 ptm_driver->init_termios = tty_std_termios; in unix98_pty_init()
909 ptm_driver->init_termios.c_iflag = 0; in unix98_pty_init()
910 ptm_driver->init_termios.c_oflag = 0; in unix98_pty_init()
911 ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; in unix98_pty_init()
912 ptm_driver->init_termios.c_lflag = 0; in unix98_pty_init()
913 ptm_driver->init_termios.c_ispeed = 38400; in unix98_pty_init()
914 ptm_driver->init_termios.c_ospeed = 38400; in unix98_pty_init()
915 ptm_driver->other = pts_driver; in unix98_pty_init()
918 pts_driver->driver_name = "pty_slave"; in unix98_pty_init()
919 pts_driver->name = "pts"; in unix98_pty_init()
920 pts_driver->major = UNIX98_PTY_SLAVE_MAJOR; in unix98_pty_init()
921 pts_driver->minor_start = 0; in unix98_pty_init()
922 pts_driver->type = TTY_DRIVER_TYPE_PTY; in unix98_pty_init()
923 pts_driver->subtype = PTY_TYPE_SLAVE; in unix98_pty_init()
924 pts_driver->init_termios = tty_std_termios; in unix98_pty_init()
925 pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; in unix98_pty_init()
926 pts_driver->init_termios.c_ispeed = 38400; in unix98_pty_init()
927 pts_driver->init_termios.c_ospeed = 38400; in unix98_pty_init()
928 pts_driver->other = ptm_driver; in unix98_pty_init()