Skip to content

Commit

Permalink
Import of XANT/RFID-Libnfc-0.13 from CPAN.
Browse files Browse the repository at this point in the history
gitpan-cpan-distribution: RFID-Libnfc
gitpan-cpan-version:      0.13
gitpan-cpan-path:         XANT/RFID-Libnfc-0.13.tar.gz
gitpan-cpan-author:       XANT
gitpan-cpan-maturity:     released
  • Loading branch information
Andrea Guzzo authored and Gitpan committed Oct 23, 2014
1 parent 80a1769 commit fcfb4e4
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 79 deletions.
2 changes: 2 additions & 0 deletions Changes
Expand Up @@ -43,3 +43,5 @@ Revision history for Perl extension Libnfc.
- cleaned-up libnfc version checking logic in Makefile.PL
- wrapping allocation/release operations with proper perl macros in the XS code
- updated documentation
0.13 Mon Jan 24 01:23:59 CET 2011
- fixed support for Mifare classic 1K and 4K (was broken since 0.11)
20 changes: 13 additions & 7 deletions Libnfc.xs
Expand Up @@ -181,7 +181,7 @@ nc(THIS)
CODE:
RETVAL = THIS->device
? THIS->device->nc
: -1;
: 0xff;
OUTPUT:
RETVAL

