diff options
author | Okash Khawaja <okash.khawaja@gmail.com> | 2019-04-17 14:21:13 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-19 15:09:10 +0200 |
commit | 496124e5e16e4974c71404bc9ddaa016156f8cb0 (patch) | |
tree | 44fdfdd19c83589f60a4acb5489cbe0a783f80e9 /drivers/tty/vt/selection.c | |
parent | staging: greybus: power_supply: use struct_size() helper (diff) | |
download | linux-496124e5e16e4974c71404bc9ddaa016156f8cb0.tar.xz linux-496124e5e16e4974c71404bc9ddaa016156f8cb0.zip |
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: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Tested-by: Gregory Nowak <greg@gregn.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt/selection.c')
-rw-r--r-- | drivers/tty/vt/selection.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 07496c711d7d..78732feaf65b 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -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); |