Posso parar o Linux de ouvir um dispositivo de entrada USB como teclado, mas ainda assim capturar eventos com um programa?

11

Eu tenho um scanner de código de barras USB em /dev/input/event0( /dev/input/by-id/usb-Metrologic_Metrologic_Scanner-event-kbd) e a digitalização de um código de barras faz com que ele envie eventos de pressionamento de tecla. Estou capturando essas teclas pressionadas usando a biblioteca libdevinput Ruby, que funciona muito bem. O problema é que cada código de barras também é inserido como um nome de usuário e, posteriormente, uma senha no Raspberry Pi, causando muitas tentativas falhas de login. (O Raspberry Pi ficará sem cabeça e dentro de um microondas.)

Como posso impedir que o Linux veja o scanner de código de barras como um dispositivo de entrada e que meu programa seja o único consumidor de eventos? Ou existe uma solução diferente e melhor?

ndbroadbent
fonte
4
Eu não recomendo colocar eletrônicos no microondas. Certamente não é uma corrida.
Ignacio Vazquez-Abrams
1
Essa é definitivamente a parte mais "wtf" desta questão.
Bratchley
1
Gaiola de Faraday barata? Talvez haja muita RF na área.
Charlesbridge
4
Hahaha, não no microondas. Tudo fica atrás do PCB do controlador do micro-ondas, e não pretendo cozinhar meu Raspberry Pi. Estou adicionando um scanner de código de barras para obter instruções de culinária, controle de voz e um touch pad redesenhado.
Ndbroadbent

Respostas:

6

Descobri que preciso enviar um ioctl EVIOCGRAB para o dispositivo, que o agarra para uso exclusivo .

Veja como fazer isso em 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 : Você precisará instalar os cabeçalhos libdevinputgem ffi, e Linux. Se você estiver usando uma versão do Linux entre 3.2.0e 3.6.11, poderá substituir a FFI::ConstGeneratorpeça e EVIOCGRAB = 1074021776, em seguida, não precisará de fficabeçalhos ou Linux.

ndbroadbent
fonte
2

Parece algo semelhante a esse problema , então eu tentaria esta solução  : se eu entendi corretamente o seu problema, o scanner de código de barras deve aparecer como um ponteiro escravo do "Virtual core keyboard" quando você o faz

xinput --list

Então, talvez obter seu ID e forçá-lo a flutuar poderia ajudar:

xinput float <id>
Skippy le Grand Gourou
fonte
Eu acho que o OP está vendo isso no console, não no X. Mas no X isso deve funcionar.
Derrepert 4/13
Ah, certo. Além disso, ele já encontrou uma solução ...
Skippy le Grand Gourou 04/10