📄 sunkbd.c
字号:
/* keyboard.c: Sun keyboard driver. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Added vuid event generation and /dev/kbd device for SunOS * compatibility - Miguel (miguel@nuclecu.unam.mx) */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/mm.h>#include <linux/ptrace.h>#include <linux/signal.h>#include <linux/string.h>#include <linux/fcntl.h>#include <asm/kbio.h>#include <asm/vuid_event.h>#include <asm/delay.h>#include <asm/bitops.h>#include <asm/oplib.h>#include "../../char/kbd_kern.h"#include "../../char/diacr.h"#include "../../char/vt_kern.h"#define SIZE(x) (sizeof(x)/sizeof((x)[0]))/* Define this one if you are making a new frame buffer driver *//* it will not block the keyboard *//* #define CODING_NEW_DRIVER *//* KBD device number, temporal */#define KBD_MAJOR 11#define KBD_REPORT_ERR#define KBD_REPORT_UNKN#ifndef KBD_DEFMODE#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))#endif#ifndef KBD_DEFLEDS/* * Some laptops take the 789uiojklm,. keys as number pad when NumLock * is on. This seems a good reason to start with NumLock off. */#define KBD_DEFLEDS 0#endif#ifndef KBD_DEFLOCK#define KBD_DEFLOCK 0#endifextern void poke_blanked_console(void);extern void ctrl_alt_del(void);extern void reset_vc(unsigned int new_console);extern void scrollback(int);extern void scrollfront(int);unsigned char kbd_read_mask = 0x01; /* modified by psaux.c *//* * global state includes the following, and various static variables * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. * (last_console is now a global variable) *//* shift state counters.. */static unsigned char k_down[NR_SHIFT] = {0, };/* keyboard key bitmap */#define BITS_PER_LONG (8*sizeof(unsigned long))static unsigned long key_down[256/BITS_PER_LONG] = { 0, };void push_kbd (int scan);int kbd_redirected = 0;static int dead_key_next = 0;/* * In order to retrieve the shift_state (for the mouse server), either * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. *//*static*/ int shift_state = 0;static int npadch = -1; /* -1 or number assembled on pad */static unsigned char diacr = 0;static char rep = 0; /* flag telling character repeat */struct kbd_struct kbd_table[MAX_NR_CONSOLES];static struct tty_struct **ttytab;static struct kbd_struct * kbd = kbd_table;static struct tty_struct * tty = NULL;extern void compute_shiftstate(void);typedef void (*k_hand)(unsigned char value, char up_flag);typedef void (k_handfn)(unsigned char value, char up_flag);static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_ignore;static k_hand key_handler[16] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_ignore, do_ignore, do_ignore, do_ignore};typedef void (*void_fnp)(void);typedef void (void_fn)(void);static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, decr_console, incr_console, spawn_console, bare_num;static void_fnp spec_fn_table[] = { do_null, enter, show_ptregs, show_mem, show_state, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, decr_console, incr_console, spawn_console, bare_num};/* maximum values each key_handler can handle */const int max_vals[] = { 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 255};const int NR_TYPES = SIZE(max_vals);static void put_queue(int);static unsigned char handle_diacr(unsigned char);/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */static struct pt_regs * pt_regs;volatile unsigned char sunkbd_layout;volatile unsigned char sunkbd_type;#define SUNKBD_TYPE2 0x02#define SUNKBD_TYPE3 0x03#define SUNKBD_TYPE4 0x04#define SUNKBD_LOUT_TYP4 0x00#define SUNKBD_LOUT_TYP5 0x22volatile int kbd_reset_pending;volatile int kbd_layout_pending;/* commands */#define SKBDCMD_RESET 0x1#define SKBDCMD_GLAYOUT 0xf#define SKBDCMD_BELLON 0x2#define SKBDCMD_BELLOFF 0x3#define SKBDCMD_SETLED 0xe#define SKBDCMD_NOCLICK 0xb#define SKBDCMD_CLICK 0xastatic unsigned char sunkbd_clickp;/* The led set commands require sending the SETLED byte then * a byte encoding which led's to have set. Here are the bit * values, a bit set = led-on. */#define LED_NLOCK 0x1 /* Num-lock */#define LED_CMPOSE 0x2 /* Compose */#define LED_SCRLCK 0x4 /* Scroll-lock */#define LED_CLOCK 0x8 /* Caps-lock *//* Special state characters */#define SKBD_RESET 0xff#define SKBD_ALLUP 0x7f#define SKBD_LYOUT 0xfe/* On the Sparc the keyboard could be one of two things. * It could be a real keyboard speaking over one of the * channels of the second zs8530 chip (other channel is * used by the Sun mouse). Else we have serial console * going, and thus the other zs8530 chip is who we speak * to. Either way, we communicate through the zs8530 * driver for all our I/O. */#define SUNKBD_UBIT 0x80 /* If set, key went up */#define SUNKBD_KMASK 0x7f /* Other bits are the keycode */#define KEY_LSHIFT 0x81#define KEY_RSHIFT 0x82#define KEY_CONTROL 0x83#define KEY_NILL 0x84#define KEY_CAPSLOCK 0x85#define KEY_ALT 0x86#define KEY_L1 0x87extern void kbd_put_char(unsigned char ch);static inline void send_cmd(unsigned char c){ kbd_put_char(c);}/* kbd_bh() calls this to send the SKBDCMD_SETLED to the sun keyboard * with the proper bit pattern for the leds to be set. It basically * converts the kbd->ledflagstate values to corresponding sun kbd led * bit value. */static inline unsigned char vcleds_to_sunkbd(unsigned char vcleds){ unsigned char retval = 0; if(vcleds & (1<<VC_SCROLLOCK)) retval |= LED_SCRLCK; if(vcleds & (1<<VC_NUMLOCK)) retval |= LED_NLOCK; if(vcleds & (1<<VC_CAPSLOCK)) retval |= LED_CLOCK; return retval;}/* * Translation of escaped scancodes to keycodes. * This is now user-settable. * The keycodes 1-88,96-111,119 are fairly standard, and * should probably not be changed - changing might confuse X. * X also interprets scancode 0x5d (KEY_Begin). * * For 1-88 keycode equals scancode. */#define E0_KPENTER 96#define E0_RCTRL 97#define E0_KPSLASH 98#define E0_PRSCR 99#define E0_RALT 100#define E0_BREAK 101 /* (control-pause) */#define E0_HOME 102#define E0_UP 103#define E0_PGUP 104#define E0_LEFT 105#define E0_RIGHT 106#define E0_END 107#define E0_DOWN 108#define E0_PGDN 109#define E0_INS 110#define E0_DEL 111#define E1_PAUSE 119/* * The keycodes below are randomly located in 89-95,112-118,120-127. * They could be thrown away (and all occurrences below replaced by 0), * but that would force many users to use the `setkeycodes' utility, where * they needed not before. It does not matter that there are duplicates, as * long as no duplication occurs for any single keyboard. */#define SC_LIM 89#define FOCUS_PF1 85 /* actual code! */#define FOCUS_PF2 89#define FOCUS_PF3 90#define FOCUS_PF4 91#define FOCUS_PF5 92#define FOCUS_PF6 93#define FOCUS_PF7 94#define FOCUS_PF8 95#define FOCUS_PF9 120#define FOCUS_PF10 121#define FOCUS_PF11 122#define FOCUS_PF12 123#define JAP_86 124/* tfj@olivia.ping.dk: * The four keys are located over the numeric keypad, and are * labelled A1-A4. It's an rc930 keyboard, from * Regnecentralen/RC International, Now ICL. * Scancodes: 59, 5a, 5b, 5c. */#define RGN1 124#define RGN2 125#define RGN3 126#define RGN4 127static unsigned char high_keys[128 - SC_LIM] = { RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */};/* BTC */#define E0_MACRO 112/* LK450 */#define E0_F13 113#define E0_F14 114#define E0_HELP 115#define E0_DO 116#define E0_F17 117#define E0_KPMINPLUS 118/* * My OmniKey generates e0 4c for the "OMNI" key and the * right alt key does nada. [kkoller@nyx10.cs.du.edu] */#define E0_OK 124/* * New microsoft keyboard is rumoured to have * e0 5b (left window button), e0 5c (right window button), * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] * [or: Windows_L, Windows_R, TaskMan] */#define E0_MSLW 125#define E0_MSRW 126#define E0_MSTM 127static unsigned char e0_keys[128] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */};int setkeycode(unsigned int scancode, unsigned int keycode){ if (scancode < SC_LIM || scancode > 255 || keycode > 127) return -EINVAL; if (scancode < 128) high_keys[scancode - SC_LIM] = keycode; else e0_keys[scancode - 128] = keycode; return 0;}int getkeycode(unsigned int scancode){ return (scancode < SC_LIM || scancode > 255) ? -EINVAL : (scancode < 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];}void sunkbd_inchar(unsigned char ch, unsigned char status, struct pt_regs *regs);static void keyboard_timer (unsigned long ignored);static struct timer_listauto_repeat_timer = { NULL, NULL, 0, 0, keyboard_timer };/* Keeps track of the last pressed key */static unsigned char last_keycode;static voidkeyboard_timer (unsigned long ignored){ unsigned long flags; save_flags(flags); cli(); /* Auto repeat: send regs = 0 to indicate autorepeat */ sunkbd_inchar (last_keycode, 0, 0); del_timer (&auto_repeat_timer); auto_repeat_timer.expires = jiffies + HZ/20; add_timer (&auto_repeat_timer); restore_flags(flags);}/* #define SKBD_DEBUG *//* This is our keyboard 'interrupt' routine. */void sunkbd_inchar(unsigned char ch, unsigned char status, struct pt_regs *regs){ unsigned char keycode; char up_flag; /* 0 or SUNKBD_UBIT */ char raw_mode; if(ch == SKBD_RESET) { kbd_reset_pending = 1; return; } if(ch == SKBD_LYOUT) { kbd_layout_pending = 1; return; } if(kbd_reset_pending) { sunkbd_type = ch; kbd_reset_pending = 0; if(ch == SUNKBD_TYPE4) send_cmd(SKBDCMD_GLAYOUT); return; } else if(kbd_layout_pending) { sunkbd_layout = ch; kbd_layout_pending = 0; return; } else if(ch == SKBD_ALLUP) { /* eat it */ return; }#ifdef SKBD_DEBUG if(ch == 0x7f) printk("KBD<ALL KEYS UP>"); else printk("KBD<%x %s>", ch, ((ch&0x80) ? "UP" : "DOWN"));#endif /* Whee, a real character. */ if (regs){ pt_regs = regs; last_keycode = keycode = ch; } else keycode = ch; mark_bh(KEYBOARD_BH); do_poke_blanked_console = 1; mark_bh(CONSOLE_BH); kbd = kbd_table + fg_console; tty = ttytab[fg_console]; if((raw_mode = (kbd->kbdmode == VC_RAW))) { if (kbd_redirected == fg_console+1) push_kbd (keycode); else put_queue(keycode); /* we do not return yet, because we want to maintain * the key_down array, so that we have the correct * values when finishing RAW mode or when changing VT's. */ } up_flag = (keycode & SUNKBD_UBIT); /* The 'up' bit */ keycode &= SUNKBD_KMASK; /* all the rest */ del_timer (&auto_repeat_timer); if(up_flag) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -