static int spk_ttyio_initialise_ldisc()

in speakup/spk_ttyio.c [144:212]


static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
{
	int ret = 0;
	struct tty_struct *tty;
	struct ktermios tmp_termios;
	dev_t dev;

	ret = get_dev_to_use(synth, &dev);
	if (ret)
		return ret;

	tty = tty_kopen_exclusive(dev);
	if (IS_ERR(tty))
		return PTR_ERR(tty);

	if (tty->ops->open)
		ret = tty->ops->open(tty, NULL);
	else
		ret = -ENODEV;

	if (ret) {
		tty_unlock(tty);
		return ret;
	}

	clear_bit(TTY_HUPPED, &tty->flags);
	/* ensure hardware flow control is enabled */
	get_termios(tty, &tmp_termios);
	if (!(tmp_termios.c_cflag & CRTSCTS)) {
		tmp_termios.c_cflag |= CRTSCTS;
		tty_set_termios(tty, &tmp_termios);
		/*
		 * check c_cflag to see if it's updated as tty_set_termios
		 * may not return error even when no tty bits are
		 * changed by the request.
		 */
		get_termios(tty, &tmp_termios);
		if (!(tmp_termios.c_cflag & CRTSCTS))
			pr_warn("speakup: Failed to set hardware flow control\n");
	}

	tty_unlock(tty);

	mutex_lock(&speakup_tty_mutex);
	speakup_tty = tty;
	ret = tty_set_ldisc(tty, N_SPEAKUP);
	speakup_tty = NULL;
	mutex_unlock(&speakup_tty_mutex);

	if (!ret) {
		/* Success */
		struct spk_ldisc_data *ldisc_data = tty->disc_data;

		ldisc_data->synth = synth;
		synth->dev = tty;
		return 0;
	}

	pr_err("speakup: Failed to set N_SPEAKUP on tty\n");

	tty_lock(tty);
	if (tty->ops->close)
		tty->ops->close(tty, NULL);
	tty_unlock(tty);

	tty_kclose(tty);

	return ret;
}