Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 496124e5 authored by Okash Khawaja's avatar Okash Khawaja Committed by Greg Kroah-Hartman
Browse files

vt: selection: allow functions to be called from inside kernel



This patch breaks set_selection() into two functions so that when
called from kernel, copy_from_user() can be avoided. The two functions
are called set_selection_user() and set_selection_kernel() in order to
be explicit about their purposes. This also means updating any
references to set_selection() and fixing for name change. It also
exports set_selection_kernel() and paste_selection().

These changes are used the following patch where speakup's selection
functionality calls into the above functions, thereby doing away with
parallel implementation.

Signed-off-by: default avatarOkash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
Tested-by: default avatarGregory Nowak <greg@gregn.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 827c085b
Loading
Loading
Loading
Loading
+30 −16
Original line number Diff line number Diff line
@@ -2,7 +2,9 @@
/*
 * This module exports the functions:
 *
 *     'int set_selection(struct tiocl_selection __user *, struct tty_struct *)'
 *     'int set_selection_user(struct tiocl_selection __user *,
 *			       struct tty_struct *)'
 *     'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)'
 *     'void clear_selection(void)'
 *     'int paste_selection(struct tty_struct *)'
 *     'int sel_loadlut(char __user *)'
@@ -80,6 +82,7 @@ void clear_selection(void)
		sel_start = -1;
	}
}
EXPORT_SYMBOL_GPL(clear_selection);

/*
 * User settable table: what characters are to be considered alphabetic?
@@ -154,7 +157,7 @@ static int store_utf8(u32 c, char *p)
}

/**
 *	set_selection		- 	set the current selection.
 *	set_selection_user	-	set the current selection.
 *	@sel: user selection info
 *	@tty: the console tty
 *
@@ -163,35 +166,44 @@ static int store_utf8(u32 c, char *p)
 *	The entire selection process is managed under the console_lock. It's
 *	 a lot under the lock but its hardly a performance path
 */
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
int set_selection_user(const struct tiocl_selection __user *sel,
		       struct tty_struct *tty)
{
	struct tiocl_selection v;

	if (copy_from_user(&v, sel, sizeof(*sel)))
		return -EFAULT;

	return set_selection_kernel(&v, tty);
}

int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
{
	struct vc_data *vc = vc_cons[fg_console].d;
	int new_sel_start, new_sel_end, spc;
	struct tiocl_selection v;
	char *bp, *obp;
	int i, ps, pe, multiplier;
	u32 c;
	int mode;

	poke_blanked_console();
	if (copy_from_user(&v, sel, sizeof(*sel)))
		return -EFAULT;

	v.xs = min_t(u16, v.xs - 1, vc->vc_cols - 1);
	v.ys = min_t(u16, v.ys - 1, vc->vc_rows - 1);
	v.xe = min_t(u16, v.xe - 1, vc->vc_cols - 1);
	v.ye = min_t(u16, v.ye - 1, vc->vc_rows - 1);
	ps = v.ys * vc->vc_size_row + (v.xs << 1);
	pe = v.ye * vc->vc_size_row + (v.xe << 1);
	v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
	v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
	v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
	v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
	ps = v->ys * vc->vc_size_row + (v->xs << 1);
	pe = v->ye * vc->vc_size_row + (v->xe << 1);

	if (v.sel_mode == TIOCL_SELCLEAR) {
	if (v->sel_mode == TIOCL_SELCLEAR) {
		/* useful for screendump without selection highlights */
		clear_selection();
		return 0;
	}

	if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) {
		mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys);
	if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
		mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
			     v->ys);
		return 0;
	}

@@ -208,7 +220,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
	else
		use_unicode = 0;

	switch (v.sel_mode)
	switch (v->sel_mode)
	{
		case TIOCL_SELCHAR:	/* character-by-character selection */
			new_sel_start = ps;
@@ -322,6 +334,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
	sel_buffer_lth = bp - sel_buffer;
	return 0;
}
EXPORT_SYMBOL_GPL(set_selection_kernel);

/* Insert the contents of the selection buffer into the
 * queue of the tty associated with the current console.
@@ -367,3 +380,4 @@ int paste_selection(struct tty_struct *tty)
	tty_ldisc_deref(ld);
	return 0;
}
EXPORT_SYMBOL_GPL(paste_selection);
+4 −3
Original line number Diff line number Diff line
@@ -1804,7 +1804,7 @@ void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
	respond_string(buf, tty->port);
}

/* invoked via ioctl(TIOCLINUX) and through set_selection */
/* invoked via ioctl(TIOCLINUX) and through set_selection_user */
int mouse_reporting(void)
{
	return vc_cons[fg_console].d->vc_report_mouse;
@@ -3008,7 +3008,7 @@ static struct console vt_console_driver = {
 * There are some functions which can sleep for arbitrary periods
 * (paste_selection) but we don't need the lock there anyway.
 *
 * set_selection has locking, and definitely needs it
 * set_selection_user has locking, and definitely needs it
 */

int tioclinux(struct tty_struct *tty, unsigned long arg)
@@ -3028,7 +3028,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
	{
		case TIOCL_SETSEL:
			console_lock();
			ret = set_selection((struct tiocl_selection __user *)(p+1), tty);
			ret = set_selection_user((struct tiocl_selection
						 __user *)(p+1), tty);
			console_unlock();
			break;
		case TIOCL_PASTESEL:
+4 −3
Original line number Diff line number Diff line
@@ -11,13 +11,14 @@
#include <linux/tiocl.h>
#include <linux/vt_buffer.h>

struct tty_struct;

extern struct vc_data *sel_cons;
struct tty_struct;

extern void clear_selection(void);
extern int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty);
extern int set_selection_user(const struct tiocl_selection __user *sel,
			      struct tty_struct *tty);
extern int set_selection_kernel(struct tiocl_selection *v,
				struct tty_struct *tty);
extern int paste_selection(struct tty_struct *tty);
extern int sel_loadlut(char __user *p);
extern int mouse_reporting(void);