Author Topic: keyboard emulation LinuxCNC  (Read 682 times)

0 Members and 1 Guest are viewing this topic.

Offline JesterTopic starter

  • Frequent Contributor
  • **
  • Posts: 887
  • Country: ca
keyboard emulation LinuxCNC
« on: July 03, 2024, 11:23:44 am »
If I send keyboard characters via an Arduino board with a USB port to a Linux machines USB port, will the LinuxOS assume the characters are coming from a keyboard and act accordingly?

If it's not that simple, what is required to make LinuxCNC think the Arduino is a keyboard?

Thanks in advance. :)
 

Offline Bicurico

  • Super Contributor
  • ***
  • Posts: 1770
  • Country: pt
    • VMA's Satellite Blog
Re: keyboard emulation LinuxCNC
« Reply #1 on: July 03, 2024, 02:27:38 pm »
There are ready to go devices called RubberDuck, if I am not mistaken, which simulate a keyboard to execute predefined scripts.

The Flipper Zero does it, too.

Even if this is not the solution you want, you can peek into the F0 source code to see how it is done.
 
The following users thanked this post: Jester

Offline ralphrmartin

  • Frequent Contributor
  • **
  • Posts: 489
  • Country: gb
    • Me
Re: keyboard emulation LinuxCNC
« Reply #2 on: July 03, 2024, 06:55:22 pm »
It is most easily done using  an Arduino with HID capabilities like the Leonardo.
An example is given here:
https://www.okdo.com/project/arduino-hid/
 
The following users thanked this post: Jester

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3249
  • Country: us
Re: keyboard emulation LinuxCNC
« Reply #3 on: July 03, 2024, 09:30:13 pm »
Arduino Unos and Nanos will present themselves to a computer as a USB serial device. You could then use a program such as:

https://www.232key.com/

which will continually read the serial port and inject the input into the kernal as keystrokes. For Linux have a look at the inputattach utility:

https://wiki.archlinux.org/title/Serial_input_device_to_kernel_input

Other Arduinos can present themselves as a USB "human interface device" (HID) -- i.e. a keyboard / mouse / trackpad / etc.

See:

https://www.arduino.cc/reference/en/language/functions/usb/keyboard/

for more info and library code.
« Last Edit: July 03, 2024, 09:32:59 pm by ledtester »
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 13083
Re: keyboard emulation LinuxCNC
« Reply #4 on: July 03, 2024, 11:32:23 pm »
Yes you need an Arduino with a USB capable MCU on it.  For AVR Arduinos, that's normally anything with an ATmega32U4, e.g. Leonardo or Pro Micro. Look at the example sketch 09.USB Keyboard.

Genuine Arduino Uno R3 and Mega2560 boards have an ATmega16U2 programmed as a USB <=> UART bridge, which can be reprogrammed using HoodLoader2 to run sketches on it with USB support, e.g. to emulate a HID keyboard, but the ATmega16U2 has very little I/O apart from serial comms with the main MCU, so you'll probably end up with the extra complexity of two sketches, one on the main MCU to generate the key codes when triggered and pass them via UART to the ATmega16U2 running the HID Keyboard emulation sketch.  There is Hoodloader2 HID-Bridge example you can base it on.

Most generic clone Uno R3 and Mega2560 boards use various dedicated USB <=> UART bridge ICs that cant be reprogrammed as a general MCU, so cant use HoodLoader2. 
« Last Edit: July 03, 2024, 11:38:43 pm by Ian.M »
 
The following users thanked this post: Jester

Offline JesterTopic starter

  • Frequent Contributor
  • **
  • Posts: 887
  • Country: ca
Re: keyboard emulation LinuxCNC
« Reply #5 on: July 04, 2024, 07:44:22 am »
Thanks for all the responses.

I should have mentioned in my original post that I'm using a MKRZero (native USB port) for software development. Looks like the MKRZero supports the Arduino keyboard.h driver, so this appears like it might be pretty easy to implement.

