Hello gambasers
*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
How to read keypress from exclusive external USB keypad .
- Quincunxian
- Posts: 173
- Joined: Sunday 25th June 2017 12:14am
- Location: Western Australia
Re: How to read keypress from exclusive external USB keypad .
Hi dinge and welcome to the forum.
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 ?
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
Re: How to read keypress from exclusive external USB keypad .
Hello,
...excuse me, i have a little curiosity: where did you find those values related to EVIOCGNAME and EVIOCGRAB ?
regards.
Europaeus sum !
Amare memorentes atque deflentes ad mortem silenter labimur.
Amare memorentes atque deflentes ad mortem silenter labimur.
Re: How to read keypress from exclusive external USB keypad .
Dear Mr Quincunxian and Mr Vuott,
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.
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.
Re: How to read keypress from exclusive external USB keypad .
Hello dinge,
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 is defined as _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:
https://www.mjmwired.net/kernel/Documen ... number.txt
Regards
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 is defined as _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:
https://www.mjmwired.net/kernel/Documen ... number.txt
Regards
Europaeus sum !
Amare memorentes atque deflentes ad mortem silenter labimur.
Amare memorentes atque deflentes ad mortem silenter labimur.
Re: How to read keypress from exclusive external USB keypad .
Dear Mr Vuott,
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
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
Re: How to read keypress from exclusive external USB keypad .
Hello dinge,
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:
This page from italian wiki could be useful:
Emulare in Gambas le macro IOR, IOW e IOWR usate con la funzione ioctl()
...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:
Private fl As File
Public Sub Main()
Dim cl1 As New Class1
cl1.Event13()
fl = Open "/dev/input/event4" For Read Watch
End
Public Sub File_Read()
Print "Pressed: event4"
fl.Close
fl = Open "/dev/input/event4" For Read Watch
End
In the secondary class we will manage the other file-device:
Private fl As File
Public Sub Event13()
fl = Open "/dev/input/event13" For Read Watch
End
Public Sub File_Read()
Print "Pressed: event13"
fl.Close
fl = Open "/dev/input/event13" For Read Watch
End
_IOW(...) is a result of more Macro.
This page from italian wiki could be useful:
Emulare in Gambas le macro IOR, IOW e IOWR usate con la funzione ioctl()
Europaeus sum !
Amare memorentes atque deflentes ad mortem silenter labimur.
Amare memorentes atque deflentes ad mortem silenter labimur.
Re: How to read keypress from exclusive external USB keypad .
Dear Mr Quincunxian,
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 ... 64fa20fec1
Found a solution to grab usb device by isolating through the xinput float command
https://askubuntu.com/questions/160945/ ... l-keyboard
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
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 ... 64fa20fec1
Found a solution to grab usb device by isolating through the xinput float command
https://askubuntu.com/questions/160945/ ... l-keyboard
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
- Attachments
-
- ExtraKeypad-0.0.2.tar.gz
- (18.89 KiB) Downloaded 348 times
Re: How to read keypress from exclusive external USB keypad .
Hello dinge,dinge wrote: ↑Sunday 14th June 2020 1:35pm Used code I found on and other similar handling the grabbing and reading
https://gist.github.com/matthewaveryusa ... 64fa20fec1
I transposed to Gambas the part of the code, present in that link, relating to the keyboard:
Library "libc:6"
Public Struct timeval
tv_sec As Long
tv_usec As Long
End Struct
Public Struct input_event
time_ As Struct Timeval
type As Short
code As Short
value As Integer
End Struct
Private Const _IOC_NRSHIFT As Integer = 0
Private Const _IOC_NRBITS As Integer = 8
Private _IOC_TYPESHIFT As Long = _IOC_NRSHIFT + _IOC_NRBITS
Private Const _IOC_TYPEBITS As Long = 8
Private _IOC_SIZESHIFT As Long = _IOC_TYPESHIFT + _IOC_TYPEBITS
Private Const _IOC_SIZEBITS As Long = 14
Private _IOC_DIRSHIFT As Long = _IOC_SIZESHIFT + _IOC_SIZEBITS
Private Const _IOC_WRITE As Long = 1
Private Const _IOC_READ As Long = 2
' int ioctl(int __fd, unsigned long int __request, ...)
' Perform the I/O control operation specified by REQUEST on FD.
Private Extern ioctl_name(__fd As Integer, __request As Long, arg As Byte[]) As Integer Exec "ioctl"
' int ioctl(int __fd, unsigned long int __request, ...)
' Perform the I/O control operation specified by REQUEST on FD.
Private Extern ioctl_grab(__fd As Integer, __request As Long, arg As Integer) As Integer Exec "ioctl"
' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Input_event, __nbytes As Long) As Long Exec "read"
Public Sub Main()
Dim kfl As File
Dim keyboard_name As New Byte[256]
Dim rcode As Long
Dim ke As New Input_event
Dim tempus As Date
'' In my system KEYBOARD event file-device is "event4":
kfl = Open "/dev/input/event4" For Read
If kfl.Handle < 0 Then
kfl.Close
Error.Raise("Error !")
Endif
rcode = ioctl_name(kfl.Handle, Eviocname(Asc("E"), &h06, keyboard_name.Count), keyboard_name)
Print "Reading From: \e[34m"; keyboard_name.ToString(0, keyboard_name.Find(0))
rcode = ioctl_grab(kfl.Handle, Eviocgrab(Asc("E"), &h90, SizeOf(gb.Integer)), 1)
Print "\e[0mGetting exclusive access: "; IIf(rcode == 0, "\e[32mSUCCESS\e[0m", "\e[31mFAILURE\e[0m")
Print
tempus = Now
Repeat
If read_C(kfl.Handle, ke, Object.SizeOf(ke)) > -1 Then
Print "keyboard event: type "; ke.code; " code: "; ke.code; " value: "; ke.value
Endif
Wait 0.01
Until DateDiff(tempus, Now, gb.Second) == 10 ' We arrange for the cycle to last, for example, 10 seconds: 10 sec. to click on the keyboard.
rcode = ioctl_grab(kfl.Handle, Eviocgrab(Asc("E"), &h90, SizeOf(gb.Integer)), 1)
kfl.Close
End
Private Function Eviocname(type As Long, nr As Long, size As Long) As Long
Return Shl(_IOC_READ, _IOC_DIRSHIFT) Or Shl(type, _IOC_TYPESHIFT) Or Shl(nr, _IOC_NRSHIFT) Or Shl(size, _IOC_SIZESHIFT)
End
Private Function Eviocgrab(type As Long, nr As Long, size As Long) As Long
Return Shl(_IOC_WRITE, _IOC_DIRSHIFT) Or Shl(type, _IOC_TYPESHIFT) Or Shl(nr, _IOC_NRSHIFT) Or Shl(size, _IOC_SIZESHIFT)
End
Last edited by vuott on Monday 22nd June 2020 11:33am, edited 1 time in total.
Europaeus sum !
Amare memorentes atque deflentes ad mortem silenter labimur.
Amare memorentes atque deflentes ad mortem silenter labimur.
Re: How to read keypress from exclusive external USB keypad .
Dear Mr Vuott,
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
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