1 package Biblio::RFID::Reader::librfid;
6 use base 'Biblio::RFID::Reader::API';
9 use Data::Dump qw(dump);
13 Biblio::RFID::Reader::librfid - execute librfid-tool
17 This is wrapper around C<librfid-tool> from
19 L<http://openmrtd.org/projects/librfid/>
21 Due to limitation of L<librfid-tool> only
22 L<Biblio::RFID::Reader::API/inventory> and
23 L<Biblio::RFID::Reader::API/read_blocks> is supported.
25 This version uses modidified C<librfid-tool> which supports
26 new C<-s> flag which reads sectors 0-3 with C<-k> key and
27 sectors 4-7 with key from C<-s> option.
29 However, this code might provide template for integration
30 with any command-line utilities for different RFID readers.
32 Currently tested with only with Omnikey CardMan 5321 which
33 has problems. After a while it stops responding to commands
34 by C<librfid-tool> so I provided small C program to reset it:
36 C<examples/usbreset.c>
40 sub serial_settings {} # don't open serial
45 my ( $bin, $param, $coderef, $path ) = @_;
51 warn "# _grep_tool $bin $param\n";
52 # $param .= ' 2>/dev/null';
53 my $pipe_pid = open(my $s, '-|', "$bin $param") || die $!;
55 local $SIG{ALRM} = sub {
57 kill TERM => $pipe_pid;
69 if ( m/Layer 2 success.+\(([^\)]+)\).*:\s+(.+)/ ) {
70 ( $sid, $iso ) = ( $2, $1 );
72 my @sid = split(/\s+/, $sid);
73 @sid = reverse @sid if $iso =~ m/15693/;
74 $sid = uc join('', @sid);
75 warn "## sid=[$sid] iso=[$iso]\n";
77 $coderef->( $sid, $iso );
85 if ( $? >> 8 || $@ ) {
86 my $lsusb = `lsusb -d 076b:`;
87 if ( $lsusb =~ m/\S+\s+(\d+)\s+\S+\s+(\d+)/ ) {
88 my $cmd = "usbreset /dev/bus/usb/$1/$2";
92 warn "can't reset device $lsusb";
104 _grep_tool 'librfid-tool', '--scan' => sub {
105 my ( $sid, $iso ) = @_;
106 if ( $sid && ! exists $sid_iso->{$sid} ) {
108 $sid_iso->{$sid} = $iso;
111 warn "# invetory ",dump(@tags);
116 my ( $self, $tag ) = @_;
117 return $sid_iso->{$tag} =~ m/15693/ ? 'RFID501' : 'SmartX';
121 sub read_mifare_keys {
123 $key_path =~ s{/[^/]+$}{/};
124 $key_path .= "mifare_keys.pl";
126 if ( -e $key_path ) {
128 warn "# mifare keys for sectors ", join(' ', keys %$mifare_keys), " loaded\n";
133 my ( $self, $sid ) = @_;
135 my $iso = $sid_iso->{$sid};
138 if ( $iso =~ m/15693/ ) {
139 _grep_tool 'librfid-tool', '--read -1' => sub {
141 $blocks->{$sid}->[$1] = hex2bytes($2)
142 if m/block\[\s*(\d+):.+data.+:\s*(.+)/;
146 read_mifare_keys unless $mifare_keys;
148 =for unmodified mifate-tool
149 foreach my $sector ( keys %$mifare_keys ) {
150 my $key = lc $mifare_keys->{$sector};
151 _grep_tool 'mifare-tool', "-k $key -r $sector" => sub {
152 $blocks->{$sid}->[$sector] = hex2bytes($1)
157 _grep_tool 'mifare-tool', "-k " . $mifare_keys->{0} . " -s " . $mifare_keys->{4} => sub {
158 $blocks->{$sid}->[$1] = hex2bytes($2)
159 if m/page=(\d+).*data=\s*(.+)/;
162 warn "# read_blocks ",dump($blocks);