It is most easily done using  an Arduino with HID capabilities like the Leonardo.
An example is given here:
https://www.okdo.com/project/arduino-hid/

I'm going to start by adding keyboard.h and play with it a bit. I read that you can't be completely negligent and have your code spewing endless data towards the machine that it is  connected to however in my case that should not be a problem as I'm using a handful of custom buttons to initiate so it will be coded to only send when a button is pressed.

I'm away to the races  :)


Thanks for all the responses.
« Last Edit: July 04, 2024, 08:19:49 am by Jester »
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 4230
  • Country: gb
Re: keyboard emulation LinuxCNC
« Reply #6 on: July 21, 2024, 10:59:55 am »
Is there anything for ps/2?
Edit: typo
« Last Edit: July 22, 2024, 07:19:23 am by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6863
  • Country: fi
    • My home page and email address
Re: keyboard emulation LinuxCNC
« Reply #7 on: July 22, 2024, 12:00:56 am »
With anything Linux, the easiest is to implement an USB HID or PS/2 keyboard in hardware, whichever the Linux-based host already uses.  If you use a previously unused interface type, you may need to install the missing kernel modules (or, in the case of an optimized monolithic kernel, recompile a kernel with the necessary features enabled).

The easiest way to implement new keyboard/mouse/trackpad/joystick/gamepad-like HID devices I know of currently, is to use a Teensy 4.0 (or, if you happen to have one, a Teensy LC or a Teensy 3.2, which are no longer produced due to chipageddon and resulting IC availability and price issues) and the Teensyduino add-on to Arduino environment programming.  It has a native USB interface, and you can select the type of your device from the Arduino IDE menu (Tools > USB type in Arduino 1.8.x), including Serial, Raw HID, Keyboard, Keyboard + Touch, Keyboard + Mouse + Touch, Keyboard + Mouse + Joystick, Serial + Keyboard + Mouse + Joystick, Flight Sim Controls, or Flight Sim Controls + Joystick.  For the ones with Keyboard, you can choose the keyboard layout (Tools > Keyboard layout) from a selection of some common ones.  Then, your sketch only needs to examine the input pin states on the microcontroller, perhaps with software debouncing, and the exposed Keyboard object to emit the keypresses – there is even a "send a sequence of keypresses" available which implements the necessary interstroke delays.  It's a pity Teensy LC are no longer available; they were perfect for this kind of purpose –– similar to how ATmega32U4 and ATUSB1286 were earlier, among Atmel AVRs, both in hardware, price, and ease of development using free open source tools.  (In Teensies, only the bootloader (on the AVR chip in Teensy 2.x, on the dedicated boot chip in Teensy LC/3.x/4.x) and board files are proprietary; the Arduino core and support files are open source, and even key schematics are available.  One can even design their own Teensy-like boards, as PJRC is happy to sell pre-programmed Teensy bootloader chips, and thus take advantage of the Arduino+Teensyduino software environment for rapid development and experimentation.)

All human interface device inputs are handled by the Linux Input Subsystem.  There are Linux kernel drivers for e.g. GPIO pin matrix keypads that do the same, but you can also use the uinput module to synthesize a human interface device using userspace software (privileges are only needed during opening of the /dev/uinput device and instantiating the new device node); the synthetic uinput devices behave exactly like USB HID hardware devices would.  An application could theoretically distinguish between the two, but no userspace program I've ever seen the sources of actually try to, at all: there is no need to.  It all Just Works.

On the userspace application side, LinuxCNC uses the input event character devices directly (see e.g. lib/python/linux_event.py in the LinuxCNC sources).
This means that you need to implement either a real USB HID device, a PS/2 keyboard device (if the host exposes a PS/2 hardware interface), a kernel driver (for e.g. matrix keypads), or use a Linux uinput userspace service/daemon to convert other input formats like serial ports to HID events.

