Differenze tra le versioni di "Individuare i tasti della tastiera intercettando i dati grezzi dal suo file-device"

Da Gambas-it.org - Wikipedia.
 
(28 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
E' possibile intercettare i dati ''grezzi'' provenienti dalla tastiera, per individuare di ciascun tasto pemuto il suo [http://xoomer.virgilio.it/ramsoft/scancode.html<FONT color=#B22222>''codice di scansione''</font>].
+
E' possibile intercettare i dati ''grezzi'' provenienti dalla tastiera, per individuare di ciascun tasto premuto il suo [http://xoomer.virgilio.it/ramsoft/scancode.html''Codice di Scansione''].
  
  
Per gestire direttamente i dati grezzi della tastiera, bisogna innanzitutto individuare il suo file-device. Sappiamo che esso è presente nel percorso ''/dev/input/'', ed è rappresentato da uno dei file con il nome ''eventN''; laddove "N" è un suffisso del nome rappresentato da un numero. |[[#Note|1]]| Per individuare precisamente quale sia il file-device associato alla tastiera, fra quelli che iniziano per ''event'', bisognerà ''interrogare'' il file "''/proc/bus/input/devices''". Tale file mostra quali dispositivi e gestori di input sono attualmente attivi, ed all'interno del quale bisognerà individuare la riga che inizia per ''H:'', e che rappresenta i driver gestore associati ad un determinato dispositivo. Pertanto, la riga "H:" che si riferisce alla tastiera si presenta visivamente come segue:
+
Per gestire direttamente i dati grezzi della tastiera, bisogna innanzitutto individuare il suo file-device. Sappiamo che esso è presente nel percorso ''/dev/input/'', ed è rappresentato da uno dei file con il nome ''eventN''; laddove "N" è un suffisso del nome rappresentato da un numero. <SUP>[[#Note|nota 1]]</sup>
  H: Handlers=sysrq kbd event''N''
+
<BR>Per individuare precisamente quale sia il file-device associato alla tastiera, fra quelli che iniziano per ''event'', bisognerà ''interrogare'' il file:
laddove N è in realtà un numero.
+
''/proc/bus/input/devices''
 +
Tale file mostra quali dispositivi e gestori di input sono attualmente attivi, ed all'interno del quale bisognerà individuare la riga che inizia per ''H:'', e che rappresenta i driver gestore associati ad un determinato dispositivo. Pertanto, la riga "H:" che si riferisce alla tastiera si presenta visivamente come segue:
 +
  H: Handlers=sysrq kbd event<FONT Color=#B22222 Size=2>n</font>
 +
laddove <FONT Color=#B22222>n</font> è in realtà un numero. <SUP>[[#Note|nota 2]]</sup>
  
 
Individuato, dunque, il file-device associato alla tastiera, lo gestiremo con una variabile di tipo ''Process''.
 
Individuato, dunque, il file-device associato alla tastiera, lo gestiremo con una variabile di tipo ''Process''.
  
Per ogni tasto che viene premuto, vengono intercettati dal file-device della tastiera ben 144 dati; il 21° ci darà il ''codice di scansione'' del tasto della tastiera. Tale codice, identificando univocamente il tasto appena premuto o rilasciato, è dunque universale per tutti i calcolatori, e quindi tranquillamente utilizzabile nei nostri programmi Gambas.
+
Ogni volta che è premuto un tasto della tastiera, vengono scritti nel file-device della tastiera alcuni dati, che potranno essere ovviamente letti dal programma gambas. Il 21° dato ci darà il "''[http://spazioinwind.libero.it/ramsoft/scancode.htm Codice di Scansione]''" del tasto premuto. Tale codice, identificando univocamente il tasto appena premuto o rilasciato, è dunque universale per tutti i calcolatori, e quindi tranquillamente utilizzabile nei nostri programmi Gambas.
  
  
===Codice esemplificativo in ambiente grafico Gambas===
+
==Codice esemplificativo in ambiente grafico con le sole risorse di Gambas==
Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare in ambiente grafico di Gambas, per ciascun tasto premuto, il ''codice di scansione''. E' necessario attivare il componente ''gb.desktop'' ed aver installato ''xterm''.
+
Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare in ambiente grafico di Gambas, per ciascun tasto premuto, il "''[http://spazioinwind.libero.it/ramsoft/scancode.htm Codice di Scansione]''"
'''Private''' pr As Process
+
<BR>Supponiamo, nell'esempio che segue, che sia stato già individuato il file-device corrispondente alla tastiera, e che sia stato già da noi privato della sua protezione.
  '''Private''' lett As New String[]
+
<BR>Tale file-device sarà aperto in lettura e posto sotto ''osservazione'' con la parola-chiave ''Watch''.
 +
<BR>I dati letti dal file-device saranno caricati in una variabile di tipo ''Stringa'', dalla quale sarà estrapolato il 21° dato-valore.
 +
  Private fl As File
 
   
 
   
 
   
 
   
 
  '''Public''' Sub Form_Open()
 
  '''Public''' Sub Form_Open()
 +
 
 +
  fl = Open "/dev/input/event4" For Read Watch
 +
 
 +
'''End'''
 +
 
   
 
   
 +
'''Public''' Sub File_Read()
 +
 
 
   Dim s As String
 
   Dim s As String
   Dim ss As New String[]
+
    
   Dim j As Short
+
   TextArea1.Text &= gb.NewLine
 +
 
 +
  Read #fl, s, -256
 +
 
 +
  TextArea1.Text &= "Codice di scansione del tasto premuto:  " & Asc(s, 21)
 +
   
 +
'''End'''
 
   
 
   
   
 
    s = File.Load("/proc/bus/input/devices")
 
 
   
 
   
    s = Replace$(s, "\n", " ")
+
'''Public''' Sub Form_Close()
 +
 
 +
  fl.Close
 +
 
 +
'''End'''
 +
====Come il precedente, ma in applicazione ''a riga di comando''====
 +
Private fl As File
 
   
 
   
    ss = Split(s, " ", "", True)
 
 
   
 
   
 +
'''Public''' Sub Main()
 
   
 
   
  <FONT color=gray>' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
  <FONT Color=gray>' ''Con questa riga di comando viene eliminata la protezione al file-device da leggere.''
' ''Questa prima parte, volendo, può essere sostituita dalle seguenti righe con "Input":''
+
' ''E' necessario porre la propria "password" di sistema al posto della parola "MIA_PASSWORD":''</font>
    Dim fl As File
+
  Shell "echo <FONT Color=#B22222>''MIA_PASSWORD''</font> | sudo -S chmod 666 /dev/" Wait
 
   
 
   
    fl = Open "/proc/bus/input/devices" For Input
+
  fl = Open "/dev/input/event4" For Read Watch
 
 
    While Not Eof(fl)
 
      Input #fl, s
 
      ss.Add(s)
 
    Wend
 
' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''</font>
 
 
   
 
   
 +
'''End'''
 
   
 
   
    For j = 0 To ss.Max
+
  '''Public''' Sub File_Read()
  <FONT color=#006400>' ''Individuiamo la riga contenente il testo "Handlers=sysrq",''
+
 
' e quindi raccogliamo l'ultima parola della riga medesima. Tale parola sarà in nome del file-device della tastiera:''</font>
+
  Dim s As String
      If ss[j] = "Handlers=sysrq" Then s = ss[j + 2]
 
    Next
 
 
   
 
   
<FONT color=#006400>' ''Per leggere il file-device individuato, bisogna avere i necessari permessi.''
+
  Read #fl, s, -256
' Pertanto, se non sono stati modificati i permessi del file-device, allora vengono modificati
+
 
' (bisognerà inserire la propria password):''</font>
+
  Print "Codice di scansione del tasto premuto:  " & Asc(s, 21)
    If Stat("/dev/input" &/ s).Auth <> "rwsrwxrwx" Then
+
      
      Desktop.RunAsRoot("sudo -S chmod 4777 /dev/input" &/ s)
+
'''End'''
     Endif
 
 
   
 
   
  <FONT color=#006400>' ''Poniamo un'attesa mediante un ciclo, fino a che i permessi del file-device non saranno mutati:''</font>
+
  '''Public''' Sub Application_Read() <FONT Color=gray>' ''Se si preme il tasto "Invio" della tastiera, viene sollevato questo Evento</font>
    Do
+
 
      Wait 0.01
+
  fl.Close
    Loop Until Stat("/dev/input" &/ s).Auth = "rwsrwxrwx"
 
 
<FONT color=#006400>' ''Finalmente il file-device viene gestito mediante un "Processo":''</font>
 
    pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
 
 
   
 
   
 +
<FONT Color=gray>' ''Avendo sollevato l'Evento "Application_Read()", per chiudere l'applicazione è necessario usare l'istruzione "Quit":</font>
 +
  Quit
 +
 
 
  '''End'''
 
  '''End'''
 +
 +
==Usando la funzione esterna "ioctl()"==
 +
In questo secondo esempio useremo la funzione esterna ''ioctl( )'':
 +
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
 
   
 
   
  '''Public''' Sub processo_Read()
+
  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
 
   
 
   
  Dim b As Byte
+
<FONT Color=gray>' ''int ioctl(int __fd, unsigned long int __request, ...)''
  Dim s As String
+
' ''Perform the I/O control operation specified by REQUEST on FD.''</font>
 +
Private Extern ioctl_name(__fd As Integer, __request As Long, arg As Byte[]) As Integer Exec "ioctl"
 
   
 
   
 +
Private Extern ioctl_grab(__fd As Integer, __request As Long, arg As Integer) As Integer Exec "ioctl"
 
   
 
   
  <FONT color=#006400>' ''Legge i dati provenienti dal file-device della tastiera:''</font>
+
  <FONT Color=gray>' ''ssize_t read (int __fd, void *__buf, size_t __nbytes)
    Read #pr, b
+
' ''Read NBYTES into BUF from FD.''</font>
 +
Private Extern read_C(__fd As Integer, __buf As Input_event, __nbytes As Long) As Long Exec "read"
 
   
 
   
    lett.Add(CStr(b))
+
Private ke As New Input_event
 +
Private kfl As File
 
   
 
   
    If lett.Count = 144 Then
 
 
   
 
   
  <FONT color=#006400>' ''Legge l'elemento di numero d'indice 20 della variabile array:''</font>
+
  '''Public''' Sub Main()
      Print "Codice scansione tasto:  "; lett[20]
 
 
   
 
   
      lett.Clear
+
  Dim keyboard_name As New Byte[256]
 +
  Dim rit As Long
 +
 
 +
<FONT Color=gray>' ''Supponendo che il file-device attinente alla tastiera sia "event4" (al quale dovrà essere ovviamente eliminata la protezione), lo si apre in "Lettura" e lo si pone in "osservazione":''</font>
 +
  kfl = Open "/dev/input/event4" For Read Watch
 +
  If kfl.Handle == -1 Then
 +
    kfl.Close
 +
    Error.Raise("Error !")
 +
  Endif
 +
 
 +
  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))
 
   
 
   
    Endif
+
  rit = ioctl_grab(kfl.Handle, Eviocgrab(Asc("E"), &h90, SizeOf(gb.Integer)), 1)
 +
  Print "\e[0mGetting exclusive access: "; IIf(rit == 0, "\e[32mSUCCESS\e[0m", "\e[31mFAILURE\e[0m")
 +
 
 +
  Print
 
    
 
    
 +
'''End'''
 +
 +
'''Public''' Sub File_Read()
 +
 
 +
  Dim rit As Long
 +
 
 +
  rit = read_C(kfl.Handle, ke, Object.SizeOf(ke))
 +
 
 +
  If rit > -1 Then
 +
    Print "\e[1mtime\e[0m: "; ke.time_.tv_sec; " , \e[1mtype\e[0m: "; ke.type &
 +
    " , \e[1mcode\e[0m: "; ke.code; " , \e[1mvalue\e[0m: "; ke.value
 +
<FONT Color=gray>' ''Se viene premuto il tasto "Esc", il programma viene chiuso:''</font>
 +
    If (ke.type == 4) And (ke.code == 4) And (ke.value == 1) Then kfl.Close
 +
  Endif
 +
 
 +
'''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'''
 
  '''End'''
  
 
+
==Usando la funzione ''Exec'' e il comando bash ''cat''==
===Codice esemplificativo in applicazione Gambas ''a riga di comando''===
+
In quest'altro esempio è necessario attivare il componente ''gb.desktop'' ed aver installato ''xterm'': si provvederà da codice ad individuare e successivamente a eliminare la protezione del file-device corrispondente alla tastiera.
Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare nell'ambito di un'applicazione Gambas ''a riga di comando'', per ciascun tasto premuto, il ''codice di scansione''.
+
<BR>Per ogni tasto che viene premuto, vengono intercettati dal file-device della tastiera ben 144 dati; il 21° ci darà il ''codice di scansione'' del tasto premuto della tastiera.
  '''Private''' pr As Process
+
  Private pr As Process
  '''Private''' lett As New String[]
+
  Private lett As New String[]
 
   
 
   
 
   
 
   
Riga 100: Riga 179:
 
   
 
   
 
   Dim s As String
 
   Dim s As String
   Dim ss As New String[]
+
   Dim i As Integer
  Dim j As Short
+
 
 +
  s = File.Load("/proc/bus/input/devices")
 +
 
 +
<FONT color=gray>' ''Individuiamo la riga contenente il testo "Handlers=sysrq"; ed individuiamo il nome del file-device della tastiera:''</font>
 +
  s = Trim(Scan(s, "*Handlers=sysrq *\n*")[1])
 +
  i = InStr(s, "event")
 +
  s = Mid(s, i, 6)
 +
 
 +
<FONT color=gray>' ''Per leggere il file-device individuato, bisogna avere i necessari permessi.''
 +
' Pertanto, se non sono stati modificati i permessi del file-device, allora vengono modificati (bisognerà inserire la propria password):''</font>
 +
  If Stat("/dev/input" &/ s).Auth <> "rwsrwxrwx" Then
 +
    Desktop.RunAsRoot("sudo -S chmod 4777 /dev/input" &/ s)
 +
  Endif
 +
 
 +
<FONT color=gray>' ''Poniamo un'attesa mediante un ciclo, fino a che i permessi del file-device non saranno mutati:''</font>
 +
  Do
 +
    Wait 0.01
 +
  Loop Until Stat("/dev/input" &/ s).Auth = "rwsrwxrwx"
 +
 
 +
<FONT color=gray>' ''Finalmente il file-device viene gestito mediante un "Processo":''</font>
 +
  pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
 +
 
 +
'''End'''
 
   
 
   
   
 
    s = File.Load("/proc/bus/input/devices")
 
 
   
 
   
    s = Replace$(s, "\n", " ")
+
'''Public''' Sub processo_Read()
 
   
 
   
    ss = Split(s, " ", "", True)
+
  Dim b As Byte
+
 
+
  <FONT color=gray>' ''Legge i dati provenienti dal file-device della tastiera:''</font>
  <FONT color=gray>' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
  Read #pr, b
' ''Questa prima parte, volendo, può essere sostituita dalle seguenti righe con "Input":''
+
 
    Dim fl As File
+
  lett.Add(CStr(b))
+
 
    fl = Open "/proc/bus/input/devices" For Input
+
  If lett.Count = 144 Then
 +
 
 +
<FONT color=gray>' ''Legge l'elemento di numero d'indice 20 della variabile array:''</font>
 +
    Print "Codice scansione tasto:  "; lett[20]
 +
   
 +
    lett.Clear
 +
   
 +
  Endif
 
    
 
    
    While Not Eof(fl)
+
  '''End'''
      Input #fl, s
+
 
      ss.Add(s)
+
====Come il precedente, ma in applicazione ''a riga di comando''====
    Wend
+
Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare nell'ambito di un'applicazione Gambas ''a riga di comando'', per ciascun tasto premuto, il ''codice di scansione''.
  ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''</font>
+
Private pr As Process
 +
Private lett As New String[]
 
   
 
   
 
   
 
   
    For j = 0 To ss.Max
+
  '''Public''' Sub Main()
  <FONT color=#006400>' ''Individuiamo la riga contenente il testo "Handlers=sysrq",''
 
' e quindi raccogliamo l'ultima parola della riga medesima. Tale parola sarà in nome del file-device della tastiera:''</font>
 
      If ss[j] = "Handlers=sysrq" Then s = ss[j + 2]
 
    Next
 
 
   
 
   
  <FONT color=#006400>' ''Per leggere il file-device individuato, bisogna avere i necessari permessi, e vengono quindi modificati.''
+
  Dim s, pass As String
  ' ''La parola "mia_password" della riga seguente è la password personale dell'utente:''</font>
+
  Dim i As Integer
    Shell "echo ''mia_password'' -S chmod 4777 /dev/input" &/ s)
+
     
 +
  s = File.Load("/proc/bus/input/devices")
 +
   
 +
<FONT color=gray>' ''Individuiamo la riga contenente il testo "Handlers=sysrq"; ed individuiamo il nome del file-device della tastiera:''</font>
 +
  s = Trim(Scan(s, "*Handlers=sysrq *\n*")[1])
 +
  i = InStr(s, "event")
 +
  s = Mid(s, i, 6)
 +
   
 +
  <FONT color=gray>' ''Per leggere il file-device individuato, bisogna avere i necessari permessi. Essi vengono quindi modificati.''
 +
  ' ''E' necessario inserire nell'apposito spazio sottostante la Console (o nel Terminale) la password personale dell'utente:''</font>
 +
  Print "Inserire nello spazio sottostante la propria 'password'."
 +
  Input pass
 +
  Shell "echo " & pass & " | sudo -S chmod 4777 /dev/input" &/ s Wait
 +
  Print 
 
    
 
    
 
+
  <FONT color=gray>' ''Finalmente il file-device viene gestito mediante un "Processo":''</font>
  <FONT color=#006400>' ''Finalmente il file-device viene gestito mediante un "Processo":''</font>
+
  pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
    pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
+
 
 
 
  '''End'''
 
  '''End'''
 
   
 
   
Riga 144: Riga 259:
 
   
 
   
 
   Dim b As Byte
 
   Dim b As Byte
  Dim s As String
 
 
   
 
   
 +
  While Not Eof(pr)
 +
<FONT color=gray>' ''Legge i dati provenienti dal file-device della tastiera:''</font>
 +
    Read #pr, b
 
   
 
   
<FONT color=#006400>' ''Legge i dati provenienti dal file-device della tastiera:''</font>
+
    lett.Add(CStr(b))
    Read #pr, b
 
 
   
 
   
    lett.Add(CStr(b))
+
    If lett.Count = 144 Then
+
  <FONT color=gray>' ''Legge l'elemento di numero d'indice 20 della variabile array:''</font>
    If lett.Count = 144 Then
+
      Print "Codice scansione tasto:  "; lett[20]
+
      lett.Clear
  <FONT color=#006400>' ''Legge l'elemento di numero d'indice 20 della variabile array:''</font>
+
    Endif
      Print "Codice scansione tasto:  "; lett[20]
+
  Wend
+
      
      lett.Clear
 
 
     Endif
 
 
 
 
  '''End'''
 
  '''End'''
  
Riga 169: Riga 281:
 
=Note=
 
=Note=
 
[1] Il nome ''event'' è dato dalla circostanza che il rapporto tra i vari elementi del sottosistema di input - ossia gli ingressi principali, i driver e gestori di eventi - avviene attraverso ''eventi''.
 
[1] Il nome ''event'' è dato dalla circostanza che il rapporto tra i vari elementi del sottosistema di input - ossia gli ingressi principali, i driver e gestori di eventi - avviene attraverso ''eventi''.
 +
 +
[2] In versioni di Mint superiori alla 17 dopo la parola "event<FONT Size=2>n</font>" è presente anche la parola "''leds''". Pertanto, se ne dovrà tenere conto ai fini dell'individuazione della parola ''event<FONT Size=2>n</font>''.
 +
 +
 +
 +
 +
=Riferimenti=
 +
* https://www.win.tue.nl/~aeb/linux/kbd/scancodes.html

Versione attuale delle 06:30, 20 mar 2023

E' possibile intercettare i dati grezzi provenienti dalla tastiera, per individuare di ciascun tasto premuto il suo Codice di Scansione.


Per gestire direttamente i dati grezzi della tastiera, bisogna innanzitutto individuare il suo file-device. Sappiamo che esso è presente nel percorso /dev/input/, ed è rappresentato da uno dei file con il nome eventN; laddove "N" è un suffisso del nome rappresentato da un numero. nota 1
Per individuare precisamente quale sia il file-device associato alla tastiera, fra quelli che iniziano per event, bisognerà interrogare il file:

/proc/bus/input/devices

Tale file mostra quali dispositivi e gestori di input sono attualmente attivi, ed all'interno del quale bisognerà individuare la riga che inizia per H:, e che rappresenta i driver gestore associati ad un determinato dispositivo. Pertanto, la riga "H:" che si riferisce alla tastiera si presenta visivamente come segue:

H: Handlers=sysrq kbd eventn

laddove n è in realtà un numero. nota 2

Individuato, dunque, il file-device associato alla tastiera, lo gestiremo con una variabile di tipo Process.

Ogni volta che è premuto un tasto della tastiera, vengono scritti nel file-device della tastiera alcuni dati, che potranno essere ovviamente letti dal programma gambas. Il 21° dato ci darà il "Codice di Scansione" del tasto premuto. Tale codice, identificando univocamente il tasto appena premuto o rilasciato, è dunque universale per tutti i calcolatori, e quindi tranquillamente utilizzabile nei nostri programmi Gambas.


Codice esemplificativo in ambiente grafico con le sole risorse di Gambas

Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare in ambiente grafico di Gambas, per ciascun tasto premuto, il "Codice di Scansione"
Supponiamo, nell'esempio che segue, che sia stato già individuato il file-device corrispondente alla tastiera, e che sia stato già da noi privato della sua protezione.
Tale file-device sarà aperto in lettura e posto sotto osservazione con la parola-chiave Watch.
I dati letti dal file-device saranno caricati in una variabile di tipo Stringa, dalla quale sarà estrapolato il 21° dato-valore.

Private fl As File


Public Sub Form_Open()
 
 fl = Open "/dev/input/event4" For Read Watch
  
End


Public Sub File_Read()
 
 Dim s As String
 
 TextArea1.Text &= gb.NewLine
 
 Read #fl, s, -256
 
 TextArea1.Text &= "Codice di scansione del tasto premuto:  " & Asc(s, 21)
    
End


Public Sub Form_Close()
 
 fl.Close
 
End

Come il precedente, ma in applicazione a riga di comando

Private fl As File


Public Sub Main()

' Con questa riga di comando viene eliminata la protezione al file-device da leggere.
' E' necessario porre la propria "password" di sistema al posto della parola "MIA_PASSWORD":
 Shell "echo MIA_PASSWORD | sudo -S chmod 666 /dev/" Wait

 fl = Open "/dev/input/event4" For Read Watch

End

Public Sub File_Read()
 
 Dim s As String

 Read #fl, s, -256
 
 Print "Codice di scansione del tasto premuto:  " & Asc(s, 21)
   
End

Public Sub Application_Read() ' Se si preme il tasto "Invio" della tastiera, viene sollevato questo Evento
 
 fl.Close

' Avendo sollevato l'Evento "Application_Read()", per chiudere l'applicazione è necessario usare l'istruzione "Quit":
 Quit
 
End

Usando la funzione esterna "ioctl()"

In questo secondo esempio useremo la funzione esterna ioctl( ):

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"

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"

Private ke As New Input_event
Private kfl As File


Public Sub Main()

 Dim keyboard_name As New Byte[256]
 Dim rit As Long
  
' Supponendo che il file-device attinente alla tastiera sia "event4" (al quale dovrà essere ovviamente eliminata la protezione), lo si apre in "Lettura" e lo si pone in "osservazione":
 kfl = Open "/dev/input/event4" For Read Watch
 If kfl.Handle == -1 Then
   kfl.Close
   Error.Raise("Error !")
 Endif
  
 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))

 rit = ioctl_grab(kfl.Handle, Eviocgrab(Asc("E"), &h90, SizeOf(gb.Integer)), 1)
 Print "\e[0mGetting exclusive access: "; IIf(rit == 0, "\e[32mSUCCESS\e[0m", "\e[31mFAILURE\e[0m")
 
 Print
 
