188 lines
5.5 KiB
Diff
188 lines
5.5 KiB
Diff
|
From f5660f60455d2a86fd78d5a8949a31864233faf8 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
|
||
|
Date: Mon, 24 Sep 2012 07:58:29 +0300
|
||
|
Subject: [PATCH 05/12] fbsplash: support console switching
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
|
||
|
---
|
||
|
miscutils/fbsplash.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||
|
1 file changed, 76 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
|
||
|
index fc6c9b953..ec5947314 100644
|
||
|
--- a/miscutils/fbsplash.c
|
||
|
+++ b/miscutils/fbsplash.c
|
||
|
@@ -47,7 +47,7 @@
|
||
|
//kbuild:lib-$(CONFIG_FBSPLASH) += fbsplash.o
|
||
|
|
||
|
//usage:#define fbsplash_trivial_usage
|
||
|
-//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]"
|
||
|
+//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD] [-T tty]"
|
||
|
//usage:#define fbsplash_full_usage "\n\n"
|
||
|
//usage: " -s Image"
|
||
|
//usage: "\n -c Hide cursor"
|
||
|
@@ -57,11 +57,17 @@
|
||
|
//usage: "\n BAR_R,BAR_G,BAR_B"
|
||
|
//usage: "\n -f Control pipe (else exit after drawing image)"
|
||
|
//usage: "\n commands: 'NN' (% for progress bar) or 'exit'"
|
||
|
+//usage: "\n -T Switch to TTY to hide all console messages"
|
||
|
|
||
|
#include "libbb.h"
|
||
|
#include "common_bufsiz.h"
|
||
|
#include <linux/fb.h>
|
||
|
|
||
|
+#include <sys/vt.h>
|
||
|
+#include <sys/ioctl.h>
|
||
|
+#include <linux/tiocl.h>
|
||
|
+#include <linux/kd.h>
|
||
|
+
|
||
|
/* If you want logging messages on /tmp/fbsplash.log... */
|
||
|
#define DEBUG 0
|
||
|
|
||
|
@@ -73,6 +79,8 @@ struct globals {
|
||
|
unsigned char *addr; // pointer to framebuffer memory
|
||
|
unsigned ns[7]; // n-parameters
|
||
|
const char *image_filename;
|
||
|
+ int silent_tty, fd_tty_s;
|
||
|
+ bool do_not_draw;
|
||
|
struct fb_var_screeninfo scr_var;
|
||
|
struct fb_fix_screeninfo scr_fix;
|
||
|
unsigned bytes_per_pixel;
|
||
|
@@ -483,6 +491,11 @@ static void init(const char *cfg_filename)
|
||
|
config_close(parser);
|
||
|
}
|
||
|
|
||
|
+static void sighandler(int sig)
|
||
|
+{
|
||
|
+ ioctl(G.fd_tty_s, VT_RELDISP, sig == SIGUSR1 ? 1 : 2);
|
||
|
+ G.do_not_draw = (sig != SIGUSR2);
|
||
|
+}
|
||
|
|
||
|
int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||
|
int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
@@ -492,6 +505,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
char *num_buf;
|
||
|
unsigned num;
|
||
|
bool bCursorOff;
|
||
|
+ int fd_tty0, active_vt;
|
||
|
+ struct vt_stat vtstat;
|
||
|
+ struct vt_mode vt;
|
||
|
|
||
|
INIT_G();
|
||
|
|
||
|
@@ -499,8 +515,10 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
fb_device = "/dev/fb0";
|
||
|
cfg_filename = NULL;
|
||
|
fifo_filename = NULL;
|
||
|
- bCursorOff = 1 & getopt32(argv, "cs:d:i:f:",
|
||
|
- &G.image_filename, &fb_device, &cfg_filename, &fifo_filename);
|
||
|
+ opt_complementary = "T+"; // numeric params
|
||
|
+ bCursorOff = 1 & getopt32(argv, "cs:d:i:f:T:",
|
||
|
+ &G.image_filename, &fb_device, &cfg_filename, &fifo_filename,
|
||
|
+ &G.silent_tty);
|
||
|
|
||
|
// parse configuration file
|
||
|
if (cfg_filename)
|
||
|
@@ -510,11 +528,43 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
if (!G.image_filename)
|
||
|
bb_show_usage();
|
||
|
|
||
|
+ fd_tty0 = get_console_fd_or_die();
|
||
|
+ if (G.silent_tty) {
|
||
|
+ char buf[16];
|
||
|
+
|
||
|
+ /* Initialize TTY */
|
||
|
+ bb_signals((1LL << SIGUSR1) | (1LL << SIGUSR2), sighandler);
|
||
|
+ snprintf(buf, sizeof(buf), "/dev/tty%d", G.silent_tty);
|
||
|
+ G.fd_tty_s = xopen(buf, O_RDWR | O_NOCTTY);
|
||
|
+
|
||
|
+ /* Activate TTY */
|
||
|
+ xioctl(fd_tty0, VT_GETSTATE, &vtstat);
|
||
|
+ active_vt = vtstat.v_active;
|
||
|
+ console_make_active(fd_tty0, G.silent_tty);
|
||
|
+
|
||
|
+ /* Get notifications on console changes */
|
||
|
+ vt.mode = VT_PROCESS;
|
||
|
+ vt.waitv = 0;
|
||
|
+ vt.relsig = SIGUSR1;
|
||
|
+ vt.acqsig = SIGUSR2;
|
||
|
+ ioctl(G.fd_tty_s, VT_SETMODE, &vt);
|
||
|
+
|
||
|
+ /* Redirect all kernel messages to tty1 so that they don't get
|
||
|
+ * printed over our silent splash image. And clear it. */
|
||
|
+ buf[0] = TIOCL_SETKMSGREDIRECT;
|
||
|
+ buf[1] = 1;
|
||
|
+ ioctl(G.fd_tty_s, TIOCLINUX, buf);
|
||
|
+ full_write(G.fd_tty_s, "\e[H\e[2J" "\e[?17;0c", 7+8);
|
||
|
+ ioctl(G.fd_tty_s, KDSETMODE, KD_GRAPHICS);
|
||
|
+ } else {
|
||
|
+ G.fd_tty_s = STDOUT_FILENO;
|
||
|
+ }
|
||
|
+
|
||
|
fb_open(fb_device);
|
||
|
|
||
|
if (fifo_filename && bCursorOff) {
|
||
|
// hide cursor (BEFORE any fb ops)
|
||
|
- full_write(STDOUT_FILENO, "\033[?25l", 6);
|
||
|
+ full_write(G.fd_tty_s, "\033[?25l", 6);
|
||
|
}
|
||
|
|
||
|
fb_drawimage();
|
||
|
@@ -522,6 +572,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
if (!fifo_filename)
|
||
|
return EXIT_SUCCESS;
|
||
|
|
||
|
+ sig_block(SIGUSR1);
|
||
|
fp = xfopen_stdin(fifo_filename);
|
||
|
if (fp != stdin) {
|
||
|
// For named pipes, we want to support this:
|
||
|
@@ -537,8 +588,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
// and become an additional writer :)
|
||
|
open(fifo_filename, O_WRONLY); // errors are ignored
|
||
|
}
|
||
|
-
|
||
|
fb_drawprogressbar(0);
|
||
|
+ sig_unblock(SIGUSR1);
|
||
|
+
|
||
|
// Block on read, waiting for some input.
|
||
|
// Use of <stdio.h> style I/O allows to correctly
|
||
|
// handle a case when we have many buffered lines
|
||
|
@@ -553,12 +605,29 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv)
|
||
|
#if DEBUG
|
||
|
DEBUG_MESSAGE(itoa(num));
|
||
|
#endif
|
||
|
- fb_drawprogressbar(num);
|
||
|
+ sig_block(SIGUSR1);
|
||
|
+ if (!G.do_not_draw)
|
||
|
+ fb_drawprogressbar(num);
|
||
|
+ sig_unblock(SIGUSR1);
|
||
|
}
|
||
|
free(num_buf);
|
||
|
}
|
||
|
|
||
|
- if (bCursorOff) // restore cursor
|
||
|
+ if (G.silent_tty) {
|
||
|
+ usleep(100*1000);
|
||
|
+
|
||
|
+ ioctl(G.fd_tty_s, VT_RELDISP, 1);
|
||
|
+ ioctl(G.fd_tty_s, KDSETMODE, KD_TEXT);
|
||
|
+ vt.mode = VT_AUTO;
|
||
|
+ vt.waitv = 0;
|
||
|
+ ioctl(G.fd_tty_s, VT_SETMODE, &vt);
|
||
|
+ close(G.fd_tty_s);
|
||
|
+
|
||
|
+ xioctl(fd_tty0, VT_GETSTATE, &vtstat);
|
||
|
+ if (vtstat.v_active == G.silent_tty)
|
||
|
+ console_make_active(fd_tty0, active_vt);
|
||
|
+ ioctl(fd_tty0, VT_DISALLOCATE, (void *)(ptrdiff_t)G.silent_tty);
|
||
|
+ } else if (bCursorOff) // restore cursor
|
||
|
full_write(STDOUT_FILENO, "\033[?25h", 6);
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
--
|
||
|
2.11.0
|
||
|
|