The Input Subsystem splits HID devices into generic event devices, mice, and joysticks.  I recommend using the Event userspace API, and therefore the /dev/input/eventN character devices (as named by /sys/class/input/eventN/device/name pseudofiles).  Normally, all keyboard devices' events are forwarded to the currently active TTY by the kernel.  For multi-seat support, a session manager grabs the corresponding keyboard and mouse character devices: if you use the EVIOCGRAB ioctl on the opened file descriptor, reading the events from the character device consumes them and causes them to no longer be forwarded/copied.  Thus, if you want, you can easily write an userspace service that monitors HID devices, and grabs specific ones, consuming/translating/mapping their events to synthetic ones emitted via uinput, and thus showing up as a completely new hardware HID device.  While this is easy, using a microcontroller with native USB support and USB HID library support is obviously easier.

I personally am interested in using the cheap WCH CH552G/CH554G (currently < 0.90€ in singles at LCSC, USD $0.94 at JLCPCB assembly) for USB HID device experiments.  One can use ch55xduino Arduino add-on to program it in C (via the free and open source SDCC C compiler), and uploaded using Python, pyusb, and the chprog.py tool included in ch55xduino.  There are other options too though, including for PlatformIO and even bare hardware development, mostly using SDCC C compiler since the MCU is based on MCS51 (enhanced 8051).  Not only are the CH55x MCU's cheap, but they are easy to use, too, because they don't need an external crystal for USB 1.1 Low-Speed (1 Mbit/s) or Full-Speed (12 Mbit/s) communications; only a couple of 100nF/0.1µF bypass capacitors and maybe a 1-47µF bulk bypass capacitor, and optionally a switch and a 10kOhm resistor for switching it to bootloader mode when connecting to a host for reflashing the firmware using the built-in USB bootloader.  Very, very easy!

If CH55x for HID interests you, I recommend you check out Stefan Wagner's (wagiminator) CH552G MacroPad Plus, which has a rotary encoder with 12 programmable RGB LEDs, and 6 buttons with a programmable RGB LED each.  Both the hardware design files and the software needed are licensed under CC-BY-SA 3.0, making it perfect for learning from.

I use Linux myself, and developing and experimenting with this kind of device is real easy for me.  For testing a new USB HID device, all I need to do is program it and plug it in, and it should Just Work.  I can use evtest to examine the events it generates, or Wireshark (or similar tools) to examine the exact USB HID packets it generates (and their timing).  As the Linux input subsystem was designed along the same lines as USB HID events, I've found it very easy to deal with both, with only timing causing occasional issues on the microcontroller side (if and only if the "keyboard" interface does not examine and enforce the packet frequency set by the host) – an USB HID device cannot inject keypresses faster than a superfast robot tapping on an actual keyboard would.

The same applies to most TV boxes, routers, NAS, and other appliances, as they too tend to be based on either Linux or Android (Android kernel being a derivative of the Linux kernel), and use the exact same input subsystem.  Very useful for novel gadgets, for example if you create your own Kodi TV box, and want to experiment with gesture control of your TV.  I'm happy to provide more detailed information (like this, still perfectly valid over a decade later; this is that stable of an interface), even down to examples (like this one, which 2D transforms touch events and virtual button presses to input events).  However, I'm of very little to no use if you develop on Windows, unless you use a virtual machine running some flavour of Linux in it, for example Linux Mint.  (WSL/WSL2 is a translation layer, and is not sufficient/compatible enough for Linux-specific systems-level programming like this.)

Apologies for the long post: I had lots to say.  :P
« Last Edit: July 22, 2024, 12:06:50 am by Nominal Animal »
 
The following users thanked this post: Jester

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6863
  • Country: fi
    • My home page and email address
Re: keyboard emulation LinuxCNC
« Reply #8 on: July 22, 2024, 01:31:12 am »
Is there anything for ps/s?
Do you mean PS/2, as in the port used for keyboards and mice before USB HID became ubiquitous?

