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

📄 kbd_ttyscan.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
 *
 * Microwindows /dev/tty console scancode keyboard driver for Linux
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <linux/keyboard.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include "device.h"
#include "fb.h"

#define KEYBOARD	"/dev/tty"	/* console kbd to open*/

static int  TTY_Open(KBDDEVICE *pkd);
static void TTY_Close(void);
static void TTY_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers);
static int  TTY_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *scancode);

KBDDEVICE kbddev = {
	TTY_Open,
	TTY_Close,
	TTY_GetModifierInfo,
	TTY_Read,
	NULL
};

#define RELEASED	0
#define PRESSED		1

static	int		fd;		/* file descriptor for keyboard */
static	struct termios	old;		/* original terminal modes */
static  int 		old_kbd_mode;
static unsigned char 	key_state[MWKEY_LAST];	/* FIXME - make sparse array */
static MWKEYMOD 	key_modstate;

/* kernel unicode tables per shiftstate and scancode*/
#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)	/* kernel key maps*/
static unsigned short	os_keymap[NUM_VGAKEYMAPS][NR_KEYS];

/* PC scancode -> Microwindows key value mapping for non-Linux kernel values*/
static MWKEY		keymap[128] = {
MWKEY_UNKNOWN, MWKEY_ESCAPE, '1', '2', '3',				/* 0*/
'4', '5', '6', '7', '8',						/* 5*/
'9', '0', '-', '=', MWKEY_BACKSPACE,					/* 10*/
MWKEY_TAB, 'q', 'w', 'e', 'r',						/* 15*/
't', 'y', 'u', 'i', 'o',						/* 20*/
'o', '[', ']', MWKEY_ENTER, MWKEY_LCTRL,				/* 25*/
'a', 's', 'd', 'f', 'g',						/* 30*/
'h', 'j', 'k', 'l', ';',						/* 35*/
'\'', '`', MWKEY_LSHIFT, '\\', 'z',					/* 40*/
'x', 'c', 'v', 'b', 'n',						/* 45*/
'm', ',', '.', '/', MWKEY_RSHIFT,					/* 50*/
MWKEY_KP_MULTIPLY, MWKEY_LALT, ' ', MWKEY_CAPSLOCK, MWKEY_F1, 		/* 55*/
MWKEY_F2, MWKEY_F3, MWKEY_F4, MWKEY_F5, MWKEY_F6, 			/* 60*/
MWKEY_F7, MWKEY_F8, MWKEY_F9, MWKEY_F10, MWKEY_NUMLOCK, 		/* 65*/
MWKEY_SCROLLOCK, MWKEY_KP7, MWKEY_KP8, MWKEY_KP9, MWKEY_KP_MINUS,	/* 70*/
MWKEY_KP4, MWKEY_KP5, MWKEY_KP6, MWKEY_KP_PLUS, MWKEY_KP1, 		/* 75*/
MWKEY_KP2, MWKEY_KP3, MWKEY_KP0, MWKEY_KP_PERIOD, MWKEY_UNKNOWN, 	/* 80*/
MWKEY_UNKNOWN, MWKEY_UNKNOWN, MWKEY_F11, MWKEY_F12, MWKEY_UNKNOWN,	/* 85*/
MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,	/* 90*/
MWKEY_UNKNOWN, MWKEY_KP_ENTER, MWKEY_RCTRL, MWKEY_KP_DIVIDE,MWKEY_PRINT,/* 95*/
MWKEY_RALT, MWKEY_BREAK, MWKEY_HOME, MWKEY_UP, MWKEY_PAGEUP,		/* 100*/
MWKEY_LEFT, MWKEY_RIGHT, MWKEY_END, MWKEY_DOWN, MWKEY_PAGEDOWN,		/* 105*/
MWKEY_INSERT, MWKEY_DELETE, MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,	/* 110*/
MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_PAUSE,	/* 115*/
MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,MWKEY_UNKNOWN,	/* 120*/
MWKEY_LMETA, MWKEY_RMETA, MWKEY_MENU					/* 125*/
};

static MWBOOL	UpdateKeyState(int pressed, MWKEY mwkey);
static void	UpdateLEDState(MWKEYMOD modstate);
static MWKEY	TranslateScancode(int scancode, MWKEYMOD modstate);
static void	LoadKernelKeymaps(int fd);
static MWBOOL	switch_vt(unsigned short which);

/*
 * Open the keyboard.
 * This is real simple, we just use a special file handle
 * that allows non-blocking I/O, and put the terminal into
 * character mode.
 */
static int
TTY_Open(KBDDEVICE *pkd)
{
  char *env;

	int		i;
	int		ledstate = 0;
	struct termios	new;

	/* Open "CONSOLE" or /dev/tty device*/
	if(!(env = getenv("CONSOLE")))
		fd = open(KEYBOARD, O_NONBLOCK);
	else
		fd = open(env, O_NONBLOCK);
	if (fd < 0)
		return -1;

	/* Save previous settings*/
	if (ioctl(fd, KDGKBMODE, &old_kbd_mode) < 0) {
		perror("KDGKMODE");
		goto err;
	}
	if (tcgetattr(fd, &old) < 0)
		goto err;

	/* Set medium-raw keyboard mode */
	new = old;
	/* ISIG and BRKINT must be set otherwise '2' is ^C (scancode 3)!!*/
	new.c_lflag &= ~(ICANON | ECHO | ISIG);
	new.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON 
			| BRKINT);
	new.c_cc[VMIN] = 0;
	new.c_cc[VTIME] = 0;

	if (tcsetattr(fd, TCSAFLUSH, &new) < 0) {
		TTY_Close();
		return -1;
	}
	if (ioctl(fd, KDSKBMODE, K_MEDIUMRAW) < 0) {
		TTY_Close();
		return -1;
	}

	/* Load OS keymappings*/
	LoadKernelKeymaps(fd);

	/* Initialize keyboard state*/
	key_modstate = MWKMOD_NONE;
	for (i=0; i<MWKEY_LAST; ++i)
		key_state[i] = RELEASED;
	
	/* preset CAPSLOCK and NUMLOCK from startup LED state*/
	if (ioctl(fd, KDGETLED, &ledstate) == 0) {
		if (ledstate & LED_CAP) {
			key_modstate |= MWKMOD_CAPS;
			key_state[MWKEY_CAPSLOCK] = PRESSED;
		}
		if (ledstate & LED_NUM) {
			key_modstate |= MWKMOD_NUM;
			key_state[MWKEY_NUMLOCK] = PRESSED;
		}
	}
	UpdateLEDState(key_modstate);

	return fd;

