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
Kirill Smelkov
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
Show 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
);
/* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
struct
pt_regs
*
kbd_pt_regs
;
void
compute_shiftstate
(
void
);
extern
void
ctrl_alt_del
(
void
);
struct
console
;
/*
* 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
;
return
kbd_setkeycode
(
scancode
,
keycode
);
}
/*
* 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.
/*
* Variables/function exported for console.c
*/
int
shift_state
=
0
;
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
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 */
}
/*
* 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
));
}
}
static
void
enter
(
void
)
/* 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
;
}
/*
* 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,50 +395,62 @@ 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.
*/
if
(
tty
)
do_SAK
(
tty
);
reset_vc
(
fg_console
);
#if 0
...
...
@@ -504,47 +458,49 @@ static void SAK(void)
#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