File Coverage

blib/lib/Hardware/iButton/Connection.pm
Criterion Covered Total %
statement 72 270 26.6
branch 0 44 0.0
condition 0 12 0.0
subroutine 24 41 58.5
pod 4 16 25.0
total 100 383 26.1


line stmt bran cond sub pod time code
1             package Hardware::iButton::Connection;
2              
3 1     1   606 use strict;
  1         1  
  1         27  
4 1     1   4 no strict "subs";
  1         1  
  1         22  
5 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         4  
  1         73  
6              
7             require Exporter;
8             #require AutoLoader;
9 1     1   758 use IO::File;
  1         9783  
  1         117  
10 1     1   835 use Time::HiRes qw(usleep);
  1         1736  
  1         5  
11             #use POSIX qw(tcdrain); # for drain in write()
12 1     1   742 use Hardware::iButton::Device;
  1         3  
  1         132  
13             #use IO::Stty;
14              
15             @ISA = qw(Exporter);
16             # Items to export into callers namespace by default. Note: do not export
17             # names by default without a very good reason. Use EXPORT_OK instead.
18             # Do not simply export all your public functions/methods/constants.
19             @EXPORT = qw();
20              
21             ( $VERSION ) = '$Revision: 1.2 $ ' =~ /\$Revision:\s+([^\s]+)/;
22              
23             =head1 NAME
24              
25             Hardware::iButton - talk to DalSemi iButtons via a DS2480 serial widget
26              
27             =head1 SYNOPSIS
28              
29             use Hardware::iButton::Connection;
30             $c = new Hardware::iButton::Connection "/dev/ttyS0";
31             @b = $c->scan();
32             foreach $b (@b) {
33             print "family: ",$b->family(), "serial number: ", $b->serial(),"\n";
34             print "id: ",$b->id(),"\n"; # id = family . serial . crc
35             print "reg0: ",$b->readreg(0),"\n";
36             }
37              
38             =head1 DESCRIPTION
39              
40             This module talks to iButtons via the "active" serial interface (anything
41             using the DS2480, including the DS1411k and the DS 9097U). It builds up a list
42             of devices available, lets you read and write their registers, etc.
43              
44             The connection object is an Hardware::iButton::Connection. The main
45             user-visible purpose of it is to provide a list of Hardware::iButton::Device
46             objects. These can be subclassed once their family codes are known to provide
47             specialized methods unique to the capabilities of that device. Those devices
48             will then be Hardware::iButton::Device::DS1920, etc.
49              
50             iButtons and solder-mount Touch Memory devices are each identified with a
51             unique 64-bit number. This is broken up into 8 bits of a "family code", which
52             specifies the part number (and consequently the capabilities), then 48 bits
53             of device ID (which Dallas insures is globally unique), then 8 bits of CRC.
54             When you pass these IDs to and from this package, use hex strings like
55             "0123456789ab".
56              
57             =head1 AUTHOR
58              
59             Brian Warner, warner@lothar.com
60              
61             =head1 SEE ALSO
62              
63             http://www.ibutton.com, http://sof.mit.edu/ibuttonpunks/
64              
65             =cut
66              
67             # constants listed in the Book of DS19xx iButton Standards
68              
69             # "Network Layer" constants
70 1     1   6 use constant READ_ROM => "\x33";
  1         2  
  1         91  
71 1     1   5 use constant SKIP_ROM => "\xcc";
  1         2  
  1         41  
72 1     1   4 use constant MATCH_ROM => "\x55";
  1         2  
  1         45  
73 1     1   4 use constant SEARCH_ROM => "\xf0";
  1         2  
  1         40  
74 1     1   5 use constant OD_SKIP_ROM => "\x3c";
  1         2  
  1         42  
75 1     1   5 use constant OD_MATCH_ROM => "\x69";
  1         2  
  1         38  
76             # "Transport Layer" constants
77 1     1   4 use constant READ_MEMORY => "\xf0";
  1         2  
  1         59  
78 1     1   5 use constant EXT_READ_MEMORY => "\xa5";
  1         2  
  1         36  
79 1     1   4 use constant READ_SUBKEY => "\x66";
  1         2  
  1         57  
80 1     1   5 use constant WRITE_SCRATCHPAD => "\x0f";
  1         22  
  1         49  
81 1     1   5 use constant READ_SCRATCHPAD => "\xaa";
  1         1  
  1         54  
