2

I'm working with an nVidia card and multiple monitors, and the monitor that is used by default for text mode is in portrait mode, forcing me to crane my head to the side to use it when I switch to a console. How can I switch the default text mode monitor to one of the other connected monitors? Switching the cables around on the card isn't an option.

Tano
  • 214

1 Answers1

0

You can move a specific VT to another head with con2fb (source code, also in the first link, and also also below, in case those links evaporate). Then you use con2fb /dev/fb1 /dev/tty2 to move TTY2 to the second framebuffer.

The possible drawback to this is that the old monitor (your portrait monitor, in this case), doesn't accept input any more. That said, I'm not sure how one would shift focus between terminals without using something like Alt+F1 or Ctrl+Alt+F1, so this is a pretty minor drawback.

See also: LinuxQuestions and LWN, which, despite their age, are also attempts to answer this question (also here in case the first link goes away). The LWN post threatens dire warnings if you try to run X after doing this, but it also discusses that the multiple framebuffer patches aren't in the kernel yet, so it's somewhat out of date.

con2fb.c:

/* This is a userspace utility which allows you to redirect the console to
another framebuffer device.  You can specify devices & consoles by both numbers
and devices.  Framebuffers numbers are zero-based (/dev/fb0, ...), while
consoles are one-based (/dev/tty1, ...).

Original source: https://www.dafyddcrosby.com/dual-framebuffers/   
Slightly updated from the original by Ben Stern to fix some minor warnings.
License: GPL v2.  Compile with: gcc -O2 -Wall -Werror -o con2fb con2fb.c */

#include <errno.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    struct fb_con2fbmap c2m;
    char* fbPath;
    u_int32_t con, fb;
    char* e;
    char* progname;
    struct stat sbf;
    int rv = 0;
    int f = -1;

    progname = strrchr(argv[0], '/');

    if (progname != NULL) {
        progname++;
    } else {
        progname = argv[0];
    }
    if (argc < 3) {
        fprintf(stderr, "usage: %s fbdev console\n", progname);
        return ENOENT;
    }

    do {
        fb = strtoul(argv[1], &e, 10);
        if (*e) {
            if (stat(argv[1], &sbf) < 0) {      
                rv = errno;
                fprintf(stderr, "%s: Can't stat %s: %s\n",
                    progname, argv[1], strerror(errno));
                break;
            }

            if (!S_ISCHR(sbf.st_mode)) {
                fprintf(stderr, "%s: %s isn't a character device!\n",
                    progname, argv[1]);
                rv = EINVAL;
                break;
            }

            fb = sbf.st_rdev & 0xFF;
            if (fb >= 32) {
                fb >>= 5;
            }
            fbPath = argv[1];
        } else  {
            fbPath = "/dev/fb0";
        }

        con = strtoul(argv[2], &e, 10);
        if (*e) {
            if (stat(argv[2], &sbf) < 0) {
                rv = errno;
                fprintf(stderr, "%s: Can't stat %s: %s\n",
                    progname, argv[2], strerror(errno));
                break;
            }
            if (!S_ISCHR(sbf.st_mode)) {
                fprintf(stderr, "%s: %s isn't a character device!\n",
                    progname, argv[2]);
                rv = EINVAL;
                break;
            }
            con = sbf.st_rdev & 0xFF;
        }

        c2m.console = con;
        c2m.framebuffer = fb;
        f = open(fbPath, O_RDWR);
        if (f < 0) {
            rv = errno;
            fprintf(stderr, "%s: Can't open %s: %s\n",
                progname, fbPath, strerror(errno));
            break;
        }

        if (ioctl(f, FBIOPUT_CON2FBMAP, &c2m)) {
            rv = errno;
            fprintf(stderr, "%s: Can't set console mapping: %s\n",
                progname, strerror(errno));
            break;
        }
    } while (0);

    if (f >= 0) {
        close(f);
    }
    return rv;
}
Ben Stern
  • 101