line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Device::USB::PCSensor::HidTEMPer::Device; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
16014
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
5
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
103
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Device::USB::PCSensor::HidTEMPer::Device - Generic device class |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 VERSION |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Version 0.02 |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=cut |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = 0.02; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 SYNOPSIS |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
None |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 DESCRIPTION |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
This module contains a generic class that all HidTEMPer devices should |
26
|
|
|
|
|
|
|
inherit from, thereby keeping the implemented methods consistent and making it |
27
|
|
|
|
|
|
|
possible to use the same code to contact every supported device. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head2 CONSTANTS |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=over 3 |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=item * CONNECTION_TIMEOUT |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
USB communication timeout, specified in milliseconds. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=back |
38
|
|
|
|
|
|
|
=cut |
39
|
|
|
|
|
|
|
|
40
|
1
|
|
|
1
|
|
5
|
use constant CONNECTION_TIMEOUT => 60; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
829
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head2 METHODS |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=over 3 |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item * new( $usb_device ) |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Creates a new generic Device object. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=cut |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub new |
53
|
|
|
|
|
|
|
{ |
54
|
0
|
|
|
0
|
1
|
0
|
my $class = shift; |
55
|
0
|
|
|
|
|
0
|
my ( $usb ) = @_; # Device::USB::Device interface that should be used |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Make sure that this is always a reference to the device. |
58
|
0
|
0
|
|
|
|
0
|
$usb = ref $usb |
59
|
|
|
|
|
|
|
? $usb |
60
|
|
|
|
|
|
|
: \$usb; |
61
|
|
|
|
|
|
|
|
62
|
0
|
|
|
|
|
0
|
my $self = { |
63
|
|
|
|
|
|
|
device => $usb, |
64
|
|
|
|
|
|
|
}; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# Possible sensors |
67
|
0
|
|
|
|
|
0
|
$self->{sensor} = { |
68
|
|
|
|
|
|
|
internal => undef, |
69
|
|
|
|
|
|
|
external => undef, |
70
|
|
|
|
|
|
|
}; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# If the two interfaces are currently in use, detach them and thereby |
73
|
|
|
|
|
|
|
# make them available for use. |
74
|
0
|
0
|
|
|
|
0
|
$usb->detach_kernel_driver_np(0) if $usb->get_driver_np(0); |
75
|
0
|
0
|
|
|
|
0
|
$usb->detach_kernel_driver_np(1) if $usb->get_driver_np(1); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Opens the device for use by this object. |
78
|
0
|
0
|
|
|
|
0
|
croak 'Error opening device' unless $usb->open(); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# It is only needed to set the configuration used under a Windows system. |
81
|
0
|
0
|
|
|
|
0
|
$usb->set_configuration(1) if $^O eq 'MSWin32'; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Claim the two interfaces for use by this object. |
84
|
0
|
0
|
|
|
|
0
|
croak 'Could not claim interface' if $usb->claim_interface(0); |
85
|
0
|
0
|
|
|
|
0
|
croak 'Could not claim interface' if $usb->claim_interface(1); |
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
0
|
bless $self, $class; |
88
|
0
|
|
|
|
|
0
|
return $self; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub DESTROY |
92
|
|
|
|
|
|
|
{ |
93
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Delete sensors |
96
|
0
|
|
|
|
|
0
|
delete $self->{sensor}->{internal}; |
97
|
0
|
|
|
|
|
0
|
delete $self->{sensor}->{external}; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# Release the interfaces back to the operating system. |
100
|
0
|
|
|
|
|
0
|
$self->{device}->release_interface(0); |
101
|
0
|
|
|
|
|
0
|
$self->{device}->release_interface(1); |
102
|
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
0
|
delete $self->{device}; |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
0
|
return undef; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=item * identifier() |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
This method is used to acquire the numerical value representing the device |
111
|
|
|
|
|
|
|
type identifier. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=cut |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub identifier |
116
|
|
|
|
|
|
|
{ |
117
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Command 0x52 will return the following 8 byte result, repeated 4 times. |
120
|
|
|
|
|
|
|
# Position 0: unknown |
121
|
|
|
|
|
|
|
# Position 1: Device ID |
122
|
|
|
|
|
|
|
# Position 2: Calibration value one for the internal sensor |
123
|
|
|
|
|
|
|
# Position 3: Calibration value two for the internal sensor |
124
|
|
|
|
|
|
|
# Position 4: Calibration value one for the external sensor |
125
|
|
|
|
|
|
|
# Position 5: Calibration value two for the external sensor |
126
|
|
|
|
|
|
|
# Position 6: unknown |
127
|
|
|
|
|
|
|
# Position 7: unknown |
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
0
|
my ( undef, $identifier ) = $self->_read( 0x52 ); |
130
|
0
|
|
|
|
|
0
|
return $identifier; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# _read( @command_bytes ) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# Used to read information from the device. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Input parameter |
138
|
|
|
|
|
|
|
# @command_bytes = Array of 8 bit hex values, maximum of 32 bytes, |
139
|
|
|
|
|
|
|
# representing the commands that will be executed by the device. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# Output parameter |
142
|
|
|
|
|
|
|
# An array of 8 bit hex values or a text string using chars |
143
|
|
|
|
|
|
|
# (from 0x00 to 0xFF) to represent the hex values. Returns undef on error. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub _read |
146
|
|
|
|
|
|
|
{ |
147
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
148
|
0
|
|
|
|
|
0
|
my ( @bytes ) = @_; |
149
|
0
|
|
|
|
|
0
|
my ( $data, $checksum ) = ( 0, 0 ); |
150
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x2 ); |
152
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, @bytes ); |
153
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
154
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
155
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
156
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
157
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
158
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
159
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0x0 ); |
160
|
0
|
|
|
|
|
0
|
$checksum += $self->_command(32, 0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x1 ); |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# On error a wrong amount of bytes is returened. |
163
|
0
|
0
|
|
|
|
0
|
carp 'The device returned to few bytes' if $checksum < 320; |
164
|
0
|
0
|
|
|
|
0
|
carp 'The device returned to many bytes' if $checksum > 320; |
165
|
0
|
0
|
|
|
|
0
|
return undef if $checksum != 320; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Send a message to the device, capturing the output into into $data |
168
|
0
|
|
|
|
|
0
|
$checksum = $self->{device}->control_msg( |
169
|
|
|
|
|
|
|
0xA1, # Request type |
170
|
|
|
|
|
|
|
0x1, # Request |
171
|
|
|
|
|
|
|
0x300, # Value |
172
|
|
|
|
|
|
|
0x1, # Index |
173
|
|
|
|
|
|
|
$data, # Bytes to be transfeered |
174
|
|
|
|
|
|
|
32, # Number of bytes to be transferred, more than 32 eq seg fault |
175
|
|
|
|
|
|
|
CONNECTION_TIMEOUT # Timeout |
176
|
|
|
|
|
|
|
); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Ensure that 32 bytes are read from the device. |
179
|
0
|
0
|
|
|
|
0
|
carp 'Error reading information from device' if $checksum != 32; |
180
|
|
|
|
|
|
|
|
181
|
0
|
0
|
|
|
|
0
|
return wantarray ? unpack "C*", $data : $data; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# _command( $total_byte_size, @data ) |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# This method is used to send a command to the device, only used for commands |
187
|
|
|
|
|
|
|
# where the output is not needed to be captured. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Input parameters |
190
|
|
|
|
|
|
|
# $total_byte_size = The total size that should be sent. Zero padding will be |
191
|
|
|
|
|
|
|
# added at the end to achieve specified length. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# @data = An array of 8bit hex values representing the data that |
194
|
|
|
|
|
|
|
# should be sent. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# Output parameter |
197
|
|
|
|
|
|
|
# Returns the number of bytes that where sent to the device if successful |
198
|
|
|
|
|
|
|
# execution. This is the same amout of bytes that where specified as input. |
199
|
|
|
|
|
|
|
# Returns undef on error. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub _command |
202
|
|
|
|
|
|
|
{ |
203
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
204
|
0
|
|
|
|
|
0
|
my ( $size, @bytes ) = @_; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# Convert to char and add zero padding at the end |
207
|
0
|
|
|
|
|
0
|
my $data = join '', map{ chr $_ } @bytes; |
|
0
|
|
|
|
|
0
|
|
208
|
0
|
|
|
|
|
0
|
$data .= join '', map{ chr $_ } ( (0)x( $size - $#bytes ) ); |
|
0
|
|
|
|
|
0
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# Send the message to the device |
211
|
0
|
|
|
|
|
0
|
my $return = $self->{device}->control_msg( |
212
|
|
|
|
|
|
|
0x21, # Request type |
213
|
|
|
|
|
|
|
0x9, # Request |
214
|
|
|
|
|
|
|
0x200, # Value |
215
|
|
|
|
|
|
|
0x1, # Index |
216
|
|
|
|
|
|
|
$data, # Bytes to be transferred |
217
|
|
|
|
|
|
|
$size, # Number of bytes to be transferred |
218
|
|
|
|
|
|
|
CONNECTION_TIMEOUT # Timeout |
219
|
|
|
|
|
|
|
); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# If the device returns correct amount of bytes return count, all OK. |
222
|
0
|
0
|
|
|
|
0
|
return $return if $return == $size; |
223
|
|
|
|
|
|
|
|
224
|
0
|
0
|
|
|
|
0
|
carp 'The device return less bytes than anticipated' if $return < $size; |
225
|
0
|
0
|
|
|
|
0
|
carp 'The device returned more bytes than anticipated' if $return > $size; |
226
|
0
|
|
|
|
|
0
|
return undef; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# _write( @bytes ) |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# This method is used to write information back to the device. Be carefull |
232
|
|
|
|
|
|
|
# when using this, since any wrong information sent may destroy the device. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# Input parameter |
235
|
|
|
|
|
|
|
# @bytes = The bytes that should be written to the device, a maximum of |
236
|
|
|
|
|
|
|
# 32 bytes. |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# Output parameter |
239
|
|
|
|
|
|
|
# Returns the number of bytes that where sent to the device if successful |
240
|
|
|
|
|
|
|
# execution. This should be 288 if everything is successful. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub _write |
243
|
|
|
|
|
|
|
{ |
244
|
2
|
|
|
2
|
|
772
|
my $self = shift; |
245
|
2
|
|
|
|
|
3
|
my ( @bytes ) = @_; |
246
|
2
|
|
|
|
|
5
|
my ( $data, $checksum ) = ( 0, 0 ); |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Filter out possible actions |
249
|
2
|
50
|
66
|
|
|
17
|
return undef if $bytes[0] > 0x68 || $bytes[0] < 0x61; |
250
|
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0xA, 0xB, 0xC, 0xD, 0x0, 0x0, 0x2 ); |
252
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, @bytes ); |
253
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
254
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
255
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
256
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
257
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
258
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
259
|
0
|
|
|
|
|
|
$checksum += $self->_command(32, 0x0 ); |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# On error a wrong amount of bytes is returened. |
262
|
0
|
0
|
|
|
|
|
carp 'The device returned to few bytes' if $checksum < 288; |
263
|
0
|
0
|
|
|
|
|
carp 'The device returned to many bytes' if $checksum > 288; |
264
|
0
|
0
|
|
|
|
|
return undef if $checksum != 288; |
265
|
|
|
|
|
|
|
|
266
|
0
|
|
|
|
|
|
return $checksum; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=item * internal() |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Returns the corresponding Sensor object representing the internal sensor |
272
|
|
|
|
|
|
|
connected to the device. If the device does not have an internal sensor undef |
273
|
|
|
|
|
|
|
is returned. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=cut |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub internal |
278
|
|
|
|
|
|
|
{ |
279
|
0
|
|
|
0
|
1
|
|
return $_[0]->{sensor}->{internal}; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item * external() |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Returns the corresponding Sensor object representing the external sensor |
285
|
|
|
|
|
|
|
connected to the device. If the device does not have an external sensor undef |
286
|
|
|
|
|
|
|
is returned. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=cut |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub external |
291
|
|
|
|
|
|
|
{ |
292
|
0
|
|
|
0
|
1
|
|
return $_[0]->{sensor}->{external}; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=item * init() |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Empty method that should be implemented in order to be able to initialize |
298
|
|
|
|
|
|
|
a object instance. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=cut |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub init |
303
|
|
|
|
|
|
|
{ |
304
|
0
|
|
|
0
|
1
|
|
return undef; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=back |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
This module internally includes and takes use of the following packages: |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
use Carp; |
314
|
|
|
|
|
|
|
use Device::USB; |
315
|
|
|
|
|
|
|
use Device::USB::Device; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
This module uses the strict and warning pragmas. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=head1 BUGS |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
Please report any bugs or missing features using the CPAN RT tool. |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 FOR MORE INFORMATION |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
None |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 AUTHOR |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Magnus Sulland < msulland@cpan.org > |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
None |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
Copyright (c) 2010-2011 Magnus Sulland |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
340
|
|
|
|
|
|
|
under the same terms as Perl itself. |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
1; |