1 package RFID::Serial::CPRM02;
3 use base 'RFID::Serial';
7 use Data::Dump qw(dump);
11 sub serial_settings {{
12 device => "/dev/ttyUSB0",
20 sub cpr_m02_checksum {
27 foreach my $i ( 0 .. length($data) - 1 ) {
28 $crc ^= ord(substr($data,$i,1));
29 for my $j ( 0 .. 7 ) {
30 if ( $crc & 0x0001 ) {
31 $crc = ( $crc >> 1 ) ^ $polynom;
36 # warn sprintf('%d %04x', $i, $crc & 0xffff);
39 return pack('v', $crc);
43 Time::HiRes::sleep 0.010;
49 my ( $hex, $description, $coderef ) = @_;
50 my $bytes = hex2bytes($hex);
51 my $len = pack( 'c', length( $bytes ) + 3 );
52 my $send = $len . $bytes;
53 my $checksum = cpr_m02_checksum($send);
56 warn "##>> ", as_hex( $send ), "\t\t[$description]\n";
57 $port->write( $send );
61 my $r_len = $port->read(1);
65 if ( $count-- == 0 ) {
66 warn "no response from device";
70 $r_len = $port->read(1);
75 my $data_len = ord($r_len) - 1;
76 my $data = $port->read( $data_len );
77 warn "##<< ", as_hex( $r_len . $data ),"\n";
81 $coderef->( $data ) if $coderef;
92 cpr( 'FF 52 00', 'Boud Rate Detection' );
94 cpr( 'FF 65', 'Get Software Version' );
96 cpr( 'FF 66 00', 'Get Reader Info - General hard and firware' );
98 cpr( 'FF 69', 'RF Reset' );
104 my $hex_uid = as_hex($uid);
108 cpr( "FF B0 2B 01 $hex_uid", "Get System Information $hex_uid", sub {
111 warn "# data ",as_hex($data);
113 my $DSFID = substr($data,5-2,1);
114 my $UID = substr($data,6-2,8);
115 my $AFI = substr($data,14-2,1);
116 my $MEM = substr($data,15-2,1);
117 my $SIZE = substr($data,16-2,1);
118 my $IC_REF = substr($data,17-2,1);
120 warn "# split ",as_hex( $DSFID, $UID, $AFI, $MEM, $SIZE, $IC_REF );
122 $max_block = ord($SIZE);
125 my $transponder_data;
128 while ( $block < $max_block ) {
129 cpr( sprintf("FF B0 23 01 $hex_uid %02x 04", $block), "Read Multiple Blocks $block", sub {
132 my $DB_N = ord substr($data,5-2,1);
133 my $DB_SIZE = ord substr($data,6-2,1);
135 $data = substr($data,7-2,-2);
136 # warn "# DB N: $DB_N SIZE: $DB_SIZE ", as_hex( $data ), " transponder_data: [$transponder_data] ",length($transponder_data),"\n";
137 foreach ( 1 .. $DB_N ) {
138 my $sec = substr($data,0,1);
139 my $db = substr($data,1,$DB_SIZE);
140 warn "## block $_ ",dump( $sec, $db ) if $debug;
141 $transponder_data .= reverse split(//,$db);
142 $data = substr($data, $DB_SIZE + 1);
148 warn "# DATA $hex_uid ", dump($transponder_data);
149 return $transponder_data;
158 cpr( 'FF B0 01 00', 'ISO - Inventory', sub {
160 if (length($data) < 5 + 2 ) {
161 warn "# no tags in range\n";
164 my $data_sets = ord(substr($data,3,1));
165 $data = substr($data,4);
166 foreach ( 1 .. $data_sets ) {
167 my $tr_type = substr($data,0,1);
168 die "FIXME only TR-TYPE=3 ISO 15693 supported" unless $tr_type eq "\x03";
169 my $dsfid = substr($data,1,1);
170 my $uid = substr($data,2,8);
171 $data = substr($data,10);
172 warn "# TAG $_ ",as_hex( $tr_type, $dsfid, $uid ),$/;
174 $inventory->{$uid} ||= cpr_read( $uid );
177 warn "# inventory: ",dump($inventory);