Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vt:tackle kbd_table

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.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Cox and committed by
Greg Kroah-Hartman
079c9534 0fb8379d

+660 -377
+3 -6
drivers/accessibility/braille/braille_console.c
··· 244 244 245 245 switch (val) { 246 246 case KVAL(K_CAPS): 247 - on_off = vc_kbd_led(kbd_table + fg_console, 248 - VC_CAPSLOCK); 247 + on_off = vt_get_leds(fg_console, VC_CAPSLOCK); 249 248 break; 250 249 case KVAL(K_NUM): 251 - on_off = vc_kbd_led(kbd_table + fg_console, 252 - VC_NUMLOCK); 250 + on_off = vt_get_leds(fg_console, VC_NUMLOCK); 253 251 break; 254 252 case KVAL(K_HOLD): 255 - on_off = vc_kbd_led(kbd_table + fg_console, 256 - VC_SCROLLOCK); 253 + on_off = vt_get_leds(fg_console, VC_SCROLLOCK); 257 254 break; 258 255 } 259 256 if (on_off == 1)
+4 -4
drivers/staging/speakup/main.c
··· 1731 1731 switch (value) { 1732 1732 case KVAL(K_CAPS): 1733 1733 label = msg_get(MSG_KEYNAME_CAPSLOCK); 1734 - on_off = (vc_kbd_led(kbd_table + vc->vc_num, VC_CAPSLOCK)); 1734 + on_off = vt_get_leds(fg_console, VC_CAPSLOCK); 1735 1735 break; 1736 1736 case KVAL(K_NUM): 1737 1737 label = msg_get(MSG_KEYNAME_NUMLOCK); 1738 - on_off = (vc_kbd_led(kbd_table + vc->vc_num, VC_NUMLOCK)); 1738 + on_off = vt_get_leds(fg_console, VC_NUMLOCK); 1739 1739 break; 1740 1740 case KVAL(K_HOLD): 1741 1741 label = msg_get(MSG_KEYNAME_SCROLLLOCK); 1742 - on_off = (vc_kbd_led(kbd_table + vc->vc_num, VC_SCROLLOCK)); 1742 + on_off = vt_get_leds(fg_console, VC_SCROLLOCK); 1743 1743 if (speakup_console[vc->vc_num]) 1744 1744 speakup_console[vc->vc_num]->tty_stopped = on_off; 1745 1745 break; ··· 2020 2020 if (type >= 0xf0) 2021 2021 type -= 0xf0; 2022 2022 if (type == KT_PAD 2023 - && (vc_kbd_led(kbd_table + fg_console, VC_NUMLOCK))) { 2023 + && (vt_get_leds(fg_console, VC_NUMLOCK))) { 2024 2024 if (up_flag) { 2025 2025 spk_keydown = 0; 2026 2026 goto out;
+2 -4
drivers/tty/sysrq.c
··· 110 110 #ifdef CONFIG_VT 111 111 static void sysrq_handle_unraw(int key) 112 112 { 113 - struct kbd_struct *kbd = &kbd_table[fg_console]; 114 - 115 - if (kbd) 116 - kbd->kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; 113 + vt_reset_unicode(fg_console); 117 114 } 115 + 118 116 static struct sysrq_key_op sysrq_unraw_op = { 119 117 .handler = sysrq_handle_unraw, 120 118 .help_msg = "unRaw",
+595 -26
drivers/tty/vt/keyboard.c
··· 68 68 69 69 #define KBD_DEFLOCK 0 70 70 71 - void compute_shiftstate(void); 72 - 73 71 /* 74 72 * Handler Tables. 75 73 */ ··· 98 100 * Variables exported for vt_ioctl.c 99 101 */ 100 102 101 - /* maximum values each key_handler can handle */ 102 - const int max_vals[] = { 103 - 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, 104 - NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 105 - 255, NR_LOCK - 1, 255, NR_BRL - 1 106 - }; 107 - 108 - const int NR_TYPES = ARRAY_SIZE(max_vals); 109 - 110 - struct kbd_struct kbd_table[MAX_NR_CONSOLES]; 111 - EXPORT_SYMBOL_GPL(kbd_table); 112 - static struct kbd_struct *kbd = kbd_table; 113 - 114 103 struct vt_spawn_console vt_spawn_con = { 115 104 .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock), 116 105 .pid = NULL, 117 106 .sig = 0, 118 107 }; 119 108 120 - /* 121 - * Variables exported for vt.c 122 - */ 123 - 124 - int shift_state = 0; 125 109 126 110 /* 127 111 * Internal Data. 128 112 */ 113 + 114 + static struct kbd_struct kbd_table[MAX_NR_CONSOLES]; 115 + static struct kbd_struct *kbd = kbd_table; 116 + 117 + /* maximum values each key_handler can handle */ 118 + static const int max_vals[] = { 119 + 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, 120 + NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 121 + 255, NR_LOCK - 1, 255, NR_BRL - 1 122 + }; 123 + 124 + static const int NR_TYPES = ARRAY_SIZE(max_vals); 129 125 130 126 static struct input_handler kbd_handler; 131 127 static DEFINE_SPINLOCK(kbd_event_lock); ··· 129 137 static int npadch = -1; /* -1 or number assembled on pad */ 130 138 static unsigned int diacr; 131 139 static char rep; /* flag telling character repeat */ 140 + 141 + static int shift_state = 0; 132 142 133 143 static unsigned char ledstate = 0xff; /* undefined */ 134 144 static unsigned char ledioctl; ··· 182 188 return d->error == 0; /* stop as soon as we successfully get one */ 183 189 } 184 190 185 - int getkeycode(unsigned int scancode) 191 + static int getkeycode(unsigned int scancode) 186 192 { 187 193 struct getset_keycode_data d = { 188 194 .ke = { ··· 209 215 return d->error == 0; /* stop as soon as we successfully set one */ 210 216 } 211 217 212 - int setkeycode(unsigned int scancode, unsigned int keycode) 218 + static int setkeycode(unsigned int scancode, unsigned int keycode) 213 219 { 214 220 struct getset_keycode_data d = { 215 221 .ke = { ··· 377 383 /* 378 384 * Called after returning from RAW mode or when changing consoles - recompute 379 385 * shift_down[] and shift_state from key_down[] maybe called when keymap is 380 - * undefined, so that shiftkey release is seen 386 + * undefined, so that shiftkey release is seen. The caller must hold the 387 + * kbd_event_lock. 381 388 */ 382 - void compute_shiftstate(void) 389 + 390 + static void do_compute_shiftstate(void) 383 391 { 384 392 unsigned int i, j, k, sym, val; 385 393 ··· 412 416 shift_state |= (1 << val); 413 417 } 414 418 } 419 + } 420 + 421 + /* We still have to export this method to vt.c */ 422 + void compute_shiftstate(void) 423 + { 424 + unsigned long flags; 425 + spin_lock_irqsave(&kbd_event_lock, flags); 426 + do_compute_shiftstate(); 427 + spin_unlock_irqrestore(&kbd_event_lock, flags); 415 428 } 416 429 417 430 /* ··· 642 637 643 638 static void fn_null(struct vc_data *vc) 644 639 { 645 - compute_shiftstate(); 640 + do_compute_shiftstate(); 646 641 } 647 642 648 643 /* ··· 995 990 996 991 void setledstate(struct kbd_struct *kbd, unsigned int led) 997 992 { 993 + unsigned long flags; 994 + spin_lock_irqsave(&kbd_event_lock, flags); 998 995 if (!(led & ~7)) { 999 996 ledioctl = led; 1000 997 kbd->ledmode = LED_SHOW_IOCTL; ··· 1004 997 kbd->ledmode = LED_SHOW_FLAGS; 1005 998 1006 999 set_leds(); 1000 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1007 1001 } 1008 1002 1009 1003 static inline unsigned char getleds(void) ··· 1042 1034 } 1043 1035 1044 1036 return 0; 1037 + } 1038 + 1039 + /** 1040 + * vt_get_leds - helper for braille console 1041 + * @console: console to read 1042 + * @flag: flag we want to check 1043 + * 1044 + * Check the status of a keyboard led flag and report it back 1045 + */ 1046 + int vt_get_leds(int console, int flag) 1047 + { 1048 + unsigned long flags; 1049 + struct kbd_struct * kbd = kbd_table + console; 1050 + int ret; 1051 + 1052 + spin_lock_irqsave(&kbd_event_lock, flags); 1053 + ret = vc_kbd_led(kbd, flag); 1054 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1055 + 1056 + return ret; 1057 + } 1058 + EXPORT_SYMBOL_GPL(vt_get_leds); 1059 + 1060 + /** 1061 + * vt_set_led_state - set LED state of a console 1062 + * @console: console to set 1063 + * @leds: LED bits 1064 + * 1065 + * Set the LEDs on a console. This is a wrapper for the VT layer 1066 + * so that we can keep kbd knowledge internal 1067 + */ 1068 + void vt_set_led_state(int console, int leds) 1069 + { 1070 + struct kbd_struct * kbd = kbd_table + console; 1071 + setledstate(kbd, leds); 1072 + } 1073 + 1074 + /** 1075 + * vt_kbd_con_start - Keyboard side of console start 1076 + * @console: console 1077 + * 1078 + * Handle console start. This is a wrapper for the VT layer 1079 + * so that we can keep kbd knowledge internal 1080 + */ 1081 + void vt_kbd_con_start(int console) 1082 + { 1083 + struct kbd_struct * kbd = kbd_table + console; 1084 + unsigned long flags; 1085 + spin_lock_irqsave(&kbd_event_lock, flags); 1086 + clr_vc_kbd_led(kbd, VC_SCROLLOCK); 1087 + set_leds(); 1088 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1089 + } 1090 + 1091 + /** 1092 + * vt_kbd_con_stop - Keyboard side of console stop 1093 + * @console: console 1094 + * 1095 + * Handle console stop. This is a wrapper for the VT layer 1096 + * so that we can keep kbd knowledge internal 1097 + */ 1098 + void vt_kbd_con_stop(int console) 1099 + { 1100 + struct kbd_struct * kbd = kbd_table + console; 1101 + unsigned long flags; 1102 + spin_lock_irqsave(&kbd_event_lock, flags); 1103 + set_vc_kbd_led(kbd, VC_SCROLLOCK); 1104 + set_leds(); 1105 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1045 1106 } 1046 1107 1047 1108 /* ··· 1332 1255 if (rc == NOTIFY_STOP || !key_map) { 1333 1256 atomic_notifier_call_chain(&keyboard_notifier_list, 1334 1257 KBD_UNBOUND_KEYCODE, &param); 1335 - compute_shiftstate(); 1258 + do_compute_shiftstate(); 1336 1259 kbd->slockstate = 0; 1337 1260 return; 1338 1261 } ··· 1691 1614 } 1692 1615 } 1693 1616 return ret; 1617 + } 1618 + 1619 + /** 1620 + * vt_do_kdskbmode - set keyboard mode ioctl 1621 + * @console: the console to use 1622 + * @arg: the requested mode 1623 + * 1624 + * Update the keyboard mode bits while holding the correct locks. 1625 + * Return 0 for success or an error code. 1626 + */ 1627 + int vt_do_kdskbmode(int console, unsigned int arg) 1628 + { 1629 + struct kbd_struct * kbd = kbd_table + console; 1630 + int ret = 0; 1631 + unsigned long flags; 1632 + 1633 + spin_lock_irqsave(&kbd_event_lock, flags); 1634 + switch(arg) { 1635 + case K_RAW: 1636 + kbd->kbdmode = VC_RAW; 1637 + break; 1638 + case K_MEDIUMRAW: 1639 + kbd->kbdmode = VC_MEDIUMRAW; 1640 + break; 1641 + case K_XLATE: 1642 + kbd->kbdmode = VC_XLATE; 1643 + do_compute_shiftstate(); 1644 + break; 1645 + case K_UNICODE: 1646 + kbd->kbdmode = VC_UNICODE; 1647 + do_compute_shiftstate(); 1648 + break; 1649 + case K_OFF: 1650 + kbd->kbdmode = VC_OFF; 1651 + break; 1652 + default: 1653 + ret = -EINVAL; 1654 + } 1655 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1656 + return ret; 1657 + } 1658 + 1659 + /** 1660 + * vt_do_kdskbmeta - set keyboard meta state 1661 + * @console: the console to use 1662 + * @arg: the requested meta state 1663 + * 1664 + * Update the keyboard meta bits while holding the correct locks. 1665 + * Return 0 for success or an error code. 1666 + */ 1667 + int vt_do_kdskbmeta(int console, unsigned int arg) 1668 + { 1669 + struct kbd_struct * kbd = kbd_table + console; 1670 + int ret = 0; 1671 + unsigned long flags; 1672 + 1673 + spin_lock_irqsave(&kbd_event_lock, flags); 1674 + switch(arg) { 1675 + case K_METABIT: 1676 + clr_vc_kbd_mode(kbd, VC_META); 1677 + break; 1678 + case K_ESCPREFIX: 1679 + set_vc_kbd_mode(kbd, VC_META); 1680 + break; 1681 + default: 1682 + ret = -EINVAL; 1683 + } 1684 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1685 + return ret; 1686 + } 1687 + 1688 + int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, 1689 + int perm) 1690 + { 1691 + struct kbkeycode tmp; 1692 + int kc = 0; 1693 + 1694 + if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 1695 + return -EFAULT; 1696 + switch (cmd) { 1697 + case KDGETKEYCODE: 1698 + kc = getkeycode(tmp.scancode); 1699 + if (kc >= 0) 1700 + kc = put_user(kc, &user_kbkc->keycode); 1701 + break; 1702 + case KDSETKEYCODE: 1703 + if (!perm) 1704 + return -EPERM; 1705 + kc = setkeycode(tmp.scancode, tmp.keycode); 1706 + break; 1707 + } 1708 + return kc; 1709 + } 1710 + 1711 + #define i (tmp.kb_index) 1712 + #define s (tmp.kb_table) 1713 + #define v (tmp.kb_value) 1714 + 1715 + int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, 1716 + int console) 1717 + { 1718 + struct kbd_struct * kbd = kbd_table + console; 1719 + struct kbentry tmp; 1720 + ushort *key_map, *new_map, val, ov; 1721 + unsigned long flags; 1722 + 1723 + if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 1724 + return -EFAULT; 1725 + 1726 + if (!capable(CAP_SYS_TTY_CONFIG)) 1727 + perm = 0; 1728 + 1729 + switch (cmd) { 1730 + case KDGKBENT: 1731 + /* Ensure another thread doesn't free it under us */ 1732 + spin_lock_irqsave(&kbd_event_lock, flags); 1733 + key_map = key_maps[s]; 1734 + if (key_map) { 1735 + val = U(key_map[i]); 1736 + if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 1737 + val = K_HOLE; 1738 + } else 1739 + val = (i ? K_HOLE : K_NOSUCHMAP); 1740 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1741 + return put_user(val, &user_kbe->kb_value); 1742 + case KDSKBENT: 1743 + if (!perm) 1744 + return -EPERM; 1745 + if (!i && v == K_NOSUCHMAP) { 1746 + spin_lock_irqsave(&kbd_event_lock, flags); 1747 + /* deallocate map */ 1748 + key_map = key_maps[s]; 1749 + if (s && key_map) { 1750 + key_maps[s] = NULL; 1751 + if (key_map[0] == U(K_ALLOCATED)) { 1752 + kfree(key_map); 1753 + keymap_count--; 1754 + } 1755 + } 1756 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1757 + break; 1758 + } 1759 + 1760 + if (KTYP(v) < NR_TYPES) { 1761 + if (KVAL(v) > max_vals[KTYP(v)]) 1762 + return -EINVAL; 1763 + } else 1764 + if (kbd->kbdmode != VC_UNICODE) 1765 + return -EINVAL; 1766 + 1767 + /* ++Geert: non-PC keyboards may generate keycode zero */ 1768 + #if !defined(__mc68000__) && !defined(__powerpc__) 1769 + /* assignment to entry 0 only tests validity of args */ 1770 + if (!i) 1771 + break; 1772 + #endif 1773 + 1774 + new_map = kmalloc(sizeof(plain_map), GFP_KERNEL); 1775 + if (!new_map) 1776 + return -ENOMEM; 1777 + spin_lock_irqsave(&kbd_event_lock, flags); 1778 + key_map = key_maps[s]; 1779 + if (key_map == NULL) { 1780 + int j; 1781 + 1782 + if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 1783 + !capable(CAP_SYS_RESOURCE)) { 1784 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1785 + kfree(new_map); 1786 + return -EPERM; 1787 + } 1788 + key_maps[s] = new_map; 1789 + key_map[0] = U(K_ALLOCATED); 1790 + for (j = 1; j < NR_KEYS; j++) 1791 + key_map[j] = U(K_HOLE); 1792 + keymap_count++; 1793 + } else 1794 + kfree(new_map); 1795 + 1796 + ov = U(key_map[i]); 1797 + if (v == ov) 1798 + goto out; 1799 + /* 1800 + * Attention Key. 1801 + */ 1802 + if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) { 1803 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1804 + return -EPERM; 1805 + } 1806 + key_map[i] = U(v); 1807 + if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 1808 + do_compute_shiftstate(); 1809 + out: 1810 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1811 + break; 1812 + } 1813 + return 0; 1814 + } 1815 + #undef i 1816 + #undef s 1817 + #undef v 1818 + 1819 + /* FIXME: This one needs untangling and locking */ 1820 + int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 1821 + { 1822 + struct kbsentry *kbs; 1823 + char *p; 1824 + u_char *q; 1825 + u_char __user *up; 1826 + int sz; 1827 + int delta; 1828 + char *first_free, *fj, *fnw; 1829 + int i, j, k; 1830 + int ret; 1831 + 1832 + if (!capable(CAP_SYS_TTY_CONFIG)) 1833 + perm = 0; 1834 + 1835 + kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 1836 + if (!kbs) { 1837 + ret = -ENOMEM; 1838 + goto reterr; 1839 + } 1840 + 1841 + /* we mostly copy too much here (512bytes), but who cares ;) */ 1842 + if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 1843 + ret = -EFAULT; 1844 + goto reterr; 1845 + } 1846 + kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 1847 + i = kbs->kb_func; 1848 + 1849 + switch (cmd) { 1850 + case KDGKBSENT: 1851 + sz = sizeof(kbs->kb_string) - 1; /* sz should have been 1852 + a struct member */ 1853 + up = user_kdgkb->kb_string; 1854 + p = func_table[i]; 1855 + if(p) 1856 + for ( ; *p && sz; p++, sz--) 1857 + if (put_user(*p, up++)) { 1858 + ret = -EFAULT; 1859 + goto reterr; 1860 + } 1861 + if (put_user('\0', up)) { 1862 + ret = -EFAULT; 1863 + goto reterr; 1864 + } 1865 + kfree(kbs); 1866 + return ((p && *p) ? -EOVERFLOW : 0); 1867 + case KDSKBSENT: 1868 + if (!perm) { 1869 + ret = -EPERM; 1870 + goto reterr; 1871 + } 1872 + 1873 + q = func_table[i]; 1874 + first_free = funcbufptr + (funcbufsize - funcbufleft); 1875 + for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 1876 + ; 1877 + if (j < MAX_NR_FUNC) 1878 + fj = func_table[j]; 1879 + else 1880 + fj = first_free; 1881 + 1882 + delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 1883 + if (delta <= funcbufleft) { /* it fits in current buf */ 1884 + if (j < MAX_NR_FUNC) { 1885 + memmove(fj + delta, fj, first_free - fj); 1886 + for (k = j; k < MAX_NR_FUNC; k++) 1887 + if (func_table[k]) 1888 + func_table[k] += delta; 1889 + } 1890 + if (!q) 1891 + func_table[i] = fj; 1892 + funcbufleft -= delta; 1893 + } else { /* allocate a larger buffer */ 1894 + sz = 256; 1895 + while (sz < funcbufsize - funcbufleft + delta) 1896 + sz <<= 1; 1897 + fnw = kmalloc(sz, GFP_KERNEL); 1898 + if(!fnw) { 1899 + ret = -ENOMEM; 1900 + goto reterr; 1901 + } 1902 + 1903 + if (!q) 1904 + func_table[i] = fj; 1905 + if (fj > funcbufptr) 1906 + memmove(fnw, funcbufptr, fj - funcbufptr); 1907 + for (k = 0; k < j; k++) 1908 + if (func_table[k]) 1909 + func_table[k] = fnw + (func_table[k] - funcbufptr); 1910 + 1911 + if (first_free > fj) { 1912 + memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 1913 + for (k = j; k < MAX_NR_FUNC; k++) 1914 + if (func_table[k]) 1915 + func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 1916 + } 1917 + if (funcbufptr != func_buf) 1918 + kfree(funcbufptr); 1919 + funcbufptr = fnw; 1920 + funcbufleft = funcbufleft - delta + sz - funcbufsize; 1921 + funcbufsize = sz; 1922 + } 1923 + strcpy(func_table[i], kbs->kb_string); 1924 + break; 1925 + } 1926 + ret = 0; 1927 + reterr: 1928 + kfree(kbs); 1929 + return ret; 1930 + } 1931 + 1932 + int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm) 1933 + { 1934 + struct kbd_struct * kbd = kbd_table + console; 1935 + unsigned long flags; 1936 + unsigned char ucval; 1937 + 1938 + switch(cmd) { 1939 + /* the ioctls below read/set the flags usually shown in the leds */ 1940 + /* don't use them - they will go away without warning */ 1941 + case KDGKBLED: 1942 + spin_lock_irqsave(&kbd_event_lock, flags); 1943 + ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 1944 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1945 + return put_user(ucval, (char __user *)arg); 1946 + 1947 + case KDSKBLED: 1948 + if (!perm) 1949 + return -EPERM; 1950 + if (arg & ~0x77) 1951 + return -EINVAL; 1952 + spin_lock_irqsave(&kbd_event_lock, flags); 1953 + kbd->ledflagstate = (arg & 7); 1954 + kbd->default_ledflagstate = ((arg >> 4) & 7); 1955 + set_leds(); 1956 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1957 + break; 1958 + 1959 + /* the ioctls below only set the lights, not the functions */ 1960 + /* for those, see KDGKBLED and KDSKBLED above */ 1961 + case KDGETLED: 1962 + ucval = getledstate(); 1963 + return put_user(ucval, (char __user *)arg); 1964 + 1965 + case KDSETLED: 1966 + if (!perm) 1967 + return -EPERM; 1968 + setledstate(kbd, arg); 1969 + return 0; 1970 + } 1971 + return -ENOIOCTLCMD; 1972 + } 1973 + 1974 + int vt_do_kdgkbmode(int console) 1975 + { 1976 + struct kbd_struct * kbd = kbd_table + console; 1977 + /* This is a spot read so needs no locking */ 1978 + switch (kbd->kbdmode) { 1979 + case VC_RAW: 1980 + return K_RAW; 1981 + case VC_MEDIUMRAW: 1982 + return K_MEDIUMRAW; 1983 + case VC_UNICODE: 1984 + return K_UNICODE; 1985 + case VC_OFF: 1986 + return K_OFF; 1987 + default: 1988 + return K_XLATE; 1989 + } 1990 + } 1991 + 1992 + /** 1993 + * vt_do_kdgkbmeta - report meta status 1994 + * @console: console to report 1995 + * 1996 + * Report the meta flag status of this console 1997 + */ 1998 + int vt_do_kdgkbmeta(int console) 1999 + { 2000 + struct kbd_struct * kbd = kbd_table + console; 2001 + /* Again a spot read so no locking */ 2002 + return vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT; 2003 + } 2004 + 2005 + /** 2006 + * vt_reset_unicode - reset the unicode status 2007 + * @console: console being reset 2008 + * 2009 + * Restore the unicode console state to its default 2010 + */ 2011 + void vt_reset_unicode(int console) 2012 + { 2013 + unsigned long flags; 2014 + 2015 + spin_lock_irqsave(&kbd_event_lock, flags); 2016 + kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; 2017 + spin_unlock_irqrestore(&kbd_event_lock, flags); 2018 + } 2019 + 2020 + /** 2021 + * vt_get_shiftstate - shift bit state 2022 + * 2023 + * Report the shift bits from the keyboard state. We have to export 2024 + * this to support some oddities in the vt layer. 2025 + */ 2026 + int vt_get_shift_state(void) 2027 + { 2028 + /* Don't lock as this is a transient report */ 2029 + return shift_state; 2030 + } 2031 + 2032 + /** 2033 + * vt_reset_keyboard - reset keyboard state 2034 + * @console: console to reset 2035 + * 2036 + * Reset the keyboard bits for a console as part of a general console 2037 + * reset event 2038 + */ 2039 + void vt_reset_keyboard(int console) 2040 + { 2041 + struct kbd_struct * kbd = kbd_table + console; 2042 + unsigned long flags; 2043 + 2044 + spin_lock_irqsave(&kbd_event_lock, flags); 2045 + set_vc_kbd_mode(kbd, VC_REPEAT); 2046 + clr_vc_kbd_mode(kbd, VC_CKMODE); 2047 + clr_vc_kbd_mode(kbd, VC_APPLIC); 2048 + clr_vc_kbd_mode(kbd, VC_CRLF); 2049 + kbd->lockstate = 0; 2050 + kbd->slockstate = 0; 2051 + kbd->ledmode = LED_SHOW_FLAGS; 2052 + kbd->ledflagstate = kbd->default_ledflagstate; 2053 + /* do not do set_leds here because this causes an endless tasklet loop 2054 + when the keyboard hasn't been initialized yet */ 2055 + spin_unlock_irqrestore(&kbd_event_lock, flags); 2056 + } 2057 + 2058 + /** 2059 + * vt_get_kbd_mode_bit - read keyboard status bits 2060 + * @console: console to read from 2061 + * @bit: mode bit to read 2062 + * 2063 + * Report back a vt mode bit. We do this without locking so the 2064 + * caller must be sure that there are no synchronization needs 2065 + */ 2066 + 2067 + int vt_get_kbd_mode_bit(int console, int bit) 2068 + { 2069 + struct kbd_struct * kbd = kbd_table + console; 2070 + return vc_kbd_mode(kbd, bit); 2071 + } 2072 + 2073 + /** 2074 + * vt_set_kbd_mode_bit - read keyboard status bits 2075 + * @console: console to read from 2076 + * @bit: mode bit to read 2077 + * 2078 + * Set a vt mode bit. We do this without locking so the 2079 + * caller must be sure that there are no synchronization needs 2080 + */ 2081 + 2082 + void vt_set_kbd_mode_bit(int console, int bit) 2083 + { 2084 + struct kbd_struct * kbd = kbd_table + console; 2085 + unsigned long flags; 2086 + 2087 + spin_lock_irqsave(&kbd_event_lock, flags); 2088 + set_vc_kbd_mode(kbd, bit); 2089 + spin_unlock_irqrestore(&kbd_event_lock, flags); 2090 + } 2091 + 2092 + /** 2093 + * vt_clr_kbd_mode_bit - read keyboard status bits 2094 + * @console: console to read from 2095 + * @bit: mode bit to read 2096 + * 2097 + * Report back a vt mode bit. We do this without locking so the 2098 + * caller must be sure that there are no synchronization needs 2099 + */ 2100 + 2101 + void vt_clr_kbd_mode_bit(int console, int bit) 2102 + { 2103 + struct kbd_struct * kbd = kbd_table + console; 2104 + unsigned long flags; 2105 + 2106 + spin_lock_irqsave(&kbd_event_lock, flags); 2107 + clr_vc_kbd_mode(kbd, bit); 2108 + spin_unlock_irqrestore(&kbd_event_lock, flags); 1694 2109 }
+7 -2
drivers/tty/vt/selection.c
··· 30 30 31 31 extern void poke_blanked_console(void); 32 32 33 + /* FIXME: all this needs locking */ 33 34 /* Variables for selection control. */ 34 35 /* Use a dynamic buffer, instead of static (Dec 1994) */ 35 36 struct vc_data *sel_cons; /* must not be deallocated */ ··· 139 138 char *bp, *obp; 140 139 int i, ps, pe, multiplier; 141 140 u16 c; 142 - struct kbd_struct *kbd = kbd_table + fg_console; 141 + int mode; 143 142 144 143 poke_blanked_console(); 145 144 ··· 183 182 clear_selection(); 184 183 sel_cons = vc_cons[fg_console].d; 185 184 } 186 - use_unicode = kbd && kbd->kbdmode == VC_UNICODE; 185 + mode = vt_do_kdgkbmode(fg_console); 186 + if (mode == K_UNICODE) 187 + use_unicode = 1; 188 + else 189 + use_unicode = 0; 187 190 188 191 switch (sel_mode) 189 192 {
+8 -19
drivers/tty/vt/vt.c
··· 1028 1028 * VT102 emulator 1029 1029 */ 1030 1030 1031 - #define set_kbd(vc, x) set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) 1032 - #define clr_kbd(vc, x) clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) 1033 - #define is_kbd(vc, x) vc_kbd_mode(kbd_table + (vc)->vc_num, (x)) 1031 + #define set_kbd(vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x)) 1032 + #define clr_kbd(vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x)) 1033 + #define is_kbd(vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x)) 1034 1034 1035 1035 #define decarm VC_REPEAT 1036 1036 #define decckm VC_CKMODE ··· 1652 1652 vc->vc_deccm = global_cursor_default; 1653 1653 vc->vc_decim = 0; 1654 1654 1655 - set_kbd(vc, decarm); 1656 - clr_kbd(vc, decckm); 1657 - clr_kbd(vc, kbdapplic); 1658 - clr_kbd(vc, lnm); 1659 - kbd_table[vc->vc_num].lockstate = 0; 1660 - kbd_table[vc->vc_num].slockstate = 0; 1661 - kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS; 1662 - kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate; 1663 - /* do not do set_leds here because this causes an endless tasklet loop 1664 - when the keyboard hasn't been initialized yet */ 1655 + vt_reset_keyboard(vc->vc_num); 1665 1656 1666 1657 vc->vc_cursor_type = cur_default; 1667 1658 vc->vc_complement_mask = vc->vc_s_complement_mask; ··· 1970 1979 case 'q': /* DECLL - but only 3 leds */ 1971 1980 /* map 0,1,2,3 to 0,1,2,4 */ 1972 1981 if (vc->vc_par[0] < 4) 1973 - setledstate(kbd_table + vc->vc_num, 1982 + vt_set_led_state(vc->vc_num, 1974 1983 (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4); 1975 1984 return; 1976 1985 case 'r': ··· 2633 2642 * kernel-internal variable; programs not closely 2634 2643 * related to the kernel should not use this. 2635 2644 */ 2636 - data = shift_state; 2645 + data = vt_get_shift_state(); 2637 2646 ret = __put_user(data, p); 2638 2647 break; 2639 2648 case TIOCL_GETMOUSEREPORTING: ··· 2744 2753 console_num = tty->index; 2745 2754 if (!vc_cons_allocated(console_num)) 2746 2755 return; 2747 - set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); 2748 - set_leds(); 2756 + vt_kbd_con_stop(console_num); 2749 2757 } 2750 2758 2751 2759 /* ··· 2758 2768 console_num = tty->index; 2759 2769 if (!vc_cons_allocated(console_num)) 2760 2770 return; 2761 - clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); 2762 - set_leds(); 2771 + vt_kbd_con_start(console_num); 2763 2772 } 2764 2773 2765 2774 static void con_flush_chars(struct tty_struct *tty)
+17 -308
drivers/tty/vt/vt_ioctl.c
··· 195 195 #define GPLAST 0x3df 196 196 #define GPNUM (GPLAST - GPFIRST + 1) 197 197 198 - #define i (tmp.kb_index) 199 - #define s (tmp.kb_table) 200 - #define v (tmp.kb_value) 201 - static inline int 202 - do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd) 203 - { 204 - struct kbentry tmp; 205 - ushort *key_map, val, ov; 206 198 207 - if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 208 - return -EFAULT; 209 - 210 - if (!capable(CAP_SYS_TTY_CONFIG)) 211 - perm = 0; 212 - 213 - switch (cmd) { 214 - case KDGKBENT: 215 - key_map = key_maps[s]; 216 - if (key_map) { 217 - val = U(key_map[i]); 218 - if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 219 - val = K_HOLE; 220 - } else 221 - val = (i ? K_HOLE : K_NOSUCHMAP); 222 - return put_user(val, &user_kbe->kb_value); 223 - case KDSKBENT: 224 - if (!perm) 225 - return -EPERM; 226 - if (!i && v == K_NOSUCHMAP) { 227 - /* deallocate map */ 228 - key_map = key_maps[s]; 229 - if (s && key_map) { 230 - key_maps[s] = NULL; 231 - if (key_map[0] == U(K_ALLOCATED)) { 232 - kfree(key_map); 233 - keymap_count--; 234 - } 235 - } 236 - break; 237 - } 238 - 239 - if (KTYP(v) < NR_TYPES) { 240 - if (KVAL(v) > max_vals[KTYP(v)]) 241 - return -EINVAL; 242 - } else 243 - if (kbd->kbdmode != VC_UNICODE) 244 - return -EINVAL; 245 - 246 - /* ++Geert: non-PC keyboards may generate keycode zero */ 247 - #if !defined(__mc68000__) && !defined(__powerpc__) 248 - /* assignment to entry 0 only tests validity of args */ 249 - if (!i) 250 - break; 251 - #endif 252 - 253 - if (!(key_map = key_maps[s])) { 254 - int j; 255 - 256 - if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 257 - !capable(CAP_SYS_RESOURCE)) 258 - return -EPERM; 259 - 260 - key_map = kmalloc(sizeof(plain_map), 261 - GFP_KERNEL); 262 - if (!key_map) 263 - return -ENOMEM; 264 - key_maps[s] = key_map; 265 - key_map[0] = U(K_ALLOCATED); 266 - for (j = 1; j < NR_KEYS; j++) 267 - key_map[j] = U(K_HOLE); 268 - keymap_count++; 269 - } 270 - ov = U(key_map[i]); 271 - if (v == ov) 272 - break; /* nothing to do */ 273 - /* 274 - * Attention Key. 275 - */ 276 - if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) 277 - return -EPERM; 278 - key_map[i] = U(v); 279 - if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 280 - compute_shiftstate(); 281 - break; 282 - } 283 - return 0; 284 - } 285 - #undef i 286 - #undef s 287 - #undef v 288 - 289 - static inline int 290 - do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm) 291 - { 292 - struct kbkeycode tmp; 293 - int kc = 0; 294 - 295 - if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 296 - return -EFAULT; 297 - switch (cmd) { 298 - case KDGETKEYCODE: 299 - kc = getkeycode(tmp.scancode); 300 - if (kc >= 0) 301 - kc = put_user(kc, &user_kbkc->keycode); 302 - break; 303 - case KDSETKEYCODE: 304 - if (!perm) 305 - return -EPERM; 306 - kc = setkeycode(tmp.scancode, tmp.keycode); 307 - break; 308 - } 309 - return kc; 310 - } 311 - 312 - static inline int 313 - do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 314 - { 315 - struct kbsentry *kbs; 316 - char *p; 317 - u_char *q; 318 - u_char __user *up; 319 - int sz; 320 - int delta; 321 - char *first_free, *fj, *fnw; 322 - int i, j, k; 323 - int ret; 324 - 325 - if (!capable(CAP_SYS_TTY_CONFIG)) 326 - perm = 0; 327 - 328 - kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 329 - if (!kbs) { 330 - ret = -ENOMEM; 331 - goto reterr; 332 - } 333 - 334 - /* we mostly copy too much here (512bytes), but who cares ;) */ 335 - if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 336 - ret = -EFAULT; 337 - goto reterr; 338 - } 339 - kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 340 - i = kbs->kb_func; 341 - 342 - switch (cmd) { 343 - case KDGKBSENT: 344 - sz = sizeof(kbs->kb_string) - 1; /* sz should have been 345 - a struct member */ 346 - up = user_kdgkb->kb_string; 347 - p = func_table[i]; 348 - if(p) 349 - for ( ; *p && sz; p++, sz--) 350 - if (put_user(*p, up++)) { 351 - ret = -EFAULT; 352 - goto reterr; 353 - } 354 - if (put_user('\0', up)) { 355 - ret = -EFAULT; 356 - goto reterr; 357 - } 358 - kfree(kbs); 359 - return ((p && *p) ? -EOVERFLOW : 0); 360 - case KDSKBSENT: 361 - if (!perm) { 362 - ret = -EPERM; 363 - goto reterr; 364 - } 365 - 366 - q = func_table[i]; 367 - first_free = funcbufptr + (funcbufsize - funcbufleft); 368 - for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 369 - ; 370 - if (j < MAX_NR_FUNC) 371 - fj = func_table[j]; 372 - else 373 - fj = first_free; 374 - 375 - delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 376 - if (delta <= funcbufleft) { /* it fits in current buf */ 377 - if (j < MAX_NR_FUNC) { 378 - memmove(fj + delta, fj, first_free - fj); 379 - for (k = j; k < MAX_NR_FUNC; k++) 380 - if (func_table[k]) 381 - func_table[k] += delta; 382 - } 383 - if (!q) 384 - func_table[i] = fj; 385 - funcbufleft -= delta; 386 - } else { /* allocate a larger buffer */ 387 - sz = 256; 388 - while (sz < funcbufsize - funcbufleft + delta) 389 - sz <<= 1; 390 - fnw = kmalloc(sz, GFP_KERNEL); 391 - if(!fnw) { 392 - ret = -ENOMEM; 393 - goto reterr; 394 - } 395 - 396 - if (!q) 397 - func_table[i] = fj; 398 - if (fj > funcbufptr) 399 - memmove(fnw, funcbufptr, fj - funcbufptr); 400 - for (k = 0; k < j; k++) 401 - if (func_table[k]) 402 - func_table[k] = fnw + (func_table[k] - funcbufptr); 403 - 404 - if (first_free > fj) { 405 - memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 406 - for (k = j; k < MAX_NR_FUNC; k++) 407 - if (func_table[k]) 408 - func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 409 - } 410 - if (funcbufptr != func_buf) 411 - kfree(funcbufptr); 412 - funcbufptr = fnw; 413 - funcbufleft = funcbufleft - delta + sz - funcbufsize; 414 - funcbufsize = sz; 415 - } 416 - strcpy(func_table[i], kbs->kb_string); 417 - break; 418 - } 419 - ret = 0; 420 - reterr: 421 - kfree(kbs); 422 - return ret; 423 - } 424 199 425 200 static inline int 426 201 do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) ··· 272 497 { 273 498 struct vc_data *vc = tty->driver_data; 274 499 struct console_font_op op; /* used in multiple places here */ 275 - struct kbd_struct * kbd; 276 500 unsigned int console; 277 501 unsigned char ucval; 278 502 unsigned int uival; ··· 297 523 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 298 524 perm = 1; 299 525 300 - kbd = kbd_table + console; 301 526 switch (cmd) { 302 527 case TIOCLINUX: 303 528 ret = tioclinux(tty, arg); ··· 338 565 * this is naive. 339 566 */ 340 567 ucval = KB_101; 341 - goto setchar; 568 + ret = put_user(ucval, (char __user *)arg); 569 + break; 342 570 343 571 /* 344 572 * These cannot be implemented on any machine that implements ··· 444 670 case KDSKBMODE: 445 671 if (!perm) 446 672 goto eperm; 447 - switch(arg) { 448 - case K_RAW: 449 - kbd->kbdmode = VC_RAW; 450 - break; 451 - case K_MEDIUMRAW: 452 - kbd->kbdmode = VC_MEDIUMRAW; 453 - break; 454 - case K_XLATE: 455 - kbd->kbdmode = VC_XLATE; 456 - compute_shiftstate(); 457 - break; 458 - case K_UNICODE: 459 - kbd->kbdmode = VC_UNICODE; 460 - compute_shiftstate(); 461 - break; 462 - case K_OFF: 463 - kbd->kbdmode = VC_OFF; 464 - break; 465 - default: 466 - ret = -EINVAL; 467 - goto out; 468 - } 469 - tty_ldisc_flush(tty); 673 + ret = vt_do_kdskbmode(console, arg); 674 + if (ret == 0) 675 + tty_ldisc_flush(tty); 470 676 break; 471 677 472 678 case KDGKBMODE: 473 - switch (kbd->kbdmode) { 474 - case VC_RAW: 475 - uival = K_RAW; 476 - break; 477 - case VC_MEDIUMRAW: 478 - uival = K_MEDIUMRAW; 479 - break; 480 - case VC_UNICODE: 481 - uival = K_UNICODE; 482 - break; 483 - case VC_OFF: 484 - uival = K_OFF; 485 - break; 486 - default: 487 - uival = K_XLATE; 488 - break; 489 - } 490 - goto setint; 679 + uival = vt_do_kdgkbmode(console); 680 + ret = put_user(uival, (int __user *)arg); 681 + break; 491 682 492 683 /* this could be folded into KDSKBMODE, but for compatibility 493 684 reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 494 685 case KDSKBMETA: 495 - switch(arg) { 496 - case K_METABIT: 497 - clr_vc_kbd_mode(kbd, VC_META); 498 - break; 499 - case K_ESCPREFIX: 500 - set_vc_kbd_mode(kbd, VC_META); 501 - break; 502 - default: 503 - ret = -EINVAL; 504 - } 686 + ret = vt_do_kdskbmeta(console, arg); 505 687 break; 506 688 507 689 case KDGKBMETA: 508 - uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 690 + /* FIXME: should review whether this is worth locking */ 691 + uival = vt_do_kdgkbmeta(console); 509 692 setint: 510 693 ret = put_user(uival, (int __user *)arg); 511 694 break; ··· 471 740 case KDSETKEYCODE: 472 741 if(!capable(CAP_SYS_TTY_CONFIG)) 473 742 perm = 0; 474 - ret = do_kbkeycode_ioctl(cmd, up, perm); 743 + ret = vt_do_kbkeycode_ioctl(cmd, up, perm); 475 744 break; 476 745 477 746 case KDGKBENT: 478 747 case KDSKBENT: 479 - ret = do_kdsk_ioctl(cmd, up, perm, kbd); 748 + ret = vt_do_kdsk_ioctl(cmd, up, perm, console); 480 749 break; 481 750 482 751 case KDGKBSENT: 483 752 case KDSKBSENT: 484 - ret = do_kdgkb_ioctl(cmd, up, perm); 753 + ret = vt_do_kdgkb_ioctl(cmd, up, perm); 485 754 break; 486 755 487 756 /* Diacritical processing. Handled in keyboard.c as it has ··· 496 765 /* the ioctls below read/set the flags usually shown in the leds */ 497 766 /* don't use them - they will go away without warning */ 498 767 case KDGKBLED: 499 - ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 500 - goto setchar; 501 - 502 768 case KDSKBLED: 503 - if (!perm) 504 - goto eperm; 505 - if (arg & ~0x77) { 506 - ret = -EINVAL; 507 - break; 508 - } 509 - kbd->ledflagstate = (arg & 7); 510 - kbd->default_ledflagstate = ((arg >> 4) & 7); 511 - set_leds(); 512 - break; 513 - 514 - /* the ioctls below only set the lights, not the functions */ 515 - /* for those, see KDGKBLED and KDSKBLED above */ 516 769 case KDGETLED: 517 - ucval = getledstate(); 518 - setchar: 519 - ret = put_user(ucval, (char __user *)arg); 520 - break; 521 - 522 770 case KDSETLED: 523 - if (!perm) 524 - goto eperm; 525 - setledstate(kbd, arg); 771 + ret = vt_do_kdskled(console, cmd, arg, perm); 526 772 break; 527 773 528 774 /* ··· 994 1286 void reset_vc(struct vc_data *vc) 995 1287 { 996 1288 vc->vc_mode = KD_TEXT; 997 - kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; 1289 + vt_reset_unicode(vc->vc_num); 998 1290 vc->vt_mode.mode = VT_AUTO; 999 1291 vc->vt_mode.waitv = 0; 1000 1292 vc->vt_mode.relsig = 0; ··· 1017 1309 console_lock(); 1018 1310 vc = vc_con->d; 1019 1311 if (vc) { 1312 + /* FIXME: review tty ref counting */ 1020 1313 tty = vc->port.tty; 1021 1314 /* 1022 1315 * SAK should also work in all raw modes and reset
+1 -6
include/linux/kbd_kern.h
··· 7 7 8 8 extern struct tasklet_struct keyboard_tasklet; 9 9 10 - extern int shift_state; 11 - 12 10 extern char *func_table[MAX_NR_FUNC]; 13 11 extern char func_buf[]; 14 12 extern char *funcbufptr; ··· 63 65 #define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */ 64 66 }; 65 67 66 - extern struct kbd_struct kbd_table[]; 67 - 68 68 extern int kbd_init(void); 69 69 70 70 extern unsigned char getledstate(void); ··· 75 79 extern int set_console(int nr); 76 80 extern void schedule_console_callback(void); 77 81 82 + /* FIXME: review locking for vt.c callers */ 78 83 static inline void set_leds(void) 79 84 { 80 85 tasklet_schedule(&keyboard_tasklet); ··· 139 142 140 143 struct console; 141 144 142 - int getkeycode(unsigned int scancode); 143 - int setkeycode(unsigned int scancode, unsigned int keycode); 144 145 void compute_shiftstate(void); 145 146 146 147 /* defkeymap.c */
-2
include/linux/keyboard.h
··· 24 24 25 25 #ifdef __KERNEL__ 26 26 struct notifier_block; 27 - extern const int NR_TYPES; 28 - extern const int max_vals[]; 29 27 extern unsigned short *key_maps[MAX_NR_KEYMAPS]; 30 28 extern unsigned short plain_map[NR_KEYS]; 31 29
+23
include/linux/vt_kern.h
··· 169 169 170 170 /* keyboard provided interfaces */ 171 171 extern int vt_do_diacrit(unsigned int cmd, void __user *up, int eperm); 172 + extern int vt_do_kdskbmode(int console, unsigned int arg); 173 + extern int vt_do_kdskbmeta(int console, unsigned int arg); 174 + extern int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, 175 + int perm); 176 + extern int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, 177 + int perm, int console); 178 + extern int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, 179 + int perm); 180 + extern int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm); 181 + extern int vt_do_kdgkbmode(int console); 182 + extern int vt_do_kdgkbmeta(int console); 183 + extern void vt_reset_unicode(int console); 184 + extern int vt_get_shift_state(void); 185 + extern void vt_reset_keyboard(int console); 186 + extern int vt_get_leds(int console, int flag); 187 + extern int vt_get_kbd_mode_bit(int console, int bit); 188 + extern void vt_set_kbd_mode_bit(int console, int bit); 189 + extern void vt_clr_kbd_mode_bit(int console, int bit); 190 + extern void vt_set_led_state(int console, int leds); 191 + extern void vt_set_led_state(int console, int leds); 192 + extern void vt_kbd_con_start(int console); 193 + extern void vt_kbd_con_stop(int console); 194 + 172 195 173 196 #endif /* _VT_KERN_H */