82 1     1   4 use constant COPY_SCRATCHPAD => "\x55";
  1         2  
  1         47  
83             # etc..
84              
85             # there are constants used by the DS2480 too.
86 1     1   5 use constant SET_DATA_MODE => "\xe1";
  1         2  
  1         44  
87 1     1   4 use constant SET_COMMAND_MODE => "\xe3";
  1         1  
  1         55  
88             # XXX Not sure if this is the correct method.
89 1     1   10 use constant SET_FINDALARM_MODE => "\xec";
  1         1  
  1         40  
90 1     1   5 use constant SEARCH_ACCEL_ON => "\xb1";
  1         1  
  1         55  
91 1     1   6 use constant SEARCH_ACCEL_OFF => "\xa1";
  1         2  
  1         51  
92              
93 1     1   5 use constant DEBUG => 0;
  1         2  
  1         2473  
94              
95             $Hardware::iButton::Connection::debug = 0;
96              
97             # devices are in one of three states: active in network layer, deselected,
98             # active in transport layer. In addition some devices can be "overdrive active"
99             # in the transport layer. We call these states "active, deselected,
100             # selected, OD selected".
101              
102             # after a bus reset, all devices are active in the "network layer" and you're
103             # only supposed to do "network layer" commands.
104             # READ_ROM gets everybody's id at once. If the CRC is right then there was
105             # only one device. Everyone is still active
106             # SKIP_ROM selects everyone
107             # MATCH_ROM selects the device with a matching ID, deselects everyone else
108             # SEARCH_ROM will end up selecting one device, deselecting the others
109             # OD_SKIP_ROM makes everyone OD selected
110             # OD_MATCH_ROM will OD select the matching device, deselect everyone else
111              
112             # Preloaded methods go here.
113              
114             # we need some kind of slow substitute if Time::HiRes is not available
115              
116             #sub usleep {
117             # my($usec) = @_;
118             # sleep(1);
119             #}
120              
121             =head2 new
122              
123             $c = new Hardware::iButton::Connection "/dev/ttyS0";
124              
125             Creates a new Hardware::iButton::Connection object by opening the given serial
126             port and attempting to communicate with a DS2480 chip.
127              
128             =cut
129              
130             sub new {
131 0     0 1   my($class, $port) = @_;
132 0           my $self = bless {},$class;
133 0           $self->{'port'} = $port;
134              
135 0           $self->{'s'} = new IO::File "+<$port";
136 0 0         return undef unless $self->{'s'};
137             #print "orig settings: ",IO::Stty::stty($self->{'s'},'-a'),"\n";
138             #$self->{'s.oldstty'} = IO::Stty::stty($self->{'s'},'-g');
139 0           $self->{'s.changed'} = 1;
140 0           $self->{'s'}->blocking(0);
141 0           $self->{'s'}->autoflush(1);
142             #IO::Stty::stty($self->{'s'}, qw(9600 raw -echo -echoe -echok));
143             #print "new settings: ",IO::Stty::stty($self->{'s'},'-a'),"\n";
144              
145             # we should also do the equivalent of a 'stty raw' here
146             # stty 9600 raw -onlcr -iexten -echo -echoe -echok -echoctl -echoke
147              
148             # reset
149 0           $self->{'mode'} = SET_COMMAND_MODE;
150 0           $self->write(SET_COMMAND_MODE);
151 0           usleep(50 * 1000);
152 0           $self->write("\xc1");
153 0           usleep(50 * 1000);
154 0           $self->write("\xf1");
155 0           usleep(50 * 1000);
156 0           $self->write("\xc1");
157 0           usleep(50 * 1000);
158 0           $self->write("\xf1");
159 0           usleep(50 * 1000);
160 0           my $dummy;
161 0           $dummy = $self->read(0); # flush
162             #print "dummy (",length($dummy),"): ",unpack("H*",$dummy),"\n";
163              
164 0           my $times = 1;
165 0           while ($times) {
166 0           $self->write("\xc1");
167 0           usleep(50 * 1000);
168 0           $dummy = $self->read(0);
169 0 0 0       last if (length($dummy) == 1 and ((ord($dummy) & 0xdc) == 0xc8));
170 0           print "reset, but got back (",length($dummy),"): ",unpack("H*",$dummy),"\n";
171 0           usleep(300 * 1000); $self->read(0);
  0            
172 0           $times--;
173             }
174 0 0         if (!$times) {
175             #k die "couldn't reset bus";
176             }
177            
178             # we just reset.. all buttons are listening, so none is currently selected
179 0           $self->{'selected'} = undef;
180              
181 0           return $self;
182             }
183              
184             sub resetstty {
185 0     0 0   my($self) = @_;
186             #print "resetstty\n";
187             #foreach my $key (keys(%$self)) {
188             #print "$key: $self->{$key}\n";
189             #}
190 0 0         unless ($self->{'s.changed'}) {
191             #print "not restoring\n";
192 0           return;
193             }
194             #print "restoring..\n";
195             # restore terminal parameters
196             #print "current settings: ",IO::Stty::stty($self->{'s'},'-a'),"\n";
197             #IO::Stty::stty($self->{'s'},$self->{'s.oldstty'});
198 0           $self->{'s.changed'} = 0;
199             #print "restored settings: ",IO::Stty::stty($self->{'s'},'-a'),"\n";
200             }
201              
202             sub DESTROY {
203 0     0     my($self) = @_;
204             #print "DESTROY $self\n";
205 0           $self->resetstty();
206 0           undef $self;
207             }
208              
209             # write string, wait for output to drain, wait a bit more
210             sub write {
211 0     0 0   my($self, $string) = @_;
212 0 0         print "write(",length($string),": ",unpack("H*",$string),")\n"
213             if $Hardware::iButton::Connection::debug;
214 0           $self->{'s'}->syswrite($string, length($string));
215             # drain
216             #print "fileno: ",$self->{'s'}->fileno(),"\n";
217             #my $r = tcdrain($self->{'s'}->fileno()); print "tcdrain: $r\n";
218 0           usleep(1000);
219             }
220              
221             # read $bytes. If $timeout seconds goes by without anything read,
222             # return whatever we've got. If $timeout is unspecified, use a system default
223             # of 100ms. If $bytes is 0, just read whatever is available.
224             sub read {
225 0     0 0   my($self, $bytes, $timeout) = @_;
226 0           my($dummy, $input);
227 0 0         if ($bytes) {
228 0           my $start = time;
229 0           while($bytes) {
230 0           my $count = $self->{'s'}->sysread($dummy, $bytes);
231 0 0         unless ($count) {
232             # error. Probably EWOULDBLOCK.
233 0           print "sleep\n" if DEBUG;
234 0           usleep(1000);
235 0 0         if (time - $start > 2) {
236 0           warn("read timed out, got ",length($input),
237             " still want $bytes\n");
238 0 0         print "read(",length($input),": ",unpack("H*",$input),")\n"
239             if $Hardware::iButton::Connection::debug;
240 0           return $input;
241             }
242 0           next;
243             }
244 0           $input .= $dummy; $bytes -= $count;
  0            
245             }
246             } else {
247 0           $self->{'s'}->sysread($input, 10000);
248             }
249 0 0         print "read(",length($input),": ",unpack("H*",$input),")\n"
250             if $Hardware::iButton::Connection::debug;
251 0           return $input;
252             }
253              
254             sub mode {
255 0     0 0   my($self, $newmode) = @_;
256 0 0         if ($self->{'mode'} ne $newmode) {
257 0           $self->write($newmode);
258 0           $self->{'mode'} = $newmode;
259             }
260             }
261              
262             # send a series of bytes to the one-wire bus, as opposed to merely sending a
263             # series of bytes to the DS2480. This deals with making sure we're in the
264             # SET_DATA_MODE and escaping the SET_COMMAND_MODE chars
265              
266             sub send {
267 0     0 0   my($self, $str) = @_;
268 0           $self->mode(SET_DATA_MODE);
269 0           $str =~ s/\xe3/\xe3\xe3/g; # double SET_COMMAND_MODE chars
270 0           $self->write($str);
271             }
272              
273             # DESTROY: nothing special to do, the port will be closed for us. Once we
274             # start doing 'stty' stuff, though, we should really return the port to the
275             # way it was before
276              
277             =head2 reset
278              
279             $status = $c->reset();
280              
281             resets the One-Wire bus. Returns a status code:
282             0: bus shorted
283             1: presence pulse: at least one device is present on the bus
284             2: alarming presence pulse: at least one device is alarmed
285             3: no presence pulse: there are no devices on the bus
286              
287             =cut
288              
289             sub reset {
290 0     0 1   my($self) = @_;
291              
292 0           $self->read(0);
293 0           $self->mode(SET_COMMAND_MODE);
294 0           $self->write("\xc1");
295 0           $self->{'selected'} = undef;
296 0           my $status = $self->read(1);
297 0           $status = ord($status) & 0x03;
298 0           return $status;
299             }
300              
301             =head2 scan
302              
303             @buttons = $c->scan();
304             @buttons = $c->scan($family_code);
305             $button = $c->scan($family_code, $serial);
306              
307             scans the One-Wire bus with the ROM Search command and builds up a list of all
308             devices present. Hardware::iButton::Device objects are created for each, and
309             an array of these objects is returned. If a family code is given, the search
310             is restricted to devices of that family type. If a serial number is given
311             (which must be a 12 character string), then the bus is searched for that one
312             particular device (family code plus id) and, if present, an object is returned
313             for it.
314              
315             If no buttons match the search criteria (or none are present), an empty list
316             or undef is returned.
317              
318             =cut
319              
320             # encode bits into the 16-byte string used to give the Search Accelerator
321             # command a preferred path
322             # $byte[0] = "b3XXb2XXb1XXb0XX", $byte[1] = "b7XXb6XXb5XXb4XX", etc
323             # $byte[0] = $bit[3] << 7 | $bit[2] << 5 | $bit[1] << 3 | $bit[0] << 1
324             # etc
325             # take an array of 0 or 1
326             # return a 16 character string ready to be written
327             # the One-Wire protocol uses ROM values that are 64 bits, LSB first, first
328             # the family code, then serial number, then CRC.
329             sub packbits {
330 0     0 0   my($bits) = @_; # [0 .. 63], each either 1 or 0
331 0           print "packbits(bits=($bits)\n" if DEBUG;
332 0           $bits =~ s/(.)/0 . $1/ge; # insert the "XX"s as zeros
  0            
333 0           $bits = pack("b128", $bits);
334 0           print " (",length($bits),"):",join(',',unpack("C*",$bits)),"\n" if DEBUG;
335 0           return $bits;
336             }
337              
338             # extract bits returned by the Search Accelerator command
339             # the bits are interleaved "chosen bits" and "discrepancy bits"
340             # first byte is r3d3r2d2r1d1r0d0
341             # second is r7d7r6d6r5d5r4d4
342             # we are given a string of 16 chars straight from read()
343             # generate two arrays, $r[0..63] and $d[0..63], each with 0 or 1
344             # find $firstconflict: the lowest $i>=$bits for which $conflict[$i] == 1,
345             # return $firstconflict, @r
346             sub unpackbits {
347 0     0 0   my($bits, $string) = @_;
348 0           print "unpackbits(bits=$bits,string(",length($string),"):" if DEBUG;
349 0           print join(',',map {sprintf('0x%02x',$_)} unpack("C*",$string)),")\n"
350             if DEBUG;
351 0           my $b1 = unpack("b128", $string);
352             # now extract every other char into a separate array
353 0           my($chosen,$d) = ($b1,$b1);
354 0           $chosen =~ s/.(.)/$1/g;
355 0           $d =~ s/(.)./$1/g;
356 0           print " r: $chosen\n" if DEBUG; print " d: $d\n" if DEBUG;
  0            
357 0           my(@conflict) = split(//,$d);
358             # find $firstconflict
359 0           my $firstconflict = -1;
360 0           for(my $i=$bits; $i<64; $i++) {
361 0 0         if ($conflict[$i]) {
362 0           $firstconflict = $i;
363 0           last;
364             }
365             }
366 0           print " first=$firstconflict, chosen=$chosen\n" if DEBUG;
367 0           return($firstconflict, $chosen);
368             }
369              
370             # find all IDs that have substr($path, 0, $bits) in them. Recurse.
371             # substr($path, $bits+1) will be all "0"s
372             sub scan1 {
373 0     0 0   my($self, $bits, $path) = @_;
374 0           print "scan1(bits=$bits,path=$path)\n" if DEBUG;
375              
376             #print "str: ",join(' ', map {sprintf('0x%02x', ord($_))} (split(//,$str))),"\n" if DEBUG;
377 0           $self->reset(); # puts us in COMMAND_MODE
378 0           $self->mode(SET_DATA_MODE);
379 0           $self->write(SEARCH_ROM);
380 0           $self->mode(SET_COMMAND_MODE);
381 0           $self->write(SEARCH_ACCEL_ON);
382 0           $self->mode(SET_DATA_MODE);
383 0           $self->write(packbits($path));
384 0           $self->mode(SET_COMMAND_MODE);
385 0           $self->write(SEARCH_ACCEL_OFF);
386              
387 0           my $in = $self->read(17);
388             # the first byte is the echo of SEARCH_ROM. Then 16 bytes of data.
389 0           print "read ",length($in)," bytes: " if DEBUG;
390 0           print join(',',map{sprintf('0x%02x',$_)} unpack("C*",$in)),"\n" if DEBUG;
391 0           $in = substr($in, 1);
392 0           my($firstconflict, $chosen) = unpackbits($bits, $in);
393 0 0         if ($firstconflict == -1) {
394             # there was no conflict. That means there was only one ID with this
395             # prefix. Return it.
396 0           return ($chosen);
397             } else {
398             # there was a conflict at $firstconflict. Recurse and return the two
399             # possible paths. The Search Accelerator has already given us the
400             # lowest numerical ID with this prefix (since we gave 0's to @path)
401             # but using that data would be too much of a nuisance.
402 0           my($way0,$way1) = ($path,$path);
403 0           substr($way0, $firstconflict, 1) = "0";
404 0           substr($way1, $firstconflict, 1) = "1";
405 0           return($self->scan1($firstconflict+1, $way0),
406             $self->scan1($firstconflict+1, $way1));
407             }
408             }
409              
410             sub scan {
411 0     0 1   my($self, $family_code, $serial) = @_;
412 0           my(@buttons);
413             my(@ids);
414              
415             # scan bus. Each ID is an 8 byte list, starting with the family code,
416             # then 6 ID bytes, then the CRC. The ID bytes are in the same order as
417             # the label engraved on the button, which is backwards of the order
418             # read from the bus.
419            
420 0           my $r = $self->reset();
421 0 0 0       if ($r == 0 or $r == 3) {
422             # short or nothing present
423 0           return undef;
424             }
425              
426             # use the DS2480's Search Accelerator function
427 0           my(@raw_ids);
428             # the raw_ids used here are 64-char strings:
429             # f0f1f2f3..f7 . s0s1s2s3..s47 . c0c1..c7
430             # f: family code (lsb first)
431             # s: serial number (lsb first). label is printed msb first.
432             # c: crc (lsb first)
433              
434 0 0         if (!defined($family_code)) {
435             # find everyone
436 0           @raw_ids = $self->scan1(0, "0" x 64);
437             } else {
438 0           my $family_bits;
439 0           $family_bits = unpack("b8", chr(hex($family_code)));
440 0 0         if (defined($serial)) {
441 0           my $device_bits;
442             # find this particular device
443 0 0         die 'scan(): \$serial must have 12 hex chars'
444             unless ($serial =~ /^[0-9a-fA-f]{12}$/);
445 0           $device_bits = reverse(unpack("B48",pack("H12",$serial)));
446 0           @raw_ids = $self->scan1(8+48, $family_bits . $device_bits . "0"x8);
447 0           @raw_ids = grep {/^\Q$family_bits$device_bits\E/} @raw_ids;
  0            
448             } else {
449             # find everyone with this family code
450 0           @raw_ids = $self->scan1(8, $family_bits . "0" x 56);
451 0           @raw_ids = grep {/^\Q$family_bits\E/} @raw_ids;
  0            
452             }
453             }
454              
455              
456 0           foreach my $raw_id (@raw_ids) {
457             # $raw_id is a 64 character string of "0" and "1"
458 0           my $button = Hardware::iButton::Device->new($self, $raw_id);
459             #print "id: ",$button->id(),"\n";
460 0           push(@buttons, $button);
461             }
462              
463 0           $self->reset();
464 0           return @buttons;
465             }
466              
467             =head2 readrom
468              
469             @id = $c->readrom(); # FIXME
470              
471             Run a Read ROM command on the bus, and return the 8 bytes that result as a
472             string of 16 hex chars. This command is only useful if there is exactly 1
473             device on the bus. This is rarely the case, since most containers of DS2480
474             chips have solder-mount touch memory devices already on the bus (the 1411k
475             seems to have a DS2401 id-only device on it, and the DS9097U appears to have a
476             DS2502 1k add-only eprom in it).
477              
478             =cut
479              
480             sub readrom {
481 0     0 1   my($self) = @_;
482              
483 0           $self->write("\xc1\xe1\x33\xff\xff\xff\xff\xff\xff\xff\xff\xe3\xc9");
484 0           my $dummy = $self->read(11);
485 0           my(@bin_id) = map {ord($_)} split(//, $dummy);
  0            
486             # first byte is the reset result, second is an echo of the 0x33 Read ROM
487             # code. Next 8 are familycode, id[5..0], then crc. Last is reset result.
488 0           my(@id) = @bin_id[2,8,7,6,5,4,3,9];
489              
490 0           return @id;
491             }
492              
493             # $c->select($rawid);
494             # activate the button with $rawid, if it isn't already.
495              
496             # todo: keep track of how long it's been since we actually heard from this
497             # device. If it's been more than a couple of seconds, do a Search ROM
498             # ($self->scan($family,$serial)) to make sure it's still there.
499             sub select {
500 0     0 0   my($self, $rawid) = @_;
501              
502 0 0 0       if ($self->{'selected'} and $self->{'selected'} eq $rawid) {
503             # already selected
504 0           return 1;
505             }
506              
507 0           my $r = $self->reset();
508 0 0 0       if ($r == 0 or $r == 3) {
509             # short or nothing present
510 0           return undef;
511             }
512              
513             # send Match ROM command
514 0           my $str = MATCH_ROM . pack("b64",$rawid);
515 0           $self->send($str);
516 0           $self->read(length($str)); # read echos
517              
518 0           $self->{'selected'} = $rawid;
519             # see if anyone is still there??
520             # nope, no way to tell
521              
522 0           return 1;
523             }
524              
525             sub verify {
526 0     0 0   my ($self, $rawid) = @_;
527 0           my $str = MATCH_ROM . "\xFF" x 24 . pack("b64",$rawid);
528 0           $self->send($str);
529 0           my $ret = $self->read(length($str)); # read echos
530             # return (ord(substr($ret, 32, 1)) == 121);
531 0           print STDERR "LEN = " . length($ret) . "\n";
532 0           print STDERR "RET = '$ret'\n";
533 0           print STDERR "CHARS = ";
534 0           foreach my $chr (split(//, $ret)) {
535 0           print STDERR ord($chr) . " ";
536             }
537 0           print STDERR "\n";
538 0           print STDERR "LAST = " . ord(substr($ret, 32, 1)) . "\n";
539             # 218, 121
540 0 0         if ($ret eq "") {
541 0           print STDERR "0\n";
542 0           return 0;
543             } else {
544 0           print STDERR "1\n";
545 0           return 1;
546             }
547             # print STDERR "'$ret'\n";
548             }
549              
550             # for (i = 0; i < 192; i += 3)
551             # {
552             # tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) |
553             # bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]);
554             #
555             # s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][0]);
556             #
557             # if (tst == 0x03) // no device on line
558             # {
559             # goodbits = 0; // number of good bits set to zero
560             # break; // quit
561             # }
562             #
563             # if (((s == 0x01) && (tst == 0x02)) ||
564             # ((s == 0x00) && (tst == 0x01)) ) // correct bit
565             # goodbits++; // count as a good bit
566             # }
567             #
568             # // check too see if there were enough good bits to be successful
569             # if (goodbits >= 8)
570             # return TRUE;
571              
572              
573             sub crc {
574 0     0 0   my($crc, @newbytes) = @_;
575            
576             sub addbit {
577 0     0 0   my($crc, $bit) = @_;
578             #printf("addbit($bit): 0x%02x -> ",$crc);;
579 0           my $in = ($crc & 1) ^ $bit;
580 0 0         $crc ^= 0x18 if $in;
581 0           $crc >>= 1;
582 0 0         $crc |= 0x80 if $in;
583             #printf("0x%02x\n",$crc);
584 0           return $crc;
585             }
586            
587 0           foreach my $byte (@newbytes) {
588 0           my $bits = unpack("b8", $byte);
589 0           my(@bits) = split(//,$bits);
590 0           foreach (@bits) {
591 0           $crc = addbit($crc, $_);
592             }
593             }
594 0           return $crc;
595             }
596              
597              
598             # Autoload methods go after =cut, and are processed by the autosplit program.
599              
600             1;
601             __END__