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>
This commit is contained in:
parent
827c085bae
commit
496124e5e1
@ -2,7 +2,9 @@
|
|||||||
/*
|
/*
|
||||||
* This module exports the functions:
|
* 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)'
|
* 'void clear_selection(void)'
|
||||||
* 'int paste_selection(struct tty_struct *)'
|
* 'int paste_selection(struct tty_struct *)'
|
||||||
* 'int sel_loadlut(char __user *)'
|
* 'int sel_loadlut(char __user *)'
|
||||||
@ -80,6 +82,7 @@ void clear_selection(void)
|
|||||||
sel_start = -1;
|
sel_start = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(clear_selection);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User settable table: what characters are to be considered alphabetic?
|
* 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
|
* @sel: user selection info
|
||||||
* @tty: the console tty
|
* @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
|
* The entire selection process is managed under the console_lock. It's
|
||||||
* a lot under the lock but its hardly a performance path
|
* 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;
|
struct vc_data *vc = vc_cons[fg_console].d;
|
||||||
int new_sel_start, new_sel_end, spc;
|
int new_sel_start, new_sel_end, spc;
|
||||||
struct tiocl_selection v;
|
|
||||||
char *bp, *obp;
|
char *bp, *obp;
|
||||||
int i, ps, pe, multiplier;
|
int i, ps, pe, multiplier;
|
||||||
u32 c;
|
u32 c;
|
||||||
int mode;
|
int mode;
|
||||||
|
|
||||||
poke_blanked_console();
|
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->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
|
||||||
v.ys = min_t(u16, v.ys - 1, vc->vc_rows - 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->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
|
||||||
v.ye = min_t(u16, v.ye - 1, vc->vc_rows - 1);
|
v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
|
||||||
ps = v.ys * vc->vc_size_row + (v.xs << 1);
|
ps = v->ys * vc->vc_size_row + (v->xs << 1);
|
||||||
pe = v.ye * vc->vc_size_row + (v.xe << 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 */
|
/* useful for screendump without selection highlights */
|
||||||
clear_selection();
|
clear_selection();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) {
|
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
|
||||||
mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys);
|
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
|
||||||
|
v->ys);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +220,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
|
|||||||
else
|
else
|
||||||
use_unicode = 0;
|
use_unicode = 0;
|
||||||
|
|
||||||
switch (v.sel_mode)
|
switch (v->sel_mode)
|
||||||
{
|
{
|
||||||
case TIOCL_SELCHAR: /* character-by-character selection */
|
case TIOCL_SELCHAR: /* character-by-character selection */
|
||||||
new_sel_start = ps;
|
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;
|
sel_buffer_lth = bp - sel_buffer;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(set_selection_kernel);
|
||||||
|
|
||||||
/* Insert the contents of the selection buffer into the
|
/* Insert the contents of the selection buffer into the
|
||||||
* queue of the tty associated with the current console.
|
* queue of the tty associated with the current console.
|
||||||
@ -367,3 +380,4 @@ int paste_selection(struct tty_struct *tty)
|
|||||||
tty_ldisc_deref(ld);
|
tty_ldisc_deref(ld);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(paste_selection);
|
||||||
|
@ -1804,7 +1804,7 @@ void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
|
|||||||
respond_string(buf, tty->port);
|
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)
|
int mouse_reporting(void)
|
||||||
{
|
{
|
||||||
return vc_cons[fg_console].d->vc_report_mouse;
|
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
|
* There are some functions which can sleep for arbitrary periods
|
||||||
* (paste_selection) but we don't need the lock there anyway.
|
* (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)
|
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:
|
case TIOCL_SETSEL:
|
||||||
console_lock();
|
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();
|
console_unlock();
|
||||||
break;
|
break;
|
||||||
case TIOCL_PASTESEL:
|
case TIOCL_PASTESEL:
|
||||||
|
@ -11,13 +11,14 @@
|
|||||||
#include <linux/tiocl.h>
|
#include <linux/tiocl.h>
|
||||||
#include <linux/vt_buffer.h>
|
#include <linux/vt_buffer.h>
|
||||||
|
|
||||||
struct tty_struct;
|
|
||||||
|
|
||||||
extern struct vc_data *sel_cons;
|
extern struct vc_data *sel_cons;
|
||||||
struct tty_struct;
|
struct tty_struct;
|
||||||
|
|
||||||
extern void clear_selection(void);
|
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 paste_selection(struct tty_struct *tty);
|
||||||
extern int sel_loadlut(char __user *p);
|
extern int sel_loadlut(char __user *p);
|
||||||
extern int mouse_reporting(void);
|
extern int mouse_reporting(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user