TTY: create drivers/tty/vt and move the vt code there
The vt and other related code is moved into the drivers/tty/vt directory. Acked-by: Arnd Bergmann <arnd@arndb.de> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
这个提交包含在:
@@ -7,3 +7,5 @@ obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
|
||||
obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
||||
obj-$(CONFIG_N_GSM) += n_gsm.o
|
||||
obj-$(CONFIG_R3964) += n_r3964.o
|
||||
|
||||
obj-y += vt/
|
||||
|
34
drivers/tty/vt/Makefile
普通文件
34
drivers/tty/vt/Makefile
普通文件
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# This file contains the font map for the default (hardware) font
|
||||
#
|
||||
FONTMAPFILE = cp437.uni
|
||||
|
||||
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \
|
||||
selection.o keyboard.o
|
||||
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
|
||||
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := consolemap_deftbl.c defkeymap.c
|
||||
|
||||
quiet_cmd_conmk = CONMK $@
|
||||
cmd_conmk = scripts/conmakehash $< > $@
|
||||
|
||||
$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE)
|
||||
$(call cmd,conmk)
|
||||
|
||||
$(obj)/defkeymap.o: $(obj)/defkeymap.c
|
||||
|
||||
# Uncomment if you're changing the keymap and have an appropriate
|
||||
# loadkeys version for the map. By default, we'll use the shipped
|
||||
# versions.
|
||||
# GENERATE_KEYMAP := 1
|
||||
|
||||
ifdef GENERATE_KEYMAP
|
||||
|
||||
$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map
|
||||
loadkeys --mktable $< > $@.tmp
|
||||
sed -e 's/^static *//' $@.tmp > $@
|
||||
rm $@.tmp
|
||||
|
||||
endif
|
745
drivers/tty/vt/consolemap.c
普通文件
745
drivers/tty/vt/consolemap.c
普通文件
@@ -0,0 +1,745 @@
|
||||
/*
|
||||
* consolemap.c
|
||||
*
|
||||
* Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
|
||||
* to font positions.
|
||||
*
|
||||
* aeb, 950210
|
||||
*
|
||||
* Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
|
||||
*
|
||||
* Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/consolemap.h>
|
||||
#include <linux/vt_kern.h>
|
||||
|
||||
static unsigned short translations[][256] = {
|
||||
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* VT100 graphics mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
|
||||
0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
|
||||
0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
|
||||
0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
|
||||
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
|
||||
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* IBM Codepage 437 mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
},
|
||||
/* User mapping -- default to codes for direct font mapping */
|
||||
{
|
||||
0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
|
||||
0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
|
||||
0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
|
||||
0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
|
||||
0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
|
||||
0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
|
||||
0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
|
||||
0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
|
||||
0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
|
||||
0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
|
||||
0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
|
||||
0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
|
||||
0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
|
||||
0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
|
||||
0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
|
||||
0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
|
||||
0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
|
||||
0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
|
||||
0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
|
||||
0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
|
||||
0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
|
||||
0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
|
||||
0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
|
||||
0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
|
||||
0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
|
||||
0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
|
||||
0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
|
||||
0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
|
||||
0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
|
||||
0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
|
||||
0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
|
||||
0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
|
||||
}
|
||||
};
|
||||
|
||||
/* The standard kernel character-to-font mappings are not invertible
|
||||
-- this is just a best effort. */
|
||||
|
||||
#define MAX_GLYPH 512 /* Max possible glyph value */
|
||||
|
||||
static int inv_translate[MAX_NR_CONSOLES];
|
||||
|
||||
struct uni_pagedir {
|
||||
u16 **uni_pgdir[32];
|
||||
unsigned long refcount;
|
||||
unsigned long sum;
|
||||
unsigned char *inverse_translations[4];
|
||||
u16 *inverse_trans_unicode;
|
||||
int readonly;
|
||||
};
|
||||
|
||||
static struct uni_pagedir *dflt;
|
||||
|
||||
static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
|
||||
{
|
||||
int j, glyph;
|
||||
unsigned short *t = translations[i];
|
||||
unsigned char *q;
|
||||
|
||||
if (!p) return;
|
||||
q = p->inverse_translations[i];
|
||||
|
||||
if (!q) {
|
||||
q = p->inverse_translations[i] = (unsigned char *)
|
||||
kmalloc(MAX_GLYPH, GFP_KERNEL);
|
||||
if (!q) return;
|
||||
}
|
||||
memset(q, 0, MAX_GLYPH);
|
||||
|
||||
for (j = 0; j < E_TABSZ; j++) {
|
||||
glyph = conv_uni_to_pc(conp, t[j]);
|
||||
if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
|
||||
/* prefer '-' above SHY etc. */
|
||||
q[glyph] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_inverse_trans_unicode(struct vc_data *conp,
|
||||
struct uni_pagedir *p)
|
||||
{
|
||||
int i, j, k, glyph;
|
||||
u16 **p1, *p2;
|
||||
u16 *q;
|
||||
|
||||
if (!p) return;
|
||||
q = p->inverse_trans_unicode;
|
||||
if (!q) {
|
||||
q = p->inverse_trans_unicode =
|
||||
kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
|
||||
if (!q)
|
||||
return;
|
||||
}
|
||||
memset(q, 0, MAX_GLYPH * sizeof(u16));
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
p1 = p->uni_pgdir[i];
|
||||
if (!p1)
|
||||
continue;
|
||||
for (j = 0; j < 32; j++) {
|
||||
p2 = p1[j];
|
||||
if (!p2)
|
||||
continue;
|
||||
for (k = 0; k < 64; k++) {
|
||||
glyph = p2[k];
|
||||
if (glyph >= 0 && glyph < MAX_GLYPH
|
||||
&& q[glyph] < 32)
|
||||
q[glyph] = (i << 11) + (j << 6) + k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short *set_translate(int m, struct vc_data *vc)
|
||||
{
|
||||
inv_translate[vc->vc_num] = m;
|
||||
return translations[m];
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse translation is impossible for several reasons:
|
||||
* 1. The font<->character maps are not 1-1.
|
||||
* 2. The text may have been written while a different translation map
|
||||
* was active.
|
||||
* Still, it is now possible to a certain extent to cut and paste non-ASCII.
|
||||
*/
|
||||
u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
|
||||
{
|
||||
struct uni_pagedir *p;
|
||||
int m;
|
||||
if (glyph < 0 || glyph >= MAX_GLYPH)
|
||||
return 0;
|
||||
else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
|
||||
return glyph;
|
||||
else if (use_unicode) {
|
||||
if (!p->inverse_trans_unicode)
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_trans_unicode[glyph];
|
||||
} else {
|
||||
m = inv_translate[conp->vc_num];
|
||||
if (!p->inverse_translations[m])
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_translations[m][glyph];
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inverse_translate);
|
||||
|
||||
static void update_user_maps(void)
|
||||
{
|
||||
int i;
|
||||
struct uni_pagedir *p, *q = NULL;
|
||||
|
||||
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
||||
if (!vc_cons_allocated(i))
|
||||
continue;
|
||||
p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
|
||||
if (p && p != q) {
|
||||
set_inverse_transl(vc_cons[i].d, p, USER_MAP);
|
||||
set_inverse_trans_unicode(vc_cons[i].d, p);
|
||||
q = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Load customizable translation table
|
||||
* arg points to a 256 byte translation table.
|
||||
*
|
||||
* The "old" variants are for translation directly to font (using the
|
||||
* 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
|
||||
* Unicodes explicitly.
|
||||
*/
|
||||
int con_set_trans_old(unsigned char __user * arg)
|
||||
{
|
||||
int i;
|
||||
unsigned short *p = translations[USER_MAP];
|
||||
|
||||
if (!access_ok(VERIFY_READ, arg, E_TABSZ))
|
||||
return -EFAULT;
|
||||
|
||||
for (i=0; i<E_TABSZ ; i++) {
|
||||
unsigned char uc;
|
||||
__get_user(uc, arg+i);
|
||||
p[i] = UNI_DIRECT_BASE | uc;
|
||||
}
|
||||
|
||||
update_user_maps();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_get_trans_old(unsigned char __user * arg)
|
||||
{
|
||||
int i, ch;
|
||||
unsigned short *p = translations[USER_MAP];
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
|
||||
return -EFAULT;
|
||||
|
||||
for (i=0; i<E_TABSZ ; i++)
|
||||
{
|
||||
ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
|
||||
__put_user((ch & ~0xff) ? 0 : ch, arg+i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_set_trans_new(ushort __user * arg)
|
||||
{
|
||||
int i;
|
||||
unsigned short *p = translations[USER_MAP];
|
||||
|
||||
if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
|
||||
return -EFAULT;
|
||||
|
||||
for (i=0; i<E_TABSZ ; i++) {
|
||||
unsigned short us;
|
||||
__get_user(us, arg+i);
|
||||
p[i] = us;
|
||||
}
|
||||
|
||||
update_user_maps();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_get_trans_new(ushort __user * arg)
|
||||
{
|
||||
int i;
|
||||
unsigned short *p = translations[USER_MAP];
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
|
||||
return -EFAULT;
|
||||
|
||||
for (i=0; i<E_TABSZ ; i++)
|
||||
__put_user(p[i], arg+i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicode -> current font conversion
|
||||
*
|
||||
* A font has at most 512 chars, usually 256.
|
||||
* But one font position may represent several Unicode chars.
|
||||
* A hashtable is somewhat of a pain to deal with, so use a
|
||||
* "paged table" instead. Simulation has shown the memory cost of
|
||||
* this 3-level paged table scheme to be comparable to a hash table.
|
||||
*/
|
||||
|
||||
extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
|
||||
extern u16 dfont_unitable[];
|
||||
|
||||
static void con_release_unimap(struct uni_pagedir *p)
|
||||
{
|
||||
u16 **p1;
|
||||
int i, j;
|
||||
|
||||
if (p == dflt) dflt = NULL;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((p1 = p->uni_pgdir[i]) != NULL) {
|
||||
for (j = 0; j < 32; j++)
|
||||
kfree(p1[j]);
|
||||
kfree(p1);
|
||||
}
|
||||
p->uni_pgdir[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
kfree(p->inverse_translations[i]);
|
||||
p->inverse_translations[i] = NULL;
|
||||
}
|
||||
if (p->inverse_trans_unicode) {
|
||||
kfree(p->inverse_trans_unicode);
|
||||
p->inverse_trans_unicode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void con_free_unimap(struct vc_data *vc)
|
||||
{
|
||||
struct uni_pagedir *p;
|
||||
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
if (!p)
|
||||
return;
|
||||
*vc->vc_uni_pagedir_loc = 0;
|
||||
if (--p->refcount)
|
||||
return;
|
||||
con_release_unimap(p);
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
|
||||
{
|
||||
int i, j, k;
|
||||
struct uni_pagedir *q;
|
||||
|
||||
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
||||
if (!vc_cons_allocated(i))
|
||||
continue;
|
||||
q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
|
||||
if (!q || q == p || q->sum != p->sum)
|
||||
continue;
|
||||
for (j = 0; j < 32; j++) {
|
||||
u16 **p1, **q1;
|
||||
p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
|
||||
if (!p1 && !q1)
|
||||
continue;
|
||||
if (!p1 || !q1)
|
||||
break;
|
||||
for (k = 0; k < 32; k++) {
|
||||
if (!p1[k] && !q1[k])
|
||||
continue;
|
||||
if (!p1[k] || !q1[k])
|
||||
break;
|
||||
if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
|
||||
break;
|
||||
}
|
||||
if (k < 32)
|
||||
break;
|
||||
}
|
||||
if (j == 32) {
|
||||
q->refcount++;
|
||||
*conp->vc_uni_pagedir_loc = (unsigned long)q;
|
||||
con_release_unimap(p);
|
||||
kfree(p);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
|
||||
{
|
||||
int i, n;
|
||||
u16 **p1, *p2;
|
||||
|
||||
if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
|
||||
p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
|
||||
if (!p1) return -ENOMEM;
|
||||
for (i = 0; i < 32; i++)
|
||||
p1[i] = NULL;
|
||||
}
|
||||
|
||||
if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
|
||||
p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
|
||||
if (!p2) return -ENOMEM;
|
||||
memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
|
||||
}
|
||||
|
||||
p2[unicode & 0x3f] = fontpos;
|
||||
|
||||
p->sum += (fontpos << 20) + unicode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ui is a leftover from using a hashtable, but might be used again */
|
||||
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
|
||||
{
|
||||
struct uni_pagedir *p, *q;
|
||||
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
if (p && p->readonly) return -EIO;
|
||||
if (!p || --p->refcount) {
|
||||
q = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!q) {
|
||||
if (p) p->refcount++;
|
||||
return -ENOMEM;
|
||||
}
|
||||
q->refcount=1;
|
||||
*vc->vc_uni_pagedir_loc = (unsigned long)q;
|
||||
} else {
|
||||
if (p == dflt) dflt = NULL;
|
||||
p->refcount++;
|
||||
p->sum = 0;
|
||||
con_release_unimap(p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
||||
{
|
||||
int err = 0, err1, i;
|
||||
struct uni_pagedir *p, *q;
|
||||
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
if (p->readonly) return -EIO;
|
||||
|
||||
if (!ct) return 0;
|
||||
|
||||
if (p->refcount > 1) {
|
||||
int j, k;
|
||||
u16 **p1, *p2, l;
|
||||
|
||||
err1 = con_clear_unimap(vc, NULL);
|
||||
if (err1) return err1;
|
||||
|
||||
q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
for (i = 0, l = 0; i < 32; i++)
|
||||
if ((p1 = p->uni_pgdir[i]))
|
||||
for (j = 0; j < 32; j++)
|
||||
if ((p2 = p1[j]))
|
||||
for (k = 0; k < 64; k++, l++)
|
||||
if (p2[k] != 0xffff) {
|
||||
err1 = con_insert_unipair(q, l, p2[k]);
|
||||
if (err1) {
|
||||
p->refcount++;
|
||||
*vc->vc_uni_pagedir_loc = (unsigned long)p;
|
||||
con_release_unimap(q);
|
||||
kfree(q);
|
||||
return err1;
|
||||
}
|
||||
}
|
||||
p = q;
|
||||
} else if (p == dflt)
|
||||
dflt = NULL;
|
||||
|
||||
while (ct--) {
|
||||
unsigned short unicode, fontpos;
|
||||
__get_user(unicode, &list->unicode);
|
||||
__get_user(fontpos, &list->fontpos);
|
||||
if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
|
||||
err = err1;
|
||||
list++;
|
||||
}
|
||||
|
||||
if (con_unify_unimap(vc, p))
|
||||
return err;
|
||||
|
||||
for (i = 0; i <= 3; i++)
|
||||
set_inverse_transl(vc, p, i); /* Update all inverse translations */
|
||||
set_inverse_trans_unicode(vc, p);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
|
||||
The representation used was the most compact I could come up
|
||||
with. This routine is executed at sys_setup time, and when the
|
||||
PIO_FONTRESET ioctl is called. */
|
||||
|
||||
int con_set_default_unimap(struct vc_data *vc)
|
||||
{
|
||||
int i, j, err = 0, err1;
|
||||
u16 *q;
|
||||
struct uni_pagedir *p;
|
||||
|
||||
if (dflt) {
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
if (p == dflt)
|
||||
return 0;
|
||||
dflt->refcount++;
|
||||
*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
|
||||
if (p && --p->refcount) {
|
||||
con_release_unimap(p);
|
||||
kfree(p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The default font is always 256 characters */
|
||||
|
||||
err = con_clear_unimap(vc, NULL);
|
||||
if (err) return err;
|
||||
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
q = dfont_unitable;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
for (j = dfont_unicount[i]; j; j--) {
|
||||
err1 = con_insert_unipair(p, *(q++), i);
|
||||
if (err1)
|
||||
err = err1;
|
||||
}
|
||||
|
||||
if (con_unify_unimap(vc, p)) {
|
||||
dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i <= 3; i++)
|
||||
set_inverse_transl(vc, p, i); /* Update all inverse translations */
|
||||
set_inverse_trans_unicode(vc, p);
|
||||
dflt = p;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(con_set_default_unimap);
|
||||
|
||||
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
|
||||
{
|
||||
struct uni_pagedir *q;
|
||||
|
||||
if (!*src_vc->vc_uni_pagedir_loc)
|
||||
return -EINVAL;
|
||||
if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
|
||||
return 0;
|
||||
con_free_unimap(dst_vc);
|
||||
q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
|
||||
q->refcount++;
|
||||
*dst_vc->vc_uni_pagedir_loc = (long)q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
|
||||
{
|
||||
int i, j, k, ect;
|
||||
u16 **p1, *p2;
|
||||
struct uni_pagedir *p;
|
||||
|
||||
ect = 0;
|
||||
if (*vc->vc_uni_pagedir_loc) {
|
||||
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
for (i = 0; i < 32; i++)
|
||||
if ((p1 = p->uni_pgdir[i]))
|
||||
for (j = 0; j < 32; j++)
|
||||
if ((p2 = *(p1++)))
|
||||
for (k = 0; k < 64; k++) {
|
||||
if (*p2 < MAX_GLYPH && ect++ < ct) {
|
||||
__put_user((u_short)((i<<11)+(j<<6)+k),
|
||||
&list->unicode);
|
||||
__put_user((u_short) *p2,
|
||||
&list->fontpos);
|
||||
list++;
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
__put_user(ect, uct);
|
||||
return ((ect <= ct) ? 0 : -ENOMEM);
|
||||
}
|
||||
|
||||
void con_protect_unimap(struct vc_data *vc, int rdonly)
|
||||
{
|
||||
struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
|
||||
|
||||
if (p)
|
||||
p->readonly = rdonly;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always use USER_MAP. These functions are used by the keyboard,
|
||||
* which shouldn't be affected by G0/G1 switching, etc.
|
||||
* If the user map still contains default values, i.e. the
|
||||
* direct-to-font mapping, then assume user is using Latin1.
|
||||
*/
|
||||
/* may be called during an interrupt */
|
||||
u32 conv_8bit_to_uni(unsigned char c)
|
||||
{
|
||||
unsigned short uni = translations[USER_MAP][c];
|
||||
return uni == (0xf000 | c) ? c : uni;
|
||||
}
|
||||
|
||||
int conv_uni_to_8bit(u32 uni)
|
||||
{
|
||||
int c;
|
||||
for (c = 0; c < 0x100; c++)
|
||||
if (translations[USER_MAP][c] == uni ||
|
||||
(translations[USER_MAP][c] == (c | 0xf000) && uni == c))
|
||||
return c;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
conv_uni_to_pc(struct vc_data *conp, long ucs)
|
||||
{
|
||||
int h;
|
||||
u16 **p1, *p2;
|
||||
struct uni_pagedir *p;
|
||||
|
||||
/* Only 16-bit codes supported at this time */
|
||||
if (ucs > 0xffff)
|
||||
return -4; /* Not found */
|
||||
else if (ucs < 0x20)
|
||||
return -1; /* Not a printable character */
|
||||
else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
|
||||
return -2; /* Zero-width space */
|
||||
/*
|
||||
* UNI_DIRECT_BASE indicates the start of the region in the User Zone
|
||||
* which always has a 1:1 mapping to the currently loaded font. The
|
||||
* UNI_DIRECT_MASK indicates the bit span of the region.
|
||||
*/
|
||||
else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
|
||||
return ucs & UNI_DIRECT_MASK;
|
||||
|
||||
if (!*conp->vc_uni_pagedir_loc)
|
||||
return -3;
|
||||
|
||||
p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
|
||||
if ((p1 = p->uni_pgdir[ucs >> 11]) &&
|
||||
(p2 = p1[(ucs >> 6) & 0x1f]) &&
|
||||
(h = p2[ucs & 0x3f]) < MAX_GLYPH)
|
||||
return h;
|
||||
|
||||
return -4; /* not found */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called at sys_setup time, after memory and the console are
|
||||
* initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
|
||||
* from this function, hence the call from sys_setup.
|
||||
*/
|
||||
void __init
|
||||
console_map_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_NR_CONSOLES; i++)
|
||||
if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
|
||||
con_set_default_unimap(vc_cons[i].d);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(con_copy_unimap);
|
291
drivers/tty/vt/cp437.uni
普通文件
291
drivers/tty/vt/cp437.uni
普通文件
@@ -0,0 +1,291 @@
|
||||
#
|
||||
# Unicode table for IBM Codepage 437. Note that there are many more
|
||||
# substitutions that could be conceived (for example, thick-line
|
||||
# graphs probably should be replaced with double-line ones, accented
|
||||
# Latin characters should replaced with their nonaccented versions,
|
||||
# and some upper case Greek characters could be replaced by Latin), however,
|
||||
# I have limited myself to the Unicodes used by the kernel ISO 8859-1,
|
||||
# DEC VT, and IBM CP 437 tables.
|
||||
#
|
||||
# --------------------------------
|
||||
#
|
||||
# Basic IBM dingbats, some of which will never have a purpose clear
|
||||
# to mankind
|
||||
#
|
||||
0x00 U+0000
|
||||
0x01 U+263a
|
||||
0x02 U+263b
|
||||
0x03 U+2665
|
||||
0x04 U+2666 U+25c6
|
||||
0x05 U+2663
|
||||
0x06 U+2660
|
||||
0x07 U+2022
|
||||
0x08 U+25d8
|
||||
0x09 U+25cb
|
||||
0x0a U+25d9
|
||||
0x0b U+2642
|
||||
0x0c U+2640
|
||||
0x0d U+266a
|
||||
0x0e U+266b
|
||||
0x0f U+263c U+00a4
|
||||
0x10 U+25b6 U+25ba
|
||||
0x11 U+25c0 U+25c4
|
||||
0x12 U+2195
|
||||
0x13 U+203c
|
||||
0x14 U+00b6
|
||||
0x15 U+00a7
|
||||
0x16 U+25ac
|
||||
0x17 U+21a8
|
||||
0x18 U+2191
|
||||
0x19 U+2193
|
||||
0x1a U+2192
|
||||
0x1b U+2190
|
||||
0x1c U+221f
|
||||
0x1d U+2194
|
||||
0x1e U+25b2
|
||||
0x1f U+25bc
|
||||
#
|
||||
# The ASCII range is identity-mapped, but some of the characters also
|
||||
# have to act as substitutes, especially the upper-case characters.
|
||||
#
|
||||
0x20 U+0020
|
||||
0x21 U+0021
|
||||
0x22 U+0022 U+00a8
|
||||
0x23 U+0023
|
||||
0x24 U+0024
|
||||
0x25 U+0025
|
||||
0x26 U+0026
|
||||
0x27 U+0027 U+00b4
|
||||
0x28 U+0028
|
||||
0x29 U+0029
|
||||
0x2a U+002a
|
||||
0x2b U+002b
|
||||
0x2c U+002c U+00b8
|
||||
0x2d U+002d U+00ad
|
||||
0x2e U+002e
|
||||
0x2f U+002f
|
||||
0x30 U+0030
|
||||
0x31 U+0031
|
||||
0x32 U+0032
|
||||
0x33 U+0033
|
||||
0x34 U+0034
|
||||
0x35 U+0035
|
||||
0x36 U+0036
|
||||
0x37 U+0037
|
||||
0x38 U+0038
|
||||
0x39 U+0039
|
||||
0x3a U+003a
|
||||
0x3b U+003b
|
||||
0x3c U+003c
|
||||
0x3d U+003d
|
||||
0x3e U+003e
|
||||
0x3f U+003f
|
||||
0x40 U+0040
|
||||
0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3
|
||||
0x42 U+0042
|
||||
0x43 U+0043 U+00a9
|
||||
0x44 U+0044 U+00d0
|
||||
0x45 U+0045 U+00c8 U+00ca U+00cb
|
||||
0x46 U+0046
|
||||
0x47 U+0047
|
||||
0x48 U+0048
|
||||
0x49 U+0049 U+00cc U+00cd U+00ce U+00cf
|
||||
0x4a U+004a
|
||||
0x4b U+004b U+212a
|
||||
0x4c U+004c
|
||||
0x4d U+004d
|
||||
0x4e U+004e
|
||||
0x4f U+004f U+00d2 U+00d3 U+00d4 U+00d5
|
||||
0x50 U+0050
|
||||
0x51 U+0051
|
||||
0x52 U+0052 U+00ae
|
||||
0x53 U+0053
|
||||
0x54 U+0054
|
||||
0x55 U+0055 U+00d9 U+00da U+00db
|
||||
0x56 U+0056
|
||||
0x57 U+0057
|
||||
0x58 U+0058
|
||||
0x59 U+0059 U+00dd
|
||||
0x5a U+005a
|
||||
0x5b U+005b
|
||||
0x5c U+005c
|
||||
0x5d U+005d
|
||||
0x5e U+005e
|
||||
0x5f U+005f U+23bd U+f804
|
||||
0x60 U+0060
|
||||
0x61 U+0061 U+00e3
|
||||
0x62 U+0062
|
||||
0x63 U+0063
|
||||
0x64 U+0064
|
||||
0x65 U+0065
|
||||
0x66 U+0066
|
||||
0x67 U+0067
|
||||
0x68 U+0068
|
||||
0x69 U+0069
|
||||
0x6a U+006a
|
||||
0x6b U+006b
|
||||
0x6c U+006c
|
||||
0x6d U+006d
|
||||
0x6e U+006e
|
||||
0x6f U+006f U+00f5
|
||||
0x70 U+0070
|
||||
0x71 U+0071
|
||||
0x72 U+0072
|
||||
0x73 U+0073
|
||||
0x74 U+0074
|
||||
0x75 U+0075
|
||||
0x76 U+0076
|
||||
0x77 U+0077
|
||||
0x78 U+0078 U+00d7
|
||||
0x79 U+0079 U+00fd
|
||||
0x7a U+007a
|
||||
0x7b U+007b
|
||||
0x7c U+007c U+00a6
|
||||
0x7d U+007d
|
||||
0x7e U+007e
|
||||
#
|
||||
# Okay, what on Earth is this one supposed to be used for?
|
||||
#
|
||||
0x7f U+2302
|
||||
#
|
||||
# Non-English characters, mostly lower case letters...
|
||||
#
|
||||
0x80 U+00c7
|
||||
0x81 U+00fc
|
||||
0x82 U+00e9
|
||||
0x83 U+00e2
|
||||
0x84 U+00e4
|
||||
0x85 U+00e0
|
||||
0x86 U+00e5
|
||||
0x87 U+00e7
|
||||
0x88 U+00ea
|
||||
0x89 U+00eb
|
||||
0x8a U+00e8
|
||||
0x8b U+00ef
|
||||
0x8c U+00ee
|
||||
0x8d U+00ec
|
||||
0x8e U+00c4
|
||||
0x8f U+00c5 U+212b
|
||||
0x90 U+00c9
|
||||
0x91 U+00e6
|
||||
0x92 U+00c6
|
||||
0x93 U+00f4
|
||||
0x94 U+00f6
|
||||
0x95 U+00f2
|
||||
0x96 U+00fb
|
||||
0x97 U+00f9
|
||||
0x98 U+00ff
|
||||
0x99 U+00d6
|
||||
0x9a U+00dc
|
||||
0x9b U+00a2
|
||||
0x9c U+00a3
|
||||
0x9d U+00a5
|
||||
0x9e U+20a7
|
||||
0x9f U+0192
|
||||
0xa0 U+00e1
|
||||
0xa1 U+00ed
|
||||
0xa2 U+00f3
|
||||
0xa3 U+00fa
|
||||
0xa4 U+00f1
|
||||
0xa5 U+00d1
|
||||
0xa6 U+00aa
|
||||
0xa7 U+00ba
|
||||
0xa8 U+00bf
|
||||
0xa9 U+2310
|
||||
0xaa U+00ac
|
||||
0xab U+00bd
|
||||
0xac U+00bc
|
||||
0xad U+00a1
|
||||
0xae U+00ab
|
||||
0xaf U+00bb
|
||||
#
|
||||
# Block graphics
|
||||
#
|
||||
0xb0 U+2591
|
||||
0xb1 U+2592
|
||||
0xb2 U+2593
|
||||
0xb3 U+2502
|
||||
0xb4 U+2524
|
||||
0xb5 U+2561
|
||||
0xb6 U+2562
|
||||
0xb7 U+2556
|
||||
0xb8 U+2555
|
||||
0xb9 U+2563
|
||||
0xba U+2551
|
||||
0xbb U+2557
|
||||
0xbc U+255d
|
||||
0xbd U+255c
|
||||
0xbe U+255b
|
||||
0xbf U+2510
|
||||
0xc0 U+2514
|
||||
0xc1 U+2534
|
||||
0xc2 U+252c
|
||||
0xc3 U+251c
|
||||
0xc4 U+2500
|
||||
0xc5 U+253c
|
||||
0xc6 U+255e
|
||||
0xc7 U+255f
|
||||
0xc8 U+255a
|
||||
0xc9 U+2554
|
||||
0xca U+2569
|
||||
0xcb U+2566
|
||||
0xcc U+2560
|
||||
0xcd U+2550
|
||||
0xce U+256c
|
||||
0xcf U+2567
|
||||
0xd0 U+2568
|
||||
0xd1 U+2564
|
||||
0xd2 U+2565
|
||||
0xd3 U+2559
|
||||
0xd4 U+2558
|
||||
0xd5 U+2552
|
||||
0xd6 U+2553
|
||||
0xd7 U+256b
|
||||
0xd8 U+256a
|
||||
0xd9 U+2518
|
||||
0xda U+250c
|
||||
0xdb U+2588
|
||||
0xdc U+2584
|
||||
0xdd U+258c
|
||||
0xde U+2590
|
||||
0xdf U+2580
|
||||
#
|
||||
# Greek letters and mathematical symbols
|
||||
#
|
||||
0xe0 U+03b1
|
||||
0xe1 U+03b2 U+00df
|
||||
0xe2 U+0393
|
||||
0xe3 U+03c0
|
||||
0xe4 U+03a3
|
||||
0xe5 U+03c3
|
||||
0xe6 U+00b5 U+03bc
|
||||
0xe7 U+03c4
|
||||
0xe8 U+03a6 U+00d8
|
||||
0xe9 U+0398
|
||||
0xea U+03a9 U+2126
|
||||
0xeb U+03b4 U+00f0
|
||||
0xec U+221e
|
||||
0xed U+03c6 U+00f8
|
||||
0xee U+03b5 U+2208
|
||||
0xef U+2229
|
||||
0xf0 U+2261
|
||||
0xf1 U+00b1
|
||||
0xf2 U+2265
|
||||
0xf3 U+2264
|
||||
0xf4 U+2320
|
||||
0xf5 U+2321
|
||||
0xf6 U+00f7
|
||||
0xf7 U+2248
|
||||
0xf8 U+00b0
|
||||
0xf9 U+2219
|
||||
0xfa U+00b7
|
||||
0xfb U+221a
|
||||
0xfc U+207f
|
||||
0xfd U+00b2
|
||||
#
|
||||
# Square bullet, non-spacing blank
|
||||
# Mapping U+fffd to the square bullet means it is the substitution
|
||||
# character
|
||||
#
|
||||
0xfe U+25a0 U+fffd
|
||||
0xff U+00a0
|
262
drivers/tty/vt/defkeymap.c_shipped
普通文件
262
drivers/tty/vt/defkeymap.c_shipped
普通文件
@@ -0,0 +1,262 @@
|
||||
/* Do not edit this file! It was automatically generated by */
|
||||
/* loadkeys --mktable defkeymap.map > defkeymap.c */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/keyboard.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
u_short plain_map[NR_KEYS] = {
|
||||
0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
|
||||
0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
|
||||
0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
|
||||
0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
|
||||
0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
|
||||
0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
|
||||
0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
|
||||
0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
|
||||
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
|
||||
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
|
||||
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
|
||||
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short shift_map[NR_KEYS] = {
|
||||
0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
|
||||
0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
|
||||
0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
|
||||
0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
|
||||
0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
|
||||
0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
|
||||
0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
|
||||
0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
|
||||
0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
|
||||
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
|
||||
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
|
||||
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short altgr_map[NR_KEYS] = {
|
||||
0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
|
||||
0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
|
||||
0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
|
||||
0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
|
||||
0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
|
||||
0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
|
||||
0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
|
||||
0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
|
||||
0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
|
||||
0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
|
||||
0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
|
||||
0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short ctrl_map[NR_KEYS] = {
|
||||
0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
|
||||
0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
|
||||
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
|
||||
0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
|
||||
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
|
||||
0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
|
||||
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
|
||||
0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
|
||||
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
|
||||
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
|
||||
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
|
||||
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short shift_ctrl_map[NR_KEYS] = {
|
||||
0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
|
||||
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
|
||||
0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
|
||||
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
|
||||
0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
|
||||
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
|
||||
0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
|
||||
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
|
||||
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short alt_map[NR_KEYS] = {
|
||||
0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
|
||||
0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
|
||||
0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
|
||||
0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
|
||||
0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
|
||||
0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
|
||||
0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
|
||||
0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
|
||||
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
|
||||
0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
|
||||
0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
|
||||
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
u_short ctrl_alt_map[NR_KEYS] = {
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
|
||||
0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
|
||||
0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
|
||||
0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
|
||||
0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
|
||||
0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
|
||||
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
|
||||
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
|
||||
0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
|
||||
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
ushort *key_maps[MAX_NR_KEYMAPS] = {
|
||||
plain_map, shift_map, altgr_map, NULL,
|
||||
ctrl_map, shift_ctrl_map, NULL, NULL,
|
||||
alt_map, NULL, NULL, NULL,
|
||||
ctrl_alt_map, NULL
|
||||
};
|
||||
|
||||
unsigned int keymap_count = 7;
|
||||
|
||||
/*
|
||||
* Philosophy: most people do not define more strings, but they who do
|
||||
* often want quite a lot of string space. So, we statically allocate
|
||||
* the default and allocate dynamically in chunks of 512 bytes.
|
||||
*/
|
||||
|
||||
char func_buf[] = {
|
||||
'\033', '[', '[', 'A', 0,
|
||||
'\033', '[', '[', 'B', 0,
|
||||
'\033', '[', '[', 'C', 0,
|
||||
'\033', '[', '[', 'D', 0,
|
||||
'\033', '[', '[', 'E', 0,
|
||||
'\033', '[', '1', '7', '~', 0,
|
||||
'\033', '[', '1', '8', '~', 0,
|
||||
'\033', '[', '1', '9', '~', 0,
|
||||
'\033', '[', '2', '0', '~', 0,
|
||||
'\033', '[', '2', '1', '~', 0,
|
||||
'\033', '[', '2', '3', '~', 0,
|
||||
'\033', '[', '2', '4', '~', 0,
|
||||
'\033', '[', '2', '5', '~', 0,
|
||||
'\033', '[', '2', '6', '~', 0,
|
||||
'\033', '[', '2', '8', '~', 0,
|
||||
'\033', '[', '2', '9', '~', 0,
|
||||
'\033', '[', '3', '1', '~', 0,
|
||||
'\033', '[', '3', '2', '~', 0,
|
||||
'\033', '[', '3', '3', '~', 0,
|
||||
'\033', '[', '3', '4', '~', 0,
|
||||
'\033', '[', '1', '~', 0,
|
||||
'\033', '[', '2', '~', 0,
|
||||
'\033', '[', '3', '~', 0,
|
||||
'\033', '[', '4', '~', 0,
|
||||
'\033', '[', '5', '~', 0,
|
||||
'\033', '[', '6', '~', 0,
|
||||
'\033', '[', 'M', 0,
|
||||
'\033', '[', 'P', 0,
|
||||
};
|
||||
|
||||
char *funcbufptr = func_buf;
|
||||
int funcbufsize = sizeof(func_buf);
|
||||
int funcbufleft = 0; /* space left */
|
||||
|
||||
char *func_table[MAX_NR_FUNC] = {
|
||||
func_buf + 0,
|
||||
func_buf + 5,
|
||||
func_buf + 10,
|
||||
func_buf + 15,
|
||||
func_buf + 20,
|
||||
func_buf + 25,
|
||||
func_buf + 31,
|
||||
func_buf + 37,
|
||||
func_buf + 43,
|
||||
func_buf + 49,
|
||||
func_buf + 55,
|
||||
func_buf + 61,
|
||||
func_buf + 67,
|
||||
func_buf + 73,
|
||||
func_buf + 79,
|
||||
func_buf + 85,
|
||||
func_buf + 91,
|
||||
func_buf + 97,
|
||||
func_buf + 103,
|
||||
func_buf + 109,
|
||||
func_buf + 115,
|
||||
func_buf + 120,
|
||||
func_buf + 125,
|
||||
func_buf + 130,
|
||||
func_buf + 135,
|
||||
func_buf + 140,
|
||||
func_buf + 145,
|
||||
NULL,
|
||||
NULL,
|
||||
func_buf + 149,
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct kbdiacruc accent_table[MAX_DIACR] = {
|
||||
{'`', 'A', 0300}, {'`', 'a', 0340},
|
||||
{'\'', 'A', 0301}, {'\'', 'a', 0341},
|
||||
{'^', 'A', 0302}, {'^', 'a', 0342},
|
||||
{'~', 'A', 0303}, {'~', 'a', 0343},
|
||||
{'"', 'A', 0304}, {'"', 'a', 0344},
|
||||
{'O', 'A', 0305}, {'o', 'a', 0345},
|
||||
{'0', 'A', 0305}, {'0', 'a', 0345},
|
||||
{'A', 'A', 0305}, {'a', 'a', 0345},
|
||||
{'A', 'E', 0306}, {'a', 'e', 0346},
|
||||
{',', 'C', 0307}, {',', 'c', 0347},
|
||||
{'`', 'E', 0310}, {'`', 'e', 0350},
|
||||
{'\'', 'E', 0311}, {'\'', 'e', 0351},
|
||||
{'^', 'E', 0312}, {'^', 'e', 0352},
|
||||
{'"', 'E', 0313}, {'"', 'e', 0353},
|
||||
{'`', 'I', 0314}, {'`', 'i', 0354},
|
||||
{'\'', 'I', 0315}, {'\'', 'i', 0355},
|
||||
{'^', 'I', 0316}, {'^', 'i', 0356},
|
||||
{'"', 'I', 0317}, {'"', 'i', 0357},
|
||||
{'-', 'D', 0320}, {'-', 'd', 0360},
|
||||
{'~', 'N', 0321}, {'~', 'n', 0361},
|
||||
{'`', 'O', 0322}, {'`', 'o', 0362},
|
||||
{'\'', 'O', 0323}, {'\'', 'o', 0363},
|
||||
{'^', 'O', 0324}, {'^', 'o', 0364},
|
||||
{'~', 'O', 0325}, {'~', 'o', 0365},
|
||||
{'"', 'O', 0326}, {'"', 'o', 0366},
|
||||
{'/', 'O', 0330}, {'/', 'o', 0370},
|
||||
{'`', 'U', 0331}, {'`', 'u', 0371},
|
||||
{'\'', 'U', 0332}, {'\'', 'u', 0372},
|
||||
{'^', 'U', 0333}, {'^', 'u', 0373},
|
||||
{'"', 'U', 0334}, {'"', 'u', 0374},
|
||||
{'\'', 'Y', 0335}, {'\'', 'y', 0375},
|
||||
{'T', 'H', 0336}, {'t', 'h', 0376},
|
||||
{'s', 's', 0337}, {'"', 'y', 0377},
|
||||
{'s', 'z', 0337}, {'i', 'j', 0377},
|
||||
};
|
||||
|
||||
unsigned int accent_table_size = 68;
|
357
drivers/tty/vt/defkeymap.map
普通文件
357
drivers/tty/vt/defkeymap.map
普通文件
@@ -0,0 +1,357 @@
|
||||
# Default kernel keymap. This uses 7 modifier combinations.
|
||||
keymaps 0-2,4-5,8,12
|
||||
# Change the above line into
|
||||
# keymaps 0-2,4-6,8,12
|
||||
# in case you want the entries
|
||||
# altgr control keycode 83 = Boot
|
||||
# altgr control keycode 111 = Boot
|
||||
# below.
|
||||
#
|
||||
# In fact AltGr is used very little, and one more keymap can
|
||||
# be saved by mapping AltGr to Alt (and adapting a few entries):
|
||||
# keycode 100 = Alt
|
||||
#
|
||||
keycode 1 = Escape Escape
|
||||
alt keycode 1 = Meta_Escape
|
||||
keycode 2 = one exclam
|
||||
alt keycode 2 = Meta_one
|
||||
keycode 3 = two at at
|
||||
control keycode 3 = nul
|
||||
shift control keycode 3 = nul
|
||||
alt keycode 3 = Meta_two
|
||||
keycode 4 = three numbersign
|
||||
control keycode 4 = Escape
|
||||
alt keycode 4 = Meta_three
|
||||
keycode 5 = four dollar dollar
|
||||
control keycode 5 = Control_backslash
|
||||
alt keycode 5 = Meta_four
|
||||
keycode 6 = five percent
|
||||
control keycode 6 = Control_bracketright
|
||||
alt keycode 6 = Meta_five
|
||||
keycode 7 = six asciicircum
|
||||
control keycode 7 = Control_asciicircum
|
||||
alt keycode 7 = Meta_six
|
||||
keycode 8 = seven ampersand braceleft
|
||||
control keycode 8 = Control_underscore
|
||||
alt keycode 8 = Meta_seven
|
||||
keycode 9 = eight asterisk bracketleft
|
||||
control keycode 9 = Delete
|
||||
alt keycode 9 = Meta_eight
|
||||
keycode 10 = nine parenleft bracketright
|
||||
alt keycode 10 = Meta_nine
|
||||
keycode 11 = zero parenright braceright
|
||||
alt keycode 11 = Meta_zero
|
||||
keycode 12 = minus underscore backslash
|
||||
control keycode 12 = Control_underscore
|
||||
shift control keycode 12 = Control_underscore
|
||||
alt keycode 12 = Meta_minus
|
||||
keycode 13 = equal plus
|
||||
alt keycode 13 = Meta_equal
|
||||
keycode 14 = Delete Delete
|
||||
control keycode 14 = BackSpace
|
||||
alt keycode 14 = Meta_Delete
|
||||
keycode 15 = Tab Tab
|
||||
alt keycode 15 = Meta_Tab
|
||||
keycode 16 = q
|
||||
keycode 17 = w
|
||||
keycode 18 = e
|
||||
altgr keycode 18 = Hex_E
|
||||
keycode 19 = r
|
||||
keycode 20 = t
|
||||
keycode 21 = y
|
||||
keycode 22 = u
|
||||
keycode 23 = i
|
||||
keycode 24 = o
|
||||
keycode 25 = p
|
||||
keycode 26 = bracketleft braceleft
|
||||
control keycode 26 = Escape
|
||||
alt keycode 26 = Meta_bracketleft
|
||||
keycode 27 = bracketright braceright asciitilde
|
||||
control keycode 27 = Control_bracketright
|
||||
alt keycode 27 = Meta_bracketright
|
||||
keycode 28 = Return
|
||||
alt keycode 28 = Meta_Control_m
|
||||
keycode 29 = Control
|
||||
keycode 30 = a
|
||||
altgr keycode 30 = Hex_A
|
||||
keycode 31 = s
|
||||
keycode 32 = d
|
||||
altgr keycode 32 = Hex_D
|
||||
keycode 33 = f
|
||||
altgr keycode 33 = Hex_F
|
||||
keycode 34 = g
|
||||
keycode 35 = h
|
||||
keycode 36 = j
|
||||
keycode 37 = k
|
||||
keycode 38 = l
|
||||
keycode 39 = semicolon colon
|
||||
alt keycode 39 = Meta_semicolon
|
||||
keycode 40 = apostrophe quotedbl
|
||||
control keycode 40 = Control_g
|
||||
alt keycode 40 = Meta_apostrophe
|
||||
keycode 41 = grave asciitilde
|
||||
control keycode 41 = nul
|
||||
alt keycode 41 = Meta_grave
|
||||
keycode 42 = Shift
|
||||
keycode 43 = backslash bar
|
||||
control keycode 43 = Control_backslash
|
||||
alt keycode 43 = Meta_backslash
|
||||
keycode 44 = z
|
||||
keycode 45 = x
|
||||
keycode 46 = c
|
||||
altgr keycode 46 = Hex_C
|
||||
keycode 47 = v
|
||||
keycode 48 = b
|
||||
altgr keycode 48 = Hex_B
|
||||
keycode 49 = n
|
||||
keycode 50 = m
|
||||
keycode 51 = comma less
|
||||
alt keycode 51 = Meta_comma
|
||||
keycode 52 = period greater
|
||||
control keycode 52 = Compose
|
||||
alt keycode 52 = Meta_period
|
||||
keycode 53 = slash question
|
||||
control keycode 53 = Delete
|
||||
alt keycode 53 = Meta_slash
|
||||
keycode 54 = Shift
|
||||
keycode 55 = KP_Multiply
|
||||
keycode 56 = Alt
|
||||
keycode 57 = space space
|
||||
control keycode 57 = nul
|
||||
alt keycode 57 = Meta_space
|
||||
keycode 58 = Caps_Lock
|
||||
keycode 59 = F1 F11 Console_13
|
||||
control keycode 59 = F1
|
||||
alt keycode 59 = Console_1
|
||||
control alt keycode 59 = Console_1
|
||||
keycode 60 = F2 F12 Console_14
|
||||
control keycode 60 = F2
|
||||
alt keycode 60 = Console_2
|
||||
control alt keycode 60 = Console_2
|
||||
keycode 61 = F3 F13 Console_15
|
||||
control keycode 61 = F3
|
||||
alt keycode 61 = Console_3
|
||||
control alt keycode 61 = Console_3
|
||||
keycode 62 = F4 F14 Console_16
|
||||
control keycode 62 = F4
|
||||
alt keycode 62 = Console_4
|
||||
control alt keycode 62 = Console_4
|
||||
keycode 63 = F5 F15 Console_17
|
||||
control keycode 63 = F5
|
||||
alt keycode 63 = Console_5
|
||||
control alt keycode 63 = Console_5
|
||||
keycode 64 = F6 F16 Console_18
|
||||
control keycode 64 = F6
|
||||
alt keycode 64 = Console_6
|
||||
control alt keycode 64 = Console_6
|
||||
keycode 65 = F7 F17 Console_19
|
||||
control keycode 65 = F7
|
||||
alt keycode 65 = Console_7
|
||||
control alt keycode 65 = Console_7
|
||||
keycode 66 = F8 F18 Console_20
|
||||
control keycode 66 = F8
|
||||
alt keycode 66 = Console_8
|
||||
control alt keycode 66 = Console_8
|
||||
keycode 67 = F9 F19 Console_21
|
||||
control keycode 67 = F9
|
||||
alt keycode 67 = Console_9
|
||||
control alt keycode 67 = Console_9
|
||||
keycode 68 = F10 F20 Console_22
|
||||
control keycode 68 = F10
|
||||
alt keycode 68 = Console_10
|
||||
control alt keycode 68 = Console_10
|
||||
keycode 69 = Num_Lock
|
||||
shift keycode 69 = Bare_Num_Lock
|
||||
keycode 70 = Scroll_Lock Show_Memory Show_Registers
|
||||
control keycode 70 = Show_State
|
||||
alt keycode 70 = Scroll_Lock
|
||||
keycode 71 = KP_7
|
||||
alt keycode 71 = Ascii_7
|
||||
altgr keycode 71 = Hex_7
|
||||
keycode 72 = KP_8
|
||||
alt keycode 72 = Ascii_8
|
||||
altgr keycode 72 = Hex_8
|
||||
keycode 73 = KP_9
|
||||
alt keycode 73 = Ascii_9
|
||||
altgr keycode 73 = Hex_9
|
||||
keycode 74 = KP_Subtract
|
||||
keycode 75 = KP_4
|
||||
alt keycode 75 = Ascii_4
|
||||
altgr keycode 75 = Hex_4
|
||||
keycode 76 = KP_5
|
||||
alt keycode 76 = Ascii_5
|
||||
altgr keycode 76 = Hex_5
|
||||
keycode 77 = KP_6
|
||||
alt keycode 77 = Ascii_6
|
||||
altgr keycode 77 = Hex_6
|
||||
keycode 78 = KP_Add
|
||||
keycode 79 = KP_1
|
||||
alt keycode 79 = Ascii_1
|
||||
altgr keycode 79 = Hex_1
|
||||
keycode 80 = KP_2
|
||||
alt keycode 80 = Ascii_2
|
||||
altgr keycode 80 = Hex_2
|
||||
keycode 81 = KP_3
|
||||
alt keycode 81 = Ascii_3
|
||||
altgr keycode 81 = Hex_3
|
||||
keycode 82 = KP_0
|
||||
alt keycode 82 = Ascii_0
|
||||
altgr keycode 82 = Hex_0
|
||||
keycode 83 = KP_Period
|
||||
# altgr control keycode 83 = Boot
|
||||
control alt keycode 83 = Boot
|
||||
keycode 84 = Last_Console
|
||||
keycode 85 =
|
||||
keycode 86 = less greater bar
|
||||
alt keycode 86 = Meta_less
|
||||
keycode 87 = F11 F11 Console_23
|
||||
control keycode 87 = F11
|
||||
alt keycode 87 = Console_11
|
||||
control alt keycode 87 = Console_11
|
||||
keycode 88 = F12 F12 Console_24
|
||||
control keycode 88 = F12
|
||||
alt keycode 88 = Console_12
|
||||
control alt keycode 88 = Console_12
|
||||
keycode 89 =
|
||||
keycode 90 =
|
||||
keycode 91 =
|
||||
keycode 92 =
|
||||
keycode 93 =
|
||||
keycode 94 =
|
||||
keycode 95 =
|
||||
keycode 96 = KP_Enter
|
||||
keycode 97 = Control
|
||||
keycode 98 = KP_Divide
|
||||
keycode 99 = Control_backslash
|
||||
control keycode 99 = Control_backslash
|
||||
alt keycode 99 = Control_backslash
|
||||
keycode 100 = AltGr
|
||||
keycode 101 = Break
|
||||
keycode 102 = Find
|
||||
keycode 103 = Up
|
||||
keycode 104 = Prior
|
||||
shift keycode 104 = Scroll_Backward
|
||||
keycode 105 = Left
|
||||
alt keycode 105 = Decr_Console
|
||||
keycode 106 = Right
|
||||
alt keycode 106 = Incr_Console
|
||||
keycode 107 = Select
|
||||
keycode 108 = Down
|
||||
keycode 109 = Next
|
||||
shift keycode 109 = Scroll_Forward
|
||||
keycode 110 = Insert
|
||||
keycode 111 = Remove
|
||||
# altgr control keycode 111 = Boot
|
||||
control alt keycode 111 = Boot
|
||||
keycode 112 = Macro
|
||||
keycode 113 = F13
|
||||
keycode 114 = F14
|
||||
keycode 115 = Help
|
||||
keycode 116 = Do
|
||||
keycode 117 = F17
|
||||
keycode 118 = KP_MinPlus
|
||||
keycode 119 = Pause
|
||||
keycode 120 =
|
||||
keycode 121 =
|
||||
keycode 122 =
|
||||
keycode 123 =
|
||||
keycode 124 =
|
||||
keycode 125 =
|
||||
keycode 126 =
|
||||
keycode 127 =
|
||||
string F1 = "\033[[A"
|
||||
string F2 = "\033[[B"
|
||||
string F3 = "\033[[C"
|
||||
string F4 = "\033[[D"
|
||||
string F5 = "\033[[E"
|
||||
string F6 = "\033[17~"
|
||||
string F7 = "\033[18~"
|
||||
string F8 = "\033[19~"
|
||||
string F9 = "\033[20~"
|
||||
string F10 = "\033[21~"
|
||||
string F11 = "\033[23~"
|
||||
string F12 = "\033[24~"
|
||||
string F13 = "\033[25~"
|
||||
string F14 = "\033[26~"
|
||||
string F15 = "\033[28~"
|
||||
string F16 = "\033[29~"
|
||||
string F17 = "\033[31~"
|
||||
string F18 = "\033[32~"
|
||||
string F19 = "\033[33~"
|
||||
string F20 = "\033[34~"
|
||||
string Find = "\033[1~"
|
||||
string Insert = "\033[2~"
|
||||
string Remove = "\033[3~"
|
||||
string Select = "\033[4~"
|
||||
string Prior = "\033[5~"
|
||||
string Next = "\033[6~"
|
||||
string Macro = "\033[M"
|
||||
string Pause = "\033[P"
|
||||
compose '`' 'A' to '<27>'
|
||||
compose '`' 'a' to '<27>'
|
||||
compose '\'' 'A' to '<27>'
|
||||
compose '\'' 'a' to '<27>'
|
||||
compose '^' 'A' to '<27>'
|
||||
compose '^' 'a' to '<27>'
|
||||
compose '~' 'A' to '<27>'
|
||||
compose '~' 'a' to '<27>'
|
||||
compose '"' 'A' to '<27>'
|
||||
compose '"' 'a' to '<27>'
|
||||
compose 'O' 'A' to '<27>'
|
||||
compose 'o' 'a' to '<27>'
|
||||
compose '0' 'A' to '<27>'
|
||||
compose '0' 'a' to '<27>'
|
||||
compose 'A' 'A' to '<27>'
|
||||
compose 'a' 'a' to '<27>'
|
||||
compose 'A' 'E' to '<27>'
|
||||
compose 'a' 'e' to '<27>'
|
||||
compose ',' 'C' to '<27>'
|
||||
compose ',' 'c' to '<27>'
|
||||
compose '`' 'E' to '<27>'
|
||||
compose '`' 'e' to '<27>'
|
||||
compose '\'' 'E' to '<27>'
|
||||
compose '\'' 'e' to '<27>'
|
||||
compose '^' 'E' to '<27>'
|
||||
compose '^' 'e' to '<27>'
|
||||
compose '"' 'E' to '<27>'
|
||||
compose '"' 'e' to '<27>'
|
||||
compose '`' 'I' to '<27>'
|
||||
compose '`' 'i' to '<27>'
|
||||
compose '\'' 'I' to '<27>'
|
||||
compose '\'' 'i' to '<27>'
|
||||
compose '^' 'I' to '<27>'
|
||||
compose '^' 'i' to '<27>'
|
||||
compose '"' 'I' to '<27>'
|
||||
compose '"' 'i' to '<27>'
|
||||
compose '-' 'D' to '<27>'
|
||||
compose '-' 'd' to '<27>'
|
||||
compose '~' 'N' to '<27>'
|
||||
compose '~' 'n' to '<27>'
|
||||
compose '`' 'O' to '<27>'
|
||||
compose '`' 'o' to '<27>'
|
||||
compose '\'' 'O' to '<27>'
|
||||
compose '\'' 'o' to '<27>'
|
||||
compose '^' 'O' to '<27>'
|
||||
compose '^' 'o' to '<27>'
|
||||
compose '~' 'O' to '<27>'
|
||||
compose '~' 'o' to '<27>'
|
||||
compose '"' 'O' to '<27>'
|
||||
compose '"' 'o' to '<27>'
|
||||
compose '/' 'O' to '<27>'
|
||||
compose '/' 'o' to '<27>'
|
||||
compose '`' 'U' to '<27>'
|
||||
compose '`' 'u' to '<27>'
|
||||
compose '\'' 'U' to '<27>'
|
||||
compose '\'' 'u' to '<27>'
|
||||
compose '^' 'U' to '<27>'
|
||||
compose '^' 'u' to '<27>'
|
||||
compose '"' 'U' to '<27>'
|
||||
compose '"' 'u' to '<27>'
|
||||
compose '\'' 'Y' to '<27>'
|
||||
compose '\'' 'y' to '<27>'
|
||||
compose 'T' 'H' to '<27>'
|
||||
compose 't' 'h' to '<27>'
|
||||
compose 's' 's' to '<27>'
|
||||
compose '"' 'y' to '<27>'
|
||||
compose 's' 'z' to '<27>'
|
||||
compose 'i' 'j' to '<27>'
|
1454
drivers/tty/vt/keyboard.c
普通文件
1454
drivers/tty/vt/keyboard.c
普通文件
文件差异内容过多而无法显示
加载差异
348
drivers/tty/vt/selection.c
普通文件
348
drivers/tty/vt/selection.c
普通文件
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* linux/drivers/char/selection.c
|
||||
*
|
||||
* This module exports the functions:
|
||||
*
|
||||
* 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)'
|
||||
* 'void clear_selection(void)'
|
||||
* 'int paste_selection(struct tty_struct *)'
|
||||
* 'int sel_loadlut(char __user *)'
|
||||
*
|
||||
* Now that /dev/vcs exists, most of this can disappear again.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <linux/kbd_kern.h>
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/consolemap.h>
|
||||
#include <linux/selection.h>
|
||||
#include <linux/tiocl.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
|
||||
#define isspace(c) ((c) == ' ')
|
||||
|
||||
extern void poke_blanked_console(void);
|
||||
|
||||
/* Variables for selection control. */
|
||||
/* Use a dynamic buffer, instead of static (Dec 1994) */
|
||||
struct vc_data *sel_cons; /* must not be deallocated */
|
||||
static int use_unicode;
|
||||
static volatile int sel_start = -1; /* cleared by clear_selection */
|
||||
static int sel_end;
|
||||
static int sel_buffer_lth;
|
||||
static char *sel_buffer;
|
||||
|
||||
/* clear_selection, highlight and highlight_pointer can be called
|
||||
from interrupt (via scrollback/front) */
|
||||
|
||||
/* set reverse video on characters s-e of console with selection. */
|
||||
static inline void highlight(const int s, const int e)
|
||||
{
|
||||
invert_screen(sel_cons, s, e-s+2, 1);
|
||||
}
|
||||
|
||||
/* use complementary color to show the pointer */
|
||||
static inline void highlight_pointer(const int where)
|
||||
{
|
||||
complement_pos(sel_cons, where);
|
||||
}
|
||||
|
||||
static u16
|
||||
sel_pos(int n)
|
||||
{
|
||||
return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
|
||||
use_unicode);
|
||||
}
|
||||
|
||||
/* remove the current selection highlight, if any,
|
||||
from the console holding the selection. */
|
||||
void
|
||||
clear_selection(void) {
|
||||
highlight_pointer(-1); /* hide the pointer */
|
||||
if (sel_start != -1) {
|
||||
highlight(sel_start, sel_end);
|
||||
sel_start = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* User settable table: what characters are to be considered alphabetic?
|
||||
* 256 bits
|
||||
*/
|
||||
static u32 inwordLut[8]={
|
||||
0x00000000, /* control chars */
|
||||
0x03FF0000, /* digits */
|
||||
0x87FFFFFE, /* uppercase and '_' */
|
||||
0x07FFFFFE, /* lowercase */
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0xFF7FFFFF, /* latin-1 accented letters, not multiplication sign */
|
||||
0xFF7FFFFF /* latin-1 accented letters, not division sign */
|
||||
};
|
||||
|
||||
static inline int inword(const u16 c) {
|
||||
return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
|
||||
}
|
||||
|
||||
/* set inwordLut contents. Invoked by ioctl(). */
|
||||
int sel_loadlut(char __user *p)
|
||||
{
|
||||
return copy_from_user(inwordLut, (u32 __user *)(p+4), 32) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
/* does screen address p correspond to character at LH/RH edge of screen? */
|
||||
static inline int atedge(const int p, int size_row)
|
||||
{
|
||||
return (!(p % size_row) || !((p + 2) % size_row));
|
||||
}
|
||||
|
||||
/* constrain v such that v <= u */
|
||||
static inline unsigned short limit(const unsigned short v, const unsigned short u)
|
||||
{
|
||||
return (v > u) ? u : v;
|
||||
}
|
||||
|
||||
/* stores the char in UTF8 and returns the number of bytes used (1-3) */
|
||||
static int store_utf8(u16 c, char *p)
|
||||
{
|
||||
if (c < 0x80) {
|
||||
/* 0******* */
|
||||
p[0] = c;
|
||||
return 1;
|
||||
} else if (c < 0x800) {
|
||||
/* 110***** 10****** */
|
||||
p[0] = 0xc0 | (c >> 6);
|
||||
p[1] = 0x80 | (c & 0x3f);
|
||||
return 2;
|
||||
} else {
|
||||
/* 1110**** 10****** 10****** */
|
||||
p[0] = 0xe0 | (c >> 12);
|
||||
p[1] = 0x80 | ((c >> 6) & 0x3f);
|
||||
p[2] = 0x80 | (c & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* set the current selection. Invoked by ioctl() or by kernel code. */
|
||||
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
|
||||
{
|
||||
struct vc_data *vc = vc_cons[fg_console].d;
|
||||
int sel_mode, new_sel_start, new_sel_end, spc;
|
||||
char *bp, *obp;
|
||||
int i, ps, pe, multiplier;
|
||||
u16 c;
|
||||
struct kbd_struct *kbd = kbd_table + fg_console;
|
||||
|
||||
poke_blanked_console();
|
||||
|
||||
{ unsigned short xs, ys, xe, ye;
|
||||
|
||||
if (!access_ok(VERIFY_READ, sel, sizeof(*sel)))
|
||||
return -EFAULT;
|
||||
__get_user(xs, &sel->xs);
|
||||
__get_user(ys, &sel->ys);
|
||||
__get_user(xe, &sel->xe);
|
||||
__get_user(ye, &sel->ye);
|
||||
__get_user(sel_mode, &sel->sel_mode);
|
||||
xs--; ys--; xe--; ye--;
|
||||
xs = limit(xs, vc->vc_cols - 1);
|
||||
ys = limit(ys, vc->vc_rows - 1);
|
||||
xe = limit(xe, vc->vc_cols - 1);
|
||||
ye = limit(ye, vc->vc_rows - 1);
|
||||
ps = ys * vc->vc_size_row + (xs << 1);
|
||||
pe = ye * vc->vc_size_row + (xe << 1);
|
||||
|
||||
if (sel_mode == TIOCL_SELCLEAR) {
|
||||
/* useful for screendump without selection highlights */
|
||||
clear_selection();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) {
|
||||
mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps > pe) /* make sel_start <= sel_end */
|
||||
{
|
||||
int tmp = ps;
|
||||
ps = pe;
|
||||
pe = tmp;
|
||||
}
|
||||
|
||||
if (sel_cons != vc_cons[fg_console].d) {
|
||||
clear_selection();
|
||||
sel_cons = vc_cons[fg_console].d;
|
||||
}
|
||||
use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
|
||||
|
||||
switch (sel_mode)
|
||||
{
|
||||
case TIOCL_SELCHAR: /* character-by-character selection */
|
||||
new_sel_start = ps;
|
||||
new_sel_end = pe;
|
||||
break;
|
||||
case TIOCL_SELWORD: /* word-by-word selection */
|
||||
spc = isspace(sel_pos(ps));
|
||||
for (new_sel_start = ps; ; ps -= 2)
|
||||
{
|
||||
if ((spc && !isspace(sel_pos(ps))) ||
|
||||
(!spc && !inword(sel_pos(ps))))
|
||||
break;
|
||||
new_sel_start = ps;
|
||||
if (!(ps % vc->vc_size_row))
|
||||
break;
|
||||
}
|
||||
spc = isspace(sel_pos(pe));
|
||||
for (new_sel_end = pe; ; pe += 2)
|
||||
{
|
||||
if ((spc && !isspace(sel_pos(pe))) ||
|
||||
(!spc && !inword(sel_pos(pe))))
|
||||
break;
|
||||
new_sel_end = pe;
|
||||
if (!((pe + 2) % vc->vc_size_row))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TIOCL_SELLINE: /* line-by-line selection */
|
||||
new_sel_start = ps - ps % vc->vc_size_row;
|
||||
new_sel_end = pe + vc->vc_size_row
|
||||
- pe % vc->vc_size_row - 2;
|
||||
break;
|
||||
case TIOCL_SELPOINTER:
|
||||
highlight_pointer(pe);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* remove the pointer */
|
||||
highlight_pointer(-1);
|
||||
|
||||
/* select to end of line if on trailing space */
|
||||
if (new_sel_end > new_sel_start &&
|
||||
!atedge(new_sel_end, vc->vc_size_row) &&
|
||||
isspace(sel_pos(new_sel_end))) {
|
||||
for (pe = new_sel_end + 2; ; pe += 2)
|
||||
if (!isspace(sel_pos(pe)) ||
|
||||
atedge(pe, vc->vc_size_row))
|
||||
break;
|
||||
if (isspace(sel_pos(pe)))
|
||||
new_sel_end = pe;
|
||||
}
|
||||
if (sel_start == -1) /* no current selection */
|
||||
highlight(new_sel_start, new_sel_end);
|
||||
else if (new_sel_start == sel_start)
|
||||
{
|
||||
if (new_sel_end == sel_end) /* no action required */
|
||||
return 0;
|
||||
else if (new_sel_end > sel_end) /* extend to right */
|
||||
highlight(sel_end + 2, new_sel_end);
|
||||
else /* contract from right */
|
||||
highlight(new_sel_end + 2, sel_end);
|
||||
}
|
||||
else if (new_sel_end == sel_end)
|
||||
{
|
||||
if (new_sel_start < sel_start) /* extend to left */
|
||||
highlight(new_sel_start, sel_start - 2);
|
||||
else /* contract from left */
|
||||
highlight(sel_start, new_sel_start - 2);
|
||||
}
|
||||
else /* some other case; start selection from scratch */
|
||||
{
|
||||
clear_selection();
|
||||
highlight(new_sel_start, new_sel_end);
|
||||
}
|
||||
sel_start = new_sel_start;
|
||||
sel_end = new_sel_end;
|
||||
|
||||
/* Allocate a new buffer before freeing the old one ... */
|
||||
multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
|
||||
bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL);
|
||||
if (!bp) {
|
||||
printk(KERN_WARNING "selection: kmalloc() failed\n");
|
||||
clear_selection();
|
||||
return -ENOMEM;
|
||||
}
|
||||
kfree(sel_buffer);
|
||||
sel_buffer = bp;
|
||||
|
||||
obp = bp;
|
||||
for (i = sel_start; i <= sel_end; i += 2) {
|
||||
c = sel_pos(i);
|
||||
if (use_unicode)
|
||||
bp += store_utf8(c, bp);
|
||||
else
|
||||
*bp++ = c;
|
||||
if (!isspace(c))
|
||||
obp = bp;
|
||||
if (! ((i + 2) % vc->vc_size_row)) {
|
||||
/* strip trailing blanks from line and add newline,
|
||||
unless non-space at end of line. */
|
||||
if (obp != bp) {
|
||||
bp = obp;
|
||||
*bp++ = '\r';
|
||||
}
|
||||
obp = bp;
|
||||
}
|
||||
}
|
||||
sel_buffer_lth = bp - sel_buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert the contents of the selection buffer into the
|
||||
* queue of the tty associated with the current console.
|
||||
* Invoked by ioctl().
|
||||
*/
|
||||
int paste_selection(struct tty_struct *tty)
|
||||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
int pasted = 0;
|
||||
unsigned int count;
|
||||
struct tty_ldisc *ld;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
/* always called with BTM from vt_ioctl */
|
||||
WARN_ON(!tty_locked());
|
||||
|
||||
acquire_console_sem();
|
||||
poke_blanked_console();
|
||||
release_console_sem();
|
||||
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (!ld) {
|
||||
tty_unlock();
|
||||
ld = tty_ldisc_ref_wait(tty);
|
||||
tty_lock();
|
||||
}
|
||||
|
||||
add_wait_queue(&vc->paste_wait, &wait);
|
||||
while (sel_buffer && sel_buffer_lth > pasted) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||
schedule();
|
||||
continue;
|
||||
}
|
||||
count = sel_buffer_lth - pasted;
|
||||
count = min(count, tty->receive_room);
|
||||
tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
|
||||
NULL, count);
|
||||
pasted += count;
|
||||
}
|
||||
remove_wait_queue(&vc->paste_wait, &wait);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
tty_ldisc_deref(ld);
|
||||
return 0;
|
||||
}
|
644
drivers/tty/vt/vc_screen.c
普通文件
644
drivers/tty/vt/vc_screen.c
普通文件
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* linux/drivers/char/vc_screen.c
|
||||
*
|
||||
* Provide access to virtual console memory.
|
||||
* /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
|
||||
* /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
|
||||
* [minor: N]
|
||||
*
|
||||
* /dev/vcsaN: idem, but including attributes, and prefixed with
|
||||
* the 4 bytes lines,columns,x,y (as screendump used to give).
|
||||
* Attribute/character pair is in native endianity.
|
||||
* [minor: N+128]
|
||||
*
|
||||
* This replaces screendump and part of selection, so that the system
|
||||
* administrator can control access using file system permissions.
|
||||
*
|
||||
* aeb@cwi.nl - efter Friedas begravelse - 950211
|
||||
*
|
||||
* machek@k332.feld.cvut.cz - modified not to send characters to wrong console
|
||||
* - fixed some fatal off-by-one bugs (0-- no longer == -1 -> looping and looping and looping...)
|
||||
* - making it shorter - scr_readw are macros which expand in PRETTY long code
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/selection.h>
|
||||
#include <linux/kbd_kern.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#undef attr
|
||||
#undef org
|
||||
#undef addr
|
||||
#define HEADER_SIZE 4
|
||||
|
||||
struct vcs_poll_data {
|
||||
struct notifier_block notifier;
|
||||
unsigned int cons_num;
|
||||
bool seen_last_update;
|
||||
wait_queue_head_t waitq;
|
||||
struct fasync_struct *fasync;
|
||||
};
|
||||
|
||||
static int
|
||||
vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
|
||||
{
|
||||
struct vt_notifier_param *param = _param;
|
||||
struct vc_data *vc = param->vc;
|
||||
struct vcs_poll_data *poll =
|
||||
container_of(nb, struct vcs_poll_data, notifier);
|
||||
int currcons = poll->cons_num;
|
||||
|
||||
if (code != VT_UPDATE)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (currcons == 0)
|
||||
currcons = fg_console;
|
||||
else
|
||||
currcons--;
|
||||
if (currcons != vc->vc_num)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
poll->seen_last_update = false;
|
||||
wake_up_interruptible(&poll->waitq);
|
||||
kill_fasync(&poll->fasync, SIGIO, POLL_IN);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
vcs_poll_data_free(struct vcs_poll_data *poll)
|
||||
{
|
||||
unregister_vt_notifier(&poll->notifier);
|
||||
kfree(poll);
|
||||
}
|
||||
|
||||
static struct vcs_poll_data *
|
||||
vcs_poll_data_get(struct file *file)
|
||||
{
|
||||
struct vcs_poll_data *poll = file->private_data;
|
||||
|
||||
if (poll)
|
||||
return poll;
|
||||
|
||||
poll = kzalloc(sizeof(*poll), GFP_KERNEL);
|
||||
if (!poll)
|
||||
return NULL;
|
||||
poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
|
||||
init_waitqueue_head(&poll->waitq);
|
||||
poll->notifier.notifier_call = vcs_notifier;
|
||||
if (register_vt_notifier(&poll->notifier) != 0) {
|
||||
kfree(poll);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This code may be called either through ->poll() or ->fasync().
|
||||
* If we have two threads using the same file descriptor, they could
|
||||
* both enter this function, both notice that the structure hasn't
|
||||
* been allocated yet and go ahead allocating it in parallel, but
|
||||
* only one of them must survive and be shared otherwise we'd leak
|
||||
* memory with a dangling notifier callback.
|
||||
*/
|
||||
spin_lock(&file->f_lock);
|
||||
if (!file->private_data) {
|
||||
file->private_data = poll;
|
||||
} else {
|
||||
/* someone else raced ahead of us */
|
||||
vcs_poll_data_free(poll);
|
||||
poll = file->private_data;
|
||||
}
|
||||
spin_unlock(&file->f_lock);
|
||||
|
||||
return poll;
|
||||
}
|
||||
|
||||
static int
|
||||
vcs_size(struct inode *inode)
|
||||
{
|
||||
int size;
|
||||
int minor = iminor(inode);
|
||||
int currcons = minor & 127;
|
||||
struct vc_data *vc;
|
||||
|
||||
if (currcons == 0)
|
||||
currcons = fg_console;
|
||||
else
|
||||
currcons--;
|
||||
if (!vc_cons_allocated(currcons))
|
||||
return -ENXIO;
|
||||
vc = vc_cons[currcons].d;
|
||||
|
||||
size = vc->vc_rows * vc->vc_cols;
|
||||
|
||||
if (minor & 128)
|
||||
size = 2*size + HEADER_SIZE;
|
||||
return size;
|
||||
}
|
||||
|
||||
static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
|
||||
{
|
||||
int size;
|
||||
|
||||
mutex_lock(&con_buf_mtx);
|
||||
size = vcs_size(file->f_path.dentry->d_inode);
|
||||
switch (orig) {
|
||||
default:
|
||||
mutex_unlock(&con_buf_mtx);
|
||||
return -EINVAL;
|
||||
case 2:
|
||||
offset += size;
|
||||
break;
|
||||
case 1:
|
||||
offset += file->f_pos;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
if (offset < 0 || offset > size) {
|
||||
mutex_unlock(&con_buf_mtx);
|
||||
return -EINVAL;
|
||||
}
|
||||
file->f_pos = offset;
|
||||
mutex_unlock(&con_buf_mtx);
|
||||
return file->f_pos;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
unsigned int currcons = iminor(inode);
|
||||
struct vc_data *vc;
|
||||
struct vcs_poll_data *poll;
|
||||
long pos;
|
||||
long viewed, attr, read;
|
||||
int col, maxcol;
|
||||
unsigned short *org = NULL;
|
||||
ssize_t ret;
|
||||
|
||||
mutex_lock(&con_buf_mtx);
|
||||
|
||||
pos = *ppos;
|
||||
|
||||
/* Select the proper current console and verify
|
||||
* sanity of the situation under the console lock.
|
||||
*/
|
||||
acquire_console_sem();
|
||||
|
||||
attr = (currcons & 128);
|
||||
currcons = (currcons & 127);
|
||||
if (currcons == 0) {
|
||||
currcons = fg_console;
|
||||
viewed = 1;
|
||||
} else {
|
||||
currcons--;
|
||||
viewed = 0;
|
||||
}
|
||||
ret = -ENXIO;
|
||||
if (!vc_cons_allocated(currcons))
|
||||
goto unlock_out;
|
||||
vc = vc_cons[currcons].d;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (pos < 0)
|
||||
goto unlock_out;
|
||||
poll = file->private_data;
|
||||
if (count && poll)
|
||||
poll->seen_last_update = true;
|
||||
read = 0;
|
||||
ret = 0;
|
||||
while (count) {
|
||||
char *con_buf0, *con_buf_start;
|
||||
long this_round, size;
|
||||
ssize_t orig_count;
|
||||
long p = pos;
|
||||
|
||||
/* Check whether we are above size each round,
|
||||
* as copy_to_user at the end of this loop
|
||||
* could sleep.
|
||||
*/
|
||||
size = vcs_size(inode);
|
||||
if (pos >= size)
|
||||
break;
|
||||
if (count > size - pos)
|
||||
count = size - pos;
|
||||
|
||||
this_round = count;
|
||||
if (this_round > CON_BUF_SIZE)
|
||||
this_round = CON_BUF_SIZE;
|
||||
|
||||
/* Perform the whole read into the local con_buf.
|
||||
* Then we can drop the console spinlock and safely
|
||||
* attempt to move it to userspace.
|
||||
*/
|
||||
|
||||
con_buf_start = con_buf0 = con_buf;
|
||||
orig_count = this_round;
|
||||
maxcol = vc->vc_cols;
|
||||
if (!attr) {
|
||||
org = screen_pos(vc, p, viewed);
|
||||
col = p % maxcol;
|
||||
p += maxcol - col;
|
||||
while (this_round-- > 0) {
|
||||
*con_buf0++ = (vcs_scr_readw(vc, org++) & 0xff);
|
||||
if (++col == maxcol) {
|
||||
org = screen_pos(vc, p, viewed);
|
||||
col = 0;
|
||||
p += maxcol;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (p < HEADER_SIZE) {
|
||||
size_t tmp_count;
|
||||
|
||||
con_buf0[0] = (char)vc->vc_rows;
|
||||
con_buf0[1] = (char)vc->vc_cols;
|
||||
getconsxy(vc, con_buf0 + 2);
|
||||
|
||||
con_buf_start += p;
|
||||
this_round += p;
|
||||
if (this_round > CON_BUF_SIZE) {
|
||||
this_round = CON_BUF_SIZE;
|
||||
orig_count = this_round - p;
|
||||
}
|
||||
|
||||
tmp_count = HEADER_SIZE;
|
||||
if (tmp_count > this_round)
|
||||
tmp_count = this_round;
|
||||
|
||||
/* Advance state pointers and move on. */
|
||||
this_round -= tmp_count;
|
||||
p = HEADER_SIZE;
|
||||
con_buf0 = con_buf + HEADER_SIZE;
|
||||
/* If this_round >= 0, then p is even... */
|
||||
} else if (p & 1) {
|
||||
/* Skip first byte for output if start address is odd
|
||||
* Update region sizes up/down depending on free
|
||||
* space in buffer.
|
||||
*/
|
||||
con_buf_start++;
|
||||
if (this_round < CON_BUF_SIZE)
|
||||
this_round++;
|
||||
else
|
||||
orig_count--;
|
||||
}
|
||||
if (this_round > 0) {
|
||||
unsigned short *tmp_buf = (unsigned short *)con_buf0;
|
||||
|
||||
p -= HEADER_SIZE;
|
||||
p /= 2;
|
||||
col = p % maxcol;
|
||||
|
||||
org = screen_pos(vc, p, viewed);
|
||||
p += maxcol - col;
|
||||
|
||||
/* Buffer has even length, so we can always copy
|
||||
* character + attribute. We do not copy last byte
|
||||
* to userspace if this_round is odd.
|
||||
*/
|
||||
this_round = (this_round + 1) >> 1;
|
||||
|
||||
while (this_round) {
|
||||
*tmp_buf++ = vcs_scr_readw(vc, org++);
|
||||
this_round --;
|
||||
if (++col == maxcol) {
|
||||
org = screen_pos(vc, p, viewed);
|
||||
col = 0;
|
||||
p += maxcol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, release the console semaphore while we push
|
||||
* all the data to userspace from our temporary buffer.
|
||||
*
|
||||
* AKPM: Even though it's a semaphore, we should drop it because
|
||||
* the pagefault handling code may want to call printk().
|
||||
*/
|
||||
|
||||
release_console_sem();
|
||||
ret = copy_to_user(buf, con_buf_start, orig_count);
|
||||
acquire_console_sem();
|
||||
|
||||
if (ret) {
|
||||
read += (orig_count - ret);
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
buf += orig_count;
|
||||
pos += orig_count;
|
||||
read += orig_count;
|
||||
count -= orig_count;
|
||||
}
|
||||
*ppos += read;
|
||||
if (read)
|
||||
ret = read;
|
||||
unlock_out:
|
||||
release_console_sem();
|
||||
mutex_unlock(&con_buf_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
unsigned int currcons = iminor(inode);
|
||||
struct vc_data *vc;
|
||||
long pos;
|
||||
long viewed, attr, size, written;
|
||||
char *con_buf0;
|
||||
int col, maxcol;
|
||||
u16 *org0 = NULL, *org = NULL;
|
||||
size_t ret;
|
||||
|
||||
mutex_lock(&con_buf_mtx);
|
||||
|
||||
pos = *ppos;
|
||||
|
||||
/* Select the proper current console and verify
|
||||
* sanity of the situation under the console lock.
|
||||
*/
|
||||
acquire_console_sem();
|
||||
|
||||
attr = (currcons & 128);
|
||||
currcons = (currcons & 127);
|
||||
|
||||
if (currcons == 0) {
|
||||
currcons = fg_console;
|
||||
viewed = 1;
|
||||
} else {
|
||||
currcons--;
|
||||
viewed = 0;
|
||||
}
|
||||
ret = -ENXIO;
|
||||
if (!vc_cons_allocated(currcons))
|
||||
goto unlock_out;
|
||||
vc = vc_cons[currcons].d;
|
||||
|
||||
size = vcs_size(inode);
|
||||
ret = -EINVAL;
|
||||
if (pos < 0 || pos > size)
|
||||
goto unlock_out;
|
||||
if (count > size - pos)
|
||||
count = size - pos;
|
||||
written = 0;
|
||||
while (count) {
|
||||
long this_round = count;
|
||||
size_t orig_count;
|
||||
long p;
|
||||
|
||||
if (this_round > CON_BUF_SIZE)
|
||||
this_round = CON_BUF_SIZE;
|
||||
|
||||
/* Temporarily drop the console lock so that we can read
|
||||
* in the write data from userspace safely.
|
||||
*/
|
||||
release_console_sem();
|
||||
ret = copy_from_user(con_buf, buf, this_round);
|
||||
acquire_console_sem();
|
||||
|
||||
if (ret) {
|
||||
this_round -= ret;
|
||||
if (!this_round) {
|
||||
/* Abort loop if no data were copied. Otherwise
|
||||
* fail with -EFAULT.
|
||||
*/
|
||||
if (written)
|
||||
break;
|
||||
ret = -EFAULT;
|
||||
goto unlock_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* The vcs_size might have changed while we slept to grab
|
||||
* the user buffer, so recheck.
|
||||
* Return data written up to now on failure.
|
||||
*/
|
||||
size = vcs_size(inode);
|
||||
if (pos >= size)
|
||||
break;
|
||||
if (this_round > size - pos)
|
||||
this_round = size - pos;
|
||||
|
||||
/* OK, now actually push the write to the console
|
||||
* under the lock using the local kernel buffer.
|
||||
*/
|
||||
|
||||
con_buf0 = con_buf;
|
||||
orig_count = this_round;
|
||||
maxcol = vc->vc_cols;
|
||||
p = pos;
|
||||
if (!attr) {
|
||||
org0 = org = screen_pos(vc, p, viewed);
|
||||
col = p % maxcol;
|
||||
p += maxcol - col;
|
||||
|
||||
while (this_round > 0) {
|
||||
unsigned char c = *con_buf0++;
|
||||
|
||||
this_round--;
|
||||
vcs_scr_writew(vc,
|
||||
(vcs_scr_readw(vc, org) & 0xff00) | c, org);
|
||||
org++;
|
||||
if (++col == maxcol) {
|
||||
org = screen_pos(vc, p, viewed);
|
||||
col = 0;
|
||||
p += maxcol;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (p < HEADER_SIZE) {
|
||||
char header[HEADER_SIZE];
|
||||
|
||||
getconsxy(vc, header + 2);
|
||||
while (p < HEADER_SIZE && this_round > 0) {
|
||||
this_round--;
|
||||
header[p++] = *con_buf0++;
|
||||
}
|
||||
if (!viewed)
|
||||
putconsxy(vc, header + 2);
|
||||
}
|
||||
p -= HEADER_SIZE;
|
||||
col = (p/2) % maxcol;
|
||||
if (this_round > 0) {
|
||||
org0 = org = screen_pos(vc, p/2, viewed);
|
||||
if ((p & 1) && this_round > 0) {
|
||||
char c;
|
||||
|
||||
this_round--;
|
||||
c = *con_buf0++;
|
||||
#ifdef __BIG_ENDIAN
|
||||
vcs_scr_writew(vc, c |
|
||||
(vcs_scr_readw(vc, org) & 0xff00), org);
|
||||
#else
|
||||
vcs_scr_writew(vc, (c << 8) |
|
||||
(vcs_scr_readw(vc, org) & 0xff), org);
|
||||
#endif
|
||||
org++;
|
||||
p++;
|
||||
if (++col == maxcol) {
|
||||
org = screen_pos(vc, p/2, viewed);
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
p /= 2;
|
||||
p += maxcol - col;
|
||||
}
|
||||
while (this_round > 1) {
|
||||
unsigned short w;
|
||||
|
||||
w = get_unaligned(((unsigned short *)con_buf0));
|
||||
vcs_scr_writew(vc, w, org++);
|
||||
con_buf0 += 2;
|
||||
this_round -= 2;
|
||||
if (++col == maxcol) {
|
||||
org = screen_pos(vc, p, viewed);
|
||||
col = 0;
|
||||
p += maxcol;
|
||||
}
|
||||
}
|
||||
if (this_round > 0) {
|
||||
unsigned char c;
|
||||
|
||||
c = *con_buf0++;
|
||||
#ifdef __BIG_ENDIAN
|
||||
vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff) | (c << 8), org);
|
||||
#else
|
||||
vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff00) | c, org);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
count -= orig_count;
|
||||
written += orig_count;
|
||||
buf += orig_count;
|
||||
pos += orig_count;
|
||||
if (org0)
|
||||
update_region(vc, (unsigned long)(org0), org - org0);
|
||||
}
|
||||
*ppos += written;
|
||||
ret = written;
|
||||
if (written)
|
||||
vcs_scr_updated(vc);
|
||||
|
||||
unlock_out:
|
||||
release_console_sem();
|
||||
|
||||
mutex_unlock(&con_buf_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
vcs_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct vcs_poll_data *poll = vcs_poll_data_get(file);
|
||||
int ret = 0;
|
||||
|
||||
if (poll) {
|
||||
poll_wait(file, &poll->waitq, wait);
|
||||
if (!poll->seen_last_update)
|
||||
ret = POLLIN | POLLRDNORM;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
vcs_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct vcs_poll_data *poll = file->private_data;
|
||||
|
||||
if (!poll) {
|
||||
/* don't allocate anything if all we want is disable fasync */
|
||||
if (!on)
|
||||
return 0;
|
||||
poll = vcs_poll_data_get(file);
|
||||
if (!poll)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return fasync_helper(fd, file, on, &poll->fasync);
|
||||
}
|
||||
|
||||
static int
|
||||
vcs_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
unsigned int currcons = iminor(inode) & 127;
|
||||
int ret = 0;
|
||||
|
||||
tty_lock();
|
||||
if(currcons && !vc_cons_allocated(currcons-1))
|
||||
ret = -ENXIO;
|
||||
tty_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vcs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct vcs_poll_data *poll = file->private_data;
|
||||
|
||||
if (poll)
|
||||
vcs_poll_data_free(poll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations vcs_fops = {
|
||||
.llseek = vcs_lseek,
|
||||
.read = vcs_read,
|
||||
.write = vcs_write,
|
||||
.poll = vcs_poll,
|
||||
.fasync = vcs_fasync,
|
||||
.open = vcs_open,
|
||||
.release = vcs_release,
|
||||
};
|
||||
|
||||
static struct class *vc_class;
|
||||
|
||||
void vcs_make_sysfs(int index)
|
||||
{
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL,
|
||||
"vcs%u", index + 1);
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL,
|
||||
"vcsa%u", index + 1);
|
||||
}
|
||||
|
||||
void vcs_remove_sysfs(int index)
|
||||
{
|
||||
device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1));
|
||||
device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129));
|
||||
}
|
||||
|
||||
int __init vcs_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
|
||||
panic("unable to get major %d for vcs device", VCS_MAJOR);
|
||||
vc_class = class_create(THIS_MODULE, "vc");
|
||||
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
|
||||
for (i = 0; i < MIN_NR_CONSOLES; i++)
|
||||
vcs_make_sysfs(i);
|
||||
return 0;
|
||||
}
|
4209
drivers/tty/vt/vt.c
普通文件
4209
drivers/tty/vt/vt.c
普通文件
文件差异内容过多而无法显示
加载差异
1788
drivers/tty/vt/vt_ioctl.c
普通文件
1788
drivers/tty/vt/vt_ioctl.c
普通文件
文件差异内容过多而无法显示
加载差异
在新工单中引用
屏蔽一个用户