File Coverage

lib/Device/ParallelPort/drv.pm
Criterion Covered Total %
statement 36 72 50.0
branch 11 26 42.3
condition 1 3 33.3
subroutine 7 21 33.3
pod 5 19 26.3
total 60 141 42.5


line stmt bran cond sub pod time code
1             package Device::ParallelPort::drv;
2 1     1   7 use Carp;
  1         2  
  1         2035  
3              
4             =head1 NAME
5              
6             Device::ParallelPort::drv - Standard pacakge to be imported by all drivers
7              
8             =head1 SYNOPSIS
9              
10             (Not Applicable) - do not use this directly, use another driver
11              
12             * Device::ParallelPort::drv::auto
13             * Device::ParallelPort::drv::linux
14             * Device::ParallelPort::drv::parport
15             * Device::ParallelPort::drv::win32
16              
17             =head1 DESCRIPTION
18              
19             This driver is the base class recommended for all Parallel Port Drivers.
20             It is not useful in itself. Although against proper OO
21             design, this particular module does not work by itself.
22              
23             =head1 METHODS
24              
25             =head2 new
26              
27             =head2 get_bit
28              
29             =head2 get_byte
30              
31             =head2 set_bit
32              
33             =head2 set_byte
34              
35             =head1 NOTES
36              
37             =head2 Device Names
38              
39             A special system of device names has been deviced.
40             Basically we are trying to be compatible with most systems, and not force
41             people to learn something new.
42              
43             You can enter parallel port device in a number of ways
44              
45             - N Unix style, where 0 is the first port
46             - lptN Windows style, where 1 is the first port
47             - 0xNNN Direct hardware location
48              
49             This is totally dependent on the driver being used.
50             For example the script driver would not use these but the auto driver does.
51              
52             Now these are not necessarily supported in all operating systems. By default
53             this base driver converts lpt notation into lp notation, it then optionally
54             converts all lp notation into a hardware location. However what would not work
55             for parport control, which is generally done as parport device, mapping the
56             same number as the lp above (check that?), in that case passing the direct
57             hardware location is pointless.
58              
59             =head1 COPYRIGHT
60              
61             Copyright (c) 2002,2004 Scott Penrose. All rights reserved.
62             This program is free software; you can redistribute it and/or modify
63             it under the same terms as Perl itself.
64              
65             =head1 AUTHOR
66              
67             Scott Penrose L, L
68              
69             =head1 SEE ALSO
70              
71             L
72              
73             =cut
74              
75             # Some constants that are useful
76 0     0 0 0 sub BASE_0 { 0x378; } # Intel x86 Base Port
77 0     0 0 0 sub OFFSET_DATA { 0; }
78 0     0 0 0 sub OFFSET_STATUS { 1; }
79 0     0 0 0 sub OFFSET_CONTROL { 2; }
80              
81             sub new {
82 2     2 1 8 my ($class, $str, @params) = @_;
83 2   33     23 my $this = bless {}, ref($class) || $class;
84 2 50       26 $this->init($str, @params) if ($this->can('init'));
85 2         42 return $this;
86             }
87              
88             # ------------------------------------------------------------------------------
89             # BIT -> BYTE and BYTE -> BIT Autoamtic Support
90             # ------------------------------------------------------------------------------
91             # This seciton basically provides
92             sub get_bit {
93 6     6 1 13 my ($this, $bit) = @_;
94 6 50       19 unless ($this->INFO->{type} eq "byte") { croak "Unsupported in this driver"; }
  0         0  
95             # Find the byte
96 6         24 my $byte = int($bit / 8);
97 6         11 $bit = $bit - ($byte * 8);
98 6         21 return _bit_from_byte($this->get_byte($byte), $bit);
99             }
100              
101             sub _bit_from_byte {
102 14     14   25 my ($byte, $bit) = @_;
103 14 100       75 return ((ord($byte) & (1 << $bit)) == (1 << $bit)) ? 1 : 0;
104             }
105              
106             sub get_byte {
107 6     6 1 8 my ($this, $byte) = @_;
108 6 50       17 unless ($this->INFO->{type} eq "bit") { croak "Unsupported in this driver"; }
  0         0  
109 6         19 my $ret = 0;
110 6         10 my $first_bit = ($byte * 8);
111 6         19 for (my $bit = $first_bit; $bit < ($first_bit + 8); $bit++) {
112 48 100       165 if ($this->get_bit($bit)) {
113 7         22 $ret = $ret + (1 << ($bit - ($byte * 8)));
114             }
115             }
116 6         32 return chr($ret);
117             }
118              
119             sub get_byte_uninvert {
120 0     0 0 0 my ($this, $byte) = @_;
121 0         0 return $this->uninvert($byte, $this->get_byte($byte));
122             }
123              
124             sub set_byte_uninvert {
125 0     0 0 0 my ($this, $byte, $val) = @_;
126 0         0 return $this->set_byte($byte, $this->uninvert($byte, $val));
127             }
128              
129             sub set_bit {
130 3     3 1 8 my ($this, $bit, $val) = @_;
131 3 50       10 unless ($this->INFO->{type} eq "byte") { croak "Unsupported in this driver"; }
  0         0  
132 3         12 my $byte = int($bit / 8);
133 3         6 $bit = $bit - ($byte * 8);
134 3         9 my $current = $this->get_byte($byte);
135 3 50       9 if (defined($current)) {
136 3         5 $current = ord($current);
137             } else {
138 0         0 $current = 0;
139             }
140 3 50       7 if ($val) {
141 3         9 $current = $current | (1 << $bit);
142             } else {
143 0         0 $current = $current & (~ (1 << $bit));
144             }
145 3         14 $this->set_byte($byte, chr($current));
146             }
147              
148             sub set_byte {
149 1     1 1 130 my ($this, $byte, $val) = @_;
150 1 50       6 unless ($this->INFO->{type} eq "bit") { croak "Unsupported in this driver"; }
  0         0  
151 1         8 for(my $i = 0; $i < 8; $i++) {
152 8         20 $this->set_bit(
153             $i + ($byte * 8),
154             _bit_from_byte($val, $i),
155             );
156             }
157             }
158              
159             # Shortcuts for those who want data, control and status for standard parallel
160             # ports seprarately.
161              
162             sub get_data {
163 0     0 0   my ($this) = @_;
164 0           return $this->get_byte($this->OFFSET_DATA);
165             }
166              
167             sub get_control {
168 0     0 0   my ($this) = @_;
169 0           return $this->get_byte($this->OFFSET_CONTROL);
170             }
171              
172             sub get_status {
173 0     0 0   my ($this) = @_;
174 0           return $this->get_byte($this->OFFSET_STATUS);
175             }
176              
177             sub set_data {
178 0     0 0   my ($this, $val) = @_;
179 0           return $this->set_byte($this->OFFSET_DATA, $val);
180             }
181              
182             sub set_control {
183 0     0 0   my ($this, $val) = @_;
184 0           return $this->set_byte($this->OFFSET_CONTROL, $val);
185             }
186              
187             sub set_status {
188 0     0 0   my ($this, $val) = @_;
189 0           return $this->set_byte($this->OFFSET_STATUS, $val);
190             }
191              
192             # HELPER METHODS
193              
194             # TODO - Real byte converter - CHAR from Number
195             # Convert an integer to a real byte - just in case someone has passed in a
196             # number instead of a byte.
197             #sub real_byte {
198             # my ($this, $val) = @_;
199             # return $val;
200             #}
201              
202             # TODO - Invert / Uninverter - Just swaps bits
203             # Convert all inverted bits back to normal
204             #sub uninvert {
205             # my ($this, $byte, $val, $bits) = @_;
206             # if ($byte == 0) { # BYTE
207             # $bits ||= [];
208             # } elsif ($byte == 1) { # STATUS
209             # $bits ||= [qw/7/];
210             # } elsif ($byte == 2) { # STATUS
211             # $bits ||= [qw/0 1 3/];
212             # }
213             # my $ret = $val;
214             # foreach my $bit (@$bits) {
215             # # XXX XOR Bit here
216             # }
217             #}
218              
219             # ADDRESS METHODS
220              
221             sub address_to_num {
222 0     0 0   my ($this, $address) = @_;
223 0 0         if (($address * 1) == $address) {
    0          
224 0           return $address;
225             } elsif ($address =~/^lpt(\d)$/) {
226 0           return $1 - 1;
227             } else {
228 0           croak "Unable to convert $address to something meaninful to Device::ParallelPort - try 0..9 or lpt1..lpt9";
229             }
230             }
231              
232             sub num_to_hardware {
233 0     0 0   my ($this, $num) = @_;
234 0 0         if ($num == 0) {
    0          
235 0           return 0x378;
236             } elsif ($num == 1) {
237 0           return 0x278;
238             } else {
239 0           croak "No known lookup for hardware address $num to Device::ParallelPort - Try 0..1";
240             }
241             }
242              
243             1;