I write some software for Linux, which uses libevdev for input processing.
To my surprise all virtual onscreen keyboards that I found simulate high level X Window Server events. So, they're not recognized by udev, don't appear at /dev/input folder and aren't visible with evtest.
Is there any software keyboard that is low-level enough for that? Or maybe some trick for that?
There is a good reason why this is done in this way. The /dev/input devices are devices that have somekind of physical (electrical, optical and/or mechanical) input. These are converted by the linux kernel drive into something that generates EV_EVENTS. These events are processed by the xf86_input_evdev driver in to X11 inputs, which are understood by the server. As you can generate X11 inputs from an X11 program, it is quite a lot of work to create a device driver that accepts input on one side from an X11 app and generates input on the other. So while not impossible, it is a lot of work for no gain to create a driver or two for this purpose.
Related
I was searching for a syscall that would draw a pixel on a given coordinate on the screen on something similar. But I couldn't find any such syscalls in this site.
I came to know that OS interacts with monitors using graphic drivers. But these drivers may be different on different machines. So is there a common native API provided by linux for handling these?
Much like how there are syscalls for opening, closing, reading, writing to files. Even though underlying file systems maybe different, these syscalls provide an abstract API for user programs to simplify things. I was searching something similar for drawing onto the screen.
Typically a user is running a display server and window system which organizes the screen into windows which applications draw to individually using the API provided by that system. The details will depend on the architecture of this system.
The traditional window system on Linux is the X window system and the more modern Wayland display server/protocol is also in common use. For example X has commands to instruct the X server to draw primitives to the screen.
If no such system is in use, you can directly draw to a display either via a framebuffer device or using the DRM API. Both are not accessed by special syscalls, but instead by using normal file syscalls like open, read, write, etc., but also ioctl, on special device files in /dev, e.g. /dev/dri/card0 for DRM to the first graphics card or /dev/fb0 for the first framebuffer device. DRM is also used for applications to render directly to the screen or a buffer when under a display server or window system as above.
In any case DRM is usually not used directly to draw e.g. pixels to the screen. It still is specific to the graphics card. Typically a library like Mesa3D is used to translate the specific details into a common API like OpenGL or Vulkan for applications to use.
I have an unusual exploratory test automation task, which relies on detecting keyboard input. (certain trigger words).
However, to automate the task, has proven very difficult, as the input must pass through the keyboard driver it seems. Thus, setting UI automation (like Sikuli, or even ghost mouse) to click on the on-screen keyboard, OR using Sikuli to 'type' or copy/paste text into any windows UI, is not registered.
Any ideas of how to emulate physical keyboard input for the purpose of automation?
You could use an Arduino to emulate a physical keyboard (there are easy to use libraries available). Also, if you use one of the more capable Arduino's with multiple serial ports you can send it what keypresses to emulate through the serial port. The computer will think it is a keyboard like any other. Except you can control it with software.
Of course, this solution assumes you can connect something to the USB port of the test computer.
I am looking forward to learn writing a typical linux device driver. Can anyone guide me how can i learn all the aspects of a typical linux device driver ? The examples i see on internet are way too simple, they just send a "hello world" msg from user space to kernel driver module, and echo back "hello". I want to touch almost all areas in a simple way, one would face in writing a real world driver. Would i need to have a real hardware to go forward to meet my requirement ? Cannot system's memory simulate the hardware peripheral and let me treat it as a hardware and control it vie kernel driver covering good set of operations ? Any examples/guidance for this ?
Take a look at the following example of network driver. It uses QEMU for development and testing.
http://www.codeproject.com/Articles/1087177/Linux-Ethernet-Driver-using-Qemu
Sample drivers usually don't control real hardware. The QEMU answer mentioned here is a good exception I guess.
It depends what type of driver you want to focus on. Most classes of drivers distributed with the kernel have some simpler drivers you can learn from. Nbd for example is great for block subsystem and loop devices:
https://github.com/torvalds/linux/blob/c05c2ec96bb8b7310da1055c7b9d786a3ec6dc0c/drivers/block/nbd.c
Look at the smallest file sizes in a drivers/xyz directory and go up until the code is too complex.
I need to write a program in linux (debian, to be exact) that disables a USB device if it doesn't pass specific filters. For example, the program might be set to disallow webcams, usb sticks and keyboards, enable mice and printer (through usb). The filters may change in runtime. For example, the program might receive a message to enable usb sticks and it should respond without rebooting the system. The program is written in python but embedding c code (or others) is also acceptable.
What I have tried
I have tried many methods but some of them aren't about programming.
First, I tried to mess with udev. I can monitor the activities when a device is plugged and write filters. There used to be an option "ignore_device" that ignored the filtered devices. For example, to ignore all the devices that are a member of usb subsystem, I would write this as a udev rule:
ACTION=="add", SUBSYSTEM=="usb", OPTIONS+="ignore_device"
But this option is released in this release of udev. What I get so far is that udev can currently be used mainly for monitoring. Sure, I can write additional rules for the rule above that runs a script, but I have to do the disabling elsewhere.
Second, I tried ioctl to send a DISCONNECT signal to device handle. I'm testing this with a USB mouse. This is the python code for that: (I have also tried this in C, nothing changed)
import fcntl
import sys
USBDEVFS_RESET = ord('U') << (4*2) | 20
USBDEVFS_DISCONNECT = ord('U') << (4*2) | 22
raw_name = "/dev/bus/usb/{:03d}/{:03d}"
filename = raw_name.format(1,2)
fd = open(filename, "wb")
fcntl.ioctl(fd, USBDEVFS_DISCONNECT, 0)
Here, if I would send USBDEVFS_RESET, it works, the mouse input is ignored for a second or two. But disconnect signal raises an error:
IOError: [Errno 25] Inappropriate ioctl for device
What I get from here is, I cannot send disconnect signal to a mouse. Maybe a usb stick or printer or some other devices would work, I haven't tried. I want to develop the program as generic as possible so as to prevent writing additional device-specific code, so this approach seems useless for me. And another point here is that when I manually disconnect/connect my mouse, I see events in udev monitor. But when I send reset signal, no event is sent.
The udev monitor says that the mouse was mounted to this path: /sys/bus/usb/devices/1-3 (which is a symlink for /sys/devices/pci0000:00/0000:00:14.0/usb1/1-3). Some documents told me that this folder contains the device's settings and setting /power/level to "off" or "suspended" would turn the device power off. But I cannot manipulate any files in /power. Come to think about it, it might not be a good idea after all.
The Question
So, the question is, what is the best way to achieve such task? I have an idea but I'm not sure whether it will work and even if it does, it might be overkill. My idea is writing a "wrapper driver" that identifies itself to linux kernel as driver for all usb devices. The "wrapper driver" reads the device information and if the device is good to go, it acts as a wrapper for real drivers in the kernel, calling their functions. If not, the "wrapper driver" just ignores the device.
I'm not sure it can even be done, I'm not experienced in kernel or driver programming.
Another way is, -somehow- getting the handle of the device programatically and telling it to power off (or making it busy forever, whatever works). I have also done some little research but couldn't find a proper-easy way. They say all devices are considered as "files" but I cannot reach those files at all.
Note:
The question is mostly about linux internals but it also involves kernel programming. I read a lot about usb manipulation/monitoring programs, I read manual pages of udevadm. But these approaches do not help me at all. I think I need to alter either kernel or device internals programatically.
I have also tried manipulating authorized file that resides in /sys/devices/pci0000:00/0000:00:14.0/usb1/1-4 (for a keyboard). It's default value is 1. Changing it to 0 successfully disabled the bus (NOT device, but the physical usb port. The same device can still be used when plugged in another port). But making it 0 also stopped udev events from this usb port. So, I can disable the port if the user plugs in a forbidden device but I cannot decide when to enable it since I cannot listen to remove events in udev. Would it make sense if I delve deeper to lower levels of code (possibly kernel) and listen to usb events in some other way?
I think the simplest way to solve your problem is balcklisting all usb device drivers excepting mouse, keyboard etc.
The cleanest way is whitlisting mouse etc. with udev using usb device id's
Writing a wrapper driver is an absolute overkill never chose that way.
One possible solution could be tying usb access to user permissions. here is a related link you may find handy
http://robots.mobilerobots.com/wiki/Linux_udev_USB_Device_Permissions_Configuration
I have a program (a bash script actually - console only) that scans or makes copies, etc based on user input. It asks questions such as how many copies would you like to make, etc and then scans the document, and prints it to another printer. The program runs in a loop so it's always there when a user passes by, and using a keyboard or number pad you can easily operate it. It basically makes a simple scanner/printer combo into a complex multifunction device.
I can leave it running on a dedicated system just fine, but to save electricity and resources, I would love to have it run on a computer someone else is already using. There is a user who has a laptop on the same desk as the scanner, and I was wanting to have her be able to do her thing in Xorg, as per usual, but have this little program running on an external monitor. That part is easy, but separating input is not. First of all the window has to be in focus, and then any input from the laptop keyboard OR usb keyboard is sent to the program, obviously.
I can think of one way to do this: using virtualbox, I can run a virtual machine without X, have it permanently ssh into the host OS (to which the usb scanner is connected) and I have virtualbox grab the usb keyboard input. But that seems excessive.
Does anyone know of a way to map input from a specific keyboard to a specific program or tty?