Expand Down Expand Up @@ -491,10 +491,13 @@ nfc_initiator_transceive_bits(pnd, pbtTx, uiTxBits)
byte_t pbtRx[MAX_FRAME_LEN];
SV *sv = &PL_sv_undef;
CODE:
sv = newSV(0);
// TODO - handle parity
if (nfc_initiator_transceive_bits(pnd->device, pbtTx, uiTxBits, NULL, pbtRx, &puiRxBits, NULL))
sv_setpvn(sv, pbtRx, puiRxBits/8);
if (nfc_initiator_transceive_bits(pnd->device, pbtTx, uiTxBits, NULL, pbtRx, &puiRxBits, NULL)) {
if (puiRxBits)
sv = newSVpv(pbtRx, puiRxBits/8);
else
sv = newSVpv("", 0);
}
RETVAL = sv;
OUTPUT:
RETVAL
Expand All @@ -513,9 +516,12 @@ nfc_initiator_transceive_bytes(pnd, pbtTx, uiTxLen)
size_t puiRxLen = 0;
SV *sv = &PL_sv_undef;
CODE:
sv = newSV(0);
if (nfc_initiator_transceive_bytes(pnd->device, pbtTx, uiTxLen, pbtRx, &puiRxLen))
sv_setpvn(sv, pbtRx, puiRxLen);
if (nfc_initiator_transceive_bytes(pnd->device, pbtTx, uiTxLen, pbtRx, &puiRxLen)) {
if (puiRxLen)
sv = newSVpv(pbtRx, puiRxLen);
else
sv = newSVpv("", 0);
}
RETVAL = sv;
OUTPUT:
RETVAL
Expand Down
2 changes: 1 addition & 1 deletion META.yml
@@ -1,6 +1,6 @@
--- #YAML:1.0
name: RFID-Libnfc
version: 0.12
version: 0.13
abstract: Perl extension for libnfc (Near Field Communication < http://www.libnfc.org/ >)
author:
- Xant <xant@cpan.org>
Expand Down
4 changes: 2 additions & 2 deletions lib/RFID/Libnfc.pm
Expand Up @@ -11,7 +11,7 @@ use RFID::Libnfc::Constants;

our @ISA = qw(Exporter);

our $VERSION = '0.12';
our $VERSION = '0.13';

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
Expand Down Expand Up @@ -183,7 +183,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@cpan.org>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
68 changes: 32 additions & 36 deletions lib/RFID/Libnfc/Constants.pm
Expand Up @@ -2,7 +2,7 @@ package RFID::Libnfc::Constants;

use Exporter;
our @ISA = qw( Exporter );
our $VERSION = '0.12';
our $VERSION = '0.13';

BEGIN { # must be defined at compile time
%constants = (
Expand Down Expand Up @@ -95,12 +95,13 @@ RFID::Libnfc::Constants
use RFID::Libnfc::Constants qw(<category>);
where <category> can be any of :
* NDO
* IM
* MC
* MU
* NMT
* NBR
- NDO
- IM
- MC
- MU
- NC
- NMT
- NBR
=head1 DESCRIPTION
Expand Down Expand Up @@ -178,81 +179,76 @@ RFID::Libnfc::Constants
=item * IM
IM_ISO14443A_106 => 0x00,
Mifare Classic (both 1K and 4K) and ULTRA tags conform to IM_ISO14443A_106.
At the moment these are the only implemented tag types.
IM_FELICA_212 => 0x01,
* UNIMPLEMENTED *
IM_FELICA_424 => 0x02,
* UNIMPLEMENTED *
IM_ISO14443B_106 => 0x03,
* UNIMPLEMENTED *
IM_JEWEL_106 => 0x04
* UNIMPLEMENTED *
=item * MC
MC_AUTH_A => 0x60,
Select the A key
MC_AUTH_B => 0x61,
Select the B key
MC_READ => 0x30,
Perform a read operation
MC_WRITE => 0xA0,
Perform a write operation
MC_TRANSFER => 0xB0,
MC_DECREMENT => 0xC0,
Increment the value of a byte
MC_INCREMENT => 0xC1,
Increment the value of a byte
MC_STORE => 0xC2
=item * MU
MU_REQA => 0x26,
MU_WUPA => 0x52,
MU_SELECT1 => 0x93,
MU_SELECT2 => 0x95,
MU_READ => 0x30,
MU_WRITE => 0xA2,
MU_CWRITE => 0xA0,
MU_HALT => 0x50
=item * NMT
NMT_ISO14443A => 0,
Mifare Classic (both 1K and 4K) and ULTRA tags conform to IM_ISO14443A_106.
At the moment these are the only implemented tag types.
NMT_ISO14443B => 1,
* UNIMPLEMENTED *
NMT_FELICA => 2,
* UNIMPLEMENTED *
NMT_JEWEL => 3,
* UNIMPLEMENTED *
NMT_DEP => 4
* UNIMPLEMENTED *
=item * NBR
NBR_UNDEFINED => 0,
NBR_106 => 1,
NBR_212 => 2,
NBR_424 => 3,
NBR_847 => 4
=item * NC
NC_UNDEFINED => 0xff,
* Undefined reader type *
This will be returned also when an error condition occurs
NC_PN531 => 0x10
NC_PN532 => 0x20
NC_PN533 => 0x30
Expand All @@ -271,7 +267,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@cpan.org>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
2 changes: 1 addition & 1 deletion lib/RFID/Libnfc/Device.pm
Expand Up @@ -70,7 +70,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@cpan.org>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
2 changes: 1 addition & 1 deletion lib/RFID/Libnfc/Modulation.pm
Expand Up @@ -67,7 +67,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@cpan.org>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
4 changes: 2 additions & 2 deletions lib/RFID/Libnfc/Reader.pm
Expand Up @@ -9,7 +9,7 @@ use RFID::Libnfc qw(nfc_connect nfc_disconnect nfc_initiator_init nfc_configure)
use RFID::Libnfc::Tag;
use RFID::Libnfc::Constants;

our $VERSION = '0.12';
our $VERSION = '0.13';

sub new {
my ($class, %args) = @_;
Expand Down Expand Up @@ -126,7 +126,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@xant.net>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
4 changes: 2 additions & 2 deletions lib/RFID/Libnfc/Tag.pm
Expand Up @@ -6,7 +6,7 @@ use RFID::Libnfc qw(nfc_configure nfc_initiator_select_passive_target nfc_initia
use RFID::Libnfc::Constants;
use Data::Dumper;

our $VERSION = '0.12';
our $VERSION = '0.13';

my %types = (
scalar(IM_ISO14443A_106) => 'RFID::Libnfc::Tag::ISO14443A_106'
Expand Down Expand Up @@ -149,7 +149,7 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@xant.net>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
Expand Down
7 changes: 3 additions & 4 deletions lib/RFID/Libnfc/Tag/ISO14443A_106.pm
Expand Up @@ -5,7 +5,7 @@ use strict;
use base qw(RFID::Libnfc::Tag);
use RFID::Libnfc::Constants;

our $VERSION = "0.12";
our $VERSION = "0.13";

sub init {
my ($self) = @_;
Expand Down Expand Up @@ -188,8 +188,6 @@ Compute the crc as required by ISO14443A_106 standard
=item * error ( )
returns the underlying reader descriptor (to be used with the RFID::Libnfc procedural api)
$pdi = $r->pdi
=back
Expand All @@ -206,11 +204,12 @@ xant
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by xant <xant@xant.net>
Copyright (C) 2009-2011 by xant <xant@cpan.org>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
at your option, any later version of Perl 5 you may have available.
=cut
50 changes: 33 additions & 17 deletions lib/RFID/Libnfc/Tag/ISO14443A_106/Classic.pm
@@ -1,12 +1,12 @@
package RFID::Libnfc::Tag::ISO14443A_106::4K;
package RFID::Libnfc::Tag::ISO14443A_106::Classic;

use strict;

use base qw(RFID::Libnfc::Tag::ISO14443A_106);
use RFID::Libnfc qw(nfc_initiator_select_tag nfc_initiator_transceive_bytes print_hex);
use RFID::Libnfc qw(nfc_configure nfc_initiator_transceive_bytes print_hex);
use RFID::Libnfc::Constants;

our $VERSION = '0.12';
our $VERSION = '0.13';

# Internal representation of TABLE 3 (M001053_MF1ICS50_rev5_3.pdf)
# the key are the actual ACL bits (C1 C2 C3) ,
Expand Down Expand Up @@ -70,6 +70,18 @@ my %data_acl = ( # read, write, increment, decrement/restore/transfer
7 => [ 0, 0, 0, 0 ] # never never never never
);

sub init {
my $self = shift;

nfc_configure($self->{reader}->pdi, NDO_AUTO_ISO14443_4, 0);
# XXX - EASY_FRAMING has been introduced since libnfc 1.4 and
# and if enabled allows us to avoid sending the preamble
# when initiating the communication
# TODO - make it optional and continue supporting full raw-frame sending
nfc_configure($self->{reader}->pdi, NDO_EASY_FRAMING, 1);
$self->SUPER::init(@_);
}

sub read_block {
my ($self, $block, $noauth) = @_;

Expand All @@ -91,8 +103,10 @@ sub read_block {
return undef unless
$self->unlock($sector, (@{$acl->{parsed}->{$datanum}}[0] == 2) ? MC_AUTH_B : MC_AUTH_A);
}
my $initiator_exchange_data = pack("C5", 0xD4, 0x40, 0x01, MC_READ, $block);
if (my $resp = nfc_initiator_transceive_bytes($self->reader->pdi, $initiatior_exchange_data, 5)) {
# XXX - we are using EASY_FRAMING now .. so no need for the preamble
#my $initiator_exchange_data = pack("C5", 0xD4, 0x40, 0x01, MC_READ, $block);
my $initiator_exchange_data = pack("C2", MC_READ, $block);
if (my $resp = nfc_initiator_transceive_bytes($self->reader->pdi, $initiator_exchange_data, 2)) {
return unpack("a16", $resp);
} else {
$self->{_last_error} = "Error reading $sector, block $block"; # XXX - does libnfc provide any clue on the ongoing error?
Expand Down Expand Up @@ -129,8 +143,10 @@ sub write_block {
$self->unlock($sector, (@{$acl->{parsed}->{$datanum}}[1] == 2) ? MC_AUTH_B : MC_AUTH_A);
}

my $initiator_exchange_data = pack("C5a16", 0xD4, 0x40, 0x01, MC_WRITE, $block, $data);
if (nfc_initiator_transceive_bytes($self->reader->pdi, $initiatior_exchange_data, 5+16)) {
# XXX - we are using EASY_FRAMING now .. so no need for the preamble
#my $initiator_exchange_data = pack("C5a16", 0xD4, 0x40, 0x01, MC_WRITE, $block, $data);
my $initiator_exchange_data = pack("C2a16", MC_WRITE, $block, $data);
if (nfc_initiator_transceive_bytes($self->reader->pdi, $initiator_exchange_data, 2+16)) {
return 1;
} else {
# XXX can libnfc provide more info about the failure?
Expand Down Expand Up @@ -187,14 +203,13 @@ sub unlock {
$keytype = MC_AUTH_A unless ($keytype and ($keytype == MC_AUTH_A or $keytype == MC_AUTH_B));
my $keyidx = ($keytype == MC_AUTH_A) ? 0 : 1;

printf("unlocking sector $sector with key/uid : " .
"%x " x 6 . " ---- " . "%x " x 4 . "\n", unpack("C10", $mpt->mpa)) if $self->{debug};

my $initiator_exchange_data = pack("C5a6C4", 0xD4, 0x40, 0x01, $keytype, $tblock, $self->{_keys}->[$sector][$keyidx], @{$self->uid});
return 1 if (nfc_initiator_transceive_bytes($self->reader->pdi, $initiatior_exchange_data, 5+6+4));
# XXX - we are using EASY_FRAMING now .. so no need for the preamble
#my $initiator_exchange_data = pack("C5a6C4", 0xD4, 0x40, 0x01, $keytype, $tblock, $self->{_keys}->[$sector][$keyidx], @{$self->uid});
my $initiator_exchange_data = pack("C2a6C4", $keytype, $tblock, $self->{_keys}->[$sector][$keyidx], @{$self->uid});
return 1 if (defined nfc_initiator_transceive_bytes($self->reader->pdi, $initiator_exchange_data, 2+6+4));

$self->{_last_error} = "Failed to authenticate on sector $sector (tblock:$tblock) with key " .
sprintf("%x " x 6 . "\n", unpack("C6", $mpt->mpa));
sprintf("%x " x 6 . "\n", unpack("C6", $self->{_keys}->[$sector][$keyidx]));

return 0;
}
Expand All @@ -204,10 +219,11 @@ sub acl {
my $tblock = $self->trailer_block($sector);

if ($self->unlock($sector)) {
my $initiator_exchange_data = pack("C5", 0xD4, 0x40, 0x01, MC_READ, $tblock);
if (nfc_initiator_transceive_bytes($self->reader->pdi, $initiator_exchange_data, 5)) {
my $j = $mpt->mpd;
return $self->_parse_acl(unpack("x6a4x6", $mpt->mpd));
# XXX - we are using EASY_FRAMING now .. so no need for the preamble
#my $initiator_exchange_data = pack("C5", 0xD4, 0x40, 0x01, MC_READ, $tblock);
my $initiator_exchange_data = pack("C2", MC_READ, $tblock);
if (my $data = nfc_initiator_transceive_bytes($self->reader->pdi, $initiator_exchange_data, 2)) {
return $self->_parse_acl(unpack("x6a4x6", $data));
}
}
return undef;
Expand Down

0 comments on commit fcfb4e4

Please sign in to comment.