X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=lib%2FRFID%2FBiblio%2FReader%2F3M810.pm;h=a0d127c0d31f029c91fe99786db4d8dbe5757654;hb=3bd73ca701a227de504cb3d24c1936cbfe9433bd;hp=f26e9ab51692326a5e28392e2aa0b9a00dfa7f91;hpb=75a8809d9f67c952c0db9c3941ec615cace3c716;p=Biblio-RFID.git diff --git a/lib/RFID/Biblio/Reader/3M810.pm b/lib/RFID/Biblio/Reader/3M810.pm index f26e9ab..a0d127c 100644 --- a/lib/RFID/Biblio/Reader/3M810.pm +++ b/lib/RFID/Biblio/Reader/3M810.pm @@ -6,11 +6,11 @@ RFID::Biblio::Reader::3M810 - support for 3M 810 RFID reader =head1 DESCRIPTION -This module implement serial protocol (over USB/serial adapter) with 3M 810 RFID -reader, often used in library applications. +This module uses L over USB/serial adapter +with 3M 810 RFID reader, often used in library applications. -This is most complete implementation which supports full API defined -in L. This include scanning for all tags in reader +This is most mature implementation which supports full API defined +in L. This include scanning for all tags in reader range, reading and writing of data, and AFI security manipulation. This implementation is developed using Portmon on Windows to capture serial traffic @@ -19,12 +19,15 @@ L Checksum for this reader is developed using help from C L +More inforation about process of reverse engeeniring protocol with +this reader is available at L + =cut use warnings; use strict; -use base 'RFID::Biblio'; +use base 'RFID::Biblio::Reader::Serial'; use RFID::Biblio; use Data::Dump qw(dump); @@ -33,7 +36,6 @@ use Time::HiRes; use Digest::CRC; sub serial_settings {{ - device => "/dev/ttyUSB1", # FIXME comment out before shipping baudrate => "19200", databits => "8", parity => "none", @@ -41,6 +43,8 @@ sub serial_settings {{ handshake => "none", }} +sub assert; + my $port; sub init { my $self = shift; @@ -52,14 +56,33 @@ sub init { # drain on startup my ( $count, $str ) = $port->read(3); - my $data = $port->read( ord(substr($str,2,1)) ); - warn "drain ",as_hex( $str, $data ),"\n"; + if ( $count ) { + my $data = $port->read( ord(substr($str,2,1)) ); + warn "drain ",as_hex( $str, $data ),"\n"; + } $port->read_char_time(100); # 0.1 s char timeout $port->read_const_time(500); # 0.5 s read timeout - setup(); + $port->write( hex2bytes( 'D5 00 05 04 00 11 8C66' ) ); + # hw-version expect: 'D5 00 09 04 00 11 0A 05 00 02 7250' + my $data = $port->read( 12 ); + return unless $data; + + warn "# probe response: ",as_hex($data); + if ( my $rest = assert $data => 'D5 00 09 04 00 11' ) { + my $hw_ver = join('.', unpack('CCCC', $rest)); + warn "# 3M 810 hardware version $hw_ver\n"; + cmd( +'13 04 01 00 02 00 03 00 04 00','FIXME: stats? rf-on?', sub { assert(shift, +'13 00 02 01 01 03 02 02 03 00' + )}); + + return $hw_ver; + } + + return; } sub checksum { @@ -72,10 +95,6 @@ sub checksum { pack('n', $crc->digest); } -sub wait_device { - Time::HiRes::sleep 0.015; -} - sub cmd { my ( $hex, $description, $coderef ) = @_; my $bytes = hex2bytes($hex); @@ -86,33 +105,22 @@ sub cmd { $bytes = "\xD6" . $bytes . $checksum; } - warn ">> ", as_hex( $bytes ), "\t\t[$description]\n"; + warn ">> ", as_hex( $bytes ), "\t\t[$description]\n" if $debug; $port->write( $bytes ); - wait_device; - my $r_len = $port->read(3); while ( length($r_len) < 3 ) { - wait_device; $r_len = $port->read( 3 - length($r_len) ); } - wait_device; - my $len = ord( substr($r_len,2,1) ); my $data = $port->read( $len ); - while ( length($data) < $len ) { - warn "# short read ", length($data), " < $len\n"; - wait_device; - $data .= $port->read( $len - length($data) ); - } - warn "<< ", as_hex($r_len,$data), ' | ', substr($data,-2,2) eq checksum(substr($r_len,1).substr($data,0,-2)) ? 'OK' : 'ERROR', - " $len bytes\n"; + " $len bytes\n" if $debug; $coderef->( $data ) if $coderef; @@ -132,27 +140,6 @@ sub assert { return substr($got,$len); } -sub setup { - -cmd( -'D5 00 05 04 00 11 8C66', 'hw version', sub { - my $data = shift; - my $rest = assert $data => '04 00 11'; - my $hw_ver = join('.', unpack('CCCC', $rest)); - warn "# 3M 810 hardware version $hw_ver\n"; -}); - -cmd( -'13 04 01 00 02 00 03 00 04 00','FIXME: stats? rf-on?', sub { assert(shift, -'13 00 02 01 01 03 02 02 03 00' -)}); -} - -=head2 inventory - - my @tags = inventory; - -=cut sub inventory { @@ -192,7 +179,7 @@ sub _matched { my $b = hex2bytes $hex; my $l = length($b); if ( substr($data,0,$l) eq $b ) { - warn "_matched $hex [$l] in ",as_hex($data); + warn "_matched $hex [$l] in ",as_hex($data) if $debug; return substr($data,$l); } } @@ -221,9 +208,9 @@ sub read_blocks { } elsif ( $rest = _matched $data => 'FE 00 00 05 01' ) { warn "FIXME ready? ",as_hex $rest; } elsif ( $rest = _matched $data => '02 06' ) { - warn "ERROR ",as_hex($rest); + die "ERROR ",as_hex($rest); } else { - warn "FIXME unsuported ",as_hex($rest); + die "FIXME unsuported ",as_hex($rest); } }); @@ -256,7 +243,7 @@ sub write_blocks { my $blocks = substr($rest,8,1); warn "# WRITE ",as_hex($tag), " [$blocks]\n"; } elsif ( $rest = _matched $data => '04 06' ) { - warn "ERROR ",as_hex($rest); + die "ERROR ",as_hex($rest); } else { die "UNSUPPORTED"; } @@ -283,9 +270,9 @@ sub read_afi { warn "# SECURITY ", hex_tag($tag), " AFI: ", as_hex($afi); } elsif ( $rest = _matched $data => '0A 06' ) { - warn "ERROR reading security from $tag ", as_hex($data); + die "ERROR reading security from $tag ", as_hex($data); } else { - warn "IGNORED ",as_hex($data); + die "IGNORED ",as_hex($data); } }); warn "## read_afi ",dump($tag, $afi); @@ -308,11 +295,9 @@ sub write_afi { die "write_afi got $tag_back expected $tag" if $tag_back ne $tag; warn "# SECURITY ", hex_tag($tag), " AFI: ", as_hex($afi); } elsif ( $rest = _matched $data => '0A 06' ) { - warn "ERROR writing AFI to $tag ", as_hex($data); - undef $afi; + die "ERROR writing AFI to $tag ", as_hex($data); } else { - warn "IGNORED ",as_hex($data); - undef $afi; + die "IGNORED ",as_hex($data); } }); warn "## write_afi ", dump( $tag, $afi ); @@ -320,3 +305,9 @@ sub write_afi { } 1 + +__END__ + +=head1 SEE ALSO + +L