drivers/tty/tty_ioctl.c

Source file repositories/reference/linux-study-clean/drivers/tty/tty_ioctl.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/tty_ioctl.c
Extension
.c
Size
26062 bytes
Lines
986
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (tty_chars_in_buffer(tty)) {
			tty_write_unlock(tty);
			goto retry_write_wait;
		}

		ld = tty_ldisc_ref(tty);
		if (ld != NULL) {
			if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
				ld->ops->flush_buffer(tty);
			tty_ldisc_deref(ld);
		}

		if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) {
			tty->ops->wait_until_sent(tty, 0);
			if (signal_pending(current)) {
				tty_write_unlock(tty);
				return -ERESTARTSYS;
			}
		}

		tty_set_termios(tty, &tmp_termios);

		tty_write_unlock(tty);
	} else {
		tty_set_termios(tty, &tmp_termios);
	}

	/* FIXME: Arguably if tmp_termios == tty->termios AND the
	   actual requested termios was not tmp_termios then we may
	   want to return an error as no user requested change has
	   succeeded */
	return 0;
}

static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
{
	down_read(&tty->termios_rwsem);
	*kterm = tty->termios;
	up_read(&tty->termios_rwsem);
}

static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
{
	down_read(&tty->termios_rwsem);
	*kterm = tty->termios_locked;
	up_read(&tty->termios_rwsem);
}

static int get_termio(struct tty_struct *tty, struct termio __user *termio)
{
	struct ktermios kterm;
	copy_termios(tty, &kterm);
	if (kernel_termios_to_user_termio(termio, &kterm))
		return -EFAULT;
	return 0;
}

#ifdef TIOCGETP
/*
 * These are deprecated, but there is limited support..
 *
 * The "sg_flags" translation is a joke..
 */
static int get_sgflags(struct tty_struct *tty)
{
	int flags = 0;

	if (!L_ICANON(tty)) {
		if (L_ISIG(tty))
			flags |= 0x02;		/* cbreak */
		else
			flags |= 0x20;		/* raw */
	}
	if (L_ECHO(tty))
		flags |= 0x08;			/* echo */
	if (O_OPOST(tty))
		if (O_ONLCR(tty))
			flags |= 0x10;		/* crmod */
	return flags;
}

static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
{
	struct sgttyb tmp;

	down_read(&tty->termios_rwsem);
	tmp.sg_ispeed = tty->termios.c_ispeed;
	tmp.sg_ospeed = tty->termios.c_ospeed;
	tmp.sg_erase = tty->termios.c_cc[VERASE];
	tmp.sg_kill = tty->termios.c_cc[VKILL];

Annotation

Implementation Notes