PS/2 port has 5V logic levels, a dedicated 5V supply pin you can draw up to 275mA from, a clock line, and a data line, both clock and data being open collector with pull-ups to 5V.  The nominal clock frequency is between 10 kHz and 16.7 kHz, but the host can pull the clock line low similar to I²C/SMBus clock stretching.  The data format is similar to various serial protocols: 1 start bit, 8 data bits, 1 odd parity bit, 1 stop bit, and an additional acknowledge bit for host-to-device transfers.  It is very simple to bit-bang on a microcontroller, especially if one implements the simpler version that ignores host commands/messages/retransmit requests and parity checking, like old IBM AT keyboards did.

Linux PS/2 keyboard and mouse drivers interface to the Linux Input Subsystem exactly the same way as generic USB HID devices do; the reports are just converted to input events by the driver used.  (Note that the /dev/input/mice does the inverse: it is always present, and provides the events from all mouse and touch devices in one of the PS/2 formats, selectable via an ioctl.  This is for easy support of some very old software and hot-plugging mice.  X, Wayland, and other environments and session managers –– and LinuxCNC –– use the event character devices instead.)  From userspace, even when using the event device interface like LinuxCNC does, it does not matter whether the events were generated by an USB HID device or a PS/2 keyboard or mouse; they will look pretty much the same in any case.  ("Pretty much" instead of "exactly" because driver-specific translation or configuration settings like keyboard mappings can sometimes (depending on the driver!) be used for minor adjustments, for example to support different keymaps and keyboard layouts.  For USB HID devices, this is usually done at the userspace level, for example X or Wayland or the widget toolkit, though.

For LinuxCNC, this means that if the host has PS/2 hardware, you only need to ensure the linux kernel used has a compatible PS/2 keyboard driver enabled or loaded.  For SBCs, this is typically part of the platform driver.  (Even on x86 and x86-64, many touchpads and laptop keyboards still use PS/2 interface, so the needed drivers tend to be enabled/loaded more often than not.)

For interfacing an existing PS/2 keyboard to a host providing only an USB connector, you could use a WCH CH55x, and bit-bang the PS/2 interface.  (For the clock pin, you'll want to use a pin that supports an interrupt on the falling edge, to detect when the host wants to send some data.)

For interfacing an USB keyboard to a host providing only PS/2 ports, you could use a Teensy 4.0 or 4.1 (with an USB host port) and a voltage level translator like TXS0102, or a WCH CH554G/CH554T/CH559T (which do have USB host port support) at 5V logic level.

For interfacing to PS/2 keyboards using any microcontroller in the Arduino environment, see the PS2Keyboard Arduino library developed by Paul Stoffregen, the author of the Teensy development boards, but note that it only supports a single instance of the PS/2 keyboard object.  For CH55x, you'd need to port the C++ code to C for the SDCC compiler, but it's rather straightforward.

For creating a custom keyboard/mouse device with a PS/2 interface, any reasonable microcontroller will do; the data clock rate is quite low, anything between 10 kHz and 16.7 kHz will do.  If you can, pick one that can use 5V logic levels, and supports interrupt on the falling edge of the clock pin; otherwise you'll need a bidirectional voltage translator for both clock and data.  I would personally consider WCH CH554T or CH559T MCUs (which have both USB host support and 5V logic levels on GPIO pins), so that both USB and PS/2 interfaces could be supported with the same hardware, leaving about 12 GPIO pins for the button matrix.  (If you need more than 36 buttons you can get with a 6×6 matrix, use a separate counter or serial-to-parallel IC and N×8 matrix.)

For the CH55xT-based solutions, I recommend taking a look at Wagiminator's CH55xT development boards and GitHub sources and examples[/RL].
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 4230
  • Country: gb
Re: keyboard emulation LinuxCNC
« Reply #9 on: July 22, 2024, 07:21:12 am »
Do you mean PS/2, as in the port used for keyboards and mice before USB HID became ubiquitous?

Yup, typo.
I am only curious about existing similar projects or products.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 
The following users thanked this post: Jester


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf