📄 vtswitch.c
字号:
#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <sys/ioctl.h>//#include <linux/vt.h>#include <assert.h># include <syslog.h>#include "native.h"#include "fb.h"static int vtswitch_initialised = 0;static struct vt_mode startup_vtmode;volatile int switching_blocked = 0;volatile static int console_active = 1; /* are we active? */volatile static int console_should_be_active = 1; /* should we be? */static int ttyfd = -1; /* /dev/tty0*/static int current_vt;static void vt_switch_requested(int signo);static void poll_console_switch (void);static void come_back(void);static void go_away(void);int init_vtswitch(void) { struct sigaction sa; struct vt_mode vtm; struct vt_stat stat; if (vtswitch_initialised) return 0; /* shouldn't happen */ ttyfd = open("/dev/tty", O_RDONLY); if(ttyfd == -1) { fprintf(stderr,"Error can't open tty: %m\n"); return -1; } ioctl(ttyfd, VT_GETSTATE, &stat); current_vt = stat.v_active; console_active = console_should_be_active = 1; /* Hook the signals */ sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGIO); /* block async IO during the VT switch */ sa.sa_flags = 0; sa.sa_handler = vt_switch_requested; if ((sigaction(SIGRELVT, &sa, NULL) < 0) || (sigaction(SIGACQVT, &sa, NULL) < 0)) { fprintf(stderr,"init_vtswitch:Unable to control VT switch"); return -1; } /* Save old mode, take control, and arrange for the signals * to be raised. */ ioctl(ttyfd, VT_GETMODE, &startup_vtmode); vtm = startup_vtmode; vtm.mode = VT_PROCESS; vtm.relsig = SIGRELVT; vtm.acqsig = SIGACQVT; ioctl(ttyfd, VT_SETMODE, &vtm); vtswitch_initialised = 1; return 0;}/* vt_switch_requested: * This is our signal handler; it gets called whenever a switch is * requested, because either SIGRELVT or SIGACQVT is raised. */static void vt_switch_requested(int signo){ syslog(LOG_INFO,"vt_switch_requested:Here I am called!signo:%d",signo); switch (signo) { case SIGRELVT: console_should_be_active = 0; break; case SIGACQVT: console_should_be_active = 1; break; default: return; } poll_console_switch();}/* poll_console_switch: * Checks whether a switch is needed and not blocked; if so, * makes the switch. */static void poll_console_switch (void){ if (console_active == console_should_be_active) return; if (switching_blocked) return; switching_blocked++; if (console_should_be_active) come_back(); else go_away();}/* come_back: * Performs a switch back. */static void come_back(void){ int i;#if 0 _sigalrm_disable_interrupts(); if (gfx_driver && gfx_driver->restore_video_state) gfx_driver->restore_video_state(); _restore_switch_state(); ioctl(__al_linux_console_fd, VT_RELDISP, VT_ACKACQ); console_active = 1; __al_linux_enable_standard_driver(STD_KBD); __al_linux_enable_standard_driver(STD_MOUSE); _sigalrm_enable_interrupts(); for (i=0; i<MAX_SWITCH_CALLBACKS; i++) if (switch_in_cb[i]) switch_in_cb[i](); __al_linux_switching_blocked--;#endif }/* go_away: * Performs a switch away. */static void go_away(void){ int i; syslog(LOG_INFO,"go_away():Here I am called!");#if 0 for (i=0; i<MAX_SWITCH_CALLBACKS; i++) if (switch_out_cb[i]) switch_out_cb[i](); _sigalrm_disable_interrupts(); if ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA)) _sigalrm_pause(); /* Disable input devices while we're away */ __al_linux_disable_standard_driver(STD_MOUSE); __al_linux_disable_standard_driver(STD_KBD); _save_switch_state(switch_mode); if (gfx_driver && gfx_driver->save_video_state) gfx_driver->save_video_state(); ioctl (__al_linux_console_fd, VT_RELDISP, 1); console_active = 0; __al_linux_switching_blocked--; if ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA)) { __al_linux_wait_for_display(); _sigalrm_unpause(); } _sigalrm_enable_interrupts();#endif}/* done_vtswitch: * Undoes the effect of `init_vtswitch'. */int done_vtswitch(void){ struct sigaction sa; if (!vtswitch_initialised) return 0; /* shouldn't really happen either */ /* !trout gfoot. Must turn off the signals before unhooking them... */ ioctl(ttyfd, VT_SETMODE, &startup_vtmode); sigemptyset (&sa.sa_mask); sa.sa_handler = SIG_DFL; sa.sa_flags = SA_RESTART; sigaction (SIGRELVT, &sa, NULL); sigaction (SIGACQVT, &sa, NULL); vtswitch_initialised = 0; if(ttyfd != -1) close(ttyfd); return 0;}int vtswitch_try(int vt) { if(vt == current_vt) return 1; syslog(LOG_INFO,"vtswitch_try:%d",vt); assert ((vt <= 6) && (vt >= 0)); syslog(LOG_INFO,"vtswitch_try1:%d",vt); ioctl(ttyfd, VT_ACTIVATE, vt); syslog(LOG_INFO,"vtswitch_try2:%d",vt); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -