How to read keypress from exclusive external USB keypad .
Posted
#1
(In Topic #420)
Trainee
*trying to
-use USB external keypad
-make it exclusive to gambas program
-read keypress events
*problem
Cannot figure out how to use ioctl correct way
despite reading ioctl italian cdrom control gambas program.
I get no hold on how to write structure and pass correct arguments to ioctl.
*raw code with only essential code steps
' Gambas class file
Library "libc:6"
Public Extern ioctl(di As Integer, req As Integer, arg As Long) As Integer
Public usbdev As File
Public Struct input_event
ev As Byte
End Struct
Public Struct ev
type As Byte
code As Byte
value As Integer
End Struct
Public Enum EVIOCGNAME = &90
Public Enum EVIOCGRAB = &01
Public Sub Main
'raw code to show flow commands that works
'used lsusb to get usb device then vendor id and then get eventid
'———chmod with root permission to use /dev/input/eventid
cmdshell = "sudo -S chmod 644 /dev/input/" & eventid
Shell "echo " & <yourpassword> & " | " & cmdshell
'———-open event assigned to keypad device
eventdev = "/dev/input/ & eventid"
usbdev = Open eventdev FOR READ WATCH
'———-Here i am stuck cannot grab device
'found in c program : result =ioctl(fd,EVIOCGRAB,1);
'gambas
result = ioctl(usbdev.handle, EVIOCGRAB,1)
'gives always -1 which is an error
'how to know what error and why
'—-Here also stuck cannot get name from keypad device
'found in c program : result = ioctl(usbdev.handle,EVIOCGNAME(SizeOf(name)),name)
Tried many different ways each time error
I don't know how to declare the right way in the Gambas class and how to
translate – EVIOCGNAME(SizeOf(name)),name – into gambas syntax for ioctl.
End
Public Sub File_read()
'—-Here i am stuck not able to read EV_KEY events and code
'if i press keypad then a file_read happens and gambas error is given
Read #usbdev, input_event.ev, -256
'Tried many different ways each time read error
value2 = input_event.ev[0].value
If (value2 <> " " And input_event.ev[1].value = 1 And input_event.ev[1].type = 1) Then
Message(" code: " & input_event.ev[1].code)
Endif
End
'———————–INFORMATION GATHERED—————–
from input.h , keyboard.h , input-events-codes.h
This is the way you get the kernel generated information back
caused by the received input (eg. a keypress)
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
/* get event bits */
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
/* I suppose i have to understand it this way
_IOC_READ = READ the /dev/input/eventX by file.handle from opened device eventfile
'E' = EVIOCGBIT
'ev' = EV_KEY 'here i will get ev[ ].code -> keypress code
'len' = predefined memory reserved bytes with info ?
*/
from input-event-codes.h
#define EV_KEY 0x01
'—–input.h ———————–
/* get device name */
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len)
/* Grab/Release device */
#define EVIOCGRAB _IOW('E', 0x90, int)
I tried to give as much information necessary but stripped to the essential, hope this is clear enough to see the errors
or to be able to show the path to straigthen out my lack of knowledge in the gambas world.
Thanks ahead
Posted
Expert

I'm trying to understand why/what you are doing before getting down to the code level.
I assume you have a standard keyboard with a number pad on it.
You want to plug in an external usb number pad and distinguish between the keyboard pad and the external pad.
The standard key read process in Gambas makes no distinction between the keyboard & USB pads so if you press a number pad '5' on either device it comes up
with the same key code (53, on my standard Dell keyboard using EN-AU)
What you are trying to achieve is to interrupt the key press process and determine what device instigated the event and redirect input from the external number pad to
a separate function to manage.
Is this an accurate assessment ?
Cheers - Quin.
I code therefore I am
I code therefore I am
Posted
Regular

Hello,dinge said
Public Enum EVIOCGNAME = &90
Public Enum EVIOCGRAB = &01
…excuse me, i have a little curiosity: where did you find those values related to EVIOCGNAME and EVIOCGRAB ?
regards.
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Trainee
thanks for your swift reaction.
Here my answer to your questions.
*to Mr Quincunxian
Thanks for your welcom.
Indeed more information needed about why, what
Situation:
Laptop ASUS TP300L - 64bit - 6gb memory ( Zorin linux)
keyboard with no numeric keypad
Dekstop 32bit - 4Gb memory ( Bunsenlabs linux)
external small usb keyboard with no num keypad
What:
Use and grab external USB numeric keypad for exclusive use by Gambas program
Why:
Grab keypress events from external USB numeric keypad assigned exclusively to Gambas program.
I want to create a program with assigned macro's to keypad keys from within Gambas program.
The Gambas gui makes it easy for me to test and configure this assigned xdotool commands.
Therefore I have to grab first the keypad and reserve it to my Gb application.
Secondly read the keypress events and execute accordingly a macro what here consist of xdotool command(s) stored in a file to send to application where the cursor is active.
The xdotool commands stored in file works fine in Gambas.
Made a Arduino board with small numeric keypad with USB -arduino serial port- connection which works good.
Arduino board has also IR receiver which works also good with Gb and xdotool file macros (works but not finished yet).
I want to do the same( no IR ) with USB external keypad.
But with the real USB external keypad I am stuck
on getting keydata and grab ecxlusivity with ioctl().
I do not find the correct way to assign arguments
to use ioctl accordingly in Gambas
The Read keypress event in the Gb program does happen,
but gives errors and can't get the keypress code.
*to Mr Vuott
Information from header files which are used by ioctl()
file: /usr/include/linux/input.h
/* get device name */
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len)
/* Grab/Release device */
#define EVIOCGRAB _IOW('E', 0x90, int)
/* get event bits */
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
file: /usr/include/linux/input-event-codes.h
/* Event types */
#define EV_KEY 0x01
as I understand
_IOC_READ = gambas> READ #youreventFile, intoyourvariable, length bytes reserved to read from
'E' = eventfile = gambas> yourfile.handle
'OxHEX' = defined eg ECIOCGRAB which has address 0x90
or in case of read/get keypress = EVIOCGBIT+ EV_KEY = 0x20+0x01
len = name =string of bytes = number of bytes =lentgh ?
int = integer eg. EVIOCGRAB = 1 to grab and O to ungrab
Information gambas wiki italian - ioctl get data from cdrom and player
https://www.gambas-it.org/wiki/index.php?title=Ioctl()
Thanks for your reply , hopefully this helps you.
Posted
Regular

some reflection:
1)
In my humble opinion "EVIOCGRAB" can not have that value 1, because it's a Macro.
Infact #define EVIOCGRAB _IOW('E', 0x90, int) means:
EVIOCGRAB <COLOR color="#BF0000">is defined as</COLOR> _IOW('E', 0x90, int)
So you are forced to develop, to translate that Macro - …or better: that Function _IOW(….) - in Gambas language.
2)
Symbol 'E' in C language corresponds to the ASCII numeric value of the capital letter "E".
Anyway, to find out more about ioctl-numbers:
Linux Kernel Documentation :: ioctl-number.txt
Regards
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Trainee
thanks for your reply.
Unfamiliar with C- programming and the linux inside io lib handling , what you suspected I suppose.
Back to the drawing board !
Very helpfull link you mentioned.
Read the Gambas wiki on Extern, helped to better understand.
Was able to use a math function frexp() from libm library with the for me still nebelous pointer hassle.
The _IOW(… is another piece of cake to handle.
And yes there may be a way to get around it somehow.
Thanks for your information
Posted
Regular

Quincunxian said
… determine what device instigated the event
…i want to start with this Quincunxian's sentence.
For a quick and very simple way I would propose this code.
Let's pretend that the file-device "/dev/input/event4" corresponds to the first keyboard, and that the file-device "/dev/input/event13" corresponds to the second keyboard.
…obviously they will have been preliminarily unlocked with chmod.
Therefore we place the two file-devices under observation: if anything can be read, the "File_Read ()" Event sub-routine will be raised.
The two file-devices must be managed in different Modules/Classes, otherwise the solution will not be possible !
The code consists of the main module:
In the secondary class we will manage the other file-device:
_IOW(…) is a result of more Macro.dinge said
The _IOW(… is another piece of cake to handle.
This page from italian wiki could be useful:
Emulare in Gambas le macro IOR, IOW e IOWR usate con la funzione ioctl()
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Trainee
thanks for your reply , indeed interesting to handle two keyboard events.
For the moment I only want to use 1 external usb keypad.
Found a solution by using a small c- file , to use keypress event outside gambas application keypress_event.
Used code I found on and other similar handling the grabbing and reading
https://gist.github.com/matthewaveryusa/a721aad80ae89a5c69f7c964fa20fec1
Found a solution to grab usb device by isolating through the xinput float command
Is there a way to disable a laptop's internal keyboard? - Ask Ubuntu
It is alo possible to use and install two mousepointers or multiple keyboards .
Also thanks to Mr Stevedee and his blog brought me the idea to do the workaround with c-file ( thanks Mr Stevedee)
Overview
'USB' - Show your usbdevices from the lsusb list in lstInfo
'VENDOR' select your keyboard device inlist an d klik
'Select your slave keyboard - youtr usb device
'USE' to activate or choose another device or slave as sometimes one keypad shows two slave keyboards
'Test by typing
From here on you can use the keypress code and save in file
or code actions associatecd with keypress.
This is the next stepin the project.
Included zip program, hopefully this is helpfull and someone can explain me later also how to use
the EV_KEY structure from within gambas with external library
Thanks greetings
Posted
Regular

Hello dinge,dinge said
Used code I found on and other similar handling the grabbing and reading
https://gist.github.com/matthewaveryusa/a721aad80ae89a5c69f7c964fa20fec1
I transposed to Gambas the part of the code, present in that link, relating to the keyboard:
Code (gambas)
- Library "libc:6"
- Public Struct timeval
- End Struct
- Public Struct input_event
- time_ As Struct Timeval
- End Struct
- ' int ioctl(int __fd, unsigned long int __request, ...)
- ' Perform the I/O control operation specified by REQUEST on FD.
- ' int ioctl(int __fd, unsigned long int __request, ...)
- ' Perform the I/O control operation specified by REQUEST on FD.
- ' ssize_t read (int __fd, void *__buf, size_t __nbytes)
- ' Read NBYTES into BUF from FD.
- '' In my system KEYBOARD event file-device is "event4":
- kfl.Close
- tempus = Now
- Wait 0.01
- kfl.Close
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Trainee
thanks for your code.
Worked on the macro part, finished and using it for keymacro's with Subtitle Composer.
Thanks again , looking to understand and integrate your code now.
Greetings
Posted
Trainee
used your code as follow , also include a print result
Public Sub File_read()
Dim ev As New Input_event
Dim rd As Integer
rd = read_C(kfl.Handle, ev, Object.SizeOf(ev))
Print "ev: "; Str$(ev); " , sizeof ev: "; Object.SizeOf(ev); " , rd: "; rd; " ,time: "; ev.time_.tv_sec; " , type: "; ev.type; " , code: "; ev.code ; " , value: "; ev.value
End
<LIST>
- <LI>output print gambas program code in quote
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1177329438085223 , type: 0 , code: 0 , value: 0
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1177329438085223 , type: 0 , code: 0 , value: 0
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1177329438085223 , type: 0 , code: 0 , value: 0
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1589663478370407 , type: 0 , code: 0 , value: 0
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1589663478370407 , type: 0 , code: 0 , value: 0
ev: (input_event 0x187abb4) , sizeof ev: 24 , rd: 16 ,time: 1589663478370407 , type: 0 , code: 0 , value: 0
===========================================================================================================
evtest output in terminal from same keyboard and same pressed key (not at same moment -time difference)
Event: time 1592844255.880822, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7005d
Event: time 1592844255.880822, type 1 (EV_KEY), code 76 (KEY_KP5), value 1
Event: time 1592844255.880822, ————– SYN_REPORT ————
5Event: time 1592844255.920823, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7005d
Event: time 1592844255.920823, type 1 (EV_KEY), code 76 (KEY_KP5), value 0
Event: time 1592844255.920823, ————– SYN_REPORT ————</LI>
This code gets a result , the time is available but no keypres type, code or values.
I believe the time are the first 16 bytes and the following 8 contain the keypressed type, value, code .
Do I only get 16 bytes as rd=16 ?
The sizeof ev is correct =24.
The number of lines produced by a keypress (5) is the samefor evtest and file_read
- so the third line and sixth lines (evtest - SYN_REPORT ) should give 0 values.
Do I have to read - approach- the ev.code on another way, i am stuck, can't still a good grip on it.
The implemented code for keyboard_name returns empty string and grab with iotcl still returns -1 .
What am I doing wrong.
Thanks a lot for your code it helps to evolve.
Greetings
Posted
Regular

Code (gambas)
- Library "libc:6"
- Public Struct timeval
- End Struct
- Public Struct input_event
- time_ As Struct Timeval
- End Struct
- ' int ioctl(int __fd, unsigned long int __request, ...)
- ' Perform the I/O control operation specified by REQUEST on FD.
- ' int ioctl(int __fd, unsigned long int __request, ...)
- ' Perform the I/O control operation specified by REQUEST on FD.
- ' ssize_t read (int __fd, void *__buf, size_t __nbytes)
- ' Read NBYTES into BUF from FD.
- '' (In my system KEYBOARD event file-device is "event4"):
- kfl.Close
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Trainee
I reworked my little program to grab exclusively input from touchpad or external wacompad, keypad and also Arduino serial input.
The program is named ExtraPadMini. Included in the zipped file is a Manual.odt and dpf file which shows how to use it. It is a minimal program but usable and can be productive.
I use my touchpad now which gives me 18 programmable virtual buttons. The Wacompad Volito2 i reuse now as a external 7x9= 63 extra programmable virtual buttons. With the Arduino i have written an arduino sketch to read IR remote control pulses and assign code to the remote buttons.
There are a lot of things that have to be worked out. The password permission behaves still sometimes strange.
Password using is a problem as different Linux Os use different permission protocol - gksu, kde, sudo, . The one i found seems to work with Ubuntu,Zorin,Bunsenlab. A lot of the code is gained from internet searching as I am not a programmer I am sure there are a lot of corrections and better code that can be used.
Please feel free to correct and let the gambaser enjoy your improvements.
It runs on 64bit linux os . Strangely 32bit does not work I gues it has to do with the 8bit and 16bit difference , I suppose.
That's why I struggled so long to get it working on 32bit and worked around it with xinput commands. To my surprise the ioclt commands worked on 64bit Linux Os. There is now that little program.
I am working on a ExtraPad program with scripting possibility's and 32bit compatible , I'll put it on the Project Forum
My special thanks to Mr Vuott for the ioctl gambas coding.
Greetings
1 guest and 0 members have just viewed this.