End

Public Sub File_Read()
 
 Dim rit As Long
 
 rit = read_C(kfl.Handle, ke, Object.SizeOf(ke))
  
 If rit > -1 Then
   Print "\e[1mtime\e[0m: "; ke.time_.tv_sec; " , \e[1mtype\e[0m: "; ke.type &
   " , \e[1mcode\e[0m: "; ke.code; " , \e[1mvalue\e[0m: "; ke.value
' Se viene premuto il tasto "Esc", il programma viene chiuso:
   If (ke.type == 4) And (ke.code == 4) And (ke.value == 1) Then kfl.Close
 Endif
  
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

Usando la funzione Exec e il comando bash cat

In quest'altro esempio è necessario attivare il componente gb.desktop ed aver installato xterm: si provvederà da codice ad individuare e successivamente a eliminare la protezione del file-device corrispondente alla tastiera.
Per ogni tasto che viene premuto, vengono intercettati dal file-device della tastiera ben 144 dati; il 21° ci darà il codice di scansione del tasto premuto della tastiera.

Private pr As Process
Private lett As New String[]


Public Sub Form_Open()

 Dim s As String
 Dim i As Integer
  
  s = File.Load("/proc/bus/input/devices")
  
' Individuiamo la riga contenente il testo "Handlers=sysrq"; ed individuiamo il nome del file-device della tastiera:
  s = Trim(Scan(s, "*Handlers=sysrq *\n*")[1])
  i = InStr(s, "event")
  s = Mid(s, i, 6)
  
