Keyboard sim via userspace comp

More
24 Jul 2018 11:11 #114741 by InMyDarkestHour
Had a bit of play around and came up with this (very rough proof of concept):
Idea was inspired via this thread:
forum.linuxcnc.org/10-advanced-configura...-userspace-component
Key are sent via the pins:
keyclick simulates a single key press
keydown simulates holding a key down
keyup simulates releasing a held down key
component uinput               			"This component inserts keys presses";

pin io unsigned keyclick              	"Send down & up event";
pin io unsigned keydown					"Send key down (pressed) event";
pin io unsigned keyup					"Send key up (released) event";

option extra_setup yes;
option extra_cleanup yes;
option singleton yes;               // makes no sense to have more than one of these components running
option userspace yes;
option extra_link_args "-L/usr/lib/x86_64-linux-gnu -levdev"; //link in libevdev change path for 32 bit

// Requires installing libevdev-dev & libevdev2 packages
// When building under debian a symlink /usr/include/libevdev -> /usr/include/libevdev-1.0/libevdev
// needs to be created when libevdev-dev is installed
// Build with sudo halcompile --install --userspace uinput.comp
// If group uinput does not exist create it
// Add your user to group uinput
// /dev/uinput requires group ownership changing to uinput
// Usage: open a terminal run halrun at halcmd prompt loadusr -W uinput
// Open a second terminal and run:
// halcmd setp uinput.keyclick 33 
// this will output a lowercase f
// halcmd setp uinput.keydown 42 && halcmd setp uinput.keyclick 33 && halcmd setp uinput.keyup 42
// will output a uppercase F
// Key codes are defined in /usr/include/linux/input-event-codes.h 

author "AnnoyingMutt robertDOTmurphyATgmxDOTcom";
license "GPL";
;;
#include <stdio.h>
#include <libevdev/libevdev.h>
#include <libevdev/libevdev-uinput.h>
#include <unistd.h>

	int enable_event_code_range( int min, int max);
	

    struct libevdev *dev;
    struct libevdev_uinput *uidev;

EXTRA_SETUP()
	{    

		int err;
		dev = libevdev_new();
		libevdev_set_name(dev, "fake keyboard device");

		// We will only emulate key presses
		libevdev_enable_event_type(dev, EV_KEY);
		
		// Enable the keys ESC to Dot on Numeric keypad
		enable_event_code_range( KEY_ESC, KEY_KPDOT);
		
		err = libevdev_uinput_create_from_device(dev,
			LIBEVDEV_UINPUT_OPEN_MANAGED,
			&uidev);
	
			if (err != 0)
			{
				perror("init_uinput: Couldn't create device\n");
				return(-1);	
			}
	
		usleep(100000);		//wait for device to be grabbed by X	
		return(0);
	}
	
	
EXTRA_CLEANUP()
	{
		libevdev_uinput_destroy(uidev);
	}

void user_mainloop(void)
{

	
	while ( 1 )
	{
		FOR_ALL_INSTS()
		{

			// Only accept valid event (key) codes
			if ( keyclick >= KEY_ESC && keyclick <= KEY_KPDOT)
			{
				libevdev_uinput_write_event(uidev, EV_KEY, keyclick, 1);
				libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
				libevdev_uinput_write_event(uidev, EV_KEY, keyclick, 0);
				libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
				keyclick = 0;
			}
			
			// Only accept valid event (key) codes
			if ( keydown >= KEY_ESC && keydown <= KEY_KPDOT)
			{
				libevdev_uinput_write_event(uidev, EV_KEY, keydown, 1);
				libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
				keydown = 0;
			}

			// Only accept valid event (key) codes
			if ( keyup >= KEY_ESC && keyup <= KEY_KPDOT)
			{
				libevdev_uinput_write_event(uidev, EV_KEY, keyup, 0);
				libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
				keyup = 0;
			}
			
			
		}
		
	}
    
    exit(0);
   }


int enable_event_code_range( int min, int max) 
{
	int event_code;
		
	for ( event_code = min; event_code <= max; event_code ++) 
			libevdev_enable_event_code(dev, EV_KEY, event_code, NULL);

	return(0);
}
Attachments:

Please Log in or Create an account to join the conversation.

More
24 Jul 2018 16:56 #114754 by andypugh
Have you any thoughts on how to map between a keyboard matrix and specific key events?

I think that your component might need to (additionally) create bit input pins for a specified number of keys and a matching parameter to say what scan-code that bit should be interpreted as. (that is, if it is to be used with matrix_kb and/or the 7i73).
(

Please Log in or Create an account to join the conversation.

More
24 Jul 2018 20:39 - 25 Jul 2018 01:02 #114765 by InMyDarkestHour
Firstly you raise some very good points, and thanks Andy.

One thing I should mention that the output will go to the window that has focus, as per a normal keyboard. It also has all the issues(?) seen when a second keyboard is connected (capslock states comes to mind).

TBH as this was a proof of concept. I was concentrating on mimicking a very basic set of functions similar to some of the python libraries around (and a solution to the linked thread as I thought it would be an easy interface with arceye's code mentioned), and settled on the three functions represented via the pins created. As this was my first attempt at a component I tried to keep it pretty simple. I tend to program one bit at a time......to make life easier for myself.
Creating the extra pins I guess wouldn't be a problem, I'd have to look at some code examples of how to create pins based on load-time config.
To interpret specific scan-codes to a key would require a configuration file to load the scan-code to key-code mapping. Plus a way to to work out if it is a key-up or key-down event.
In all it would appear an extra pin is need for raw scan codes and then a pin to represent every key needed ? Is there a limit to the amount of pins a component can create ?
Or just create a pin for every required key (83 at current count) and let the user map the matrix_kb.N.key.rRcC to uinput_key_XX ?

Or create utter confusion with three two separate components (actually it may prevent unwieldy code).
One that deals with raw scan codes
Another that deals with key_XX pins
And one that works via the mechanism in the example
I guess people may ask for a single input for to access the "File Open Menu".

I'm open to all suggestions.
Last edit: 25 Jul 2018 01:02 by InMyDarkestHour.

Please Log in or Create an account to join the conversation.

Time to create page: 0.090 seconds
Powered by Kunena Forum