2021-09-17 14:36:25 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright 2021 Johannes Marbach
|
2024-01-12 09:51:43 +01:00
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
2021-09-17 14:36:25 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "terminal.h"
|
|
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
2025-07-03 14:19:10 +00:00
|
|
|
#include <limits.h>
|
2021-09-17 14:36:25 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
#include <linux/kd.h>
|
2021-09-17 14:36:25 +02:00
|
|
|
#include <linux/vt.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Static variables
|
|
|
|
|
*/
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
static int32_t _tty_size;
|
|
|
|
|
static int32_t _h_display_size;
|
|
|
|
|
static int32_t _v_display_size;
|
2021-09-17 14:36:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-03 14:19:10 +00:00
|
|
|
* Public functions
|
2021-09-17 14:36:25 +02:00
|
|
|
*/
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
void bb_terminal_init(int32_t tty_size, int32_t h_display_size, int32_t v_display_size) {
|
|
|
|
|
_tty_size = tty_size;
|
|
|
|
|
_h_display_size = h_display_size;
|
|
|
|
|
_v_display_size = v_display_size;
|
2021-09-17 14:36:25 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
void bb_terminal_shrink_current() {
|
|
|
|
|
int fd = open("/dev/tty0", O_RDONLY|O_NOCTTY);
|
|
|
|
|
if (fd < 0)
|
2021-09-17 14:36:25 +02:00
|
|
|
return;
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
/* KDFONTOP returns EINVAL if we are not in the text mode,
|
|
|
|
|
so we can skip this check */
|
|
|
|
|
/*
|
|
|
|
|
int mode;
|
|
|
|
|
if (ioctl(fd, KDGETMODE, &mode) != 0)
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
|
|
if (mode != KD_TEXT)
|
|
|
|
|
goto end;
|
|
|
|
|
*/
|
|
|
|
|
struct console_font_op cfo = {
|
|
|
|
|
.op = KD_FONT_OP_GET,
|
|
|
|
|
.width = UINT_MAX,
|
|
|
|
|
.height = UINT_MAX,
|
|
|
|
|
.charcount = UINT_MAX,
|
|
|
|
|
.data = NULL
|
|
|
|
|
};
|
|
|
|
|
if (ioctl(fd, KDFONTOP, &cfo) != 0)
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
|
|
struct winsize size;
|
|
|
|
|
size.ws_row = _tty_size / cfo.height;
|
|
|
|
|
size.ws_col = _h_display_size / cfo.width;
|
|
|
|
|
ioctl(fd, TIOCSWINSZ, &size);
|
|
|
|
|
end:
|
|
|
|
|
close(fd);
|
2021-09-17 14:36:25 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
void bb_terminal_reset_all() {
|
|
|
|
|
int fd = open("/dev/tty0", O_RDONLY|O_NOCTTY);
|
|
|
|
|
if (fd < 0)
|
2021-09-17 14:36:25 +02:00
|
|
|
return;
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
struct vt_stat state;
|
|
|
|
|
if (ioctl(fd, VT_GETSTATE, &state) != 0) {
|
|
|
|
|
close(fd);
|
2021-09-17 14:36:25 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
|
|
char buffer[sizeof("/dev/tty") + 2];
|
|
|
|
|
unsigned short mask = state.v_state >> 1;
|
|
|
|
|
unsigned int tty = 1;
|
|
|
|
|
|
|
|
|
|
for (; mask; mask >>= 1, tty++) {
|
|
|
|
|
if (mask & 0x01) {
|
|
|
|
|
sprintf(buffer, "/dev/tty%u", tty);
|
|
|
|
|
int tty_fd = open(buffer, O_RDONLY|O_NOCTTY);
|
|
|
|
|
if (tty_fd < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* KDFONTOP returns EINVAL if we are not in the text mode,
|
|
|
|
|
so we can skip this check */
|
|
|
|
|
/*
|
|
|
|
|
int mode;
|
|
|
|
|
if (ioctl(tty_fd, KDGETMODE, &mode) != 0)
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
|
|
if (mode != KD_TEXT)
|
|
|
|
|
goto end;
|
|
|
|
|
*/
|
|
|
|
|
struct console_font_op cfo = {
|
|
|
|
|
.op = KD_FONT_OP_GET,
|
|
|
|
|
.width = UINT_MAX,
|
|
|
|
|
.height = UINT_MAX,
|
|
|
|
|
.charcount = UINT_MAX,
|
|
|
|
|
.data = NULL
|
|
|
|
|
};
|
|
|
|
|
if (ioctl(tty_fd, KDFONTOP, &cfo) != 0)
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
|
|
struct winsize size;
|
|
|
|
|
size.ws_row = _v_display_size / cfo.height;
|
|
|
|
|
size.ws_col = _h_display_size / cfo.width;
|
|
|
|
|
ioctl(tty_fd, TIOCSWINSZ, &size);
|
|
|
|
|
end:
|
|
|
|
|
close(tty_fd);
|
2021-09-17 14:36:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
bool bb_terminal_is_busy(unsigned int tty) {
|
|
|
|
|
/* We can use any other terminal than `tty` here. */
|
|
|
|
|
int fd = open(tty == 1? "/dev/tty2" : "/dev/tty1", O_RDONLY|O_NOCTTY);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
return false;
|
2021-09-17 14:36:25 +02:00
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
struct vt_stat state;
|
|
|
|
|
int r = ioctl(fd, VT_GETSTATE, &state);
|
2021-09-17 14:36:25 +02:00
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
close(fd);
|
2021-09-17 14:36:25 +02:00
|
|
|
|
2025-07-03 14:19:10 +00:00
|
|
|
if (r != 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return (state.v_state >> tty) & 0x01;
|
2021-09-17 14:36:25 +02:00
|
|
|
}
|