pm.c
来自「适合KS8695X」· C语言 代码 · 共 1,810 行 · 第 1/4 页
C
1,810 行
ioctl(_PM_console_fd, KDSKBMODE, mode.kb_mode);
ioctl(_PM_console_fd, KDSETLED, mode.leds);
tcsetattr(_PM_console_fd, TCSAFLUSH, &mode.termios);
fcntl(_PM_console_fd,F_SETFL,mode.flags);
}
fclose(kbmode);
unlink(path);
in_raw_mode = false;
}
}
/****************************************************************************
REMARKS:
Safely abort the event module upon catching a fatal error.
****************************************************************************/
void _PM_abort(
int signo)
{
char buf[80];
sprintf(buf,"Terminating on signal %d",signo);
_PM_restore_kb_mode();
PM_fatalError(buf);
}
/****************************************************************************
REMARKS:
Put the keyboard into raw mode
****************************************************************************/
void _PM_keyboard_rawmode(void)
{
struct termios conf;
FILE *kbmode;
keyboard_mode mode;
char path[PM_MAX_PATH];
int i;
static int sig_list[] = {
SIGHUP,
SIGINT,
SIGQUIT,
SIGILL,
SIGTRAP,
SIGABRT,
SIGIOT,
SIGBUS,
SIGFPE,
SIGKILL,
SIGSEGV,
SIGTERM,
};
if ((kbmode = open_kb_mode("rb",path)) == NULL) {
if ((kbmode = open_kb_mode("wb",path)) == NULL)
PM_fatalError("Unable to open kbmode.dat file for writing!");
if (ioctl(_PM_console_fd, KDGKBMODE, &mode.kb_mode))
perror("KDGKBMODE");
ioctl(_PM_console_fd, KDGETLED, &mode.leds);
_PM_leds = mode.leds & 0xF;
_PM_modifiers = 0;
tcgetattr(_PM_console_fd, &mode.termios);
conf = mode.termios;
conf.c_lflag &= ~(ICANON | ECHO | ISIG);
conf.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF);
conf.c_iflag |= (IGNBRK | IGNPAR);
conf.c_cc[VMIN] = 1;
conf.c_cc[VTIME] = 0;
conf.c_cc[VSUSP] = 0;
tcsetattr(_PM_console_fd, TCSAFLUSH, &conf);
mode.flags = fcntl(_PM_console_fd,F_GETFL);
if (ioctl(_PM_console_fd, KDSKBMODE, K_MEDIUMRAW))
perror("KDSKBMODE");
atexit(_PM_restore_kb_mode);
for (i = 0; i < sizeof(sig_list)/sizeof(sig_list[0]); i++)
signal(sig_list[i], _PM_abort);
mode.startup_vc = startup_vc;
if (fwrite(&mode,1,sizeof(mode),kbmode) != sizeof(mode))
PM_fatalError("Error writing kbmode.dat!");
fclose(kbmode);
in_raw_mode = true;
}
}
int PMAPI PM_kbhit(void)
{
fd_set s;
struct timeval tv = { 0, 0 };
if (console_count == 0)
PM_fatalError("You *must* open a console before using PM_kbhit!");
if (!in_raw_mode)
_PM_keyboard_rawmode();
FD_ZERO(&s);
FD_SET(_PM_console_fd, &s);
return select(_PM_console_fd+1, &s, NULL, NULL, &tv) > 0;
}
int PMAPI PM_getch(void)
{
static uchar c;
int release;
static struct kbentry ke;
if (console_count == 0)
PM_fatalError("You *must* open a console before using PM_getch!");
if (!in_raw_mode)
_PM_keyboard_rawmode();
while (read(_PM_console_fd, &c, 1) > 0) {
release = c & 0x80;
c &= 0x7F;
if (release) {
switch(c){
case 42: case 54: /* Shift */
_PM_modifiers &= ~KB_SHIFT;
break;
case 29: case 97: /* Control */
_PM_modifiers &= ~KB_CONTROL;
break;
case 56: case 100: /* Alt / AltGr */
_PM_modifiers &= ~KB_ALT;
break;
}
continue;
}
switch (c) {
case 42: case 54: /* Shift */
_PM_modifiers |= KB_SHIFT;
break;
case 29: case 97: /* Control */
_PM_modifiers |= KB_CONTROL;
break;
case 56: case 100: /* Alt / AltGr */
_PM_modifiers |= KB_ALT;
break;
case 58: /* Caps Lock */
_PM_modifiers ^= KB_CAPS;
ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7);
break;
case 69: /* Num Lock */
_PM_modifiers ^= KB_NUMLOCK;
ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7);
break;
case 70: /* Scroll Lock */
_PM_modifiers ^= KB_SCROLL;
ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7);
break;
case 28:
return 0x1C;
default:
ke.kb_index = c;
ke.kb_table = 0;
if ((_PM_modifiers & KB_SHIFT) || (_PM_modifiers & KB_CAPS))
ke.kb_table |= K_SHIFTTAB;
if (_PM_modifiers & KB_ALT)
ke.kb_table |= K_ALTTAB;
ioctl(_PM_console_fd, KDGKBENT, (ulong)&ke);
c = ke.kb_value & 0xFF;
return c;
}
}
return 0;
}
/****************************************************************************
REMARKS:
Sleep until the virtual terminal is active
****************************************************************************/
static void wait_vt_active(
int _PM_console_fd)
{
while (ioctl(_PM_console_fd, VT_WAITACTIVE, tty_vc) < 0) {
if ((errno != EAGAIN) && (errno != EINTR)) {
perror("ioctl(VT_WAITACTIVE)");
exit(1);
}
usleep(150000);
}
}
/****************************************************************************
REMARKS:
Checks the owner of the specified virtual console.
****************************************************************************/
static int check_owner(
int vc)
{
struct stat sbuf;
char fname[30];
sprintf(fname, "/dev/tty%d", vc);
if ((stat(fname, &sbuf) >= 0) && (getuid() == sbuf.st_uid))
return 1;
printf("You must be the owner of the current console to use this program.\n");
return 0;
}
/****************************************************************************
REMARKS:
Checks if the console is currently in graphics mode, and if so we forcibly
restore it back to text mode again. This handles the case when a Nucleus or
MGL program crashes and leaves the console in graphics mode. Running the
textmode utility (or any other Nucleus/MGL program) via a telnet session
into the machine will restore it back to normal.
****************************************************************************/
static void restore_text_console(
int console_id)
{
if (ioctl(console_id, KDSETMODE, KD_TEXT) < 0)
LOGWARN("ioctl(KDSETMODE) failed");
_PM_restore_kb_mode();
}
/****************************************************************************
REMARKS:
Opens up the console device for output by finding an appropriate virutal
console that we can run on.
****************************************************************************/
PM_HWND PMAPI PM_openConsole(
PM_HWND hwndUser,
int device,
int xRes,
int yRes,
int bpp,
ibool fullScreen)
{
struct vt_mode vtm;
struct vt_stat vts;
struct stat sbuf;
char fname[30];
/* Check if we have already opened the console */
if (console_count++)
return _PM_console_fd;
/* Now, it would be great if we could use /dev/tty and see what it is
* connected to. Alas, we cannot find out reliably what VC /dev/tty is
* bound to. Thus we parse stdin through stderr for a reliable VC.
*/
startup_vc = 0;
for (_PM_console_fd = 0; _PM_console_fd < 3; _PM_console_fd++) {
if (fstat(_PM_console_fd, &sbuf) < 0)
continue;
if (ioctl(_PM_console_fd, VT_GETMODE, &vtm) < 0)
continue;
if ((sbuf.st_rdev & 0xFF00) != 0x400)
continue;
if (!(sbuf.st_rdev & 0xFF))
continue;
tty_vc = sbuf.st_rdev & 0xFF;
restore_text_console(_PM_console_fd);
return _PM_console_fd;
}
if ((_PM_console_fd = open("/dev/console", O_RDWR)) < 0) {
printf("open_dev_console: can't open /dev/console \n");
exit(1);
}
if (ioctl(_PM_console_fd, VT_OPENQRY, &tty_vc) < 0)
goto Error;
if (tty_vc <= 0)
goto Error;
sprintf(fname, "/dev/tty%d", tty_vc);
close(_PM_console_fd);
/* Change our control terminal */
setsid();
/* We must use RDWR to allow for output... */
if (((_PM_console_fd = open(fname, O_RDWR)) >= 0) &&
(ioctl(_PM_console_fd, VT_GETSTATE, &vts) >= 0)) {
if (!check_owner(vts.v_active))
goto Error;
restore_text_console(_PM_console_fd);
/* Success, redirect all stdios */
fflush(stdin);
fflush(stdout);
fflush(stderr);
close(0);
close(1);
close(2);
dup(_PM_console_fd);
dup(_PM_console_fd);
dup(_PM_console_fd);
/* clear screen and switch to it */
fwrite("\e[H\e[J", 6, 1, stderr);
fflush(stderr);
if (tty_vc != vts.v_active) {
startup_vc = vts.v_active;
ioctl(_PM_console_fd, VT_ACTIVATE, tty_vc);
wait_vt_active(_PM_console_fd);
}
}
return _PM_console_fd;
Error:
if (_PM_console_fd > 2)
close(_PM_console_fd);
console_count = 0;
PM_fatalError(
"Not running in a graphics capable console,\n"
"and unable to find one.\n");
return -1;
}
#define FONT_C 0x10000 /* 64KB for font data */
/****************************************************************************
REMARKS:
Returns the size of the console state buffer.
****************************************************************************/
int PMAPI PM_getConsoleStateSize(void)
{
if (!inited)
PM_init();
return PM_getVGAStateSize() + FONT_C*2;
}
/****************************************************************************
REMARKS:
Save the state of the Linux console.
****************************************************************************/
void PMAPI PM_saveConsoleState(void *stateBuf,int console_id)
{
uchar *regs = stateBuf;
/* Save the current console font */
if (ioctl(console_id,GIO_FONT,®s[PM_getVGAStateSize()]) < 0)
perror("ioctl(GIO_FONT)");
/* Inform the Linux console that we are going into graphics mode */
if (ioctl(console_id, KDSETMODE, KD_GRAPHICS) < 0)
perror("ioctl(KDSETMODE)");
/* Save state of VGA registers */
PM_saveVGAState(stateBuf);
}
void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags))
{
/* TODO: Implement support for allowing console switching! */
}
/****************************************************************************
REMARKS:
Restore the state of the Linux console.
****************************************************************************/
void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND console_id)
{
const uchar *regs = stateBuf;
/* Restore the state of the VGA compatible registers */
PM_restoreVGAState(stateBuf);
/* Inform the Linux console that we are back from graphics modes */
if (ioctl(console_id, KDSETMODE, KD_TEXT) < 0)
LOGWARN("ioctl(KDSETMODE) failed");
/* Restore the old console font */
if (ioctl(console_id,PIO_FONT,®s[PM_getVGAStateSize()]) < 0)
LOGWARN("ioctl(KDSETMODE) failed");
/* Coming back from graphics mode on Linux also restored the previous
* text mode console contents, so we need to clear the screen to get
* around this since the cursor does not get homed by our code.
*/
fflush(stdout);
fflush(stderr);
printf("\033[H\033[J");
fflush(stdout);
}
/****************************************************************************
REMARKS:
Close the Linux console and put it back to normal.
****************************************************************************/
void PMAPI PM_closeConsole(PM_HWND _PM_console_fd)
{
/* Restore console to normal operation */
if (--console_count == 0) {
/* Re-activate the original virtual console */
if (startup_vc > 0)
ioctl(_PM_console_fd, VT_ACTIVATE, startup_vc);
/* Close the console file descriptor */
if (_PM_console_fd > 2)
close(_PM_console_fd);
_PM_console_fd = -1;
}
}
void PM_setOSCursorLocation(int x,int y)
{
/* Nothing to do in here */
}
/****************************************************************************
REMARKS:
Set the screen width and height for the Linux console.
****************************************************************************/
void PM_setOSScreenWidth(int width,int height)
{
struct winsize ws;
struct vt_sizes vs;
/* Resize the software terminal */
ws.ws_col = width;
ws.ws_row = height;
ioctl(_PM_console_fd, TIOCSWINSZ, &ws);
/* And the hardware */
vs.v_rows = height;
vs.v_cols = width;
vs.v_scrollsize = 0;
ioctl(_PM_console_fd, VT_RESIZE, &vs);
}
ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler ih, int frequency)
{
/* TODO: Implement this for Linux */
return false;
}
void PMAPI PM_setRealTimeClockFrequency(int frequency)
{
/* TODO: Implement this for Linux */
}
void PMAPI PM_restoreRealTimeClockHandler(void)
{
/* TODO: Implement this for Linux */
}
char * PMAPI PM_getCurrentPath(
char *path,
int maxLen)
{
return getcwd(path,maxLen);
}
char PMAPI PM_getBootDrive(void)
{ return '/'; }
const char * PMAPI PM_getVBEAFPath(void)
{ return PM_getNucleusConfigPath(); }
const char * PMAPI PM_getNucleusPath(void)
{
char *env = getenv("NUCLEUS_PATH");
return env ? env : "/usr/lib/nucleus";
}
const char * PMAPI PM_getNucleusConfigPath(void)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?