input, fb, vt, sysfs: the kernel calls Xorg makes

Xorg on a framebuffer -- the fbdev video driver, the evdev input driver,
libpciaccess -- asks the kernel a fixed set of questions before it draws
anything, and gives up on the first wrong answer. These are those
answers.

evdev: EVIOCGVERSION, GID, GNAME, GPHYS, GUNIQ, GPROP, GBIT, GKEY, GABS,
GREP and the accepted setters. Xorg and libinput decide what a device
*is* from the capability bitmaps; /dev/input/eventN answered only
EVIOCGRAB, which reads as no device at all. Each device's bitmaps are
its defaults plus whatever it has reported, so a USB tablet makes the
pointer absolute.

fbdev: FBIOPUT_VSCREENINFO succeeds for the mode already set, as on
Linux -- the fbdev driver sets it every time it starts -- and still
refuses any other. FBIOPAN_DISPLAY to the origin; FBIOBLANK.

The console: KDSETMODE(KD_GRAPHICS) stops it drawing on a terminal,
KDSKBMODE(K_OFF) stops keys reaching its tty, and VT_PROCESS now does
the switch handshake: leaving the terminal sends relsig and waits for
VT_RELDISP, arriving sends acqsig. A terminal whose owner has died goes
back to the kernel whole, so a crashed X cannot leave the console dead.

/sys: boot_vga, a writable enable, and graphics/fb0 under the display
device, which is how the fbdev driver pairs a card with /dev/fb0.

ports/linux-headers: <linux/*.h> into musl's prefix, from sabotage-
linux's kernel-headers 4.19.88-2. Its checksum is recorded from the
first download; upstream publishes none.

cmd/xready makes each call and checks the answer, including the switch
handshake on tty2 and an owner that dies holding it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-24 12:06:04 +02:00
commit b1323e193a
14 changed files with 860 additions and 32 deletions

View file

@ -189,14 +189,47 @@ fb_ioctl(int request, addr_t arg)
return 0;
}
// The mode came from the bootloader's VBE call and we have no way to
// change it. Saying so is more useful than accepting the request and
// leaving the caller to discover, by drawing, that nothing happened.
case FBIOPUT_VSCREENINFO:
return -EINVAL;
// The mode came from the loader and there is no way to change it. A
// request for a *different* one is refused, which is more useful than
// accepting it and leaving the caller to discover by drawing that nothing
// happened. A request for the mode already set succeeds and is answered
// with it, as on Linux: Xorg's fbdev driver sets the mode it was just told
// about, every time it starts, and gives up if that fails.
case FBIOPUT_VSCREENINFO: {
struct fb_var_screeninfo *v =
(struct fb_var_screeninfo *)user_ptr(arg, sizeof(*v));
if (!v)
return -EFAULT;
if (v->xres != (unsigned int)w || v->yres != (unsigned int)h ||
(v->bits_per_pixel && v->bits_per_pixel != (unsigned int)gfx_fb_bpp()) ||
(v->xres_virtual && v->xres_virtual != (unsigned int)w) ||
(v->yres_virtual && v->yres_virtual != (unsigned int)h))
return -EINVAL;
unsigned int act = v->activate;
memset(v, 0, sizeof(*v));
v->xres = v->xres_virtual = (unsigned int)w;
v->yres = v->yres_virtual = (unsigned int)h;
v->bits_per_pixel = gfx_fb_bpp();
v->activate = act;
pixel_format(v, v->bits_per_pixel);
return 0;
}
// One screen-sized buffer, so the only pan there is is to the origin.
case FBIOPAN_DISPLAY: {
struct fb_var_screeninfo *v =
(struct fb_var_screeninfo *)user_ptr(arg, sizeof(*v));
if (!v)
return -EFAULT;
return (v->xoffset || v->yoffset) ? -EINVAL : 0;
}
// Blanking is a screen saver's request, and saying no makes Xorg log a
// warning every time one starts. There is no power control behind the
// framebuffer, so unblanking is all that can honestly succeed -- and
// blanking does too, as Linux's own drivers without the hook do.
case FBIOBLANK:
return -EINVAL;
return 0;
}
return -ENOTTY;