' Per leggere il file-device individuato, bisogna avere i necessari permessi.
' Pertanto, se non sono stati modificati i permessi del file-device, allora vengono modificati (bisognerà inserire la propria password):
  If Stat("/dev/input" &/ s).Auth <> "rwsrwxrwx" Then
    Desktop.RunAsRoot("sudo -S chmod 4777 /dev/input" &/ s)
  Endif
  
' Poniamo un'attesa mediante un ciclo, fino a che i permessi del file-device non saranno mutati:
  Do
    Wait 0.01
  Loop Until Stat("/dev/input" &/ s).Auth = "rwsrwxrwx"
  
' Finalmente il file-device viene gestito mediante un "Processo":
  pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
  
End


Public Sub processo_Read()

 Dim b As Byte
 
' Legge i dati provenienti dal file-device della tastiera:
  Read #pr, b
  
  lett.Add(CStr(b))
  
  If lett.Count = 144 Then
  
' Legge l'elemento di numero d'indice 20 della variabile array:
    Print "Codice scansione tasto:   "; lett[20]
    
    lett.Clear
    
  Endif
  
End

Come il precedente, ma in applicazione a riga di comando

Mostriamo di seguito un possibile codice esemplificativo per intercettare e ricavare nell'ambito di un'applicazione Gambas a riga di comando, per ciascun tasto premuto, il codice di scansione.

