¿Puedo evitar que Linux escuche un dispositivo de entrada USB como teclado, pero aún así capturar eventos con un programa?

11

Tengo un escáner de código de barras USB en /dev/input/event0( /dev/input/by-id/usb-Metrologic_Metrologic_Scanner-event-kbd), y escanear un código de barras hace que envíe eventos de pulsación de tecla. Estoy capturando estas pulsaciones de teclas usando la biblioteca libdevinput Ruby, que funciona muy bien. El problema es que cada código de barras también se ingresa como nombre de usuario y, posteriormente, como contraseña en la Raspberry Pi, lo que provoca muchos intentos fallidos de inicio de sesión. (La Raspberry Pi estará sin cabeza y dentro de un microondas).

¿Cómo puedo evitar que Linux vea el escáner de código de barras como un dispositivo de entrada y que mi programa sea el único consumidor del evento? ¿O hay una solución diferente y mejor?

ndbroadbent
fuente
44
No recomiendo poner la electrónica en un microondas. Ciertamente no uno corriendo.
Ignacio Vazquez-Abrams
1
Esa es definitivamente la parte más "wtf" de esta pregunta.
Bratchley
1
Jaula de Faraday barata? Tal vez hay mucha RF en el área.
charlesbridge
44
Jajaja, no en el microondas. Todo se encuentra detrás de la PCB controladora del microondas, y no tengo la intención de cocinar mi Raspberry Pi. Estoy agregando un escáner de código de barras para las instrucciones de cocción, así como el control por voz y un panel táctil rediseñado.
ndbroadbent

Respuestas:

6

Descubrí que necesito enviar un EVIOCGRAB ioctl al dispositivo, que lo toma para uso exclusivo .

Aquí se explica cómo hacerlo en Ruby:

#!/usr/bin/env ruby
BARCODE_SCANNER = "/dev/input/by-id/usb-Metrologic_Metrologic_Scanner-event-kbd"

require 'rubygems'
require 'libdevinput'
require 'ffi'
require 'ffi/tools/const_generator'

# We need access to the file
DevInput.class_eval { attr_reader :dev }

# Look up value of EVIOCGRAB constant
cg = FFI::ConstGenerator.new('input') do |gen|
  gen.include('linux/input.h')
  gen.const(:EVIOCGRAB, '%u', '(unsigned)')
end
EVIOCGRAB = cg['EVIOCGRAB'].to_i

scanner = DevInput.new(BARCODE_SCANNER)
# Send EVIOCGRAB to scanner, which grabs it for exclusive use by our process
scanner.dev.ioctl(EVIOCGRAB, 1)


puts "Waiting for events..."
scanner.each do |event|
  # Ignore everything except key press events
  next unless event.type == 1 && event.value == 1
  puts "Key: #{event.code_str}"
end

Nota : Deberá instalar la libdevinputgema ffiy los encabezados de Linux. Si está utilizando una versión de Linux entre 3.2.0y 3.6.11, puede reemplazar la FFI::ConstGeneratorparte con EVIOCGRAB = 1074021776, y luego no necesita ffiencabezados de Linux.

ndbroadbent
fuente
2

Suena de alguna manera similar a este problema , así que probaría esta solución  : si entiendo correctamente su problema, el escáner de código de barras debería aparecer como un puntero esclavo del "Teclado de núcleo virtual" cuando lo haga

xinput --list

Entonces, tal vez obtener su ID y obligarlo a flotar podría ayudar:

xinput float <id>
Skippy le Grand Gourou
fuente
Creo que OP está viendo estos en la consola, no X. Pero en X esto debería funcionar.
derobert
Ah bien. Además, ya ha encontrado una solución ...
Skippy le Grand Gourou