Je suis en train de créer un pilote de périphériques qui consomme des données à partir d'un périphérique d'émulation de clavier.Comportement du périphérique de l'émulateur de clavier sur Ubuntu
Le dispositif est un simple glissement de la carte, de sorte que son comportement est comme suit:
- utilisateur se dirige, Swipes carte
- Je reçois une chaîne de caractères (codes clés, vraiment, y compris les touches de modification du capital lettres)
- Je ne sais pas combien de personnages que je vais obtenir
- Je ne sais pas quand je reçois quelque chose
Puisque je ne sais pas combien de caractères je vais avoir, bloquer les lectures sur le clavier tty n'est pas utile - je finirais par bloquer après le dernier personnage. Ce que je fais est, dans Ruby, en utilisant le module IO pour effectuer des lectures asynchrones sur le clavier, et en utilisant un timeout pour déterminer que la fin des données a été atteinte. Cela fonctionne très bien logiquement (même un utilisateur balayant sa carte rapidement le fera plus lentement que le taux d'envoi entre les caractères).
Le problème est que, parfois, je perds des données à partir du milieu de la chaîne. Mon intuition est qu'il y a une sorte de débordement de tampon qui se produit parce que je lis les données trop lentement. En essayant de confirmer cela, j'ai inséré de petites attentes entre chaque processus clé. Des attentes plus longues (20ms +) aggravent le problème. Cependant, une attente d'environ 5ms le fait disparaître? La seule explication que je peux trouver est que la lecture asynchrone elle-même est chère (parce que Ruby), et les faire sans limite de vitesse est en fait plus lent que de les faire avec un délai de 5ms.
Cela semble-t-il rationnel? Y a-t-il d'autres idées sur ce que cela pourrait être?
Le rubis est en fait JRuby 9000. La machine est Ubuntu LTS 16.
Edit: voici un extrait du code correspondant
private def read_swipe(buffer_size, card_reader_input, pause_between_reads, seconds_to_complete)
limit = Time.now + seconds_to_complete.seconds
swipe_data = ''
begin
start_time = Time.now
sleep pause_between_reads
batch = card_reader_input.read_nonblock(buffer_size)
swipe_data << batch
rescue IO::WaitReadable
IO.select([card_reader_input], nil, nil, 0.5)
retry unless limit < start_time
end while start_time < limit
swipe_data
end
où card_reader_input = File.new(event_handle, 'rb')
pouvez-vous montrer une partie de votre code pour avoir une meilleure idée –
@maxpleaner done – kolosy