Private pr As Process
Private lett As New String[]


Public Sub Main()

 Dim s, pass As String
 Dim i As Integer
     
  s = File.Load("/proc/bus/input/devices")
   
' Individuiamo la riga contenente il testo "Handlers=sysrq"; ed individuiamo il nome del file-device della tastiera:
  s = Trim(Scan(s, "*Handlers=sysrq *\n*")[1])
  i = InStr(s, "event")
  s = Mid(s, i, 6)
    
' Per leggere il file-device individuato, bisogna avere i necessari permessi. Essi vengono quindi modificati.
' E' necessario inserire nell'apposito spazio sottostante la Console (o nel Terminale) la password personale dell'utente:
  Print "Inserire nello spazio sottostante la propria 'password'."
  Input pass
  Shell "echo " & pass & " | sudo -S chmod 4777 /dev/input" &/ s Wait
  Print  
 
' Finalmente il file-device viene gestito mediante un "Processo":
  pr = Exec ["cat", "/dev/input" &/ s] For Read As "processo"
  
End


Public Sub processo_Read()

 Dim b As Byte

  While Not Eof(pr)
' Legge i dati provenienti dal file-device della tastiera:
    Read #pr, b

    lett.Add(CStr(b))

    If lett.Count = 144 Then
' Legge l'elemento di numero d'indice 20 della variabile array:
      Print "Codice scansione tasto:   "; lett[20]
      lett.Clear
    Endif
  Wend
   
End




Note

[1] Il nome event è dato dalla circostanza che il rapporto tra i vari elementi del sottosistema di input - ossia gli ingressi principali, i driver e gestori di eventi - avviene attraverso eventi.

[2] In versioni di Mint superiori alla 17 dopo la parola "eventn" è presente anche la parola "leds". Pertanto, se ne dovrà tenere conto ai fini dell'individuazione della parola eventn.



Riferimenti