File Coverage

blib/lib/Device/SpaceNavigator.pm
Criterion Covered Total %
statement 43 50 86.0
branch 15 30 50.0
condition 4 6 66.6
subroutine 7 8 87.5
pod 4 4 100.0
total 73 98 74.4


line stmt bran cond sub pod time code
1             package Device::SpaceNavigator;
2 2     2   50546 use strict;
  2         5  
  2         96  
3 2     2   13 use Carp;
  2         6  
  2         165  
4 2     2   10560 use IO::Select;
  2         8023  
  2         2417  
5              
6             our $VERSION = '0.02';
7             our $AUTOLOAD;
8              
9             sub new {
10 1     1 1 14 my ($class, $device) = @_;
11              
12 1         41 my $self = {
13             device => "/dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00",
14             events => ['x', 'y', 'z', 'pitch', 'roll', 'yaw'],
15             buttons => ['left_button', 'right_button'],
16             connected => 0,
17             };
18              
19 1         2 foreach (@{$self->{'events'}}, @{$self->{'buttons'}}) {
  1         4  
  1         3  
20 8         18 $self->{$_} = 0;
21             }
22              
23            
24 1         5 bless $self, $class;
25             }
26              
27             sub open {
28 4     4 1 862 my ($self, $device) = @_;
29              
30 4 50       12 if ($device) {
31 4         12 $self->{'device'} = $device;
32             }
33              
34 4 50       271 open($self->{'_fh'}, $self->{'device'}) || croak("$!");
35 4         20 binmode $self->{'_fh'};
36              
37 4         23 $self->{'_select'} = IO::Select->new($self->{'_fh'});
38             }
39              
40             sub close {
41 0     0 1 0 my ($self) = @_;
42              
43 0 0       0 if ($self->{'_fh'}) {
44 0 0       0 CORE::close $self->{'_fh'} || croak("$!");
45             }
46             }
47              
48             sub update {
49 16     16 1 217 my ($self, $wait) = @_;
50 16         19 my $str;
51              
52 16 50       43 if (!$self->{'_fh'}) {
53 0         0 $self->open();
54             }
55              
56 16 50       70 $self->{'_select'}->can_read( defined($wait) ? $wait : 1 ) || return;
    50          
57 16 50       624 if(read($self->{'_fh'}, $str, 8) != 8) {
58 0         0 CORE::close $self->{'_fh'};
59 0         0 return 1;
60             }
61              
62 16         119 my @s = unpack("C*", $str);
63              
64             # Handle button
65 16 100 66     88 if ($s[0] == 1 && $s[1] == 0) {
66 4 50       15 if ($self->{'buttons'}->[$s[2]]) {
67 4         11 $self->{$self->{'buttons'}->[$s[2]]} = $s[4];
68             }
69             }
70              
71             # Handle move
72 16 100 66     100 if ($s[0] == 2 && $s[1] == 0) {
73 12         49 my $value = unpack("s",chr($s[4]).chr($s[5]));
74 12 50       48 if ($self->{'events'}->[$s[2]]) {
75 12         41 $self->{$self->{'events'}->[$s[2]]} = $value;
76             }
77             }
78              
79 16         90 return 1;
80             }
81              
82             sub AUTOLOAD {
83 16     16   67 my $self = shift;
84 16 50       44 my $type = ref($self)
85             or croak "$self is not an object";
86              
87 16         21 my $name = $AUTOLOAD;
88 16         79 $name =~ s/.*://; # strip fully-qualified portion
89              
90 16 50       51 return if $AUTOLOAD =~ /::DESTROY$/;
91              
92 16 50       36 unless (exists $self->{$name} ) {
93 0         0 croak "Can't access `$name' field in class $type";
94             }
95              
96 16         109 return $self->{$name};
97             }
98              
99             1;
100              
101             __END__