File Coverage

blib/lib/RFID/Reader/Serial.pm
Criterion Covered Total %
statement 24 88 27.2
branch 0 16 0.0
condition 0 7 0.0
subroutine 8 14 57.1
pod 1 1 100.0
total 33 126 26.1


line stmt bran cond sub pod time code
1             package RFID::Reader::Serial;
2 4     4   55775 use RFID::Reader qw(ref_tainted); $VERSION=$RFID::Reader::VERSION;
  4         9  
  4         355  
3             our @ISA = qw();
4              
5             # Written by Scott Gifford
6             # Copyright (C) 2004-2006 The Regents of the University of Michigan.
7             # See the file LICENSE included with the distribution for license
8             # information.
9              
10             =head1 NAME
11              
12             RFID::Reader::Serial - Abstract base class for readers implemented over a serial connection.
13              
14             =head1 SYNOPSIS
15              
16             This is an abstract base class used for building an RFID Reader class
17             implemented over a TCP connection. It provides the basic I/O methods
18             that an object based on L will expect, and
19             generally a reader based on this class will simply inherit from it and
20             add a few details. In other words, this class is fairly complete, and
21             you shouldn't have to add much to it to make it workable.
22              
23             =head1 DESCRIPTION
24              
25             =cut
26              
27 4     4   27 use constant BAUDRATE => 115200;
  4         8  
  4         284  
28 4     4   22 use constant DATABITS => 8;
  4         10  
  4         168  
29 4     4   20 use constant STOPBITS => 1;
  4         7  
  4         213  
30 4     4   20 use constant PARITY => 'none';
  4         10  
  4         235  
31 4     4   20 use constant HANDSHAKE => 'none';
  4         8  
  4         194  
32 4     4   21 use constant DEFAULT_TIMEOUT => 30; # seconds
  4         7  
  4         192  
33              
34             # This is small, but if it's larger reads will sometimes
35             # time out, and if it's zero we poll in a tight loop.
36 4     4   20 use constant STREAMLINE_BUFSIZE => 1;
  4         10  
  4         8332  
37             =head2 Constructor
38              
39             =head3 new
40              
41             This constructor accepts its parameters as a hash. Any unrecognized
42             arguments are intrepeted as parameters to the L
43             method.
44              
45             The following parameters are accepted:
46              
47             =over 4
48              
49             =item Port
50              
51             The serial port object that communication should take place over. The
52             object should be compatible with
53             L; the Unix equivalent is
54             L. You are responsible for
55             creating the serial port object.
56              
57             =item Timeout
58              
59             The maximum time to wait for a response from the reader, in seconds.
60              
61             =item Baudrate
62              
63             An integer specifying the speed at which communication should take
64             place.
65              
66             =back
67              
68             =cut
69              
70             sub new
71             {
72 0     0 1   my $class = shift;
73 0           my $self = {};
74 0           bless $self, $class;
75              
76 0           my(%p)=@_;
77              
78 0 0         $self->{com} = $p{Port}
79             or die __PACKAGE__."::new requires argument 'Port'\n";
80 0           delete $p{Port};
81 0   0       $self->{timeout} = $p{Timeout}||$p{timeout}||DEFAULT_TIMEOUT;
82 0           $self->{databits}=DATABITS;
83 0           $self->{stopbits}=STOPBITS;
84 0           $self->{parity}=PARITY;
85 0           $self->{handshake}=HANDSHAKE;
86 0   0       $self->{baudrate}=$p{Baudrate}||$p{baudrate}||BAUDRATE;
87              
88 0           $self->_init(%p);
89 0           $self;
90             }
91              
92             sub _init
93             {
94 0     0     my $self = shift;
95              
96 0           $self->{com}->databits($self->{databits});
97 0           $self->{com}->stopbits($self->{stopbits});
98 0           $self->{com}->parity($self->{parity});
99 0           $self->{com}->handshake($self->{handshake});
100              
101 0 0 0       if ($self->{baudrate} > 115200 && (ref($self->{com}) eq 'Win32::SerialPort'))
102             {
103             # This is a hack to work around an annoying bug in Win32::CommPort.
104 0           $self->{com}->baudrate(115200);
105 0           $self->{com}->{_N_BAUD}=$self->{baudrate};
106             }
107             else
108             {
109 0           $self->{com}->baudrate($self->{baudrate});
110             }
111 0 0         $self->{com}->write_settings
112             or die "No settings: $!\n";
113 0           $self->{com}->user_msg(1);
114 0           $self->{com}->error_msg(1);
115             }
116              
117             sub _writebytes
118             {
119 0     0     my $self = shift;
120 0           my($data)=join("",@_);
121 0           my $bytesleft = my $size = length($data);
122 0 0         if (ref_tainted(\$data)) { die "Attempt to send tainted data to reader"; }
  0            
123 0           my $start = time;
124 0           while ($bytesleft > 0)
125             {
126 0 0         if ( (time - $start) > $self->{timeout})
127             {
128 0           die "Write timeout.\n";
129             }
130 0 0         my $wb = $self->{com}->write($data)
131             or die "Write timeout.\n";
132 0           substr($data,0,$wb,"");
133 0           $bytesleft -= $wb;
134             }
135 0           $size;
136             }
137              
138             sub _connected
139             {
140 0     0     return $self->{com};
141             }
142              
143             sub _readbytes
144             {
145 0     0     my $self = shift;
146 0           my($bytesleft)=@_;
147 0           my $data = "";
148              
149 0           $self->{com}->read_const_time($self->{timeout}*1000);
150 0           my $start = time;
151 0           while($bytesleft > 0)
152             {
153 0 0         if ( (time - $start) > $self->{timeout})
154             {
155 0           die "Read timeout.\n";
156             }
157              
158 0           my($rb,$moredata)=$self->{com}->read($bytesleft);
159 0           $bytesleft -= $rb;
160 0           $data .= $moredata;
161             }
162 0           $data;
163             }
164              
165             sub _readuntil
166             {
167 0     0     my $self = shift;
168 0           my($delim) = @_;
169              
170 0           my $started = time;
171            
172 0           my $com = $self->{com};
173 0           $com->read_const_time($self->{timeout} * 1000);
174              
175 0           my $match;
176 0           my $i = 0;
177 0           $self->{com}->are_match($delim);
178 0           while (!($match = $com->streamline(STREAMLINE_BUFSIZE)))
179             {
180 0 0         if ( (time - $started) >= $self->{timeout})
181             {
182 0           die "Timeout waiting for response\n";
183             }
184             }
185 0           return $match;
186              
187             }
188              
189             =head1 SEE ALSO
190              
191             L, L, L,
192             L.
193              
194             =head1 AUTHOR
195              
196             Scott Gifford Egifford@umich.eduE, Esgifford@suspectclass.comE
197              
198             Copyright (C) 2004-2006 The Regents of the University of Michigan.
199              
200             See the file LICENSE included with the distribution for license
201             information.
202              
203             =cut
204              
205             1;