How to read from STDIN_FILENO even if terminal is closed? - linux

Im trying to code a program in Linux to read every input from keyboard, but using STDIN_FILENO it only reads those entered in the terminal. What I want is during execution it should read keyboard even if the terminal is closed.

STDIN_FILENO is just a helper macro.
From stdin you recieve stream of bytes that are passed to your program, they doesnt neccessary come from terminal - also can from a file, etc. It's not capturing keyboard. The terminal is capturing keyboard and then passes entered data to your program's stdin.
In order to capture keyboard you will need some other method of receiving events. I guess you are running GUI aka X server; Normally applications create windows and receive events related to them. In order to capture all keyboard events, you will have to go more low-level. Take a look at xlib which should be sufficient for you, even though it might not be.

Related

Linux program to emulate keystrokes without X

I'm writing a driver for a pda with a goal of converting UART received key numbers to keystrokes.
The way i currently have this system set up is that when a key number is received, i can exec a program. In a config it is defined what command is executed if a certain number is received by my driver. It does this by fork()ing and exec()ing. It runs at boot and immediately parses these key numbers, so i intend to use this instead of a real keyboard.
Is there any program then, with which i could simply do something like
programname KEY_SPACE 1 to press KEY_SPACE
and
programname KEY_SPACE 0 to release KEY_SPACE?
Such a program must work without, as well as with X. I'd also prefer this to be able to do mouse events as well, however if there is a different program to do that, that's fine by me. It can be run as root as well, if need be.
What you need is to use uinput, it allows to emulate input device from userspace. You have documentation here: https://www.kernel.org/doc/html/v5.11/input/uinput.html
It has an example showing how to send a KEY_SPACE press event and then a KEY_SPACE release event.

Unexpected periodic, non-continuous output for OCaml program

Someone reports that given a stream of strings on the serial port which is pipelined to the OCaml program below, the output of the program is not continuous, but instead it appears in chunks (of a few tens of lines), as if buffered.
What can be the cause of the non-continuous output?
(The output buffer should be flushed after each new line due to the use of '%!'. So this shouldn't be the cause, right?)
let tp = ref 0
let get_next_entry ic =
try
let (ts, pred, v) = Scanf.fscanf ic " #%d %s#(%d)\n" (fun x y z -> (x,y,z)) in
Printf.printf "at timepoint %d (timestamp %d): %s(%d)\n%!" !tp ts pred v;
incr tp;
true
with End_of_file ->
false
let _ =
while get_next_entry stdin do
()
done
The OCaml version used is 4.05.
It is a threefold problem. From the least likely to the most likely.
The glitching output
It is all in the eye of the beholder, as how the program output will look like depends on the environment in which it is run, i.e., on a program that runs your program and renders this on a visual device. In other words, it involves a lot of variables that are beyond the context of this program.
With that said, let me explain what flush means for the printf function. The printf facility relies on buffered channels. And each channel is roughly a pair of a buffer and system-specific file descriptor. When someone (including printf) outputs to a channel, the information first goes into the buffer and remains there until the next portion of information overrides the buffer (i.e., there is no more space in the buffer) or until the flush function is called explicitly. Then the buffer is flushed, which means that the information in the buffer is transferred to the operating system (e.g., using the write system call or library function).
What happens afterward is system dependent. If the file descriptor was associated with a regular file, then you might expect that the information will be passed to it entirely(though the file system has its own hierarchy of caches, so there're caveats also). If the descriptor was associated with a Unix-style shell process through a pipe, then it will go into the pipe's buffer, extracted from it by the shell and printed using a terminal interface, usually fulfilled with some terminal emulator. By default shells are line-buffered, so the line should be printed as a whole unless the user of the shell changes its parameters somehow.
Basically, I hope you get the idea, it is not your program which is actually manipulating with the terminal and lighting up pixels on your monitors. Your program is just outputting data and some other program is receiving this data and drawing it on the screen. And this some other program (a terminal, or terminal emulator, e.g., minicom) is making this output glitchy, not your program. Your program is doing its best to be printed correctly - full line or nothing.
Your program is glitching
And it is. The in_channel is also buffered, so it will accumulate a few bytes before calling sprintf. Therefore, you can just read from the buffered channel and expect a realtime response to it. The most reliable way for you would be to use the Unix module and process the input using your own buffering.
The glitching input
Finally, the input program can also give you the information in chunks. This is especially true for serial interfaces, so make sure that you have correctly set up your terminal interface using the Unix.tcsetattr function. In particular, when your program is blocked on the input, the operating system may decide not to wake it up on each arrived character or line. This behavior is controlled by the terminal interface (see the Canonical and Non-canonical modes. If your input doesn't have newlines, then you shall use the non-canonical mode).
Finally, the device itself could be acting jittering, and if you have an oscilloscope nearby you can observe the signals it is sending. And make sure that you have configured your serial port as prescribed in the user manual of your device.
One possibility is that fscanf is waiting until it sees everything it's looking for.

How to detect keystrokes in Swift on Linux?

I am writing a command line application in Swift that will run on Linux. I want to know what keys the user is touching in real time so I can show a value associated with each key.
Is there a a non blocking way of capturing user keystroke events in real time one key at a time?
I know of the readLine() function but that captures whole words and is blocking.
Anybody knows of a working solution?
If you know which input device (for example a USB keyboard) you want to read the real time keystrokes from, then you could use something like: https://github.com/Dev1an/InputEvents
It does not use standard command line input streams but reads the events directly from /dev/input/... devices instead.

HID input on linux for games

What is the best way to capture HID input on linux for games? I don't need anything special. Just mouse and keyboard. Right now I'm using Xlib. I have a separate input thread, which has its own connection to the X Server (Display instance) and it handles events for main render window. It is working just fine, but it is a bit limited. For example, I'm missing mouse raw input.
Have you tried opening and reading device files in /dev/input?

Serial port determinism

This seems like a simple question, but it is difficult to search for. I need to interface with a device over the serial port. In the event my program (or another) does not finish writing a command to the device, how do I ensure the next run of the program can successfully send a command?
Example:
The foo program runs and begins writing "A_VERY_LONG_COMMAND"
The user terminates the program, but the program has only written, "A_VERY"
The user runs the program again, and the command is resent. Except, the device sees "A_VERYA_VERY_LONG_COMMAND," which isn't what we want.
Is there any way to make this more deterministic? Serial port programming feels very out-of-control due to issues like this.
The required method depends on the device.
Serial ports have additional control signal lines as well as the serial data line; perhaps one of them will reset the device's input. I've never done serial port programming but I think ioctl() handles this.
There may be a single byte which will reset, e.g. some control character.
There might be a timing-based signal, e.g. Hayes command set modems use “pause +++ pause”.
It might just reset after not receiving a complete command after a fixed time.
It might be useful to know whether the device was originally intended to support interactive use (serial terminal), control by a program, or both.
I would guess that if you call write("A_VERY_LONG_COMMAND"), and then the user hits Ctrl+C while the bytes are going out on the line, the driver layer should finish sending the full buffer. And if the user interrupts in the middle of the call, the driver layer will probably just ignore the whole thing.
Just in case, when you open a new COM port, it's always wise to clear the port.
Do you have control over the device end? It might make sense to implement a timeout to make the device ignore unfinished or otherwise corrupt packets.
The embedded device should be implemented such that you can either send an abort/clear/break character that will dump the contents of its command buffer and give you a clean slate on your client app startup.
Or else it should provide a software reset character which will reset the command buffer and all state.
Or else it so be designed so that you can send a command termination (perhaps a newline, etc, depending on command protocol) and possibly have an error generated on the parsing of a garbled partial command that was in its buffer, query/clear the error, and then be good to go.
It wouldn't be a bad idea upon connection of your client program to send some health/status/error query repeatedly until you get a sound response, and only then commence sending configuration or operation commands. Unless you can via a query determine that the device was left in a suitable state, you probably want to assume nothing and configure it from scratch, after a configuration reset if available.

Resources