# Keyboard input settings



## ekvz (Aug 29, 2020)

Hi, i wonder if there is maybe different ways i could access my keyboard in X. I am thinking of something like different drivers or maybe even different layers of the input system. In short: Are there any obvious plugs and switches i could try if my keyboard is misbehaving?


----------



## chrbr (Aug 30, 2020)

I am not sure if this answers your question. You can use x11/xev to see which key generates which output. With x11/xmodmap and x11/xkbset you can change the assignment and tweak the behaviour.


----------



## ekvz (Aug 30, 2020)

chrbr said:


> I am not sure if this answers your question. You can use x11/xev to see which key generates which output. With x11/xmodmap and x11/xkbset you can change the assignment and tweak the behaviour.



Not exactly what i was looking for (i am dealing with some kind of conflict in regards to the input device i think which leads to the CPU spiking on one core and the keyboard becoming unresponsive once a key is pressed) but it's still interesting. Who knows, maybe it actually generates events even if they don't have any obvious visible effect.

On this issue in general: By now i have more or less accepted that what i am trying to do might not work exactly the way i want it but i think i might have figured out a workaround. Obviously i'd still like to go the original route so if anyone else has more recommendations on how to debug/alternate keyboard input settings in X i am all ears.


----------



## Mjölnir (Aug 30, 2020)

Please describe your problem?


----------



## ekvz (Aug 30, 2020)

Your are right, my question has practically zero context. So here it is:

It's again related to me trying to force X the run on predefined VTs. I did a lot of testing during the last days and it seems the reason for the unresponsive keyboard when starting X on a VT also used by getty is a conflict on reading from the underlying device since i actually managed to get it to work when i closed the stdin file descriptor on the target VT but i am still stuck on trying to get X to run on the VT where the startx command was issued. Simply closing stdin (or just about any combination of descriptors) before running startx doesn't seem to cut it and the result is always the same: X starts and the mouse works but as soon as you hit a key 1 core (at last it very much looks like it from the CPUmeter on my desktop) spikes to 100% but the keys don't work. To me it seems like there is some relation between the keyboard input in X and whatever other process uses the VT for input. Now i am not very good with X and it's configuration but if there was any kind of other method for X to access the keyboard it would be at least worth a try to see if this (hypothetical) other method might somehow bypass whatever makes the default method fail.


----------



## Mjölnir (Aug 30, 2020)

This may be completely wrong, I'm not a developer: Well, I see it this way: the data from any HID is routed to the active VT (/etc/ttys(5)).  Thus, the getty(8) on that line receives it.  There is no provision for X11 to receive the input from HID on a VT that is already "occupied" by a _getty_.


----------



## ekvz (Aug 30, 2020)

mjollnir said:


> This may be completely wrong, I'm not a developer: Well, I see it this way: the data from any HID is routed to the active VT (/etc/ttys(5)).  Thus, the getty(8) on that line receives it.  There is no provision for X11 to receive the input from HID on a VT that is already "occupied" by a _getty_.



That makes sense. It's also reinforced in that when i close the X Server with the non responsive keyboard there is garbage in whatever listened for input on the target VT. My line of (maybe wishful) thinking was that X might have the ability to use a keyboard driver that fetched the data on a lower level thereby bypassing the read routines of getty (or the shell started from there via login). What throws me off is the spiking CPU. "Something" obviously notices the keystroke and acts in a way that goes beyond simply not passing data to X.


----------



## mickey (Aug 30, 2020)

ekvz said:


> It's again related to me trying to force X the run on predefined VTs. I did a lot of testing during the last days and it seems the reason for the unresponsive keyboard when starting X on a VT also used by getty is a conflict on reading from the underlying device ...


Why would you even *want* to do that, and why do you expect any different outcome when two things are competing for the same resource?

From syscons(4):

```
Note that the X server usually requires a virtual terminal for display
     purposes, so at least one terminal must be left unused by getty(8) so
     that it can be used by the X server.
```


----------



## ekvz (Aug 30, 2020)

mickey said:


> Why would you even *want* to do that, and why do you expect any different outcome when two things are competing for the same resource?



As i already explained elsewhere i want to recreate my usual setup of running multiple X servers in different terminals. If the terminal is used for X or textmode is chosen at login. It's what i am used to. While i am not exactly expecting it i hope to be able to get it to work since, well, i have this working in another system. I am fully prepared for having to adapt it since another OS might require me to jump through different hoops. May it be actively detaching the competing part, using an alternative way of retrieving data or some actual coding. Of course failure is a potential outcome too.



mickey said:


> From syscons(4):
> 
> ```
> Note that the X server usually requires a virtual terminal for display
> ...



Reality isn't as absolute as the quote makes it seem. X works perfectly fine on a VT managed by getty as long you open a shell and run something like `sleep 9999 0<&-` which as i understand it resolves the conflict by closing the input descriptor. I just can't seem to find a way (maybe be because this really is impossible - i don't know) to do this for the terminal where `startx` is executed. Combined these findings point at a workaround though. It's just a little annoying and i don't have the time to code it right now so i figured why not check if there is an easier option elsewhere (as in some potential input method i don't know about that sidesteps the issue).


----------



## mickey (Aug 31, 2020)

You might want to check out `X -help` for some commandline options not documented in Xserver(1), in particular:

```
-novtswitch            don't automatically switch VT at reset & exit
-sharevts              share VTs with another X server
vtXX                   use the specified VT number (1-12)
-keeptty               don't detach controlling tty (for debugging only)
```
Also consider writing a custom startup script that uses `exec xinit [opts] -- [serveropts]` as it's last line to replace the shell process.


----------



## ekvz (Aug 31, 2020)

Cool, thanks! I actually haven't seen two of these options before (i'm obviously already using vtXX to target specific VTs and also found -novtswitch somewhere which is sadly not particularly helpful - it just keeps X from switching to the targeted VT and back again once it exits). -sharevts and -keeptty seem quite interesting though. While both are probably not even remotely intended for my usecase they might actually have some sideeffect that could very well be useful. Especially -keeptty since i was under the impression startx would not detach anyways which could easily be integral here.

As for directly executing xinit: I am not entirely sure. It's been a long time since i wrote my old scripts but i vaguely remember that doing so instead of using startx required some additional setup concerning xauth which i couldn't quite figure out (or at least wasn't sure if i was doing the right thing). I'll give it a try though. I also agree that using exec is very much the way to go here. On one hand having a shell hang around that would do nothing but exit once returned to is simply bad style and on the other it's probably best to have the least possible amount of processes running that could even just theoretically interfere.


----------



## mickey (Aug 31, 2020)

This here looks quite similar to what you are trying to accomplish, don't you think?


----------



## ekvz (Aug 31, 2020)

mickey said:


> This here looks quite similar to what you are trying to accomplish, don't you think?



It pretty much does even if in detail the author came to a somewhat different solution than i did. The thing is that it's targeting Linux which is also where i wrote my original scripts and there it's pretty much a no brainer (as in you use the vtXX parameter after figuring out the current VT and it just works). The main differences being him using `tty` where i used `fgconsole` and `xinit` vs. `startx`. As for his problems with consolekit: None of my systems run consolekit (or any *kit, logind, dbus, and so on) so i've (obviously) never had them. It's still quite interesting to see that -keeptty actually seems to have useful effects way beyond being a debug option. I am sadly quite busy right now but i will definitely give this a try once i have some open space for experimentation.


----------



## Mjölnir (Aug 31, 2020)

If you want to start X11 from the 1st VT /dev/ttyv0, keep in mind that by default in syslog.conf(5):
`*.err;kern.warning;auth.notice;mail.crit                /dev/console`
& that might interfere.  So you might want to change that to write to /var/log/console.log instead, and if you use x11/xconsole, start it with the `-file /var/log/console.log` switch.
In newsyslog.conf(5): `/var/log/console.log    root:operator   640  5     1000 *     J`
In devfs.conf(5):

```
# Allow members of group operator to read the system console
own  console root:operator
perm console 0640
```
& `service devfs restart`.  Maybe `conscontrol mute on` or use it to redirect messages to another VT.


----------



## mickey (Aug 31, 2020)

ekvz said:


> The main differences being him using `tty` where i used `fgconsole` and `xinit` vs. `startx`.


`startx` is just a somewhat more user-friendly frontend to `xinit` and also a shell script by itself, so feel free to copy&paste whatever you need from `startx` to a custom script. I'd say invoking `xinit` via `exec` alone could make a difference, and if that doesn't suffice, there's still some flags to play around with.



mjollnir said:


> If you want to start X11 from the 1st VT /dev/ttyv0, keep in mind that by default in syslog.conf(5):
> `*.err;kern.warning;auth.notice;mail.crit                /dev/console`
> & that might interfere.


For that exact reason I always set the first VT to not run a getty(8) in /etc/ttys, so that it just displays the console log but has no login capabilities:

```
ttyv0   "/usr/libexec/getty Pc"         xterm   off  secure
```


----------



## Mjölnir (Aug 31, 2020)

mickey said:


> For that exact reason I always set the first VT to not run a getty(8) in /etc/ttys, so that it just displays the console log but has no login capabilities:
> `ttyv0   "/usr/libexec/getty Pc"         xterm   off  secure`


That's dangerous: e.g. when your keyboard's ALT, CTRL and/or function keys got messed up, you can not switch the VT.  Admittedly, that happens seldomly, but we all believe in _Murphy's Law_, right?


----------



## mickey (Aug 31, 2020)

mjollnir said:


> That's dangerous: e.g. when your keyboard's ALT, CTRL and/or function keys got messed up, you can not switch the VT.  Admittedly, that happens seldomly, but we all believe in _Murphy's Law_, right?


I believe in IBM buckling spring keyboards, manufactured ~1988, there is no such thing as messed up keys


----------



## ekvz (Sep 9, 2020)

mickey said:


> You might want to check out `X -help` for some commandline options not documented in Xserver(1), in particular:
> 
> ```
> -novtswitch            don't automatically switch VT at reset & exit
> ...