err:
	close(fd);
	fd = -1;
	return -1;
}

/*
 * Close the keyboard.
 * This resets the terminal modes.
 */
static void
TTY_Close(void)
{
	int	ledstate = 0x80000000L;

	if (fd >= 0) {
		/* revert LEDs to follow key modifiers*/
		if (ioctl(fd, KDSETLED, ledstate) < 0)
			perror("KDSETLED");

		/* reset terminal mode*/
		if (ioctl(fd, KDSKBMODE, old_kbd_mode) < 0)
			perror("KDSKBMODE");
		tcsetattr(fd, TCSAFLUSH, &old);

		close(fd);
	}
	fd = -1;
}

/*
 * Return the possible modifiers and current modifiers for the keyboard.
 */
static  void
TTY_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers)
{
	if (modifiers)
		*modifiers = MWKMOD_CTRL | MWKMOD_SHIFT | MWKMOD_ALT |
			MWKMOD_META | MWKMOD_ALTGR | MWKMOD_CAPS | MWKMOD_NUM;
	if (curmodifiers)
		*curmodifiers = key_modstate;
}

/*
 * This reads one keystroke from the keyboard, and the current state of
 * the modifier keys (ALT, SHIFT, etc).  Returns -1 on error, 0 if no data
 * is ready, 1 on a keypress, and 2 on keyrelease.
 * This is a non-blocking call.
 */
static int
TTY_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *pscancode)
{
	int	cc;			/* characters read */
	int 	pressed;
	int 	scancode;
	MWKEY	mwkey;
	unsigned char buf[128];

	cc = read(fd, buf, 1);
	if (cc > 0) {
		pressed = (*buf & 0x80) ? RELEASED: PRESSED;
		scancode = *buf & 0x7f;
		mwkey = keymap[scancode];

		/**if(pressed) {
			printf("scan %02x really: %08x\n", *buf&0x7F, *buf);
			printf("mwkey: %02x (%c)\n", mwkey, mwkey);
		}**/

		/* Handle Alt-FN for vt switch */
		switch (mwkey) {
		case MWKEY_F1:
		case MWKEY_F2:
		case MWKEY_F3:
		case MWKEY_F4:
		case MWKEY_F5:
		case MWKEY_F6:
		case MWKEY_F7:
		case MWKEY_F8:
		case MWKEY_F9:
		case MWKEY_F10:
		case MWKEY_F11:
		case MWKEY_F12:
			if (key_modstate & MWKMOD_ALT) {
				if (switch_vt(mwkey-MWKEY_F1+1)) {
					mwkey = MWKEY_REDRAW;
				}
			}
			break;
			/* Fall through to normal processing */
		default:
			/* update internal key states*/
			if (!UpdateKeyState(pressed, mwkey))
				return 0;

			/* mwkey is 0 if only a modifier is hit */
			if(mwkey != MWKEY_LCTRL && 
			   mwkey != MWKEY_RCTRL &&
			   mwkey != MWKEY_LALT &&
			   mwkey != MWKEY_RALT &&
			   mwkey != MWKEY_RSHIFT &&
			   mwkey != MWKEY_LSHIFT) {
				/* translate scancode to key value*/
				mwkey = TranslateScancode(scancode, key_modstate);
			} else {
				//printf("Modifier only\n");
				//mwkey = 0;
			}
			
			/* XXX Hack to get scancodes to come out the same as 
			   everything else */
			switch(scancode) {
				case 0x1:           /* esc 		*/

				case 0x29:          /* `		*/
				case 0x2  ... 0xe:  /* 1 - BackSpace 	*/

				case 0xf  ... 0x1b: /* TAB - ] 		*/
				case 0x2b:          /* \		*/

				case 0x3a:	    /* Caps-Lock	*/
				case 0x1e ... 0x28: /* a - '		*/
				case 0x1c:          /* Enter		*/

				case 0x2a:          /* LShift		*/
				case 0x2c ... 0x35: /* z - /		*/
				case 0x36:          /* RShift		*/

				case 0x1d:          /* LCtrl		*/
				//case 0x7d:          /* LWin		*/
				case 0x38:          /* LAlt		*/
				case 0x39:          /* Space		*/
				//case 0x64:          /* RAlt		*/
				//case 0x7e:          /* RWin		*/
				//case 0x7f:          /* Win-PopupMenu	*/
				//case 0x61:          /* RCtrl		*/

				//case 0x63:          /* SysReq		*/
				//case 0x46:          /* Scroll Lock	*/
				//case 0x77:          /* Pause/Break	*/
					scancode += 8;
					break;

				case 0x6e:            /* Insert		*/
					scancode -= 0x4;
					break;
				case 0x66:            /* Home		*/

⌨️ 快捷键说明

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