vt:tackle kbd_table
Subsystems (2)
PATCH 1/1 vt:tackle kbd_table
From: Alan Cox <[email protected]>
Keyboard struct lifetime is easy, but the locking is not and is completely ignored by the existing code. Tackle this one head on
- Make the kbd_table private so we can run down all direct users
- Hoick the relevant ioctl handlers into the keyboard layer
- Lock them with the keyboard lock so they don't change mid keypress
- Add helpers for things like console stop/start so we isolate the poking around properly
- Tweak the braille console so it still builds
There are a couple of FIXME locking cases left for ioctls that are so hideous they should be addressed in a later patch. After this patch the kbd_table is private and all the keyboard jiggery pokery is in one place.
This update fixes speakup and also a memory leak in the original.
---
drivers/accessibility/braille/braille_console.c | 9 drivers/staging/speakup/main.c | 8 drivers/tty/sysrq.c | 6 drivers/tty/vt/keyboard.c | 621 ++++++++++++++++++++++- drivers/tty/vt/selection.c | 9 drivers/tty/vt/vt.c | 27 - drivers/tty/vt/vt_ioctl.c | 325 +----------- include/linux/kbd_kern.h | 7 include/linux/keyboard.h | 2 include/linux/vt_kern.h | 23 + 10 files changed, 660 insertions(+), 377 deletions(-)
drivers/accessibility/braille/braille_console.c +3 -6
@@ -244,16 +244,13 @@ static int keyboard_notifier_call(struct notifier_block *blk,switch (val) {case KVAL (K_CAPS ): - on_off =vc_kbd_led (kbd_table + fg_console, -VC_CAPSLOCK ); + on_off =vt_get_leds (fg_console,VC_CAPSLOCK );break ;case KVAL (K_NUM ): - on_off =vc_kbd_led (kbd_table + fg_console, -VC_NUMLOCK ); + on_off =vt_get_leds (fg_console,VC_NUMLOCK );break ;case KVAL (K_HOLD ): - on_off =vc_kbd_led (kbd_table + fg_console, -VC_SCROLLOCK ); + on_off =vt_get_leds (fg_console,VC_SCROLLOCK );break ; }if (on_off ==1 )
drivers/staging/speakup/main.c +4 -4
@@ -1731,15 +1731,15 @@ static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)switch (value) {case KVAL (K_CAPS ): label =msg_get (MSG_KEYNAME_CAPSLOCK ); - on_off = (vc_kbd_led (kbd_table + vc->vc_num,VC_CAPSLOCK )); + on_off =vt_get_leds (fg_console,VC_CAPSLOCK );break ;case KVAL (K_NUM ): label =msg_get (MSG_KEYNAME_NUMLOCK ); - on_off = (vc_kbd_led (kbd_table + vc->vc_num,VC_NUMLOCK )); + on_off =vt_get_leds (fg_console,VC_NUMLOCK );break ;case KVAL (K_HOLD ): label =msg_get (MSG_KEYNAME_SCROLLLOCK ); - on_off = (vc_kbd_led (kbd_table + vc->vc_num,VC_SCROLLOCK )); + on_off =vt_get_leds (fg_console,VC_SCROLLOCK );if (speakup_console[vc->vc_num]) speakup_console[vc->vc_num]->tty_stopped = on_off;break ;
@@ -2020,7 +2020,7 @@ speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,if (type >=0xf0 ) type -=0xf0 ;if (type ==KT_PAD - && (vc_kbd_led (kbd_table + fg_console,VC_NUMLOCK ))) { + && (vt_get_leds (fg_console,VC_NUMLOCK ))) {if (up_flag) { spk_keydown =0 ; goto out;
drivers/tty/sysrq.c +2 -4
@@ -110,11 +110,9 @@ static struct sysrq_key_op sysrq_SAK_op = {#ifdef CONFIG_VT static void sysrq_handle_unraw (int key) { -struct kbd_struct *kbd = &kbd_table[fg_console]; - -if (kbd) - kbd->kbdmode = default_utf8 ?VC_UNICODE :VC_XLATE ; +vt_reset_unicode (fg_console); } +static struct sysrq_key_op sysrq_unraw_op = { .handler = sysrq_handle_unraw, .help_msg = "unRaw",
drivers/tty/vt/keyboard.c +595 -26
708 lines not on this page · raw message
drivers/tty/vt/selection.c +7 -2
@@ -30,6 +30,7 @@extern void poke_blanked_console (void ); +/* FIXME: all this needs locking */ /* Variables for selection control. */ /* Use a dynamic buffer, instead of static (Dec 1994) */ struct vc_data *sel_cons;/* must not be deallocated */
@@ -138,7 +139,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tchar *bp, *obp;int i, ps, pe, multiplier;u16 c; -struct kbd_struct *kbd = kbd_table + fg_console; +int mode;poke_blanked_console ();
@@ -182,7 +183,11 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tclear_selection (); sel_cons = vc_cons[fg_console].d; } - use_unicode = kbd && kbd->kbdmode ==VC_UNICODE ; + mode =vt_do_kdgkbmode (fg_console); +if (mode ==K_UNICODE ) + use_unicode =1 ; +else + use_unicode =0 ;switch (sel_mode) {
drivers/tty/vt/vt.c +8 -19
@@ -1028,9 +1028,9 @@ void vc_deallocate(unsigned int currcons)* VT102 emulator */ -#define set_kbd (vc, x) set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) -#define clr_kbd (vc, x) clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) -#define is_kbd (vc, x) vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) +#define set_kbd (vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x)) +#define clr_kbd (vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x)) +#define is_kbd (vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x))#define decarm VC_REPEAT#define decckm VC_CKMODE
@@ -1652,16 +1652,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_deccm = global_cursor_default; vc->vc_decim =0 ; -set_kbd (vc, decarm); -clr_kbd (vc, decckm); -clr_kbd (vc, kbdapplic); -clr_kbd (vc, lnm); - kbd_table[vc->vc_num].lockstate =0 ; - kbd_table[vc->vc_num].slockstate =0 ; - kbd_table[vc->vc_num].ledmode =LED_SHOW_FLAGS ; - kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate; -/* do not do set_leds here because this causes an endless tasklet loop -when the keyboard hasn't been initialized yet */ +vt_reset_keyboard (vc->vc_num); vc->vc_cursor_type = cur_default; vc->vc_complement_mask = vc->vc_s_complement_mask;
@@ -1979,7 +1970,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)case 'q' :/* DECLL - but only 3 leds */ /* map 0,1,2,3 to 0,1,2,4 */ if (vc->vc_par[0 ] <4 ) -setledstate (kbd_table + vc->vc_num, +vt_set_led_state (vc->vc_num, (vc->vc_par[0 ] <3 ) ? vc->vc_par[0 ] :4 );return ;case 'r' :
@@ -2642,7 +2633,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)* kernel-internal variable; programs not closely * related to the kernel should not use this. */ - data = shift_state; + data =vt_get_shift_state (); ret =__put_user (data, p);break ;case TIOCL_GETMOUSEREPORTING :
@@ -2753,8 +2744,7 @@ static void con_stop(struct tty_struct *tty) console_num = tty->index;if (!vc_cons_allocated (console_num))return ; -set_vc_kbd_led (kbd_table + console_num,VC_SCROLLOCK ); -set_leds (); +vt_kbd_con_stop (console_num); }/*
@@ -2768,8 +2758,7 @@ static void con_start(struct tty_struct *tty) console_num = tty->index;if (!vc_cons_allocated (console_num))return ; -clr_vc_kbd_led (kbd_table + console_num,VC_SCROLLOCK ); -set_leds (); +vt_kbd_con_start (console_num); }static void con_flush_chars (struct tty_struct *tty)
drivers/tty/vt/vt_ioctl.c +17 -308
401 lines not on this page · raw message
include/linux/kbd_kern.h +1 -6
@@ -7,8 +7,6 @@extern struct tasklet_struct keyboard_tasklet; -extern int shift_state; -extern char *func_table[MAX_NR_FUNC ];extern char func_buf[];extern char *funcbufptr;
@@ -65,8 +63,6 @@ struct kbd_struct {#define VC_META 4/* 0 - meta, 1 - meta=prefix with ESC */ }; -extern struct kbd_struct kbd_table[]; -extern int kbd_init (void );extern unsigned char getledstate (void );
@@ -79,6 +75,7 @@ extern void (*kbd_ledfunc)(unsigned int led);extern int set_console (int nr);extern void schedule_console_callback (void ); +/* FIXME: review locking for vt.c callers */ static inline void set_leds (void ) {tasklet_schedule (&keyboard_tasklet);
@@ -142,8 +139,6 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)struct console ; -int getkeycode (unsigned int scancode); -int setkeycode (unsigned int scancode,unsigned int keycode);void compute_shiftstate (void );/* defkeymap.c */
include/linux/keyboard.h +0 -2
@@ -24,8 +24,6 @@#ifdef __KERNEL__struct notifier_block ; -extern const int NR_TYPES ; -extern const int max_vals[];extern unsigned short *key_maps[MAX_NR_KEYMAPS ];extern unsigned short plain_map[NR_KEYS ];
include/linux/vt_kern.h +23 -0
@@ -169,5 +169,28 @@ extern void hide_boot_cursor(bool hide);/* keyboard provided interfaces */ extern int vt_do_diacrit (unsigned int cmd,void __user *up,int eperm); +extern int vt_do_kdskbmode (int console,unsigned int arg); +extern int vt_do_kdskbmeta (int console,unsigned int arg); +extern int vt_do_kbkeycode_ioctl (int cmd,struct kbkeycode __user *user_kbkc, +int perm); +extern int vt_do_kdsk_ioctl (int cmd,struct kbentry __user *user_kbe, +int perm,int console); +extern int vt_do_kdgkb_ioctl (int cmd,struct kbsentry __user *user_kdgkb, +int perm); +extern int vt_do_kdskled (int console,int cmd,unsigned long arg,int perm); +extern int vt_do_kdgkbmode (int console); +extern int vt_do_kdgkbmeta (int console); +extern void vt_reset_unicode (int console); +extern int vt_get_shift_state (void ); +extern void vt_reset_keyboard (int console); +extern int vt_get_leds (int console,int flag); +extern int vt_get_kbd_mode_bit (int console,int bit); +extern void vt_set_kbd_mode_bit (int console,int bit); +extern void vt_clr_kbd_mode_bit (int console,int bit); +extern void vt_set_led_state (int console,int leds); +extern void vt_set_led_state (int console,int leds); +extern void vt_kbd_con_start (int console); +extern void vt_kbd_con_stop (int console); +#endif /* _VT_KERN_H */