Just got around to try it but sadly the hope i had put into `-keeptty` has been disappointed. The behavior stays the same (keyboard input results in 1 core spiking to 100% and nothing happening). I've noticed some other details though. As i had already mentioned before X happily uses VTs where a shell is running as long as something like `sleep 9999 0<&-` is currently executed there. Concerning this i made the following observations:

If no `sleep` is running in the shell that is occupying the target VT the characteristic CPU spike that happens with targeting the terminal where `startx` is being excuted doesn't happen and X is not fully unresponsive to keyboard input (it will eventually recognize a keypress but miss the keyup resulting in the key "hanging" and being repeated indefinitely).
While i had attributed the positive effect of the sleep command to the input redirection part closing stdin that doesn't seem to actually be the case. Just running `sleep 9999` with no redirection at all is enough to make X work on the target VT.
Using `xinit` does not seem to make any noticeable difference to using `startx`.
Neither does using exec up until the point where `startx` / `xinit` becomes a direct child of `login` (i might still try to replace login and thereby making it become a child to `init` but i somewhat doubt that to make a huge difference).
I have also experimented with running a background task to launch X while having the shell execute the otherwise magic `sleep 9999` but it won't help. Something is clearly special about launching X to run on the current VT but i can't figure out what it is.
I am pretty much at loss here. It really doesn't seem to make sense why targeting a VT with an active shell would work just because of running a simple `sleep 9999` while targeting the VT where X was started from breaks. As i said above i will likely try to also replace the login process but i don't see any logic why that could help eliminating whatever breaks the keyboard input.

Mentally i am already preparing to whip up some suid code that will put `startx` / `xinit` on an unused VT which (while kinda ugly) would according to my observations up to this point likely work around the problem. I am still puzzled as to why this issue exists in the first place and i am also quite sure there would be a cleaner solution but for now i just want to have this working so i can move on with setting up my desktop. I will update this topic when i have settled with something.


----------



## Mjölnir (Sep 9, 2020)

Doesn't X11 use the 1st unused VT by default?  Maybe additionally there's a minimum VT number hardcoded somewhere (e.g. in the display manager).


----------



## ekvz (Sep 9, 2020)

mjollnir said:


> Doesn't X11 use the 1st unused VT by default?



Yes, it does. I am overriding this behavior by using the `vtX` switch.



mjollnir said:


> Maybe additionally there's a minimum VT number hardcoded somewhere (e.g. in the display manager).



I don't think so. I am not even using a display manager and starting X on VT1 works perfectly fine (if the appropriate precautions are taken - i.e. `sleep 9999`). To archive this it just can't be started from VT1. The same happens for all the other VTs. For some bizarre reason starting X on a random VT works even if a shell is running there as long as it isn't actively waiting for input. One would think that to be the case for the shell that executes `startx` / `initx` pretty much automatically but in reality it obviously isn't.


----------



## mickey (Sep 9, 2020)

ekvz said:


> I don't think so. I am not even using a display manager and starting X on VT1 works perfectly fine (if the appropriate precautions are taken - i.e. `sleep 9999`). To archive this it just can't be started from VT1. The same happens for all the other VTs. For some bizarre reason starting X on a random VT works even if a shell is running there as long as it isn't actively waiting for input. One would think that to be the case for the shell that executes `startx` / `initx` pretty much automatically but in reality it obviously isn't.


