package Linux::Input;
$VERSION = '1.03';
use strict;
use Config;
# class data
Linux::Input->mk_classdata('event_bytes');
Linux::Input->event_bytes(
($Config{longsize} * 2) + # input_event.time (struct timeval)
($Config{i16size} * 2) + # input_event.type, input_event.code
($Config{i32size}) # input_event.value
);
Linux::Input->mk_classdata('timeout');
Linux::Input->timeout(0.01);
# instaniate a new input device
sub new {
my $class = shift;
my $filename = shift;
my $self = { };
bless ($self => $class);
$self->{fh} = IO::File->new("< $filename");
die($!) unless ($self->{fh});
return $self;
}
# get filehandle of device
sub fh {
my $self = shift;
return $self->{fh};
}
# $self's IO::Select object
sub selector {
my $self = shift;
unless ($self->{__io_select}) {
$self->{__io_select} = IO::Select->new($self->fh());
}
return $self->{__io_select};
}
# poll for all pending events
sub poll {
my $self = shift;
my $timeout = shift || ref($self)->timeout();
my $selector = $self->selector();
my @ev;
my $struct_len = Linux::Input->event_bytes();
while (my ($fh) = $selector->can_read($timeout)) {
my $buffer;
my $len = sysread($fh, $buffer, $struct_len);
my ($sec, $usec, $type, $code, $value) =
unpack('L!L!S!S!i!', $buffer);
my $event = {
tv_sec => $sec,
tv_usec => $usec,
type => $type,
code => $code,
value => $value,
};
push @ev, $event if (defined($type));
}
return @ev;
}
1;
__END__
=head1 NAME
Linux::Input - Linux input event interface
=head1 SYNOPSIS
Example: 1 joystick using event API
my $js1 = Linux::Input->new('/dev/input/event3');
while (1) {
while (my @events = $js1->poll(0.01)) {
foreach (@event) {
}
}
}
Example: 2 joysticks using joystick API (different event structure)
my $js1 = Linux::Input::Joystick->new('/dev/input/js0');
my $js2 = Linux::Input::Joystick->new('/dev/input/js1');
my $selector = IO::Select->new();
$selector->add($js1->fh);
$selector->add($js2->fh);
while (my $fh = $selector->can_read) {
my @event;
if ($fh == $js1->fh) {
@event = $js1->poll()
} elsif ($fh == $js2->fh) {
@event = $js2->poll()
}
foreach (@event) {
# work
}
}
Example 3: monitor all input devices
use File::Basename qw(basename);
my @inputs = map { "/dev/input/" . basename($_) }
</sys/class/input/event*>;
my @dev;
my $selector = IO::Select->new();
foreach (@inputs) {
my $device = Linux::Input->new($_);
$selector->add($device->fh);
push @dev, $device;
}
while (my $fh = $selector->can_read) {
# work
}
Example 4: testing for events on the command line
# information on what event queue belongs to what device
cat /proc/bus/input/devices
# verify that events are coming in
sudo evtest.pl /dev/input/event*
=head1 DESCRIPTION
L<Linux::Input> provides a pure-perl interface to the
Linux kernel's input event interface. It basically provides
a uniform API for getting realtime data from all the different
input devices that Linux supports.
For more information, please read:
F</usr/src/linux/Documentation/input/input.txt>.
=head2 Class Methods
=head3 new
This method takes one filename as a parameter and returns
a L<Linux::Input> object.
B<Example>:
my $js1 = Linux::Input->new('/dev/input/event3');
=head3 entity_bytes
This method returns the size of the event structure
on this system.
B<Example>:
my $struct_size = Linux::Input->entity_bytes();
=head3 timeout
This method can be used to read or specify the default
timeout value for the select()'ing on filehandles that
happens within the module. The default value is 0.01.
=head2 Object Methods
=head3 fh
This method returns the filehandle of a L<Linux::Input>
object.
B<Example>:
my $filehandle = $js->fh();
=head3 selector
This method is used internally to return the
L<IO::Select> object that's been assigned to
the current L<Linux::Input> object.
=head3 poll
This method takes a C<$timeout> value as a parameter
and returns a list of C<@events> for the current
L<Linux::Input> object. Each event is a hashref with
the following key/value pairs.
=over 2
=item tv_sec
=item tv_usec
=item type
=item code
=item value
=back
B<Example>:
my @events = $js->poll(0.01);
=head1 AUTHOR
John Beppu (beppu@cpan.org)
=head1 SEE ALSO
L<Linux::Input::Joystick>,
L<Class::Data::Inheritable>,
L<IO::Select>,
L<IO::File>
=cut
# vim:sw=2 sts=2 expandtab