Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
484f2a9c
Commit
484f2a9c
authored
Jul 14, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linuxconsole.bkbits.net:8080/dev
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
866aa8f7
e57e9f5f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
485 additions
and
457 deletions
+485
-457
arch/i386/kernel/apm.c
arch/i386/kernel/apm.c
+1
-1
arch/ppc/xmon/start.c
arch/ppc/xmon/start.c
+1
-1
arch/ppc64/xmon/start.c
arch/ppc64/xmon/start.c
+1
-1
drivers/acpi/system.c
drivers/acpi/system.c
+1
-1
drivers/char/console.c
drivers/char/console.c
+46
-36
drivers/char/keyboard.c
drivers/char/keyboard.c
+399
-378
drivers/char/sysrq.c
drivers/char/sysrq.c
+30
-16
drivers/char/tty_io.c
drivers/char/tty_io.c
+2
-13
include/linux/console_struct.h
include/linux/console_struct.h
+1
-0
include/linux/sysrq.h
include/linux/sysrq.h
+3
-10
No files found.
arch/i386/kernel/apm.c
View file @
484f2a9c
...
...
@@ -923,7 +923,7 @@ static void apm_power_off(void)
*/
static
void
handle_poweroff
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
struct
tty_struct
*
tty
)
{
apm_power_off
();
}
...
...
arch/ppc/xmon/start.c
View file @
484f2a9c
...
...
@@ -98,7 +98,7 @@ static unsigned long chrp_find_phys_io_base(void)
#ifdef CONFIG_MAGIC_SYSRQ
static
void
sysrq_handle_xmon
(
int
key
,
struct
pt_regs
*
regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
struct
tty_struct
*
tty
)
{
xmon
(
regs
);
}
...
...
arch/ppc64/xmon/start.c
View file @
484f2a9c
...
...
@@ -52,7 +52,7 @@ void buf_access(void)
}
#endif
static
void
sysrq_handle_xmon
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
static
void
sysrq_handle_xmon
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
tty_struct
*
tty
)
{
xmon
(
pt_regs
);
}
...
...
drivers/acpi/system.c
View file @
484f2a9c
...
...
@@ -1165,7 +1165,7 @@ acpi_system_remove_fs (
/* Simple wrapper calling power down function. */
static
void
acpi_sysrq_power_off
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
struct
tty_struct
*
tty
)
{
acpi_power_off
();
}
...
...
drivers/char/console.c
View file @
484f2a9c
...
...
@@ -126,6 +126,7 @@ const struct consw *conswitchp;
#define DEFAULT_BELL_DURATION (HZ/8)
extern
void
vcs_make_devfs
(
unsigned
int
index
,
int
unregister
);
extern
void
console_map_init
(
void
);
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
...
...
@@ -2381,6 +2382,7 @@ static int con_open(struct tty_struct *tty, struct file * filp)
vt_cons
[
currcons
]
->
vc_num
=
currcons
;
tty
->
driver_data
=
vt_cons
[
currcons
];
vc_cons
[
currcons
].
d
->
vc_tty
=
tty
;
if
(
!
tty
->
winsize
.
ws_row
&&
!
tty
->
winsize
.
ws_col
)
{
tty
->
winsize
.
ws_row
=
video_num_lines
;
...
...
@@ -2445,42 +2447,6 @@ void __init con_init(void)
return
;
}
memset
(
&
console_driver
,
0
,
sizeof
(
struct
tty_driver
));
console_driver
.
magic
=
TTY_DRIVER_MAGIC
;
console_driver
.
name
=
"vc/%d"
;
console_driver
.
name_base
=
1
;
console_driver
.
major
=
TTY_MAJOR
;
console_driver
.
minor_start
=
1
;
console_driver
.
num
=
MAX_NR_CONSOLES
;
console_driver
.
type
=
TTY_DRIVER_TYPE_CONSOLE
;
console_driver
.
init_termios
=
tty_std_termios
;
console_driver
.
flags
=
TTY_DRIVER_REAL_RAW
|
TTY_DRIVER_RESET_TERMIOS
;
/* Tell tty_register_driver() to skip consoles because they are
* registered before kmalloc() is ready. We'll patch them in later.
* See comments at console_init(); see also con_init_devfs().
*/
console_driver
.
flags
|=
TTY_DRIVER_NO_DEVFS
;
console_driver
.
refcount
=
&
console_refcount
;
console_driver
.
table
=
console_table
;
console_driver
.
termios
=
console_termios
;
console_driver
.
termios_locked
=
console_termios_locked
;
console_driver
.
open
=
con_open
;
console_driver
.
close
=
con_close
;
console_driver
.
write
=
con_write
;
console_driver
.
write_room
=
con_write_room
;
console_driver
.
put_char
=
con_put_char
;
console_driver
.
flush_chars
=
con_flush_chars
;
console_driver
.
chars_in_buffer
=
con_chars_in_buffer
;
console_driver
.
ioctl
=
vt_ioctl
;
console_driver
.
stop
=
con_stop
;
console_driver
.
start
=
con_start
;
console_driver
.
throttle
=
con_throttle
;
console_driver
.
unthrottle
=
con_unthrottle
;
if
(
tty_register_driver
(
&
console_driver
))
panic
(
"Couldn't register console driver
\n
"
);
init_timer
(
&
console_timer
);
console_timer
.
function
=
blank_screen
;
if
(
blankinterval
)
{
...
...
@@ -2519,6 +2485,50 @@ void __init con_init(void)
#endif
}
int
__init
vty_init
(
void
)
{
memset
(
&
console_driver
,
0
,
sizeof
(
struct
tty_driver
));
console_driver
.
magic
=
TTY_DRIVER_MAGIC
;
console_driver
.
name
=
"vc/%d"
;
console_driver
.
name_base
=
1
;
console_driver
.
major
=
TTY_MAJOR
;
console_driver
.
minor_start
=
1
;
console_driver
.
num
=
MAX_NR_CONSOLES
;
console_driver
.
type
=
TTY_DRIVER_TYPE_CONSOLE
;
console_driver
.
init_termios
=
tty_std_termios
;
console_driver
.
flags
=
TTY_DRIVER_REAL_RAW
|
TTY_DRIVER_RESET_TERMIOS
;
/* Tell tty_register_driver() to skip consoles because they are
* registered before kmalloc() is ready. We'll patch them in later.
* See comments at console_init(); see also con_init_devfs().
*/
console_driver
.
flags
|=
TTY_DRIVER_NO_DEVFS
;
console_driver
.
refcount
=
&
console_refcount
;
console_driver
.
table
=
console_table
;
console_driver
.
termios
=
console_termios
;
console_driver
.
termios_locked
=
console_termios_locked
;
console_driver
.
open
=
con_open
;
console_driver
.
close
=
con_close
;
console_driver
.
write
=
con_write
;
console_driver
.
write_room
=
con_write_room
;
console_driver
.
put_char
=
con_put_char
;
console_driver
.
flush_chars
=
con_flush_chars
;
console_driver
.
chars_in_buffer
=
con_chars_in_buffer
;
console_driver
.
ioctl
=
vt_ioctl
;
console_driver
.
stop
=
con_stop
;
console_driver
.
start
=
con_start
;
console_driver
.
throttle
=
con_throttle
;
console_driver
.
unthrottle
=
con_unthrottle
;
if
(
tty_register_driver
(
&
console_driver
))
panic
(
"Couldn't register console driver
\n
"
);
kbd_init
();
console_map_init
();
vcs_init
();
return
0
;
}
#ifndef VT_SINGLE_DRIVER
static
void
clear_buffer_attributes
(
int
currcons
)
...
...
drivers/char/keyboard.c
View file @
484f2a9c
...
...
@@ -36,6 +36,7 @@
#include <asm/keyboard.h>
#include <asm/bitops.h>
#include <linux/console_struct.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/vt_kern.h>
...
...
@@ -43,8 +44,14 @@
#include <linux/sysrq.h>
#include <linux/pm.h>
extern
void
ctrl_alt_del
(
void
);
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
/*
* Exported functions/variables
*/
#ifndef KBD_DEFMODE
#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
#endif
...
...
@@ -64,277 +71,121 @@
void
(
*
kbd_ledfunc
)(
unsigned
int
led
);
EXPORT_SYMBOL
(
handle_scancode
);
EXPORT_SYMBOL
(
kbd_ledfunc
);
extern
void
ctrl_alt_del
(
void
);
struct
console
;
/* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
struct
pt_regs
*
kbd_pt_regs
;
void
compute_shiftstate
(
void
);
/*
* global state includes the following, and various static variables
* in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
* (last_console is now a global variable)
*/
/* shift state counters.. */
static
unsigned
char
k_down
[
NR_SHIFT
];
/* keyboard key bitmap */
static
unsigned
long
key_down
[
256
/
BITS_PER_LONG
];
static
int
dead_key_next
;
/*
* In order to retrieve the shift_state (for the mouse server), either
* the variable must be global, or a new procedure must be created to
* return the value. I chose the former way.
* Handler Tables.
*/
int
shift_state
;
static
int
npadch
=
-
1
;
/* -1 or number assembled on pad */
static
unsigned
char
diacr
;
static
char
rep
;
/* flag telling character repeat */
struct
kbd_struct
kbd_table
[
MAX_NR_CONSOLES
];
static
struct
tty_struct
**
ttytab
;
static
struct
kbd_struct
*
kbd
=
kbd_table
;
static
struct
tty_struct
*
tty
;
void
compute_shiftstate
(
void
);
typedef
void
(
*
k_hand
)(
unsigned
char
value
,
char
up_flag
);
typedef
void
(
k_handfn
)(
unsigned
char
value
,
char
up_flag
);
static
k_handfn
do_self
,
do_fn
,
do_spec
,
do_pad
,
do_dead
,
do_cons
,
do_cur
,
do_shift
,
do_meta
,
do_ascii
,
do_lock
,
do_lowercase
,
do_slock
,
do_dead2
,
do_ignore
;
static
k_hand
key_handler
[
16
]
=
{
do_self
,
do_fn
,
do_spec
,
do_pad
,
do_dead
,
do_cons
,
do_cur
,
do_shift
,
do_meta
,
do_ascii
,
do_lock
,
do_lowercase
,
do_slock
,
do_dead2
,
do_ignore
,
do_ignore
};
/* Key types processed even in raw modes */
#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT))
#define SPECIALS_ALLOWED_IN_RAW_MODE (1 << KVAL(K_SAK))
typedef
void
(
*
void_fnp
)(
void
);
typedef
void
(
void_fn
)(
void
);
#define K_HANDLERS\
k_self, k_fn, k_spec, k_pad,\
k_dead, k_cons, k_cur, k_shift,\
k_meta, k_ascii, k_lock, k_lowercase,\
k_slock, k_dead2, k_ignore, k_ignore
static
void_fn
do_null
,
enter
,
show_ptregs
,
send_intr
,
lastcons
,
caps_toggle
,
num
,
hold
,
scroll_forw
,
scroll_back
,
boot_it
,
caps_on
,
compose
,
SAK
,
decr_console
,
incr_console
,
spawn_console
,
bare_num
;
typedef
void
(
k_handler_fn
)(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
);
static
k_handler_fn
K_HANDLERS
;
static
k_handler_fn
*
k_handler
[
16
]
=
{
K_HANDLERS
};
static
void_fnp
spec_fn_table
[]
=
{
do_null
,
enter
,
show_ptregs
,
show_mem
,
show_state
,
send_intr
,
lastcons
,
caps_toggle
,
num
,
hold
,
scroll_forw
,
scroll_back
,
boot_it
,
caps_on
,
compose
,
SAK
,
decr_console
,
incr_console
,
spawn_console
,
bare_num
};
#define FN_HANDLERS\
fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
#define SPECIALS_ALLOWED_IN_RAW_MODE (1 << KVAL(K_SAK))
typedef
void
(
fn_handler_fn
)(
struct
vc_data
*
vc
);
static
fn_handler_fn
FN_HANDLERS
;
static
fn_handler_fn
*
fn_handler
[]
=
{
FN_HANDLERS
};
/*
* Variables/functions exported for vt.c
*/
/* maximum values each key_handler can handle */
const
int
max_vals
[]
=
{
255
,
SIZE
(
func_table
)
-
1
,
SIZE
(
spec_fn_table
)
-
1
,
NR_PAD
-
1
,
NR_DEAD
-
1
,
255
,
3
,
NR_SHIFT
-
1
,
255
,
NR_ASCII
-
1
,
NR_LOCK
-
1
,
255
,
NR_LOCK
-
1
,
255
255
,
SIZE
(
func_table
)
-
1
,
SIZE
(
fn_handler
)
-
1
,
NR_PAD
-
1
,
NR_DEAD
-
1
,
255
,
3
,
NR_SHIFT
-
1
,
255
,
NR_ASCII
-
1
,
NR_LOCK
-
1
,
255
,
NR_LOCK
-
1
,
255
};
const
int
NR_TYPES
=
SIZE
(
max_vals
);
/* N.B. drivers/macintosh/mac_keyb.c needs to call put_queue */
void
put_queue
(
int
);
static
unsigned
char
handle_diacr
(
unsigned
char
);
/* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
struct
pt_regs
*
kbd_pt_regs
;
#ifdef CONFIG_MAGIC_SYSRQ
static
int
sysrq_pressed
;
#endif
static
struct
pm_dev
*
pm_kbd
;
/*
* Many other routines do put_queue, but I think either
* they produce ASCII, or they produce some user-assigned
* string, and in both cases we might assume that it is
* in utf-8 already.
*/
void
to_utf8
(
ushort
c
)
{
if
(
c
<
0x80
)
put_queue
(
c
);
/* 0******* */
else
if
(
c
<
0x800
)
{
put_queue
(
0xc0
|
(
c
>>
6
));
/* 110***** 10****** */
put_queue
(
0x80
|
(
c
&
0x3f
));
}
else
{
put_queue
(
0xe0
|
(
c
>>
12
));
/* 1110**** 10****** 10****** */
put_queue
(
0x80
|
((
c
>>
6
)
&
0x3f
));
put_queue
(
0x80
|
(
c
&
0x3f
));
}
/* UTF-8 is defined for words of up to 31 bits,
but we need only 16 bits here */
}
int
spawnpid
,
spawnsig
;
/*
* Translation of escaped scancodes to keycodes.
* This is now user-settable (for machines were it makes sense).
*/
int
setkeycode
(
unsigned
int
scancode
,
unsigned
int
keycode
)
{
return
kbd_setkeycode
(
scancode
,
keycode
);
}
int
getkeycode
(
unsigned
int
scancode
)
{
return
kbd_getkeycode
(
scancode
);
}
void
handle_scancode
(
unsigned
char
scancode
,
int
down
)
int
setkeycode
(
unsigned
int
scancode
,
unsigned
int
keycode
)
{
unsigned
char
keycode
;
char
up_flag
=
down
?
0
:
0200
;
char
raw_mode
;
pm_access
(
pm_kbd
);
add_keyboard_randomness
(
scancode
|
up_flag
);
tty
=
ttytab
?
ttytab
[
fg_console
]
:
NULL
;
if
(
tty
&&
(
!
tty
->
driver_data
))
{
/*
* We touch the tty structure via the ttytab array
* without knowing whether or not tty is open, which
* is inherently dangerous. We currently rely on that
* fact that console_open sets tty->driver_data when
* it opens it, and clears it when it closes it.
*/
tty
=
NULL
;
}
kbd
=
kbd_table
+
fg_console
;
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
)))
{
put_queue
(
scancode
|
up_flag
);
/* we do not return yet, because we want to maintain
the key_down array, so that we have the correct
values when finishing RAW mode or when changing VT's */
}
/*
* Convert scancode to keycode
*/
if
(
!
kbd_translate
(
scancode
,
&
keycode
,
raw_mode
))
goto
out
;
/*
* At this point the variable `keycode' contains the keycode.
* Note: the keycode must not be 0 (++Geert: on m68k 0 is valid).
* We keep track of the up/down status of the key, and
* return the keycode if in MEDIUMRAW mode.
*/
if
(
up_flag
)
{
rep
=
0
;
if
(
!
test_and_clear_bit
(
keycode
,
key_down
))
up_flag
=
kbd_unexpected_up
(
keycode
);
}
else
rep
=
test_and_set_bit
(
keycode
,
key_down
);
#ifdef CONFIG_MAGIC_SYSRQ
/* Handle the SysRq Hack */
if
(
keycode
==
SYSRQ_KEY
)
{
sysrq_pressed
=
!
up_flag
;
goto
out
;
}
else
if
(
sysrq_pressed
)
{
if
(
!
up_flag
)
{
handle_sysrq
(
kbd_sysrq_xlate
[
keycode
],
kbd_pt_regs
,
kbd
,
tty
);
goto
out
;
}
}
#endif
return
kbd_setkeycode
(
scancode
,
keycode
);
}
if
(
kbd
->
kbdmode
==
VC_MEDIUMRAW
)
{
/* soon keycodes will require more than one byte */
put_queue
(
keycode
+
up_flag
);
raw_mode
=
1
;
/* Most key classes will be ignored */
}
/*
* Variables/function exported for console.c
*/
int
shift_state
=
0
;
/*
* Small change in philosophy: earlier we defined repetition by
* rep = keycode == prev_keycode;
* prev_keycode = keycode;
* but now by the fact that the depressed key was down already.
* Does this ever make a difference? Yes.
*/
/*
* Internal Data.
*/
/*
* Repeat a key only if the input buffers are empty or the
* characters get echoed locally. This makes key repeat usable
* with slow applications and under heavy loads.
*/
if
(
!
rep
||
(
vc_kbd_mode
(
kbd
,
VC_REPEAT
)
&&
tty
&&
(
L_ECHO
(
tty
)
||
(
tty
->
driver
.
chars_in_buffer
(
tty
)
==
0
))))
{
u_short
keysym
;
u_char
type
;
static
unsigned
long
key_down
[
256
/
BITS_PER_LONG
];
/* keyboard key bitmap */
static
unsigned
char
shift_down
[
NR_SHIFT
];
/* shift state counters.. */
static
int
dead_key_next
;
static
int
npadch
=
-
1
;
/* -1 or number assembled on pad */
static
unsigned
char
diacr
;
static
char
rep
;
/* flag telling character repeat */
pm_callback
pm_kbd_request_override
=
NULL
;
typedef
void
(
pm_kbd_func
)
(
void
);
static
struct
pm_dev
*
pm_kbd
;
/* the XOR below used to be an OR */
int
shift_final
=
(
shift_state
|
kbd
->
slockstate
)
^
kbd
->
lockstate
;
ushort
*
key_map
=
key_maps
[
shift_final
];
static
unsigned
char
ledstate
=
0xff
;
/* undefined */
static
unsigned
char
ledioctl
;
if
(
key_map
!=
NULL
)
{
keysym
=
key_map
[
keycode
];
type
=
KTYP
(
keysym
);
static
struct
ledptr
{
unsigned
int
*
addr
;
unsigned
int
mask
;
unsigned
char
valid
:
1
;
}
ledptrs
[
3
];
if
(
type
>=
0xf0
)
{
type
-=
0xf0
;
if
(
raw_mode
&&
!
(
TYPES_ALLOWED_IN_RAW_MODE
&
(
1
<<
type
)))
goto
out
;
if
(
type
==
KT_LETTER
)
{
type
=
KT_LATIN
;
if
(
vc_kbd_led
(
kbd
,
VC_CAPSLOCK
))
{
key_map
=
key_maps
[
shift_final
^
(
1
<<
KG_SHIFT
)];
if
(
key_map
)
keysym
=
key_map
[
keycode
];
}
}
(
*
key_handler
[
type
])(
keysym
&
0xff
,
up_flag
);
if
(
type
!=
KT_SLOCK
)
kbd
->
slockstate
=
0
;
}
else
{
/* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
if
(
!
up_flag
&&
!
raw_mode
)
to_utf8
(
keysym
);
}
}
else
{
/* maybe beep? */
/* we have at least to update shift_state */
#if 1
/* how? two almost equivalent choices follow */
compute_shiftstate
();
kbd
->
slockstate
=
0
;
/* play it safe */
#else
keysym
=
U
(
plain_map
[
keycode
]);
type
=
KTYP
(
keysym
);
if
(
type
==
KT_SHIFT
)
(
*
key_handler
[
type
])(
keysym
&
0xff
,
up_flag
);
struct
kbd_struct
kbd_table
[
MAX_NR_CONSOLES
];
static
struct
kbd_struct
*
kbd
=
kbd_table
;
#ifdef CONFIG_MAGIC_SYSRQ
static
int
sysrq_pressed
;
#endif
}
}
out:
do_poke_blanked_console
=
1
;
schedule_console_callback
();
}
void
put_queue
(
int
ch
)
/*
* Helper Functions.
*/
void
put_queue
(
struct
vc_data
*
vc
,
int
ch
)
{
struct
tty_struct
*
tty
=
vc
->
vc_tty
;
if
(
tty
)
{
tty_insert_flip_char
(
tty
,
ch
,
0
);
con_schedule_flip
(
tty
);
}
}
static
void
puts_queue
(
char
*
cp
)
static
void
puts_queue
(
struct
vc_data
*
vc
,
char
*
cp
)
{
struct
tty_struct
*
tty
=
vc
->
vc_tty
;
if
(
!
tty
)
return
;
...
...
@@ -345,48 +196,139 @@ static void puts_queue(char *cp)
con_schedule_flip
(
tty
);
}
static
void
applkey
(
int
key
,
char
mode
)
static
void
applkey
(
struct
vc_data
*
vc
,
int
key
,
char
mode
)
{
static
char
buf
[]
=
{
0x1b
,
'O'
,
0x00
,
0x00
};
buf
[
1
]
=
(
mode
?
'O'
:
'['
);
buf
[
2
]
=
key
;
puts_queue
(
buf
);
puts_queue
(
vc
,
buf
);
}
/*
* Many other routines do put_queue, but I think either
* they produce ASCII, or they produce some user-assigned
* string, and in both cases we might assume that it is
* in utf-8 already. UTF-8 is defined for words of up to 31 bits,
* but we need only 16 bits here
*/
void
to_utf8
(
struct
vc_data
*
vc
,
ushort
c
)
{
if
(
c
<
0x80
)
/* 0******* */
put_queue
(
vc
,
c
);
else
if
(
c
<
0x800
)
{
/* 110***** 10****** */
put_queue
(
vc
,
0xc0
|
(
c
>>
6
));
put_queue
(
vc
,
0x80
|
(
c
&
0x3f
));
}
else
{
/* 1110**** 10****** 10*******/
put_queue
(
vc
,
0xe0
|
(
c
>>
12
));
put_queue
(
vc
,
0x80
|
((
c
>>
6
)
&
0x3f
));
put_queue
(
vc
,
0x80
|
(
c
&
0x3f
));
}
}
/* called after returning from RAW mode or when changing consoles -
recompute shift_down[] and shift_state from key_down[] */
/* maybe called when keymap is undefined, so that shiftkey release is seen */
void
compute_shiftstate
(
void
)
{
int
i
,
j
,
k
,
sym
,
val
;
shift_state
=
0
;
memset
(
shift_down
,
0
,
sizeof
(
shift_down
));
for
(
i
=
0
;
i
<
SIZE
(
key_down
);
i
++
)
{
if
(
!
key_down
[
i
])
continue
;
k
=
i
*
BITS_PER_LONG
;
for
(
j
=
0
;
j
<
BITS_PER_LONG
;
j
++
,
k
++
)
{
if
(
!
test_bit
(
k
,
key_down
))
continue
;
sym
=
U
(
plain_map
[
k
]);
if
(
KTYP
(
sym
)
!=
KT_SHIFT
&&
KTYP
(
sym
)
!=
KT_SLOCK
)
continue
;
val
=
KVAL
(
sym
);
if
(
val
==
KVAL
(
K_CAPSSHIFT
))
val
=
KVAL
(
K_SHIFT
);
shift_down
[
val
]
++
;
shift_state
|=
(
1
<<
val
);
}
}
}
/*
* We have a combining character DIACR here, followed by the character CH.
* If the combination occurs in the table, return the corresponding value.
* Otherwise, if CH is a space or equals DIACR, return DIACR.
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
unsigned
char
handle_diacr
(
struct
vc_data
*
vc
,
unsigned
char
ch
)
{
int
d
=
diacr
;
int
i
;
diacr
=
0
;
for
(
i
=
0
;
i
<
accent_table_size
;
i
++
)
{
if
(
accent_table
[
i
].
diacr
==
d
&&
accent_table
[
i
].
base
==
ch
)
return
accent_table
[
i
].
result
;
}
if
(
ch
==
' '
||
ch
==
d
)
return
d
;
put_queue
(
vc
,
d
);
return
ch
;
}
static
void
enter
(
void
)
/*
* Special function handlers
*/
static
void
fn_enter
(
struct
vc_data
*
vc
)
{
if
(
diacr
)
{
put_queue
(
diacr
);
put_queue
(
vc
,
diacr
);
diacr
=
0
;
}
put_queue
(
13
);
if
(
vc_kbd_mode
(
kbd
,
VC_CRLF
))
put_queue
(
10
);
put_queue
(
vc
,
13
);
if
(
vc_kbd_mode
(
kbd
,
VC_CRLF
))
put_queue
(
vc
,
10
);
}
static
void
caps_toggle
(
void
)
static
void
fn_caps_toggle
(
struct
vc_data
*
vc
)
{
if
(
rep
)
return
;
chg_vc_kbd_led
(
kbd
,
VC_CAPSLOCK
);
}
static
void
caps_on
(
void
)
static
void
fn_caps_on
(
struct
vc_data
*
vc
)
{
if
(
rep
)
return
;
set_vc_kbd_led
(
kbd
,
VC_CAPSLOCK
);
}
static
void
show_ptregs
(
void
)
static
void
fn_show_ptregs
(
struct
vc_data
*
vc
)
{
if
(
kbd_pt_regs
)
show_regs
(
kbd_pt_regs
);
}
static
void
hold
(
void
)
static
void
fn_hold
(
struct
vc_data
*
vc
)
{
struct
tty_struct
*
tty
=
vc
->
vc_tty
;
if
(
rep
||
!
tty
)
return
;
...
...
@@ -401,12 +343,12 @@ static void hold(void)
stop_tty
(
tty
);
}
static
void
num
(
void
)
static
void
fn_num
(
struct
vc_data
*
vc
)
{
if
(
vc_kbd_mode
(
kbd
,
VC_APPLIC
))
applkey
(
'P'
,
1
);
applkey
(
vc
,
'P'
,
1
);
else
bare_num
(
);
fn_bare_num
(
vc
);
}
/*
...
...
@@ -415,19 +357,19 @@ static void num(void)
* Bind this to NumLock if you prefer that the NumLock key always
* changes the NumLock flag.
*/
static
void
bare_num
(
void
)
static
void
fn_bare_num
(
struct
vc_data
*
vc
)
{
if
(
!
rep
)
chg_vc_kbd_led
(
kbd
,
VC_NUMLOCK
);
}
static
void
lastcons
(
void
)
static
void
fn_lastcons
(
struct
vc_data
*
vc
)
{
/* switch to the last used console, ChN */
set_console
(
last_console
);
}
static
void
decr_console
(
void
)
static
void
fn_dec_console
(
struct
vc_data
*
vc
)
{
int
i
;
...
...
@@ -440,7 +382,7 @@ static void decr_console(void)
set_console
(
i
);
}
static
void
incr_console
(
void
)
static
void
fn_inc_console
(
struct
vc_data
*
vc
)
{
int
i
;
...
...
@@ -453,98 +395,112 @@ static void incr_console(void)
set_console
(
i
);
}
static
void
send_intr
(
void
)
static
void
fn_send_intr
(
struct
vc_data
*
vc
)
{
struct
tty_struct
*
tty
=
vc
->
vc_tty
;
if
(
!
tty
)
return
;
tty_insert_flip_char
(
tty
,
0
,
TTY_BREAK
);
con_schedule_flip
(
tty
);
}
static
void
scroll_forw
(
void
)
static
void
fn_scroll_forw
(
struct
vc_data
*
vc
)
{
scrollfront
(
0
);
}
static
void
scroll_back
(
void
)
static
void
fn_scroll_back
(
struct
vc_data
*
vc
)
{
scrollback
(
0
);
}
static
void
boot_it
(
void
)
static
void
fn_show_mem
(
struct
vc_data
*
vc
)
{
show_mem
();
}
static
void
fn_show_state
(
struct
vc_data
*
vc
)
{
show_state
();
}
static
void
fn_boot_it
(
struct
vc_data
*
vc
)
{
ctrl_alt_del
();
}
static
void
compose
(
void
)
static
void
fn_compose
(
struct
vc_data
*
vc
)
{
dead_key_next
=
1
;
}
int
spawnpid
,
spawnsig
;
static
void
spawn_console
(
void
)
static
void
fn_spawn_con
(
struct
vc_data
*
vc
)
{
if
(
spawnpid
)
if
(
kill_proc
(
spawnpid
,
spawnsig
,
1
))
spawnpid
=
0
;
}
static
void
SAK
(
void
)
static
void
fn_SAK
(
struct
vc_data
*
vc
)
{
struct
tty_struct
*
tty
=
vc
->
vc_tty
;
/*
* SAK should also work in all raw modes and reset
* them properly.
*/
do_SAK
(
tty
);
if
(
tty
)
do_SAK
(
tty
);
reset_vc
(
fg_console
);
#if 0
do_unblank_screen(); /* not in interrupt routine? */
#endif
}
static
void
do_ignore
(
unsigned
char
value
,
char
up_flag
)
static
void
fn_null
(
struct
vc_data
*
vc
)
{
compute_shiftstate
();
}
static
void
do_null
()
/*
* Special key handlers
*/
static
void
k_ignore
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
compute_shiftstate
();
}
static
void
do_spec
(
unsigned
char
value
,
char
up_flag
)
static
void
k_spec
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
if
(
value
>=
SIZE
(
spec_fn_table
))
if
(
value
>=
SIZE
(
fn_handler
))
return
;
if
((
kbd
->
kbdmode
==
VC_RAW
||
kbd
->
kbdmode
==
VC_MEDIUMRAW
)
&&
!
(
SPECIALS_ALLOWED_IN_RAW_MODE
&
(
1
<<
value
)))
return
;
spec_fn_table
[
value
](
);
fn_handler
[
value
](
vc
);
}
static
void
do_lowercase
(
unsigned
char
value
,
char
up_flag
)
static
void
k_lowercase
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
printk
(
KERN_ERR
"keyboard.c: do_lowercase was called - impossible
\n
"
);
}
static
void
do_self
(
unsigned
char
value
,
char
up_flag
)
static
void
k_self
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
/* no action, if this is a key release */
if
(
diacr
)
value
=
handle_diacr
(
value
);
value
=
handle_diacr
(
v
c
,
v
alue
);
if
(
dead_key_next
)
{
dead_key_next
=
0
;
diacr
=
value
;
return
;
}
put_queue
(
value
);
put_queue
(
vc
,
value
);
}
#define A_GRAVE '`'
...
...
@@ -557,10 +513,10 @@ static unsigned char ret_diacr[NR_DEAD] =
{
A_GRAVE
,
A_ACUTE
,
A_CFLEX
,
A_TILDE
,
A_DIAER
,
A_CEDIL
};
/* Obsolete - for backwards compatibility only */
static
void
do_dead
(
unsigned
char
value
,
char
up_flag
)
static
void
k_dead
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
value
=
ret_diacr
[
value
];
do_dead2
(
value
,
up_flag
);
k_dead2
(
vc
,
value
,
up_flag
);
}
/*
...
...
@@ -568,60 +524,33 @@ static void do_dead(unsigned char value, char up_flag)
* dead keys modifying the same character. Very useful
* for Vietnamese.
*/
static
void
do_dead2
(
unsigned
char
value
,
char
up_flag
)
static
void
k_dead2
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
diacr
=
(
diacr
?
handle_diacr
(
value
)
:
value
);
diacr
=
(
diacr
?
handle_diacr
(
v
c
,
v
alue
)
:
value
);
}
/*
* We have a combining character DIACR here, followed by the character CH.
* If the combination occurs in the table, return the corresponding value.
* Otherwise, if CH is a space or equals DIACR, return DIACR.
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
unsigned
char
handle_diacr
(
unsigned
char
ch
)
{
int
d
=
diacr
;
int
i
;
diacr
=
0
;
for
(
i
=
0
;
i
<
accent_table_size
;
i
++
)
{
if
(
accent_table
[
i
].
diacr
==
d
&&
accent_table
[
i
].
base
==
ch
)
return
accent_table
[
i
].
result
;
}
if
(
ch
==
' '
||
ch
==
d
)
return
d
;
put_queue
(
d
);
return
ch
;
}
static
void
do_cons
(
unsigned
char
value
,
char
up_flag
)
static
void
k_cons
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
set_console
(
value
);
}
static
void
do_fn
(
unsigned
char
value
,
char
up_flag
)
static
void
k_fn
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
if
(
value
<
SIZE
(
func_table
))
{
if
(
func_table
[
value
])
puts_queue
(
func_table
[
value
]);
puts_queue
(
vc
,
func_table
[
value
]);
}
else
printk
(
KERN_ERR
"
do
_fn called with value=%d
\n
"
,
value
);
printk
(
KERN_ERR
"
k
_fn called with value=%d
\n
"
,
value
);
}
static
void
do_pad
(
unsigned
char
value
,
char
up_flag
)
static
void
k_pad
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
static
const
char
*
pad_chars
=
"0123456789+-*/
\015
,.?()"
;
static
const
char
*
app_map
=
"pqrstuvwxylSRQMnnmPQ"
;
...
...
@@ -630,8 +559,8 @@ static void do_pad(unsigned char value, char up_flag)
return
;
/* no action, if this is a key release */
/* kludge... shift forces cursor/number keys */
if
(
vc_kbd_mode
(
kbd
,
VC_APPLIC
)
&&
!
k
_down
[
KG_SHIFT
])
{
applkey
(
app_map
[
value
],
1
);
if
(
vc_kbd_mode
(
kbd
,
VC_APPLIC
)
&&
!
shift
_down
[
KG_SHIFT
])
{
applkey
(
vc
,
app_map
[
value
],
1
);
return
;
}
...
...
@@ -639,55 +568,55 @@ static void do_pad(unsigned char value, char up_flag)
switch
(
value
)
{
case
KVAL
(
K_PCOMMA
):
case
KVAL
(
K_PDOT
):
do_fn
(
KVAL
(
K_REMOVE
),
0
);
k_fn
(
vc
,
KVAL
(
K_REMOVE
),
0
);
return
;
case
KVAL
(
K_P0
):
do_fn
(
KVAL
(
K_INSERT
),
0
);
k_fn
(
vc
,
KVAL
(
K_INSERT
),
0
);
return
;
case
KVAL
(
K_P1
):
do_fn
(
KVAL
(
K_SELECT
),
0
);
k_fn
(
vc
,
KVAL
(
K_SELECT
),
0
);
return
;
case
KVAL
(
K_P2
):
do_cur
(
KVAL
(
K_DOWN
),
0
);
k_cur
(
vc
,
KVAL
(
K_DOWN
),
0
);
return
;
case
KVAL
(
K_P3
):
do_fn
(
KVAL
(
K_PGDN
),
0
);
k_fn
(
vc
,
KVAL
(
K_PGDN
),
0
);
return
;
case
KVAL
(
K_P4
):
do_cur
(
KVAL
(
K_LEFT
),
0
);
k_cur
(
vc
,
KVAL
(
K_LEFT
),
0
);
return
;
case
KVAL
(
K_P6
):
do_cur
(
KVAL
(
K_RIGHT
),
0
);
k_cur
(
vc
,
KVAL
(
K_RIGHT
),
0
);
return
;
case
KVAL
(
K_P7
):
do_fn
(
KVAL
(
K_FIND
),
0
);
k_fn
(
vc
,
KVAL
(
K_FIND
),
0
);
return
;
case
KVAL
(
K_P8
):
do_cur
(
KVAL
(
K_UP
),
0
);
k_cur
(
vc
,
KVAL
(
K_UP
),
0
);
return
;
case
KVAL
(
K_P9
):
do_fn
(
KVAL
(
K_PGUP
),
0
);
k_fn
(
vc
,
KVAL
(
K_PGUP
),
0
);
return
;
case
KVAL
(
K_P5
):
applkey
(
'G'
,
vc_kbd_mode
(
kbd
,
VC_APPLIC
));
applkey
(
vc
,
'G'
,
vc_kbd_mode
(
kbd
,
VC_APPLIC
));
return
;
}
put_queue
(
pad_chars
[
value
]);
put_queue
(
vc
,
pad_chars
[
value
]);
if
(
value
==
KVAL
(
K_PENTER
)
&&
vc_kbd_mode
(
kbd
,
VC_CRLF
))
put_queue
(
10
);
put_queue
(
vc
,
10
);
}
static
void
do_cur
(
unsigned
char
value
,
char
up_flag
)
static
void
k_cur
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
static
const
char
*
cur_chars
=
"BDCA"
;
if
(
up_flag
)
return
;
applkey
(
cur_chars
[
value
],
vc_kbd_mode
(
kbd
,
VC_CKMODE
));
applkey
(
vc
,
cur_chars
[
value
],
vc_kbd_mode
(
kbd
,
VC_CKMODE
));
}
static
void
do_shift
(
unsigned
char
value
,
char
up_flag
)
static
void
k_shift
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
int
old_state
=
shift_state
;
...
...
@@ -705,12 +634,12 @@ static void do_shift(unsigned char value, char up_flag)
if
(
up_flag
)
{
/* handle the case that two shift or control
keys are depressed simultaneously */
if
(
k
_down
[
value
])
k
_down
[
value
]
--
;
if
(
shift
_down
[
value
])
shift
_down
[
value
]
--
;
}
else
k
_down
[
value
]
++
;
shift
_down
[
value
]
++
;
if
(
k
_down
[
value
])
if
(
shift
_down
[
value
])
shift_state
|=
(
1
<<
value
);
else
shift_state
&=
~
(
1
<<
value
);
...
...
@@ -718,54 +647,26 @@ static void do_shift(unsigned char value, char up_flag)
/* kludge */
if
(
up_flag
&&
shift_state
!=
old_state
&&
npadch
!=
-
1
)
{
if
(
kbd
->
kbdmode
==
VC_UNICODE
)
to_utf8
(
npadch
&
0xffff
);
to_utf8
(
vc
,
npadch
&
0xffff
);
else
put_queue
(
npadch
&
0xff
);
put_queue
(
vc
,
npadch
&
0xff
);
npadch
=
-
1
;
}
}
/* called after returning from RAW mode or when changing consoles -
recompute k_down[] and shift_state from key_down[] */
/* maybe called when keymap is undefined, so that shiftkey release is seen */
void
compute_shiftstate
(
void
)
{
int
i
,
j
,
k
,
sym
,
val
;
shift_state
=
0
;
for
(
i
=
0
;
i
<
SIZE
(
k_down
);
i
++
)
k_down
[
i
]
=
0
;
for
(
i
=
0
;
i
<
SIZE
(
key_down
);
i
++
)
if
(
key_down
[
i
])
{
/* skip this word if not a single bit on */
k
=
i
*
BITS_PER_LONG
;
for
(
j
=
0
;
j
<
BITS_PER_LONG
;
j
++
,
k
++
)
if
(
test_bit
(
k
,
key_down
))
{
sym
=
U
(
plain_map
[
k
]);
if
(
KTYP
(
sym
)
==
KT_SHIFT
||
KTYP
(
sym
)
==
KT_SLOCK
)
{
val
=
KVAL
(
sym
);
if
(
val
==
KVAL
(
K_CAPSSHIFT
))
val
=
KVAL
(
K_SHIFT
);
k_down
[
val
]
++
;
shift_state
|=
(
1
<<
val
);
}
}
}
}
static
void
do_meta
(
unsigned
char
value
,
char
up_flag
)
static
void
k_meta
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
)
return
;
if
(
vc_kbd_mode
(
kbd
,
VC_META
))
{
put_queue
(
'\033'
);
put_queue
(
value
);
put_queue
(
vc
,
'\033'
);
put_queue
(
v
c
,
v
alue
);
}
else
put_queue
(
value
|
0x80
);
put_queue
(
v
c
,
v
alue
|
0x80
);
}
static
void
do_ascii
(
unsigned
char
value
,
char
up_flag
)
static
void
k_ascii
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
int
base
;
...
...
@@ -785,16 +686,16 @@ static void do_ascii(unsigned char value, char up_flag)
npadch
=
npadch
*
base
+
value
;
}
static
void
do_lock
(
unsigned
char
value
,
char
up_flag
)
static
void
k_lock
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
if
(
up_flag
||
rep
)
return
;
chg_vc_kbd_lock
(
kbd
,
value
);
}
static
void
do_slock
(
unsigned
char
value
,
char
up_flag
)
static
void
k_slock
(
struct
vc_data
*
vc
,
unsigned
char
value
,
char
up_flag
)
{
do_shift
(
value
,
up_flag
);
k_shift
(
vc
,
value
,
up_flag
);
if
(
up_flag
||
rep
)
return
;
chg_vc_kbd_slock
(
kbd
,
value
);
...
...
@@ -810,10 +711,6 @@ static void do_slock(unsigned char value, char up_flag)
* or (ii) whatever pattern of lights people want to show using KDSETLED,
* or (iii) specified bits of specified words in kernel memory.
*/
static
unsigned
char
ledstate
=
0xff
;
/* undefined */
static
unsigned
char
ledioctl
;
unsigned
char
getledstate
(
void
)
{
return
ledstate
;
}
...
...
@@ -827,12 +724,6 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) {
set_leds
();
}
static
struct
ledptr
{
unsigned
int
*
addr
;
unsigned
int
mask
;
unsigned
char
valid
:
1
;
}
ledptrs
[
3
];
void
register_leds
(
int
console
,
unsigned
int
led
,
unsigned
int
*
addr
,
unsigned
int
mask
)
{
struct
kbd_struct
*
kbd
=
kbd_table
+
console
;
...
...
@@ -888,6 +779,7 @@ static inline unsigned char getleds(void){
* used, but this allows for easy and efficient race-condition
* prevention later on.
*/
static
void
kbd_bh
(
unsigned
long
dummy
)
{
unsigned
char
leds
=
getleds
();
...
...
@@ -902,15 +794,146 @@ static void kbd_bh(unsigned long dummy)
EXPORT_SYMBOL
(
keyboard_tasklet
);
DECLARE_TASKLET_DISABLED
(
keyboard_tasklet
,
kbd_bh
,
0
);
typedef
void
(
pm_kbd_func
)
(
void
);
void
handle_scancode
(
unsigned
char
scancode
,
int
down
)
{
struct
vc_data
*
vc
=
vc_cons
[
fg_console
].
d
;
char
up_flag
=
down
?
0
:
0200
;
struct
tty_struct
*
tty
;
unsigned
char
keycode
;
char
raw_mode
;
pm_callback
pm_kbd_request_override
=
NULL
;
pm_access
(
pm_kbd
);
add_keyboard_randomness
(
scancode
|
up_flag
);
tty
=
vc
->
vc_tty
;
if
(
tty
&&
(
!
tty
->
driver_data
))
{
/*
* We touch the tty structure via the ttytab array
* without knowing whether or not tty is open, which
* is inherently dangerous. We currently rely on that
* fact that console_open sets tty->driver_data when
* it opens it, and clears it when it closes it.
*/
tty
=
NULL
;
}
kbd
=
kbd_table
+
fg_console
;
if
((
raw_mode
=
(
kbd
->
kbdmode
==
VC_RAW
)))
{
put_queue
(
vc
,
scancode
|
up_flag
);
/* we do not return yet, because we want to maintain
the key_down array, so that we have the correct
values when finishing RAW mode or when changing VT's */
}
/*
* Convert scancode to keycode
*/
if
(
!
kbd_translate
(
scancode
,
&
keycode
,
raw_mode
))
goto
out
;
/*
* At this point the variable `keycode' contains the keycode.
* Note: the keycode must not be 0 (++Geert: on m68k 0 is valid).
* We keep track of the up/down status of the key, and
* return the keycode if in MEDIUMRAW mode.
*/
if
(
up_flag
)
{
rep
=
0
;
if
(
!
test_and_clear_bit
(
keycode
,
key_down
))
up_flag
=
kbd_unexpected_up
(
keycode
);
}
else
rep
=
test_and_set_bit
(
keycode
,
key_down
);
#ifdef CONFIG_MAGIC_SYSRQ
/* Handle the SysRq Hack */
if
(
keycode
==
SYSRQ_KEY
)
{
sysrq_pressed
=
!
up_flag
;
goto
out
;
}
else
if
(
sysrq_pressed
)
{
if
(
!
up_flag
)
{
handle_sysrq
(
kbd_sysrq_xlate
[
keycode
],
kbd_pt_regs
,
tty
);
goto
out
;
}
}
#endif
if
(
kbd
->
kbdmode
==
VC_MEDIUMRAW
)
{
/* soon keycodes will require more than one byte */
put_queue
(
vc
,
keycode
+
up_flag
);
raw_mode
=
1
;
/* Most key classes will be ignored */
}
/*
* Small change in philosophy: earlier we defined repetition by
* rep = keycode == prev_keycode;
* prev_keycode = keycode;
* but now by the fact that the depressed key was down already.
* Does this ever make a difference? Yes.
*/
/*
* Repeat a key only if the input buffers are empty or the
* characters get echoed locally. This makes key repeat usable
* with slow applications and under heavy loads.
*/
if
(
!
rep
||
(
vc_kbd_mode
(
kbd
,
VC_REPEAT
)
&&
tty
&&
(
L_ECHO
(
tty
)
||
(
tty
->
driver
.
chars_in_buffer
(
tty
)
==
0
))))
{
u_short
keysym
;
u_char
type
;
/* the XOR below used to be an OR */
int
shift_final
=
(
shift_state
|
kbd
->
slockstate
)
^
kbd
->
lockstate
;
ushort
*
key_map
=
key_maps
[
shift_final
];
if
(
key_map
!=
NULL
)
{
keysym
=
key_map
[
keycode
];
type
=
KTYP
(
keysym
);
if
(
type
>=
0xf0
)
{
type
-=
0xf0
;
if
(
raw_mode
&&
!
(
TYPES_ALLOWED_IN_RAW_MODE
&
(
1
<<
type
)))
goto
out
;
if
(
type
==
KT_LETTER
)
{
type
=
KT_LATIN
;
if
(
vc_kbd_led
(
kbd
,
VC_CAPSLOCK
))
{
key_map
=
key_maps
[
shift_final
^
(
1
<<
KG_SHIFT
)];
if
(
key_map
)
keysym
=
key_map
[
keycode
];
}
}
(
*
k_handler
[
type
])(
vc
,
keysym
&
0xff
,
up_flag
);
if
(
type
!=
KT_SLOCK
)
kbd
->
slockstate
=
0
;
}
else
{
/* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
if
(
!
up_flag
&&
!
raw_mode
)
to_utf8
(
vc
,
keysym
);
}
}
else
{
/* maybe beep? */
/* we have at least to update shift_state */
#if 1
/* how? two almost equivalent choices follow */
compute_shiftstate
();
kbd
->
slockstate
=
0
;
/* play it safe */
#else
keysym
=
U
(
plain_map
[
keycode
]);
type
=
KTYP
(
keysym
);
if
(
type
==
KT_SHIFT
)
(
*
key_handler
[
type
])(
keysym
&
0xff
,
up_flag
);
#endif
}
}
out:
do_poke_blanked_console
=
1
;
schedule_console_callback
();
}
int
__init
kbd_init
(
void
)
{
int
i
;
struct
kbd_struct
kbd0
;
extern
struct
tty_driver
console_driver
;
kbd0
.
ledflagstate
=
kbd0
.
default_ledflagstate
=
KBD_DEFLEDS
;
kbd0
.
ledmode
=
LED_SHOW_FLAGS
;
...
...
@@ -922,8 +945,6 @@ int __init kbd_init(void)
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
kbd_table
[
i
]
=
kbd0
;
ttytab
=
console_driver
.
table
;
kbd_init_hw
();
tasklet_enable
(
&
keyboard_tasklet
);
...
...
drivers/char/sysrq.c
View file @
484f2a9c
...
...
@@ -45,7 +45,8 @@ void (*sysrq_power_off)(void);
/* Loglevel sysrq handler */
static
void
sysrq_handle_loglevel
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
int
i
;
i
=
key
-
'0'
;
console_loglevel
=
7
;
...
...
@@ -62,7 +63,8 @@ static struct sysrq_key_op sysrq_loglevel_op = {
/* SAK sysrq handler */
#ifdef CONFIG_VT
static
void
sysrq_handle_SAK
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
if
(
tty
)
do_SAK
(
tty
);
reset_vc
(
fg_console
);
...
...
@@ -77,7 +79,10 @@ static struct sysrq_key_op sysrq_SAK_op = {
/* unraw sysrq handler */
static
void
sysrq_handle_unraw
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
struct
kbd_struct
*
kbd
=
&
kbd_table
[
fg_console
];
if
(
kbd
)
kbd
->
kbdmode
=
VC_XLATE
;
}
...
...
@@ -90,7 +95,8 @@ static struct sysrq_key_op sysrq_unraw_op = {
/* reboot sysrq handler */
static
void
sysrq_handle_reboot
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
machine_restart
(
NULL
);
}
static
struct
sysrq_key_op
sysrq_reboot_op
=
{
...
...
@@ -218,7 +224,8 @@ void do_emergency_sync(void) {
}
static
void
sysrq_handle_sync
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
emergency_sync_scheduled
=
EMERG_SYNC
;
wakeup_bdflush
();
}
...
...
@@ -229,7 +236,8 @@ static struct sysrq_key_op sysrq_sync_op = {
};
static
void
sysrq_handle_mountro
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
emergency_sync_scheduled
=
EMERG_REMOUNT
;
wakeup_bdflush
();
}
...
...
@@ -245,7 +253,8 @@ static struct sysrq_key_op sysrq_mountro_op = {
/* SHOW SYSRQ HANDLERS BLOCK */
static
void
sysrq_handle_showregs
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
if
(
pt_regs
)
show_regs
(
pt_regs
);
}
...
...
@@ -257,7 +266,8 @@ static struct sysrq_key_op sysrq_showregs_op = {
static
void
sysrq_handle_showstate
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
show_state
();
}
static
struct
sysrq_key_op
sysrq_showstate_op
=
{
...
...
@@ -268,7 +278,8 @@ static struct sysrq_key_op sysrq_showstate_op = {
static
void
sysrq_handle_showmem
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
show_mem
();
}
static
struct
sysrq_key_op
sysrq_showmem_op
=
{
...
...
@@ -296,7 +307,8 @@ static void send_sig_all(int sig)
}
static
void
sysrq_handle_term
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
send_sig_all
(
SIGTERM
);
console_loglevel
=
8
;
}
...
...
@@ -307,7 +319,8 @@ static struct sysrq_key_op sysrq_term_op = {
};
static
void
sysrq_handle_kill
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
send_sig_all
(
SIGKILL
);
console_loglevel
=
8
;
}
...
...
@@ -416,13 +429,13 @@ void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
* and any other keycode arrives.
*/
void
handle_sysrq
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
void
handle_sysrq
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
tty_struct
*
tty
)
{
if
(
!
sysrq_enabled
)
return
;
__sysrq_lock_table
();
__handle_sysrq_nolock
(
key
,
pt_regs
,
kbd
,
tty
);
__handle_sysrq_nolock
(
key
,
pt_regs
,
tty
);
__sysrq_unlock_table
();
}
...
...
@@ -433,7 +446,8 @@ void handle_sysrq(int key, struct pt_regs *pt_regs,
*/
void
__handle_sysrq_nolock
(
int
key
,
struct
pt_regs
*
pt_regs
,
struct
kbd_struct
*
kbd
,
struct
tty_struct
*
tty
)
{
struct
tty_struct
*
tty
)
{
struct
sysrq_key_op
*
op_p
;
int
orig_log_level
;
int
i
,
j
;
...
...
@@ -449,7 +463,7 @@ void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs,
if
(
op_p
)
{
printk
(
"%s
\n
"
,
op_p
->
action_msg
);
console_loglevel
=
orig_log_level
;
op_p
->
handler
(
key
,
pt_regs
,
kbd
,
tty
);
op_p
->
handler
(
key
,
pt_regs
,
tty
);
}
else
{
printk
(
"HELP : "
);
/* Only print the help msg once per handler */
...
...
drivers/char/tty_io.c
View file @
484f2a9c
...
...
@@ -2245,9 +2245,8 @@ static struct tty_driver dev_tty_driver, dev_syscons_driver;
static
struct
tty_driver
dev_ptmx_driver
;
#endif
#ifdef CONFIG_VT
extern
void
con_init_devfs
(
void
);
extern
void
console_map_init
(
void
);
static
struct
tty_driver
dev_console_driver
;
extern
int
vty_init
(
void
);
#endif
/*
...
...
@@ -2287,13 +2286,6 @@ void __init tty_init(void)
if
(
tty_register_driver
(
&
dev_syscons_driver
))
panic
(
"Couldn't register /dev/console driver
\n
"
);
/* console calls tty_register_driver() before kmalloc() works.
* Thus, we can't devfs_register() then. Do so now, instead.
*/
#ifdef CONFIG_VT
con_init_devfs
();
#endif
#ifdef CONFIG_UNIX98_PTYS
dev_ptmx_driver
=
dev_tty_driver
;
dev_ptmx_driver
.
driver_name
=
"/dev/ptmx"
;
...
...
@@ -2317,10 +2309,7 @@ void __init tty_init(void)
if
(
tty_register_driver
(
&
dev_console_driver
))
panic
(
"Couldn't register /dev/tty0 driver
\n
"
);
vcs_init
();
kbd_init
();
console_map_init
();
vty_init
();
#endif
#ifdef CONFIG_ESPSERIAL
/* init ESP before rs, so rs doesn't see the port */
...
...
include/linux/console_struct.h
View file @
484f2a9c
...
...
@@ -33,6 +33,7 @@ struct vc_data {
unsigned
int
vc_top
,
vc_bottom
;
/* Scrolling region */
unsigned
int
vc_state
;
/* Escape sequence parser state */
unsigned
int
vc_npar
,
vc_par
[
NPAR
];
/* Parameters of current escape sequence */
struct
tty_struct
*
vc_tty
;
/* TTY we are attached to */
unsigned
long
vc_origin
;
/* [!] Start of real screen */
unsigned
long
vc_scr_end
;
/* [!] End of real screen */
unsigned
long
vc_visible_origin
;
/* [!] Top of visible window */
...
...
include/linux/sysrq.h
View file @
484f2a9c
...
...
@@ -14,12 +14,10 @@
#include <linux/config.h>
struct
pt_regs
;
struct
kbd_struct
;
struct
tty_struct
;
struct
sysrq_key_op
{
void
(
*
handler
)(
int
,
struct
pt_regs
*
,
struct
kbd_struct
*
,
struct
tty_struct
*
);
void
(
*
handler
)(
int
,
struct
pt_regs
*
,
struct
tty_struct
*
);
char
*
help_msg
;
char
*
action_msg
;
};
...
...
@@ -31,19 +29,14 @@ struct sysrq_key_op {
* are available -- else NULL's).
*/
void
handle_sysrq
(
int
,
struct
pt_regs
*
,
struct
kbd_struct
*
,
struct
tty_struct
*
);
void
handle_sysrq
(
int
,
struct
pt_regs
*
,
struct
tty_struct
*
);
/*
* Nonlocking version of handle sysrq, used by sysrq handlers that need to
* call sysrq handlers
*/
void
__handle_sysrq_nolock
(
int
,
struct
pt_regs
*
,
struct
kbd_struct
*
,
struct
tty_struct
*
);
void
__handle_sysrq_nolock
(
int
,
struct
pt_regs
*
,
struct
tty_struct
*
);
/*
* Sysrq registration manipulation functions
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment