⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sunkbd.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* keyboard.c: Sun keyboard driver. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) * * Added vuid event generation and /dev/kbd device for SunOS * compatibility - Miguel (miguel@nuclecu.unam.mx) * * Added PCI 8042 controller support -DaveM * Added Magic SysRq support -MJ */#include <linux/config.h>#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 <linux/poll.h>#include <linux/random.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/sysrq.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <linux/devfs_fs_kernel.h>#include <asm/kbio.h>#include <asm/vuid_event.h>#include <asm/bitops.h>#include <asm/oplib.h>#include <asm/uaccess.h>#include <linux/kbd_kern.h>#include <linux/kbd_diacr.h>#include <linux/vt_kern.h>#ifdef CONFIG_PCI#include <linux/pci.h>#include <asm/pbm.h>#include <asm/ebus.h>#endif#include "sunkbd.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);struct l1a_kbd_state l1a_state;#ifndef CONFIG_PCIDECLARE_WAIT_QUEUE_HEAD(keypress_wait);#endifint keyboard_wait_for_keypress(struct console *co){	sleep_on(&keypress_wait);	return 0;}static spinlock_t sunkbd_lock = SPIN_LOCK_UNLOCKED;/* * global state includes the following, and various static variables * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. * (last_console is now a global variable) *//* shift state counters.. */static unsigned char k_down[NR_SHIFT];/* keyboard key bitmap */static unsigned long key_down[256/BITS_PER_LONG];void push_kbd (int scan);int kbd_redirected;static int dead_key_next;/*  * In order to retrieve the shift_state (for the mouse server), either * the variable must be global, or a new procedure must be created to  * return the value. I chose the former way. */#ifndef CONFIG_PCI/*static*/ int shift_state;#endifstatic int npadch = -1;			/* -1 or number assembled on pad */static unsigned char diacr;static char rep;			/* flag telling character repeat */struct kbd_struct kbd_table[MAX_NR_CONSOLES];static struct tty_struct **ttytab;static struct kbd_struct * kbd = kbd_table;static struct tty_struct * tty;static int compose_led_on;static int kbd_delay_ticks = HZ / 5;static int kbd_rate_ticks = HZ / 20;void sun_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 */#ifndef CONFIG_PCIconst int max_vals[] = {	255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,	NR_DEAD - 1, 255, 3, NR_SHIFT - 1,	255, NR_ASCII - 1, NR_LOCK - 1, 255,	NR_LOCK - 1};const int NR_TYPES = SIZE(max_vals);#endifstatic 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;#ifdef CONFIG_MAGIC_SYSRQunsigned char sun_sysrq_xlate[128] =	"\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0"	/* 0x00 - 0x0f */	"\207\210\211\0\0\0\0\0\0\0\0\0\0\03312"		/* 0x10 - 0x1f */	"34567890-=`\177\0=/*"					/* 0x20 - 0x2f */	"\0\0.\0\0\011qwertyuiop"				/* 0x30 - 0x3f */	"[]\177\000789-\0\0\0\0\0asd"				/* 0x40 - 0x4f */	"fghjkl;'\\\015\0154560\0"				/* 0x50 - 0x5f */	"\0\0\0\0zxcvbnm,./\0\012"				/* 0x60 - 0x6f */	"123\0\0\0\0\0\0 \0\0\0\0\0\0";				/* 0x70 - 0x7f */#endifvolatile 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_MASK   0x20volatile 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          0x87/* Due to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing: * *	tasklet_enable(&keyboard_tasklet); *	tasklet_schedule(&keyboard_tasklet); * * this might well be called before some driver has claimed interest in * handling the keyboard input/output. So we need to assign an initial nop. */static void nop_kbd_put_char(unsigned char c) { }static void (*kbd_put_char)(unsigned char) = nop_kbd_put_char;/* Must be invoked under sunkbd_lock. */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;	if(compose_led_on)		retval |= LED_CMPOSE;	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 */};/* we use this map to determine if a particular key should not be   autorepeated. We don't autorepeat CONTROL, LSHIFT, CAPS,   ALT, LMETA, RSHIFT, RMETA, ALTG and COMPOSE */static unsigned char norepeat_keys[128] = {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,  /* 0x00-0x0f */	0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x10-0x1f */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x20-0x2f */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x30-0x3f */	0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,  /* 0x40-0x4f */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x50-0x5f */	0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,  /* 0x60-0x6f */	0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0,  /* 0x70-0x7f */};int sun_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 sun_getkeycode(unsigned int scancode){	return	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :	  (scancode < 128) ? high_keys[scancode - SC_LIM] :	    e0_keys[scancode - 128];}static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs);void sunkbd_inchar(unsigned char ch, struct pt_regs *regs);static void keyboard_timer (unsigned long ignored);static struct timer_listauto_repeat_timer = { function: keyboard_timer };/* Keeps track of the last pressed key */static unsigned char last_keycode;static voidkeyboard_timer (unsigned long ignored){	unsigned long flags;	spin_lock_irqsave(&sunkbd_lock, flags);	/* Auto repeat: send regs = 0 to indicate autorepeat */	__sunkbd_inchar (last_keycode, 0);	del_timer (&auto_repeat_timer);	if (kbd_rate_ticks) {		auto_repeat_timer.expires = jiffies + kbd_rate_ticks;		add_timer (&auto_repeat_timer);	}	spin_unlock_irqrestore(&sunkbd_lock, flags);}#ifndef CONFIG_PCIDECLARE_TASKLET_DISABLED(keyboard_tasklet, sun_kbd_bh, 0);#endif/* #define SKBD_DEBUG *//* This is our keyboard 'interrupt' routine. * Must run under sunkbd_lock. */static void __sunkbd_inchar(unsigned char ch, 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;		goto out;	}	if(ch == SKBD_LYOUT) {		kbd_layout_pending = 1;		goto out;	}	if(kbd_reset_pending) {		sunkbd_type = ch;		kbd_reset_pending = 0;		if(ch == SUNKBD_TYPE4)			send_cmd(SKBDCMD_GLAYOUT);		goto out;	} else if(kbd_layout_pending) {		sunkbd_layout = ch;		kbd_layout_pending = 0;		goto out;	} else if(ch == SKBD_ALLUP) {		del_timer (&auto_repeat_timer);		memset(key_down, 0, sizeof(key_down));		sun_compute_shiftstate();		goto out;	}#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;	}		do_poke_blanked_console = 1;	tasklet_schedule(&console_tasklet);	add_keyboard_randomness(keycode);	tty = ttytab? ttytab[fg_console]: NULL;	if (tty && (!tty->driver_data)) {		/* This is to workaround ugly bug in tty_io.c, which                   does not do locking when it should */		tty = NULL;	}	kbd = kbd_table + 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) {		rep = 0;		clear_bit(keycode, key_down);	} else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -