How to make Linux ignore a keyboard while keeping it available for my program to read? - linux

I am building some kind of kiosk system and I bought this USB DIY keyboard for it: https://www.amazon.com/gp/product/B07QPXQQ7L
This allows me to have a lot of buttons and they behave like keyboard keys.
I'm writing a program (Perl) that will take the input from that keyboard and do things based on that.
The problem is that I need to have the rest of the system (both X and the TTYs) ignore that keyboard so that it won't type random things in the terminal or in the window manager. In other words, the system should disregard it but the device itself must still be available in /dev/input/...
I don't need a real keyboard to control the machine because I connect via VNC and SSH.
Bonus points if you know how to read from a /dev/input/... keyboard and end up with letters typed just like with STDIN in a terminal.
Thanks!

I found the solution here where someone wanted the exact same thing in the case of a barcode reader:
https://serverfault.com/questions/385260/bind-usb-keyboard-exclusively-to-specific-application/976557#976557
SUBSYSTEM=="input", ACTION=="add", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", RUN+="/bin/sh -c 'echo remove > /sys$env{DEVPATH}/uevent'"
ACTION=="add", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", SYMLINK+="diykeyboard"
And then replace xxxx and yyyy by the Vendor and Product ID as found in lsusb. So in my case 1c4f and 0002:
Bus 001 Device 003: ID 1c4f:0002 SiGma Micro Keyboard TRACER Gamma Ivory
The udevadm control --reload thing didn't do it for me, I had to reboot.
Then in theory the data typed on the keyboard should be available at /dev/diykeyboard (the SYMLINK variable).
Now in my case unfortunately there are multiple events that match this vendor+product, and to match the right one I needed to add DEVPATH=="*:1.0/*", KERNEL=="event*" in the second line where it creates the SYMLINK. And then surprise it did not create the link in /dev so I had to do something dirty, create a link myself with ln:
SUBSYSTEM=="input", ACTION=="add", ATTRS{idVendor}=="1c4f", ATTRS{idProduct}=="0002", RUN+="/bin/sh -c 'echo remove > /sys$env{DEVPATH}/uevent'"
SUBSYSTEM=="input", ACTION=="add", ATTRS{idVendor}=="1c4f", ATTRS{idProduct}=="0002", DEVPATH=="*:1.0/*", KERNEL=="event*", RUN+="/bin/sh -c 'ln -sf /dev/input/$kernel /diykeyboard'"
(don't create the link in /tmp since udev happens before the mounting of /tmp at boot)
From there I can read from /diykeyboard (which usually points to /dev/input/event0) either with evtest which shows the keys typed, or directly with my program and then decoding the scancodes.

Related

Using different console for respawn process in inittab on embedded device

I am connected on my embedded device with the serial port and would like to start my custom binaries on boot and be able to see the output generated.
My /etc/inittab file contains:
console::respawn:/sbin/getty -L 115200 ttyAPP3 vt100
console::respawn:/usr/bin/mybinary
With this configuration, I can see the output of mybinary in the serial console but It is difficult/impossible to connect (insert login and password) to getty because of the interference of the output generated.
I tried to switch the output in inittab to another not used tty (tty10) like this:
console::respawn:/sbin/getty -L 115200 ttyAPP3 vt100
tty10::respawn:/usr/bin/mybinary
And now I can connect but how can I see the output generated to /dev/tty10 ?
I tried cat /dev/tty10 but nothing is shown.
I know the question is old, but it has no answers at all for crying out loud.
Remember that a TTY is both an output device and also an input device -- by cat'ing from it you're reading input from the terminal which means the keyboard, NOT the screen.
I don't know if there's a parallel in other *nixes, but Linux systems have /dev/vcsX and /dev/vcsaX character devices (nodes c,7,0+X and c,7,128+X respectively) for each /dev/ttyX device - these are mirrors of the data currently on the output of the TTY device (ie. the screen part of the TTY, not the keyboard part). These will give you what you're looking for. The vcsaX devices will give you a displaybyte+attributebyte pair (i.e. the foreground/background text colour -- see other references for more information on text attribute bytes) for each character on the screen, while the vcsX devices give only the displaybyte for each character. Of course it's a raw stream/dump so if the row and/or column count of your terminal doesn't match that of the the TTY you're dumping then you'll need to parse the data and reformat it to match.
tl;dr: use "cat /dev/vcs10"
Hope that helps.

Handling input device plug/unplug while reading from it

I have a bluetooth remote that is paired with my linux box, when active, this remote is visible at /dev/input/event13.
I have a small C program that open this device and read directly from it, which works fine.
Now, my problem is that this remote goes to sleep after a few minutes of inactivity and /dev/input/event13 disappears. It reappears as soon as I press a key on my remote.
I put the output of udevadm here: https://gist.github.com/9fff2f0d7edef1050060.
I use the following code (small ruby ext I wrote), to read from the device: https://gist.github.com/b403d538eb6a8627e2bd.
I thought of writing an udev rule that would start my program when my remote is added and stop it when it is removed. I read the udev documentation, but I couldn't figure it out how to do it. I'm open for suggestion.
After some digging and a lot of frustration I did the following:
I put into /etc/udev/rules.d/99-rmote.rules
KERNEL=="event*", SUBSYSTEM=="input", ACTION=="add|remove", ATTRS{name}=="TiVo Keyboard Remote", RUN+="/home/kuon/handleConnect.rb"
And in handleConnect.rb I check the ACTION environment variable and I start/stop my daemon accordingly. Quite simple in the end and it works well.

How to control/check gpio states with shell commands (at91sam9260 board)

I need to write a script that controls and checks the gpio states.
I have been trying for a while to find a way to do it, but I didn't succeed.
Here is for the details :
I use an at91sam9260 board with a Linux kernel 2.6.27 embedded in it.
I see the /dev/gpio device
I tried some commands like cat /dev/gpio OR echo 1> /dev/gpio but it did not give me any result ( except an error message for the first command)
I also tried to create /dev/gpio0 .. to /dev/gpio31 (with the makedev command before recompiling the CRAMFS filesystem, but I did not get more results.
Does someone know how to check these gpio states and set/clear some of them ?
More generally, Is there an easy way to find out the proper shell commands for a particular device just by looking at the driver source files ?
If your kernel has sysfs support you can access and control the gpio pins through the interface in /sys/class/gpio. See the sysfs section of the kernel document in Documentation/gpio.txt.
I have used at91sam9260. You can set/unset the gpio pins using sysfs interface.
for ex. go to: cd /sys/class/gpio and then "echo 2 > export" and then set the directions of gpio pins to input(in)/output(out) by "echo in > direction" and then you can read the value from "value" file by "cat value"
Check /sys/kernel/debug/pinctrl/ directory for verbose GPIO info.

How can I determine touch screen device in a bash script?

I am trying out the eGalax touch screen driver for my touch screen, as an alternative to the evdev/xinput_calibrator combination.
The calibration tool that comes with the eGalax driver, TKCal, takes the device to which the touch screen is connected as a command line argument.
Now I would like to start the calibration tool from a bash script. Is there some smart way to determine the device within the script, instead of hard coding "/dev/hidraw0" as in this example:
TKCal /dev/hidraw0 Cal
I presume that I can't rely on the touch screen landing on hidraw0 every time, can I? If I run my software on a different system, with a mouse and a keyboard and touch screen, I guess I have to handle that the devices can be conneted to different hdrawX devices. Please correct me if I am wrong.
Thank you very much!
/Fredrik Israelsson
Try looking at /sys/class/hidraw/hidraw*/device/uevent.
The guys developing the eGalax drive told be to try a much simpler solution:
Write a udev rule that will map the touch screen to a device name of my choice.

auto permissions on udev'd device files?

This is a dupe from SuperUser.com . Folks over there weren't smart enough or willing to help me out; maybe it's more a programmer question than an administrator one:
I have an app that reads input from 4 (four) mice that are plugged in via USB in addition to the built-in touchpad. This is no problem for Ubuntu 9.10: hald notices the new devices and udev's them brand new entries called /dev/input/mouse4 ... mouse7.
My app runs as a normal user app. The files in /dev belong to root and aren't readable to anyone else.
I don't have a problem doing chmod a+r mouse? once, but the devices come and go with every reboot and every time the dang rodents are plugged in or out.
Can someone please tell me a script or something to manipulate so my chmod happens automagically?
This information is easily discoverable, I just had to look at /etc/udev/rules.d/91-permissions.rules on a Debian configuration. :-)
Some interesting examples pasted from there:
# default permissions for block devices
SUBSYSTEM=="block", GROUP="disk"
Looks like there's this "GROUP" thing to determine the group owner...
And, you can chmod stuff apparently:
KERNEL=="pty*", MODE="0666", GROUP="tty"
Note the MODE part...
I'm sure RTFM-ing for the udev config file format will give you even more information. :-)

Resources