Have you played around with _kern.evdev.rcpt_mask_ already? The switch to evdev/libinput unfortunately left more than just a few broken eggs in it's path. Although most issues seem to have been ironed out now. As keyboard input seems to be the culprit, it's also thinkable that kbdmux(4) has something to do with it. By default _kern.evdev.rcpt_mask_ is set up to use kbdmux(4) and sysmouse(4). You could try setting _kern.evdev.rcpt_mask_ to a value of 12 (0x0C) in /etc/sysctl.conf to use hardware keyboard and hardware mouse instead, to see if it makes any difference in regards to the problem.

From /usr/src/sys/dev/evdev/evdev.h:

```
/*
 * Keyboard and mouse events recipient mask.
 * evdev_rcpt_mask variable should be respected by keyboard and mouse drivers
 * that are able to send events through both evdev and sysmouse/kbdmux
 * interfaces so user can choose prefered one to not receive one event twice.
 */
#define EVDEV_RCPT_SYSMOUSE     (1<<0)
#define EVDEV_RCPT_KBDMUX       (1<<1)
#define EVDEV_RCPT_HW_MOUSE     (1<<2)
#define EVDEV_RCPT_HW_KBD       (1<<3)
extern int evdev_rcpt_mask;
```


----------



## ekvz (Sep 9, 2020)

mickey said:


> Have you played around with _kern.evdev.rcpt_mask_ already? The switch to evdev/libinput unfortunately left more than just a few broken eggs in it's path. Although most issues seem to have been ironed out now. As keyboard input seems to be the culprit, it's also thinkable that kbdmux(4) has something to do with it. By default _kern.evdev.rcpt_mask_ is set up to use kbdmux(4) and sysmouse(4). You could try setting _kern.evdev.rcpt_mask_ to a value of 12 (0x0C) in /etc/sysctl.conf to use hardware keyboard and hardware mouse instead, to see if it makes any difference in regards to the problem.
> 
> From /usr/src/sys/dev/evdev/evdev.h:
> 
> ...



Thanks for the sugesstion. I wouldn't have known about this otherwise. Sadly it doesn't help. Starting X on the current VT still ends with 1 core spiking to 100% as soon as any key is pressed while no input is being registered.


----------



## Mjölnir (Sep 10, 2020)

Since you're still into this, why not consider to contact the respective wizzard/developer(s) via a mailing list and/or on IRC?


----------



## ekvz (Sep 10, 2020)

mjollnir said:


> Since you're still into this, why not consider to contact the respective wizzard/developer(s) via a mailing list and/or on IRC?



I might if "project DIY" fails. I am quite positive this is fixable in an ugly but pragmatic manner. Actually i wanted to get this done yesterday but then `doas` came around and required me to update my port collection (DOAS_USER working is essential unless i want to code it in C or switch to `sudo`). Really getting to the root of this is likely to require more time than i have patience for right now. So while i'd love to have a clean solution i'll have to postpone it and go for "at least it works" first.

Edit: Did a quick and dirty test with updated doas. Seems to work nicely. I'll update this thread later with an explanation how it's possible work around the keyboard issue. Sadly gotta run now.


----------



## ekvz (Sep 10, 2020)

OK, since all obvious sane solutions have failed this is what i am going to use until i have the nerve to investigate further:

It is assumed that sysutils/open (*not* suid root) and security/doas (pretty recent version with working _DOAS_USER_ environment variable) are installed. When these requirements are met the following script can be used to start a fully working X session on the current VT.


```
#!/bin/sh

exec open -w -- su "$DOAS_USER" -c "exec startx /usr/local/lib/y/x11/session -- -keeptty vt$( vidcontrol -i active )"
```

I call it _/usr/local/lib/y/x11/launch_ on my system. _/usr/local/lib/y/x11/session_ obviously has to be replaced with whatever initializes your X session and the whole thing needs to be executable as root without needing a password which can be archieved with a _doas.conf_ (suid won't work with shell scripts) somewhat like this:


```
permit nopass :mygroup as root cmd /usr/local/lib/y/x11/launch
```

Your user accounts that should be able to use this obviously have to be members of _mygroup_ though.

While this works it is an extremely ugly hack (this also inflates the process tree by 2 processes that are basically wrappers and can't be exec'd away - `open` and `su`) and i also noticed the following: If `doas /usr/local/lib/y/x11/launch` is executed from a shell without `exec` there will be garbage in said shell when the X session is closed. X is working flawlessly though. It's also not important for my usecase as execing the doas line ends up at a login prompt after X has exited with no side effects at all and that's basically how i'll use it just that the shell won't be executed to begin with. It's still kinda strange to see this behavior and it reminds one how sub optimal this whole approach is. In any case it works and that's all i care for right now as i want to continue setting up my desktop. Maybe i'll investigate this further at some later point.


----------

