Commit 1a2e5ee4bfcaf0e8b8d185137a62b35c5c0127c1

Authored by henyxia
1 parent aff6dccd

Big revision

Everything rewritten in C/C++
Customized version of Seed Studio's PN532 NFC Library
Arduino/pins_arduino.h 0 → 100644
... ... @@ -0,0 +1,218 @@
  1 +/*
  2 + pins_arduino.h - Pin definition functions for Arduino
  3 + Part of Arduino - http://www.arduino.cc/
  4 +
  5 + Copyright (c) 2007 David A. Mellis
  6 +
  7 + This library is free software; you can redistribute it and/or
  8 + modify it under the terms of the GNU Lesser General Public
  9 + License as published by the Free Software Foundation; either
  10 + version 2.1 of the License, or (at your option) any later version.
  11 +
  12 + This library is distributed in the hope that it will be useful,
  13 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + Lesser General Public License for more details.
  16 +
  17 + You should have received a copy of the GNU Lesser General
  18 + Public License along with this library; if not, write to the
  19 + Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20 + Boston, MA 02111-1307 USA
  21 +
  22 + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
  23 +*/
  24 +
  25 +#ifndef Pins_Arduino_h
  26 +#define Pins_Arduino_h
  27 +
  28 +#include <avr/pgmspace.h>
  29 +
  30 +#define NUM_DIGITAL_PINS 20
  31 +#define NUM_ANALOG_INPUTS 6
  32 +#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1)
  33 +
  34 +#if defined(__AVR_ATmega8__)
  35 +#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11)
  36 +#else
  37 +#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11)
  38 +#endif
  39 +
  40 +static const uint8_t SS = 10;
  41 +static const uint8_t MOSI = 11;
  42 +static const uint8_t MISO = 12;
  43 +static const uint8_t SCK = 13;
  44 +
  45 +static const uint8_t SDA = 18;
  46 +static const uint8_t SCL = 19;
  47 +static const uint8_t LED_BUILTIN = 13;
  48 +
  49 +static const uint8_t A0 = 14;
  50 +static const uint8_t A1 = 15;
  51 +static const uint8_t A2 = 16;
  52 +static const uint8_t A3 = 17;
  53 +static const uint8_t A4 = 18;
  54 +static const uint8_t A5 = 19;
  55 +static const uint8_t A6 = 20;
  56 +static const uint8_t A7 = 21;
  57 +
  58 +#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
  59 +#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
  60 +#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
  61 +#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
  62 +
  63 +#ifdef ARDUINO_MAIN
  64 +
  65 +// On the Arduino board, digital pins are also used
  66 +// for the analog output (software PWM). Analog input
  67 +// pins are a separate set.
  68 +
  69 +// ATMEL ATMEGA8 & 168 / ARDUINO
  70 +//
  71 +// +-\/-+
  72 +// PC6 1| |28 PC5 (AI 5)
  73 +// (D 0) PD0 2| |27 PC4 (AI 4)
  74 +// (D 1) PD1 3| |26 PC3 (AI 3)
  75 +// (D 2) PD2 4| |25 PC2 (AI 2)
  76 +// PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
  77 +// (D 4) PD4 6| |23 PC0 (AI 0)
  78 +// VCC 7| |22 GND
  79 +// GND 8| |21 AREF
  80 +// PB6 9| |20 AVCC
  81 +// PB7 10| |19 PB5 (D 13)
  82 +// PWM+ (D 5) PD5 11| |18 PB4 (D 12)
  83 +// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
  84 +// (D 7) PD7 13| |16 PB2 (D 10) PWM
  85 +// (D 8) PB0 14| |15 PB1 (D 9) PWM
  86 +// +----+
  87 +//
  88 +// (PWM+ indicates the additional PWM pins on the ATmega168.)
  89 +
  90 +// ATMEL ATMEGA1280 / ARDUINO
  91 +//
  92 +// 0-7 PE0-PE7 works
  93 +// 8-13 PB0-PB5 works
  94 +// 14-21 PA0-PA7 works
  95 +// 22-29 PH0-PH7 works
  96 +// 30-35 PG5-PG0 works
  97 +// 36-43 PC7-PC0 works
  98 +// 44-51 PJ7-PJ0 works
  99 +// 52-59 PL7-PL0 works
  100 +// 60-67 PD7-PD0 works
  101 +// A0-A7 PF0-PF7
  102 +// A8-A15 PK0-PK7
  103 +
  104 +
  105 +// these arrays map port names (e.g. port B) to the
  106 +// appropriate addresses for various functions (e.g. reading
  107 +// and writing)
  108 +const uint16_t PROGMEM port_to_mode_PGM[] = {
  109 + NOT_A_PORT,
  110 + NOT_A_PORT,
  111 + (uint16_t) &DDRB,
  112 + (uint16_t) &DDRC,
  113 + (uint16_t) &DDRD,
  114 +};
  115 +
  116 +const uint16_t PROGMEM port_to_output_PGM[] = {
  117 + NOT_A_PORT,
  118 + NOT_A_PORT,
  119 + (uint16_t) &PORTB,
  120 + (uint16_t) &PORTC,
  121 + (uint16_t) &PORTD,
  122 +};
  123 +
  124 +const uint16_t PROGMEM port_to_input_PGM[] = {
  125 + NOT_A_PORT,
  126 + NOT_A_PORT,
  127 + (uint16_t) &PINB,
  128 + (uint16_t) &PINC,
  129 + (uint16_t) &PIND,
  130 +};
  131 +
  132 +const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
  133 + PD, /* 0 */
  134 + PD,
  135 + PD,
  136 + PD,
  137 + PD,
  138 + PD,
  139 + PD,
  140 + PD,
  141 + PB, /* 8 */
  142 + PB,
  143 + PB,
  144 + PB,
  145 + PB,
  146 + PB,
  147 + PC, /* 14 */
  148 + PC,
  149 + PC,
  150 + PC,
  151 + PC,
  152 + PC,
  153 +};
  154 +
  155 +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
  156 + _BV(0), /* 0, port D */
  157 + _BV(1),
  158 + _BV(2),
  159 + _BV(3),
  160 + _BV(4),
  161 + _BV(5),
  162 + _BV(6),
  163 + _BV(7),
  164 + _BV(0), /* 8, port B */
  165 + _BV(1),
  166 + _BV(2),
  167 + _BV(3),
  168 + _BV(4),
  169 + _BV(5),
  170 + _BV(0), /* 14, port C */
  171 + _BV(1),
  172 + _BV(2),
  173 + _BV(3),
  174 + _BV(4),
  175 + _BV(5),
  176 +};
  177 +
  178 +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
  179 + NOT_ON_TIMER, /* 0 - port D */
  180 + NOT_ON_TIMER,
  181 + NOT_ON_TIMER,
  182 + // on the ATmega168, digital pin 3 has hardware pwm
  183 +#if defined(__AVR_ATmega8__)
  184 + NOT_ON_TIMER,
  185 +#else
  186 + TIMER2B,
  187 +#endif
  188 + NOT_ON_TIMER,
  189 + // on the ATmega168, digital pins 5 and 6 have hardware pwm
  190 +#if defined(__AVR_ATmega8__)
  191 + NOT_ON_TIMER,
  192 + NOT_ON_TIMER,
  193 +#else
  194 + TIMER0B,
  195 + TIMER0A,
  196 +#endif
  197 + NOT_ON_TIMER,
  198 + NOT_ON_TIMER, /* 8 - port B */
  199 + TIMER1A,
  200 + TIMER1B,
  201 +#if defined(__AVR_ATmega8__)
  202 + TIMER2,
  203 +#else
  204 + TIMER2A,
  205 +#endif
  206 + NOT_ON_TIMER,
  207 + NOT_ON_TIMER,
  208 + NOT_ON_TIMER,
  209 + NOT_ON_TIMER, /* 14 - port C */
  210 + NOT_ON_TIMER,
  211 + NOT_ON_TIMER,
  212 + NOT_ON_TIMER,
  213 + NOT_ON_TIMER,
  214 +};
  215 +
  216 +#endif
  217 +
  218 +#endif
... ...
Arduino/wiring.c 0 → 100644
... ... @@ -0,0 +1,324 @@
  1 +/*
  2 + wiring.c - Partial implementation of the Wiring API for the ATmega8.
  3 + Part of Arduino - http://www.arduino.cc/
  4 +
  5 + Copyright (c) 2005-2006 David A. Mellis
  6 +
  7 + This library is free software; you can redistribute it and/or
  8 + modify it under the terms of the GNU Lesser General Public
  9 + License as published by the Free Software Foundation; either
  10 + version 2.1 of the License, or (at your option) any later version.
  11 +
  12 + This library is distributed in the hope that it will be useful,
  13 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + Lesser General Public License for more details.
  16 +
  17 + You should have received a copy of the GNU Lesser General
  18 + Public License along with this library; if not, write to the
  19 + Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20 + Boston, MA 02111-1307 USA
  21 +
  22 + $Id$
  23 +*/
  24 +
  25 +#include "wiring_private.h"
  26 +
  27 +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
  28 +// the overflow handler is called every 256 ticks.
  29 +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
  30 +
  31 +// the whole number of milliseconds per timer0 overflow
  32 +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
  33 +
  34 +// the fractional number of milliseconds per timer0 overflow. we shift right
  35 +// by three to fit these numbers into a byte. (for the clock speeds we care
  36 +// about - 8 and 16 MHz - this doesn't lose precision.)
  37 +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
  38 +#define FRACT_MAX (1000 >> 3)
  39 +
  40 +volatile unsigned long timer0_overflow_count = 0;
  41 +volatile unsigned long timer0_millis = 0;
  42 +static unsigned char timer0_fract = 0;
  43 +
  44 +#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  45 +ISR(TIM0_OVF_vect)
  46 +#else
  47 +ISR(TIMER0_OVF_vect)
  48 +#endif
  49 +{
  50 + // copy these to local variables so they can be stored in registers
  51 + // (volatile variables must be read from memory on every access)
  52 + unsigned long m = timer0_millis;
  53 + unsigned char f = timer0_fract;
  54 +
  55 + m += MILLIS_INC;
  56 + f += FRACT_INC;
  57 + if (f >= FRACT_MAX) {
  58 + f -= FRACT_MAX;
  59 + m += 1;
  60 + }
  61 +
  62 + timer0_fract = f;
  63 + timer0_millis = m;
  64 + timer0_overflow_count++;
  65 +}
  66 +
  67 +unsigned long millis()
  68 +{
  69 + unsigned long m;
  70 + uint8_t oldSREG = SREG;
  71 +
  72 + // disable interrupts while we read timer0_millis or we might get an
  73 + // inconsistent value (e.g. in the middle of a write to timer0_millis)
  74 + cli();
  75 + m = timer0_millis;
  76 + SREG = oldSREG;
  77 +
  78 + return m;
  79 +}
  80 +
  81 +unsigned long micros() {
  82 + unsigned long m;
  83 + uint8_t oldSREG = SREG, t;
  84 +
  85 + cli();
  86 + m = timer0_overflow_count;
  87 +#if defined(TCNT0)
  88 + t = TCNT0;
  89 +#elif defined(TCNT0L)
  90 + t = TCNT0L;
  91 +#else
  92 + #error TIMER 0 not defined
  93 +#endif
  94 +
  95 +
  96 +#ifdef TIFR0
  97 + if ((TIFR0 & _BV(TOV0)) && (t < 255))
  98 + m++;
  99 +#else
  100 + if ((TIFR & _BV(TOV0)) && (t < 255))
  101 + m++;
  102 +#endif
  103 +
  104 + SREG = oldSREG;
  105 +
  106 + return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
  107 +}
  108 +
  109 +void delay(unsigned long ms)
  110 +{
  111 + uint16_t start = (uint16_t)micros();
  112 +
  113 + while (ms > 0) {
  114 + if (((uint16_t)micros() - start) >= 1000) {
  115 + ms--;
  116 + start += 1000;
  117 + }
  118 + }
  119 +}
  120 +
  121 +/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */
  122 +void delayMicroseconds(unsigned int us)
  123 +{
  124 + // calling avrlib's delay_us() function with low values (e.g. 1 or
  125 + // 2 microseconds) gives delays longer than desired.
  126 + //delay_us(us);
  127 +#if F_CPU >= 20000000L
  128 + // for the 20 MHz clock on rare Arduino boards
  129 +
  130 + // for a one-microsecond delay, simply wait 2 cycle and return. The overhead
  131 + // of the function call yields a delay of exactly a one microsecond.
  132 + __asm__ __volatile__ (
  133 + "nop" "\n\t"
  134 + "nop"); //just waiting 2 cycle
  135 + if (--us == 0)
  136 + return;
  137 +
  138 + // the following loop takes a 1/5 of a microsecond (4 cycles)
  139 + // per iteration, so execute it five times for each microsecond of
  140 + // delay requested.
  141 + us = (us<<2) + us; // x5 us
  142 +
  143 + // account for the time taken in the preceeding commands.
  144 + us -= 2;
  145 +
  146 +#elif F_CPU >= 16000000L
  147 + // for the 16 MHz clock on most Arduino boards
  148 +
  149 + // for a one-microsecond delay, simply return. the overhead
  150 + // of the function call yields a delay of approximately 1 1/8 us.
  151 + if (--us == 0)
  152 + return;
  153 +
  154 + // the following loop takes a quarter of a microsecond (4 cycles)
  155 + // per iteration, so execute it four times for each microsecond of
  156 + // delay requested.
  157 + us <<= 2;
  158 +
  159 + // account for the time taken in the preceeding commands.
  160 + us -= 2;
  161 +#else
  162 + // for the 8 MHz internal clock on the ATmega168
  163 +
  164 + // for a one- or two-microsecond delay, simply return. the overhead of
  165 + // the function calls takes more than two microseconds. can't just
  166 + // subtract two, since us is unsigned; we'd overflow.
  167 + if (--us == 0)
  168 + return;
  169 + if (--us == 0)
  170 + return;
  171 +
  172 + // the following loop takes half of a microsecond (4 cycles)
  173 + // per iteration, so execute it twice for each microsecond of
  174 + // delay requested.
  175 + us <<= 1;
  176 +
  177 + // partially compensate for the time taken by the preceeding commands.
  178 + // we can't subtract any more than this or we'd overflow w/ small delays.
  179 + us--;
  180 +#endif
  181 +
  182 + // busy wait
  183 + __asm__ __volatile__ (
  184 + "1: sbiw %0,1" "\n\t" // 2 cycles
  185 + "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
  186 + );
  187 +}
  188 +
  189 +void init()
  190 +{
  191 + // this needs to be called before setup() or some functions won't
  192 + // work there
  193 + sei();
  194 +
  195 + // on the ATmega168, timer 0 is also used for fast hardware pwm
  196 + // (using phase-correct PWM would mean that timer 0 overflowed half as often
  197 + // resulting in different millis() behavior on the ATmega8 and ATmega168)
  198 +#if defined(TCCR0A) && defined(WGM01)
  199 + sbi(TCCR0A, WGM01);
  200 + sbi(TCCR0A, WGM00);
  201 +#endif
  202 +
  203 + // set timer 0 prescale factor to 64
  204 +#if defined(__AVR_ATmega128__)
  205 + // CPU specific: different values for the ATmega128
  206 + sbi(TCCR0, CS02);
  207 +#elif defined(TCCR0) && defined(CS01) && defined(CS00)
  208 + // this combination is for the standard atmega8
  209 + sbi(TCCR0, CS01);
  210 + sbi(TCCR0, CS00);
  211 +#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
  212 + // this combination is for the standard 168/328/1280/2560
  213 + sbi(TCCR0B, CS01);
  214 + sbi(TCCR0B, CS00);
  215 +#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
  216 + // this combination is for the __AVR_ATmega645__ series
  217 + sbi(TCCR0A, CS01);
  218 + sbi(TCCR0A, CS00);
  219 +#else
  220 + #error Timer 0 prescale factor 64 not set correctly
  221 +#endif
  222 +
  223 + // enable timer 0 overflow interrupt
  224 +#if defined(TIMSK) && defined(TOIE0)
  225 + sbi(TIMSK, TOIE0);
  226 +#elif defined(TIMSK0) && defined(TOIE0)
  227 + sbi(TIMSK0, TOIE0);
  228 +#else
  229 + #error Timer 0 overflow interrupt not set correctly
  230 +#endif
  231 +
  232 + // timers 1 and 2 are used for phase-correct hardware pwm
  233 + // this is better for motors as it ensures an even waveform
  234 + // note, however, that fast pwm mode can achieve a frequency of up
  235 + // 8 MHz (with a 16 MHz clock) at 50% duty cycle
  236 +
  237 +#if defined(TCCR1B) && defined(CS11) && defined(CS10)
  238 + TCCR1B = 0;
  239 +
  240 + // set timer 1 prescale factor to 64
  241 + sbi(TCCR1B, CS11);
  242 +#if F_CPU >= 8000000L
  243 + sbi(TCCR1B, CS10);
  244 +#endif
  245 +#elif defined(TCCR1) && defined(CS11) && defined(CS10)
  246 + sbi(TCCR1, CS11);
  247 +#if F_CPU >= 8000000L
  248 + sbi(TCCR1, CS10);
  249 +#endif
  250 +#endif
  251 + // put timer 1 in 8-bit phase correct pwm mode
  252 +#if defined(TCCR1A) && defined(WGM10)
  253 + sbi(TCCR1A, WGM10);
  254 +#elif defined(TCCR1)
  255 + #warning this needs to be finished
  256 +#endif
  257 +
  258 + // set timer 2 prescale factor to 64
  259 +#if defined(TCCR2) && defined(CS22)
  260 + sbi(TCCR2, CS22);
  261 +#elif defined(TCCR2B) && defined(CS22)
  262 + sbi(TCCR2B, CS22);
  263 +#else
  264 + #warning Timer 2 not finished (may not be present on this CPU)
  265 +#endif
  266 +
  267 + // configure timer 2 for phase correct pwm (8-bit)
  268 +#if defined(TCCR2) && defined(WGM20)
  269 + sbi(TCCR2, WGM20);
  270 +#elif defined(TCCR2A) && defined(WGM20)
  271 + sbi(TCCR2A, WGM20);
  272 +#else
  273 + #warning Timer 2 not finished (may not be present on this CPU)
  274 +#endif
  275 +
  276 +#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
  277 + sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64
  278 + sbi(TCCR3B, CS30);
  279 + sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
  280 +#endif
  281 +
  282 +#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
  283 + sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
  284 + sbi(TCCR4B, CS41);
  285 + sbi(TCCR4B, CS40);
  286 + sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
  287 + sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
  288 + sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
  289 +#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
  290 +#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
  291 + sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
  292 + sbi(TCCR4B, CS40);
  293 + sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
  294 +#endif
  295 +#endif /* end timer4 block for ATMEGA1280/2560 and similar */
  296 +
  297 +#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
  298 + sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
  299 + sbi(TCCR5B, CS50);
  300 + sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode
  301 +#endif
  302 +
  303 +#if defined(ADCSRA)
  304 + // set a2d prescale factor to 128
  305 + // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
  306 + // XXX: this will not work properly for other clock speeds, and
  307 + // this code should use F_CPU to determine the prescale factor.
  308 + sbi(ADCSRA, ADPS2);
  309 + sbi(ADCSRA, ADPS1);
  310 + sbi(ADCSRA, ADPS0);
  311 +
  312 + // enable a2d conversions
  313 + sbi(ADCSRA, ADEN);
  314 +#endif
  315 +
  316 + // the bootloader connects pins 0 and 1 to the USART; disconnect them
  317 + // here so they can be used as normal digital i/o; they will be
  318 + // reconnected in Serial.begin()
  319 +#if defined(UCSRB)
  320 + UCSRB = 0;
  321 +#elif defined(UCSR0B)
  322 + UCSR0B = 0;
  323 +#endif
  324 +}
... ...
Arduino/wiring_digital.c 0 → 100644
... ... @@ -0,0 +1,178 @@
  1 +/*
  2 + wiring_digital.c - digital input and output functions
  3 + Part of Arduino - http://www.arduino.cc/
  4 +
  5 + Copyright (c) 2005-2006 David A. Mellis
  6 +
  7 + This library is free software; you can redistribute it and/or
  8 + modify it under the terms of the GNU Lesser General Public
  9 + License as published by the Free Software Foundation; either
  10 + version 2.1 of the License, or (at your option) any later version.
  11 +
  12 + This library is distributed in the hope that it will be useful,
  13 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + Lesser General Public License for more details.
  16 +
  17 + You should have received a copy of the GNU Lesser General
  18 + Public License along with this library; if not, write to the
  19 + Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20 + Boston, MA 02111-1307 USA
  21 +
  22 + Modified 28 September 2010 by Mark Sproul
  23 +
  24 + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
  25 +*/
  26 +
  27 +#define ARDUINO_MAIN
  28 +#include "wiring_private.h"
  29 +#include "pins_arduino.h"
  30 +
  31 +void pinMode(uint8_t pin, uint8_t mode)
  32 +{
  33 + uint8_t bit = digitalPinToBitMask(pin);
  34 + uint8_t port = digitalPinToPort(pin);
  35 + volatile uint8_t *reg, *out;
  36 +
  37 + if (port == NOT_A_PIN) return;
  38 +
  39 + // JWS: can I let the optimizer do this?
  40 + reg = portModeRegister(port);
  41 + out = portOutputRegister(port);
  42 +
  43 + if (mode == INPUT) {
  44 + uint8_t oldSREG = SREG;
  45 + cli();
  46 + *reg &= ~bit;
  47 + *out &= ~bit;
  48 + SREG = oldSREG;
  49 + } else if (mode == INPUT_PULLUP) {
  50 + uint8_t oldSREG = SREG;
  51 + cli();
  52 + *reg &= ~bit;
  53 + *out |= bit;
  54 + SREG = oldSREG;
  55 + } else {
  56 + uint8_t oldSREG = SREG;
  57 + cli();
  58 + *reg |= bit;
  59 + SREG = oldSREG;
  60 + }
  61 +}
  62 +
  63 +// Forcing this inline keeps the callers from having to push their own stuff
  64 +// on the stack. It is a good performance win and only takes 1 more byte per
  65 +// user than calling. (It will take more bytes on the 168.)
  66 +//
  67 +// But shouldn't this be moved into pinMode? Seems silly to check and do on
  68 +// each digitalread or write.
  69 +//
  70 +// Mark Sproul:
  71 +// - Removed inline. Save 170 bytes on atmega1280
  72 +// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
  73 +// - Added more #ifdefs, now compiles for atmega645
  74 +//
  75 +//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
  76 +//static inline void turnOffPWM(uint8_t timer)
  77 +static void turnOffPWM(uint8_t timer)
  78 +{
  79 + switch (timer)
  80 + {
  81 + #if defined(TCCR1A) && defined(COM1A1)
  82 + case TIMER1A: cbi(TCCR1A, COM1A1); break;
  83 + #endif
  84 + #if defined(TCCR1A) && defined(COM1B1)
  85 + case TIMER1B: cbi(TCCR1A, COM1B1); break;
  86 + #endif
  87 +
  88 + #if defined(TCCR2) && defined(COM21)
  89 + case TIMER2: cbi(TCCR2, COM21); break;
  90 + #endif
  91 +
  92 + #if defined(TCCR0A) && defined(COM0A1)
  93 + case TIMER0A: cbi(TCCR0A, COM0A1); break;
  94 + #endif
  95 +
  96 + #if defined(TIMER0B) && defined(COM0B1)
  97 + case TIMER0B: cbi(TCCR0A, COM0B1); break;
  98 + #endif
  99 + #if defined(TCCR2A) && defined(COM2A1)
  100 + case TIMER2A: cbi(TCCR2A, COM2A1); break;
  101 + #endif
  102 + #if defined(TCCR2A) && defined(COM2B1)
  103 + case TIMER2B: cbi(TCCR2A, COM2B1); break;
  104 + #endif
  105 +
  106 + #if defined(TCCR3A) && defined(COM3A1)
  107 + case TIMER3A: cbi(TCCR3A, COM3A1); break;
  108 + #endif
  109 + #if defined(TCCR3A) && defined(COM3B1)
  110 + case TIMER3B: cbi(TCCR3A, COM3B1); break;
  111 + #endif
  112 + #if defined(TCCR3A) && defined(COM3C1)
  113 + case TIMER3C: cbi(TCCR3A, COM3C1); break;
  114 + #endif
  115 +
  116 + #if defined(TCCR4A) && defined(COM4A1)
  117 + case TIMER4A: cbi(TCCR4A, COM4A1); break;
  118 + #endif
  119 + #if defined(TCCR4A) && defined(COM4B1)
  120 + case TIMER4B: cbi(TCCR4A, COM4B1); break;
  121 + #endif
  122 + #if defined(TCCR4A) && defined(COM4C1)
  123 + case TIMER4C: cbi(TCCR4A, COM4C1); break;
  124 + #endif
  125 + #if defined(TCCR4C) && defined(COM4D1)
  126 + case TIMER4D: cbi(TCCR4C, COM4D1); break;
  127 + #endif
  128 +
  129 + #if defined(TCCR5A)
  130 + case TIMER5A: cbi(TCCR5A, COM5A1); break;
  131 + case TIMER5B: cbi(TCCR5A, COM5B1); break;
  132 + case TIMER5C: cbi(TCCR5A, COM5C1); break;
  133 + #endif
  134 + }
  135 +}
  136 +
  137 +void digitalWrite(uint8_t pin, uint8_t val)
  138 +{
  139 + uint8_t timer = digitalPinToTimer(pin);
  140 + uint8_t bit = digitalPinToBitMask(pin);
  141 + uint8_t port = digitalPinToPort(pin);
  142 + volatile uint8_t *out;
  143 +
  144 + if (port == NOT_A_PIN) return;
  145 +
  146 + // If the pin that support PWM output, we need to turn it off
  147 + // before doing a digital write.
  148 + if (timer != NOT_ON_TIMER) turnOffPWM(timer);
  149 +
  150 + out = portOutputRegister(port);
  151 +
  152 + uint8_t oldSREG = SREG;
  153 + cli();
  154 +
  155 + if (val == LOW) {
  156 + *out &= ~bit;
  157 + } else {
  158 + *out |= bit;
  159 + }
  160 +
  161 + SREG = oldSREG;
  162 +}
  163 +
  164 +int digitalRead(uint8_t pin)
  165 +{
  166 + uint8_t timer = digitalPinToTimer(pin);
  167 + uint8_t bit = digitalPinToBitMask(pin);
  168 + uint8_t port = digitalPinToPort(pin);
  169 +
  170 + if (port == NOT_A_PIN) return LOW;
  171 +
  172 + // If the pin that support PWM output, we need to turn it off
  173 + // before getting a digital reading.
  174 + if (timer != NOT_ON_TIMER) turnOffPWM(timer);
  175 +
  176 + if (*portInputRegister(port) & bit) return HIGH;
  177 + return LOW;
  178 +}
... ...
Arduino/wiring_private.h 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +/*
  2 + wiring_private.h - Internal header file.
  3 + Part of Arduino - http://www.arduino.cc/
  4 +
  5 + Copyright (c) 2005-2006 David A. Mellis
  6 +
  7 + This library is free software; you can redistribute it and/or
  8 + modify it under the terms of the GNU Lesser General Public
  9 + License as published by the Free Software Foundation; either
  10 + version 2.1 of the License, or (at your option) any later version.
  11 +
  12 + This library is distributed in the hope that it will be useful,
  13 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + Lesser General Public License for more details.
  16 +
  17 + You should have received a copy of the GNU Lesser General
  18 + Public License along with this library; if not, write to the
  19 + Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20 + Boston, MA 02111-1307 USA
  21 +
  22 + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
  23 +*/
  24 +
  25 +#ifndef WiringPrivate_h
  26 +#define WiringPrivate_h
  27 +
  28 +#include <avr/io.h>
  29 +#include <avr/interrupt.h>
  30 +#include <stdio.h>
  31 +#include <stdarg.h>
  32 +
  33 +#include "Arduino.h"
  34 +
  35 +#ifdef __cplusplus
  36 +extern "C"{
  37 +#endif
  38 +
  39 +#ifndef cbi
  40 +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  41 +#endif
  42 +#ifndef sbi
  43 +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  44 +#endif
  45 +
  46 +#define EXTERNAL_INT_0 0
  47 +#define EXTERNAL_INT_1 1
  48 +#define EXTERNAL_INT_2 2
  49 +#define EXTERNAL_INT_3 3
  50 +#define EXTERNAL_INT_4 4
  51 +#define EXTERNAL_INT_5 5
  52 +#define EXTERNAL_INT_6 6
  53 +#define EXTERNAL_INT_7 7
  54 +
  55 +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  56 +#define EXTERNAL_NUM_INTERRUPTS 8
  57 +#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
  58 +#define EXTERNAL_NUM_INTERRUPTS 3
  59 +#elif defined(__AVR_ATmega32U4__)
  60 +#define EXTERNAL_NUM_INTERRUPTS 5
  61 +#else
  62 +#define EXTERNAL_NUM_INTERRUPTS 2
  63 +#endif
  64 +
  65 +typedef void (*voidFuncPtr)(void);
  66 +
  67 +#ifdef __cplusplus
  68 +} // extern "C"
  69 +#endif
  70 +
  71 +#endif
... ...
Makefile 0 → 100755
... ... @@ -0,0 +1,42 @@
  1 +export CC = avr-g++
  2 +
  3 +export MCU = atmega328p
  4 +export TARGET_ARCH = -mmcu=$(MCU)
  5 +
  6 +export CFLAGS = -Wall -I./ -I/usr/share/arduino/hardware/arduino/variants/standard -I./PN532_SPI -I./PN532 -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/libraries/SPI -I/usr/share/arduino/libraries -DF_CPU=16000000 -Os #-g
  7 +export LDFLAGS = -g $(TARGET_ARCH) -lm -Wl,--gc-sections # -Os
  8 +
  9 +TARGET = usb
  10 +TERM = /dev/ttyACM0
  11 +CPPFLAGS = -mmcu=$(MCU)
  12 +PGMER = -c stk500v1 -b 57600 -P $(TERM)
  13 +PGMERISP = -c stk500v1 -b 115200 -P $(TERM)
  14 +ARVDUDECONF= -C /usr/local/arduino/arduino-0022/hardware/tools/avrdude.conf
  15 +export DUDE = /usr/bin/avrdude -F -v -p $(MCU) $(AVRDUDECONF)
  16 +
  17 +C_SRC = main.c Arduino/wiring_digital.c
  18 +CPP_SRC = PN532_SPI/PN532_SPI.cpp PN532/PN532.cpp PN532/SPI.cpp
  19 +OBJS = $(C_SRC:.c=.o)
  20 +OBJS += $(CPP_SRC:.cpp=.o)
  21 +
  22 +all: $(TARGET).hex
  23 +
  24 +clean:
  25 + rm -f *.o *.hex *.elf
  26 +
  27 +%.o:%.c
  28 + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
  29 +%.o:%.cpp
  30 + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
  31 +
  32 +$(TARGET).elf: $(OBJS)
  33 + $(CC) $(LDFLAGS) -o $@ $(OBJS)
  34 +
  35 +$(TARGET).hex: $(TARGET).elf
  36 + avr-objcopy -j .text -j .data -O ihex $(TARGET).elf $(TARGET).hex
  37 + avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex $(TARGET).elf eeprom.hex
  38 +
  39 +upload: $(TARGET).hex
  40 + stty -F $(TERM) hupcl # reset
  41 + $(DUDE) $(PGMERISP) -U flash:w:$(TARGET).hex
  42 +
... ...
PN532/PN532.cpp 0 → 100644
... ... @@ -0,0 +1,886 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + @file PN532.cpp
  4 + @author Adafruit Industries & Seeed Studio
  5 + @license BSD
  6 +*/
  7 +/**************************************************************************/
  8 +
  9 +#include "Arduino.h"
  10 +#include "PN532.h"
  11 +#include "PN532_debug.h"
  12 +#include <string.h>
  13 +
  14 +#define HAL(func) (_interface->func)
  15 +
  16 +void send_serial(unsigned char);
  17 +
  18 +PN532::PN532(PN532Interface &interface)
  19 +{
  20 + _interface = &interface;
  21 +}
  22 +
  23 +/**************************************************************************/
  24 +/*!
  25 + @brief Setups the HW
  26 +*/
  27 +/**************************************************************************/
  28 +void PN532::begin()
  29 +{
  30 + send_serial('A');
  31 + HAL(begin)();
  32 + send_serial('B');
  33 + HAL(wakeup)();
  34 + send_serial('C');
  35 +}
  36 +
  37 +/**************************************************************************/
  38 +/*!
  39 + @brief Prints a hexadecimal value in plain characters
  40 +
  41 + @param data Pointer to the uint8_t data
  42 + @param numBytes Data length in bytes
  43 +*/
  44 +/**************************************************************************/
  45 +void PN532::PrintHex(const uint8_t *data, const uint32_t numBytes)
  46 +{
  47 +#ifdef ARDUINO
  48 + for (uint8_t i = 0; i < numBytes; i++) {
  49 + if (data[i] < 0x10) {
  50 + Serial.print(" 0");
  51 + } else {
  52 + Serial.print(' ');
  53 + }
  54 + Serial.print(data[i], HEX);
  55 + }
  56 + Serial.println("");
  57 +#else
  58 + for (uint8_t i = 0; i < numBytes; i++) {
  59 + printf(" %2X", data[i]);
  60 + }
  61 + printf("\n");
  62 +#endif
  63 +}
  64 +
  65 +/**************************************************************************/
  66 +/*!
  67 + @brief Prints a hexadecimal value in plain characters, along with
  68 + the char equivalents in the following format
  69 +
  70 + 00 00 00 00 00 00 ......
  71 +
  72 + @param data Pointer to the data
  73 + @param numBytes Data length in bytes
  74 +*/
  75 +/**************************************************************************/
  76 +void PN532::PrintHexChar(const uint8_t *data, const uint32_t numBytes)
  77 +{
  78 +#ifdef ARDUINO
  79 + for (uint8_t i = 0; i < numBytes; i++) {
  80 + if (data[i] < 0x10) {
  81 + Serial.print(" 0");
  82 + } else {
  83 + Serial.print(' ');
  84 + }
  85 + Serial.print(data[i], HEX);
  86 + }
  87 + Serial.print(" ");
  88 + for (uint8_t i = 0; i < numBytes; i++) {
  89 + char c = data[i];
  90 + if (c <= 0x1f || c > 0x7f) {
  91 + Serial.print('.');
  92 + } else {
  93 + Serial.print(c);
  94 + }
  95 + }
  96 + Serial.println("");
  97 +#else
  98 + for (uint8_t i = 0; i < numBytes; i++) {
  99 + printf(" %2X", data[i]);
  100 + }
  101 + printf(" ");
  102 + for (uint8_t i = 0; i < numBytes; i++) {
  103 + char c = data[i];
  104 + if (c <= 0x1f || c > 0x7f) {
  105 + printf(".");
  106 + } else {
  107 + printf("%c", c);
  108 + }
  109 + printf("\n");
  110 + }
  111 +#endif
  112 +}
  113 +
  114 +/**************************************************************************/
  115 +/*!
  116 + @brief Checks the firmware version of the PN5xx chip
  117 +
  118 + @returns The chip's firmware version and ID
  119 +*/
  120 +/**************************************************************************/
  121 +uint32_t PN532::getFirmwareVersion(void)
  122 +{
  123 + uint32_t response;
  124 +
  125 + pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
  126 +
  127 + if (HAL(writeCommand)(pn532_packetbuffer, 1)) {
  128 + return 0;
  129 + }
  130 +
  131 + // read data packet
  132 + int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  133 + if (0 > status) {
  134 + return 0;
  135 + }
  136 +
  137 + response = pn532_packetbuffer[0];
  138 + response <<= 8;
  139 + response |= pn532_packetbuffer[1];
  140 + response <<= 8;
  141 + response |= pn532_packetbuffer[2];
  142 + response <<= 8;
  143 + response |= pn532_packetbuffer[3];
  144 +
  145 + return response;
  146 +}
  147 +
  148 +
  149 +/**************************************************************************/
  150 +/*!
  151 + Writes an 8-bit value that sets the state of the PN532's GPIO pins
  152 +
  153 + @warning This function is provided exclusively for board testing and
  154 + is dangerous since it will throw an error if any pin other
  155 + than the ones marked "Can be used as GPIO" are modified! All
  156 + pins that can not be used as GPIO should ALWAYS be left high
  157 + (value = 1) or the system will become unstable and a HW reset
  158 + will be required to recover the PN532.
  159 +
  160 + pinState[0] = P30 Can be used as GPIO
  161 + pinState[1] = P31 Can be used as GPIO
  162 + pinState[2] = P32 *** RESERVED (Must be 1!) ***
  163 + pinState[3] = P33 Can be used as GPIO
  164 + pinState[4] = P34 *** RESERVED (Must be 1!) ***
  165 + pinState[5] = P35 Can be used as GPIO
  166 +
  167 + @returns 1 if everything executed properly, 0 for an error
  168 +*/
  169 +/**************************************************************************/
  170 +bool PN532::writeGPIO(uint8_t pinstate)
  171 +{
  172 + // Make sure pinstate does not try to toggle P32 or P34
  173 + pinstate |= (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
  174 +
  175 + // Fill command buffer
  176 + pn532_packetbuffer[0] = PN532_COMMAND_WRITEGPIO;
  177 + pn532_packetbuffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; // P3 Pins
  178 + pn532_packetbuffer[2] = 0x00; // P7 GPIO Pins (not used ... taken by I2C)
  179 +
  180 + DMSG("Writing P3 GPIO: ");
  181 + DMSG_HEX(pn532_packetbuffer[1]);
  182 + DMSG("\n");
  183 +
  184 + // Send the WRITEGPIO command (0x0E)
  185 + if (HAL(writeCommand)(pn532_packetbuffer, 3))
  186 + return 0;
  187 +
  188 + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
  189 +}
  190 +
  191 +/**************************************************************************/
  192 +/*!
  193 + Reads the state of the PN532's GPIO pins
  194 +
  195 + @returns An 8-bit value containing the pin state where:
  196 +
  197 + pinState[0] = P30
  198 + pinState[1] = P31
  199 + pinState[2] = P32
  200 + pinState[3] = P33
  201 + pinState[4] = P34
  202 + pinState[5] = P35
  203 +*/
  204 +/**************************************************************************/
  205 +uint8_t PN532::readGPIO(void)
  206 +{
  207 + pn532_packetbuffer[0] = PN532_COMMAND_READGPIO;
  208 +
  209 + // Send the READGPIO command (0x0C)
  210 + if (HAL(writeCommand)(pn532_packetbuffer, 1))
  211 + return 0x0;
  212 +
  213 + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  214 +
  215 + /* READGPIO response without prefix and suffix should be in the following format:
  216 +
  217 + byte Description
  218 + ------------- ------------------------------------------
  219 + b0 P3 GPIO Pins
  220 + b1 P7 GPIO Pins (not used ... taken by I2C)
  221 + b2 Interface Mode Pins (not used ... bus select pins)
  222 + */
  223 +
  224 +
  225 + DMSG("P3 GPIO: "); DMSG_HEX(pn532_packetbuffer[7]);
  226 + DMSG("P7 GPIO: "); DMSG_HEX(pn532_packetbuffer[8]);
  227 + DMSG("I0I1 GPIO: "); DMSG_HEX(pn532_packetbuffer[9]);
  228 + DMSG("\n");
  229 +
  230 + return pn532_packetbuffer[0];
  231 +}
  232 +
  233 +/**************************************************************************/
  234 +/*!
  235 + @brief Configures the SAM (Secure Access Module)
  236 +*/
  237 +/**************************************************************************/
  238 +bool PN532::SAMConfig(void)
  239 +{
  240 + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
  241 + pn532_packetbuffer[1] = 0x01; // normal mode;
  242 + pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
  243 + pn532_packetbuffer[3] = 0x01; // use IRQ pin!
  244 +
  245 + DMSG("SAMConfig\n");
  246 +
  247 + if (HAL(writeCommand)(pn532_packetbuffer, 4))
  248 + return false;
  249 +
  250 + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
  251 +}
  252 +
  253 +/**************************************************************************/
  254 +/*!
  255 + Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
  256 +
  257 + @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout
  258 + after mxRetries
  259 +
  260 + @returns 1 if everything executed properly, 0 for an error
  261 +*/
  262 +/**************************************************************************/
  263 +bool PN532::setPassiveActivationRetries(uint8_t maxRetries)
  264 +{
  265 + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
  266 + pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
  267 + pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
  268 + pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
  269 + pn532_packetbuffer[4] = maxRetries;
  270 +
  271 + if (HAL(writeCommand)(pn532_packetbuffer, 5))
  272 + return 0x0; // no ACK
  273 +
  274 + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
  275 +}
  276 +
  277 +/***** ISO14443A Commands ******/
  278 +
  279 +/**************************************************************************/
  280 +/*!
  281 + Waits for an ISO14443A target to enter the field
  282 +
  283 + @param cardBaudRate Baud rate of the card
  284 + @param uid Pointer to the array that will be populated
  285 + with the card's UID (up to 7 bytes)
  286 + @param uidLength Pointer to the variable that will hold the
  287 + length of the card's UID.
  288 + @param timeout The number of tries before timing out
  289 + @param inlist If set to true, the card will be inlisted
  290 +
  291 + @returns 1 if everything executed properly, 0 for an error
  292 +*/
  293 +/**************************************************************************/
  294 +bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout, bool inlist)
  295 +{
  296 + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
  297 + pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
  298 + pn532_packetbuffer[2] = cardbaudrate;
  299 +
  300 + if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
  301 + return 0x0; // command failed
  302 + }
  303 +
  304 + // read data packet
  305 + if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
  306 + return 0x0;
  307 + }
  308 +
  309 + // check some basic stuff
  310 + /* ISO14443A card response should be in the following format:
  311 +
  312 + byte Description
  313 + ------------- ------------------------------------------
  314 + b0 Tags Found
  315 + b1 Tag Number (only one used in this example)
  316 + b2..3 SENS_RES
  317 + b4 SEL_RES
  318 + b5 NFCID Length
  319 + b6..NFCIDLen NFCID
  320 + */
  321 +
  322 + if (pn532_packetbuffer[0] != 1)
  323 + return 0;
  324 +
  325 + uint16_t sens_res = pn532_packetbuffer[2];
  326 + sens_res <<= 8;
  327 + sens_res |= pn532_packetbuffer[3];
  328 +
  329 + DMSG("ATQA: 0x"); DMSG_HEX(sens_res);
  330 + DMSG("SAK: 0x"); DMSG_HEX(pn532_packetbuffer[4]);
  331 + DMSG("\n");
  332 +
  333 + /* Card appears to be Mifare Classic */
  334 + *uidLength = pn532_packetbuffer[5];
  335 +
  336 + for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
  337 + uid[i] = pn532_packetbuffer[6 + i];
  338 + }
  339 +
  340 + if (inlist) {
  341 + inListedTag = pn532_packetbuffer[1];
  342 + }
  343 +
  344 + return 1;
  345 +}
  346 +
  347 +
  348 +/***** Mifare Classic Functions ******/
  349 +
  350 +/**************************************************************************/
  351 +/*!
  352 + Indicates whether the specified block number is the first block
  353 + in the sector (block 0 relative to the current sector)
  354 +*/
  355 +/**************************************************************************/
  356 +bool PN532::mifareclassic_IsFirstBlock (uint32_t uiBlock)
  357 +{
  358 + // Test if we are in the small or big sectors
  359 + if (uiBlock < 128)
  360 + return ((uiBlock) % 4 == 0);
  361 + else
  362 + return ((uiBlock) % 16 == 0);
  363 +}
  364 +
  365 +/**************************************************************************/
  366 +/*!
  367 + Indicates whether the specified block number is the sector trailer
  368 +*/
  369 +/**************************************************************************/
  370 +bool PN532::mifareclassic_IsTrailerBlock (uint32_t uiBlock)
  371 +{
  372 + // Test if we are in the small or big sectors
  373 + if (uiBlock < 128)
  374 + return ((uiBlock + 1) % 4 == 0);
  375 + else
  376 + return ((uiBlock + 1) % 16 == 0);
  377 +}
  378 +
  379 +/**************************************************************************/
  380 +/*!
  381 + Tries to authenticate a block of memory on a MIFARE card using the
  382 + INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual
  383 + for more information on sending MIFARE and other commands.
  384 +
  385 + @param uid Pointer to a byte array containing the card UID
  386 + @param uidLen The length (in bytes) of the card's UID (Should
  387 + be 4 for MIFARE Classic)
  388 + @param blockNumber The block number to authenticate. (0..63 for
  389 + 1KB cards, and 0..255 for 4KB cards).
  390 + @param keyNumber Which key type to use during authentication
  391 + (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
  392 + @param keyData Pointer to a byte array containing the 6 bytes
  393 + key value
  394 +
  395 + @returns 1 if everything executed properly, 0 for an error
  396 +*/
  397 +/**************************************************************************/
  398 +uint8_t PN532::mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
  399 +{
  400 + uint8_t i;
  401 +
  402 + // Hang on to the key and uid data
  403 + memcpy (_key, keyData, 6);
  404 + memcpy (_uid, uid, uidLen);
  405 + _uidLen = uidLen;
  406 +
  407 + // Prepare the authentication command //
  408 + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
  409 + pn532_packetbuffer[1] = 1; /* Max card numbers */
  410 + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
  411 + pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
  412 + memcpy (pn532_packetbuffer + 4, _key, 6);
  413 + for (i = 0; i < _uidLen; i++) {
  414 + pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
  415 + }
  416 +
  417 + if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen))
  418 + return 0;
  419 +
  420 + // Read the response packet
  421 + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  422 +
  423 + // Check if the response is valid and we are authenticated???
  424 + // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
  425 + // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
  426 + if (pn532_packetbuffer[0] != 0x00) {
  427 + DMSG("Authentification failed\n");
  428 + return 0;
  429 + }
  430 +
  431 + return 1;
  432 +}
  433 +
  434 +/**************************************************************************/
  435 +/*!
  436 + Tries to read an entire 16-bytes data block at the specified block
  437 + address.
  438 +
  439 + @param blockNumber The block number to authenticate. (0..63 for
  440 + 1KB cards, and 0..255 for 4KB cards).
  441 + @param data Pointer to the byte array that will hold the
  442 + retrieved data (if any)
  443 +
  444 + @returns 1 if everything executed properly, 0 for an error
  445 +*/
  446 +/**************************************************************************/
  447 +uint8_t PN532::mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
  448 +{
  449 + DMSG("Trying to read 16 bytes from block ");
  450 + DMSG_INT(blockNumber);
  451 +
  452 + /* Prepare the command */
  453 + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  454 + pn532_packetbuffer[1] = 1; /* Card number */
  455 + pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
  456 + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
  457 +
  458 + /* Send the command */
  459 + if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
  460 + return 0;
  461 + }
  462 +
  463 + /* Read the response packet */
  464 + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  465 +
  466 + /* If byte 8 isn't 0x00 we probably have an error */
  467 + if (pn532_packetbuffer[0] != 0x00) {
  468 + return 0;
  469 + }
  470 +
  471 + /* Copy the 16 data bytes to the output buffer */
  472 + /* Block content starts at byte 9 of a valid response */
  473 + memcpy (data, pn532_packetbuffer + 1, 16);
  474 +
  475 + return 1;
  476 +}
  477 +
  478 +/**************************************************************************/
  479 +/*!
  480 + Tries to write an entire 16-bytes data block at the specified block
  481 + address.
  482 +
  483 + @param blockNumber The block number to authenticate. (0..63 for
  484 + 1KB cards, and 0..255 for 4KB cards).
  485 + @param data The byte array that contains the data to write.
  486 +
  487 + @returns 1 if everything executed properly, 0 for an error
  488 +*/
  489 +/**************************************************************************/
  490 +uint8_t PN532::mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
  491 +{
  492 + /* Prepare the first command */
  493 + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  494 + pn532_packetbuffer[1] = 1; /* Card number */
  495 + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
  496 + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
  497 + memcpy (pn532_packetbuffer + 4, data, 16); /* Data Payload */
  498 +
  499 + /* Send the command */
  500 + if (HAL(writeCommand)(pn532_packetbuffer, 20)) {
  501 + return 0;
  502 + }
  503 +
  504 + /* Read the response packet */
  505 + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
  506 +}
  507 +
  508 +/**************************************************************************/
  509 +/*!
  510 + Formats a Mifare Classic card to store NDEF Records
  511 +
  512 + @returns 1 if everything executed properly, 0 for an error
  513 +*/
  514 +/**************************************************************************/
  515 +uint8_t PN532::mifareclassic_FormatNDEF (void)
  516 +{
  517 + uint8_t sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
  518 + uint8_t sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
  519 + uint8_t sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  520 +
  521 + // Note 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 must be used for key A
  522 + // for the MAD sector in NDEF records (sector 0)
  523 +
  524 + // Write block 1 and 2 to the card
  525 + if (!(mifareclassic_WriteDataBlock (1, sectorbuffer1)))
  526 + return 0;
  527 + if (!(mifareclassic_WriteDataBlock (2, sectorbuffer2)))
  528 + return 0;
  529 + // Write key A and access rights card
  530 + if (!(mifareclassic_WriteDataBlock (3, sectorbuffer3)))
  531 + return 0;
  532 +
  533 + // Seems that everything was OK (?!)
  534 + return 1;
  535 +}
  536 +
  537 +/**************************************************************************/
  538 +/*!
  539 + Writes an NDEF URI Record to the specified sector (1..15)
  540 +
  541 + Note that this function assumes that the Mifare Classic card is
  542 + already formatted to work as an "NFC Forum Tag" and uses a MAD1
  543 + file system. You can use the NXP TagWriter app on Android to
  544 + properly format cards for this.
  545 +
  546 + @param sectorNumber The sector that the URI record should be written
  547 + to (can be 1..15 for a 1K card)
  548 + @param uriIdentifier The uri identifier code (0 = none, 0x01 =
  549 + "http://www.", etc.)
  550 + @param url The uri text to write (max 38 characters).
  551 +
  552 + @returns 1 if everything executed properly, 0 for an error
  553 +*/
  554 +/**************************************************************************/
  555 +uint8_t PN532::mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url)
  556 +{
  557 + // Figure out how long the string is
  558 + uint8_t len = strlen(url);
  559 +
  560 + // Make sure we're within a 1K limit for the sector number
  561 + if ((sectorNumber < 1) || (sectorNumber > 15))
  562 + return 0;
  563 +
  564 + // Make sure the URI payload is between 1 and 38 chars
  565 + if ((len < 1) || (len > 38))
  566 + return 0;
  567 +
  568 + // Note 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 must be used for key A
  569 + // in NDEF records
  570 +
  571 + // Setup the sector buffer (w/pre-formatted TLV wrapper and NDEF message)
  572 + uint8_t sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  573 + uint8_t sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  574 + uint8_t sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  575 + uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  576 + if (len <= 6) {
  577 + // Unlikely we'll get a url this short, but why not ...
  578 + memcpy (sectorbuffer1 + 9, url, len);
  579 + sectorbuffer1[len + 9] = 0xFE;
  580 + } else if (len == 7) {
  581 + // 0xFE needs to be wrapped around to next block
  582 + memcpy (sectorbuffer1 + 9, url, len);
  583 + sectorbuffer2[0] = 0xFE;
  584 + } else if ((len > 7) || (len <= 22)) {
  585 + // Url fits in two blocks
  586 + memcpy (sectorbuffer1 + 9, url, 7);
  587 + memcpy (sectorbuffer2, url + 7, len - 7);
  588 + sectorbuffer2[len - 7] = 0xFE;
  589 + } else if (len == 23) {
  590 + // 0xFE needs to be wrapped around to final block
  591 + memcpy (sectorbuffer1 + 9, url, 7);
  592 + memcpy (sectorbuffer2, url + 7, len - 7);
  593 + sectorbuffer3[0] = 0xFE;
  594 + } else {
  595 + // Url fits in three blocks
  596 + memcpy (sectorbuffer1 + 9, url, 7);
  597 + memcpy (sectorbuffer2, url + 7, 16);
  598 + memcpy (sectorbuffer3, url + 23, len - 24);
  599 + sectorbuffer3[len - 22] = 0xFE;
  600 + }
  601 +
  602 + // Now write all three blocks back to the card
  603 + if (!(mifareclassic_WriteDataBlock (sectorNumber * 4, sectorbuffer1)))
  604 + return 0;
  605 + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 1, sectorbuffer2)))
  606 + return 0;
  607 + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 2, sectorbuffer3)))
  608 + return 0;
  609 + if (!(mifareclassic_WriteDataBlock ((sectorNumber * 4) + 3, sectorbuffer4)))
  610 + return 0;
  611 +
  612 + // Seems that everything was OK (?!)
  613 + return 1;
  614 +}
  615 +
  616 +/***** Mifare Ultralight Functions ******/
  617 +
  618 +/**************************************************************************/
  619 +/*!
  620 + Tries to read an entire 4-bytes page at the specified address.
  621 +
  622 + @param page The page number (0..63 in most cases)
  623 + @param buffer Pointer to the byte array that will hold the
  624 + retrieved data (if any)
  625 +*/
  626 +/**************************************************************************/
  627 +uint8_t PN532::mifareultralight_ReadPage (uint8_t page, uint8_t *buffer)
  628 +{
  629 + if (page >= 64) {
  630 + DMSG("Page value out of range\n");
  631 + return 0;
  632 + }
  633 +
  634 + /* Prepare the command */
  635 + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  636 + pn532_packetbuffer[1] = 1; /* Card number */
  637 + pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
  638 + pn532_packetbuffer[3] = page; /* Page Number (0..63 in most cases) */
  639 +
  640 + /* Send the command */
  641 + if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
  642 + return 0;
  643 + }
  644 +
  645 + /* Read the response packet */
  646 + HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  647 +
  648 + /* If byte 8 isn't 0x00 we probably have an error */
  649 + if (pn532_packetbuffer[0] == 0x00) {
  650 + /* Copy the 4 data bytes to the output buffer */
  651 + /* Block content starts at byte 9 of a valid response */
  652 + /* Note that the command actually reads 16 bytes or 4 */
  653 + /* pages at a time ... we simply discard the last 12 */
  654 + /* bytes */
  655 + memcpy (buffer, pn532_packetbuffer + 1, 4);
  656 + } else {
  657 + return 0;
  658 + }
  659 +
  660 + // Return OK signal
  661 + return 1;
  662 +}
  663 +
  664 +/**************************************************************************/
  665 +/*!
  666 + Tries to write an entire 4-bytes data buffer at the specified page
  667 + address.
  668 +
  669 + @param page The page number to write into. (0..63).
  670 + @param buffer The byte array that contains the data to write.
  671 +
  672 + @returns 1 if everything executed properly, 0 for an error
  673 +*/
  674 +/**************************************************************************/
  675 +uint8_t PN532::mifareultralight_WritePage (uint8_t page, uint8_t *buffer)
  676 +{
  677 + /* Prepare the first command */
  678 + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  679 + pn532_packetbuffer[1] = 1; /* Card number */
  680 + pn532_packetbuffer[2] = MIFARE_CMD_WRITE_ULTRALIGHT; /* Mifare UL Write cmd = 0xA2 */
  681 + pn532_packetbuffer[3] = page; /* page Number (0..63) */
  682 + memcpy (pn532_packetbuffer + 4, buffer, 4); /* Data Payload */
  683 +
  684 + /* Send the command */
  685 + if (HAL(writeCommand)(pn532_packetbuffer, 8)) {
  686 + return 0;
  687 + }
  688 +
  689 + /* Read the response packet */
  690 + return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
  691 +}
  692 +
  693 +/**************************************************************************/
  694 +/*!
  695 + @brief Exchanges an APDU with the currently inlisted peer
  696 +
  697 + @param send Pointer to data to send
  698 + @param sendLength Length of the data to send
  699 + @param response Pointer to response data
  700 + @param responseLength Pointer to the response data length
  701 +*/
  702 +/**************************************************************************/
  703 +bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength)
  704 +{
  705 + uint8_t i;
  706 +
  707 + pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
  708 + pn532_packetbuffer[1] = inListedTag;
  709 +
  710 + if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) {
  711 + return false;
  712 + }
  713 +
  714 + int16_t status = HAL(readResponse)(response, *responseLength, 1000);
  715 + if (status < 0) {
  716 + return false;
  717 + }
  718 +
  719 + if ((response[0] & 0x3f) != 0) {
  720 + DMSG("Status code indicates an error\n");
  721 + return false;
  722 + }
  723 +
  724 + uint8_t length = status;
  725 + length -= 1;
  726 +
  727 + if (length > *responseLength) {
  728 + length = *responseLength; // silent truncation...
  729 + }
  730 +
  731 + for (uint8_t i = 0; i < length; i++) {
  732 + response[i] = response[i + 1];
  733 + }
  734 + *responseLength = length;
  735 +
  736 + return true;
  737 +}
  738 +
  739 +/**************************************************************************/
  740 +/*!
  741 + @brief 'InLists' a passive target. PN532 acting as reader/initiator,
  742 + peer acting as card/responder.
  743 +*/
  744 +/**************************************************************************/
  745 +bool PN532::inListPassiveTarget()
  746 +{
  747 + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
  748 + pn532_packetbuffer[1] = 1;
  749 + pn532_packetbuffer[2] = 0;
  750 +
  751 + DMSG("inList passive target\n");
  752 +
  753 + if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
  754 + return false;
  755 + }
  756 +
  757 + int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000);
  758 + if (status < 0) {
  759 + return false;
  760 + }
  761 +
  762 + if (pn532_packetbuffer[0] != 1) {
  763 + return false;
  764 + }
  765 +
  766 + inListedTag = pn532_packetbuffer[1];
  767 +
  768 + return true;
  769 +}
  770 +
  771 +int8_t PN532::tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout){
  772 +
  773 + int8_t status = HAL(writeCommand)(command, len);
  774 + if (status < 0) {
  775 + return -1;
  776 + }
  777 +
  778 + status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout);
  779 + if (status > 0) {
  780 + return 1;
  781 + } else if (PN532_TIMEOUT == status) {
  782 + return 0;
  783 + } else {
  784 + return -2;
  785 + }
  786 +}
  787 +
  788 +/**
  789 + * Peer to Peer
  790 + */
  791 +int8_t PN532::tgInitAsTarget(uint16_t timeout)
  792 +{
  793 + const uint8_t command[] = {
  794 + PN532_COMMAND_TGINITASTARGET,
  795 + 0,
  796 + 0x00, 0x00, //SENS_RES
  797 + 0x00, 0x00, 0x00, //NFCID1
  798 + 0x40, //SEL_RES
  799 +
  800 + 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES
  801 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  802 + 0xFF, 0xFF,
  803 +
  804 + 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value
  805 +
  806 + 0x06, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x00// LLCP magic number and version parameter
  807 + };
  808 + return tgInitAsTarget(command, sizeof(command), timeout);
  809 +}
  810 +
  811 +int16_t PN532::tgGetData(uint8_t *buf, uint8_t len)
  812 +{
  813 + buf[0] = PN532_COMMAND_TGGETDATA;
  814 +
  815 + if (HAL(writeCommand)(buf, 1)) {
  816 + return -1;
  817 + }
  818 +
  819 + int16_t status = HAL(readResponse)(buf, len, 3000);
  820 + if (0 >= status) {
  821 + return status;
  822 + }
  823 +
  824 + uint16_t length = status - 1;
  825 +
  826 +
  827 + if (buf[0] != 0) {
  828 + DMSG("status is not ok\n");
  829 + return -5;
  830 + }
  831 +
  832 + for (uint8_t i = 0; i < length; i++) {
  833 + buf[i] = buf[i + 1];
  834 + }
  835 +
  836 + return length;
  837 +}
  838 +
  839 +bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  840 +{
  841 + if (hlen > (sizeof(pn532_packetbuffer) - 1)) {
  842 + if ((body != 0) || (header == pn532_packetbuffer)) {
  843 + DMSG("tgSetData:buffer too small\n");
  844 + return false;
  845 + }
  846 +
  847 + pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
  848 + if (HAL(writeCommand)(pn532_packetbuffer, 1, header, hlen)) {
  849 + return false;
  850 + }
  851 + } else {
  852 + for (int8_t i = hlen - 1; i >= 0; i--){
  853 + pn532_packetbuffer[i + 1] = header[i];
  854 + }
  855 + pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
  856 +
  857 + if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) {
  858 + return false;
  859 + }
  860 + }
  861 +
  862 + if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) {
  863 + return false;
  864 + }
  865 +
  866 + if (0 != pn532_packetbuffer[0]) {
  867 + return false;
  868 + }
  869 +
  870 + return true;
  871 +}
  872 +
  873 +int16_t PN532::inRelease(const uint8_t relevantTarget){
  874 +
  875 + pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
  876 + pn532_packetbuffer[1] = relevantTarget;
  877 +
  878 + if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
  879 + return 0;
  880 + }
  881 +
  882 + // read data packet
  883 + return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
  884 +}
  885 +
  886 +
... ...
PN532/PN532.h 0 → 100644
... ... @@ -0,0 +1,179 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + @file PN532.h
  4 + @author Adafruit Industries & Seeed Studio
  5 + @license BSD
  6 +*/
  7 +/**************************************************************************/
  8 +
  9 +#ifndef __PN532_H__
  10 +#define __PN532_H__
  11 +
  12 +#include <stdint.h>
  13 +#include "PN532Interface.h"
  14 +
  15 +// PN532 Commands
  16 +#define PN532_COMMAND_DIAGNOSE (0x00)
  17 +#define PN532_COMMAND_GETFIRMWAREVERSION (0x02)
  18 +#define PN532_COMMAND_GETGENERALSTATUS (0x04)
  19 +#define PN532_COMMAND_READREGISTER (0x06)
  20 +#define PN532_COMMAND_WRITEREGISTER (0x08)
  21 +#define PN532_COMMAND_READGPIO (0x0C)
  22 +#define PN532_COMMAND_WRITEGPIO (0x0E)
  23 +#define PN532_COMMAND_SETSERIALBAUDRATE (0x10)
  24 +#define PN532_COMMAND_SETPARAMETERS (0x12)
  25 +#define PN532_COMMAND_SAMCONFIGURATION (0x14)
  26 +#define PN532_COMMAND_POWERDOWN (0x16)
  27 +#define PN532_COMMAND_RFCONFIGURATION (0x32)
  28 +#define PN532_COMMAND_RFREGULATIONTEST (0x58)
  29 +#define PN532_COMMAND_INJUMPFORDEP (0x56)
  30 +#define PN532_COMMAND_INJUMPFORPSL (0x46)
  31 +#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A)
  32 +#define PN532_COMMAND_INATR (0x50)
  33 +#define PN532_COMMAND_INPSL (0x4E)
  34 +#define PN532_COMMAND_INDATAEXCHANGE (0x40)
  35 +#define PN532_COMMAND_INCOMMUNICATETHRU (0x42)
  36 +#define PN532_COMMAND_INDESELECT (0x44)
  37 +#define PN532_COMMAND_INRELEASE (0x52)
  38 +#define PN532_COMMAND_INSELECT (0x54)
  39 +#define PN532_COMMAND_INAUTOPOLL (0x60)
  40 +#define PN532_COMMAND_TGINITASTARGET (0x8C)
  41 +#define PN532_COMMAND_TGSETGENERALBYTES (0x92)
  42 +#define PN532_COMMAND_TGGETDATA (0x86)
  43 +#define PN532_COMMAND_TGSETDATA (0x8E)
  44 +#define PN532_COMMAND_TGSETMETADATA (0x94)
  45 +#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
  46 +#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
  47 +#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A)
  48 +
  49 +#define PN532_RESPONSE_INDATAEXCHANGE (0x41)
  50 +#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B)
  51 +
  52 +
  53 +#define PN532_MIFARE_ISO14443A (0x00)
  54 +
  55 +// Mifare Commands
  56 +#define MIFARE_CMD_AUTH_A (0x60)
  57 +#define MIFARE_CMD_AUTH_B (0x61)
  58 +#define MIFARE_CMD_READ (0x30)
  59 +#define MIFARE_CMD_WRITE (0xA0)
  60 +#define MIFARE_CMD_WRITE_ULTRALIGHT (0xA2)
  61 +#define MIFARE_CMD_TRANSFER (0xB0)
  62 +#define MIFARE_CMD_DECREMENT (0xC0)
  63 +#define MIFARE_CMD_INCREMENT (0xC1)
  64 +#define MIFARE_CMD_STORE (0xC2)
  65 +
  66 +// Prefixes for NDEF Records (to identify record type)
  67 +#define NDEF_URIPREFIX_NONE (0x00)
  68 +#define NDEF_URIPREFIX_HTTP_WWWDOT (0x01)
  69 +#define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02)
  70 +#define NDEF_URIPREFIX_HTTP (0x03)
  71 +#define NDEF_URIPREFIX_HTTPS (0x04)
  72 +#define NDEF_URIPREFIX_TEL (0x05)
  73 +#define NDEF_URIPREFIX_MAILTO (0x06)
  74 +#define NDEF_URIPREFIX_FTP_ANONAT (0x07)
  75 +#define NDEF_URIPREFIX_FTP_FTPDOT (0x08)
  76 +#define NDEF_URIPREFIX_FTPS (0x09)
  77 +#define NDEF_URIPREFIX_SFTP (0x0A)
  78 +#define NDEF_URIPREFIX_SMB (0x0B)
  79 +#define NDEF_URIPREFIX_NFS (0x0C)
  80 +#define NDEF_URIPREFIX_FTP (0x0D)
  81 +#define NDEF_URIPREFIX_DAV (0x0E)
  82 +#define NDEF_URIPREFIX_NEWS (0x0F)
  83 +#define NDEF_URIPREFIX_TELNET (0x10)
  84 +#define NDEF_URIPREFIX_IMAP (0x11)
  85 +#define NDEF_URIPREFIX_RTSP (0x12)
  86 +#define NDEF_URIPREFIX_URN (0x13)
  87 +#define NDEF_URIPREFIX_POP (0x14)
  88 +#define NDEF_URIPREFIX_SIP (0x15)
  89 +#define NDEF_URIPREFIX_SIPS (0x16)
  90 +#define NDEF_URIPREFIX_TFTP (0x17)
  91 +#define NDEF_URIPREFIX_BTSPP (0x18)
  92 +#define NDEF_URIPREFIX_BTL2CAP (0x19)
  93 +#define NDEF_URIPREFIX_BTGOEP (0x1A)
  94 +#define NDEF_URIPREFIX_TCPOBEX (0x1B)
  95 +#define NDEF_URIPREFIX_IRDAOBEX (0x1C)
  96 +#define NDEF_URIPREFIX_FILE (0x1D)
  97 +#define NDEF_URIPREFIX_URN_EPC_ID (0x1E)
  98 +#define NDEF_URIPREFIX_URN_EPC_TAG (0x1F)
  99 +#define NDEF_URIPREFIX_URN_EPC_PAT (0x20)
  100 +#define NDEF_URIPREFIX_URN_EPC_RAW (0x21)
  101 +#define NDEF_URIPREFIX_URN_EPC (0x22)
  102 +#define NDEF_URIPREFIX_URN_NFC (0x23)
  103 +
  104 +#define PN532_GPIO_VALIDATIONBIT (0x80)
  105 +#define PN532_GPIO_P30 (0)
  106 +#define PN532_GPIO_P31 (1)
  107 +#define PN532_GPIO_P32 (2)
  108 +#define PN532_GPIO_P33 (3)
  109 +#define PN532_GPIO_P34 (4)
  110 +#define PN532_GPIO_P35 (5)
  111 +
  112 +class PN532
  113 +{
  114 +public:
  115 + PN532(PN532Interface &interface);
  116 +
  117 + void begin(void);
  118 +
  119 + // Generic PN532 functions
  120 + bool SAMConfig(void);
  121 + uint32_t getFirmwareVersion(void);
  122 + bool writeGPIO(uint8_t pinstate);
  123 + uint8_t readGPIO(void);
  124 + bool setPassiveActivationRetries(uint8_t maxRetries);
  125 +
  126 + /**
  127 + * @brief Init PN532 as a target
  128 + * @param timeout max time to wait, 0 means no timeout
  129 + * @return > 0 success
  130 + * = 0 timeout
  131 + * < 0 failed
  132 + */
  133 + int8_t tgInitAsTarget(uint16_t timeout = 0);
  134 + int8_t tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout = 0);
  135 +
  136 + int16_t tgGetData(uint8_t *buf, uint8_t len);
  137 + bool tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  138 +
  139 + int16_t inRelease(const uint8_t relevantTarget = 0);
  140 +
  141 + // ISO14443A functions
  142 + bool inListPassiveTarget();
  143 + bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000, bool inlist = false);
  144 + bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength);
  145 +
  146 + // Mifare Classic functions
  147 + bool mifareclassic_IsFirstBlock (uint32_t uiBlock);
  148 + bool mifareclassic_IsTrailerBlock (uint32_t uiBlock);
  149 + uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData);
  150 + uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data);
  151 + uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data);
  152 + uint8_t mifareclassic_FormatNDEF (void);
  153 + uint8_t mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char *url);
  154 +
  155 + // Mifare Ultralight functions
  156 + uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t *buffer);
  157 + uint8_t mifareultralight_WritePage (uint8_t page, uint8_t *buffer);
  158 +
  159 + // Help functions to display formatted text
  160 + static void PrintHex(const uint8_t *data, const uint32_t numBytes);
  161 + static void PrintHexChar(const uint8_t *pbtData, const uint32_t numBytes);
  162 +
  163 + uint8_t *getBuffer(uint8_t *len) {
  164 + *len = sizeof(pn532_packetbuffer) - 4;
  165 + return pn532_packetbuffer;
  166 + };
  167 +
  168 +private:
  169 + uint8_t _uid[7]; // ISO14443A uid
  170 + uint8_t _uidLen; // uid len
  171 + uint8_t _key[6]; // Mifare Classic key
  172 + uint8_t inListedTag; // Tg number of inlisted tag.
  173 +
  174 + uint8_t pn532_packetbuffer[64];
  175 +
  176 + PN532Interface *_interface;
  177 +};
  178 +
  179 +#endif
... ...
PN532/PN532Interface.h 0 → 100644
... ... @@ -0,0 +1,56 @@
  1 +
  2 +
  3 +#ifndef __PN532_INTERFACE_H__
  4 +#define __PN532_INTERFACE_H__
  5 +
  6 +#include <stdint.h>
  7 +
  8 +#define PN532_PREAMBLE (0x00)
  9 +#define PN532_STARTCODE1 (0x00)
  10 +#define PN532_STARTCODE2 (0xFF)
  11 +#define PN532_POSTAMBLE (0x00)
  12 +
  13 +#define PN532_HOSTTOPN532 (0xD4)
  14 +#define PN532_PN532TOHOST (0xD5)
  15 +
  16 +#define PN532_ACK_WAIT_TIME (10) // ms, timeout of waiting for ACK
  17 +
  18 +#define PN532_INVALID_ACK (-1)
  19 +#define PN532_TIMEOUT (-2)
  20 +#define PN532_INVALID_FRAME (-3)
  21 +#define PN532_NO_SPACE (-4)
  22 +
  23 +#define REVERSE_BITS_ORDER(b) b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; \
  24 + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; \
  25 + b = (b & 0xAA) >> 1 | (b & 0x55) << 1
  26 +
  27 +class PN532Interface
  28 +{
  29 +public:
  30 + virtual void begin() = 0;
  31 + virtual void wakeup() = 0;
  32 +
  33 + /**
  34 + * @brief write a command and check ack
  35 + * @param header packet header
  36 + * @param hlen length of header
  37 + * @param body packet body
  38 + * @param blen length of body
  39 + * @return 0 success
  40 + * not 0 failed
  41 + */
  42 + virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) = 0;
  43 +
  44 + /**
  45 + * @brief read the response of a command, strip prefix and suffix
  46 + * @param buf to contain the response data
  47 + * @param len lenght to read
  48 + * @param timeout max time to wait, 0 means no timeout
  49 + * @return >=0 length of response without prefix and suffix
  50 + * <0 failed to read response
  51 + */
  52 + virtual int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 1000) = 0;
  53 +};
  54 +
  55 +#endif
  56 +
... ...
PN532/PN532_debug.h 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +#ifndef __DEBUG_H__
  2 +#define __DEBUG_H__
  3 +
  4 +//#define DEBUG
  5 +
  6 +#include "Arduino.h"
  7 +
  8 +#ifdef DEBUG
  9 +#define DMSG(args...) Serial.print(args)
  10 +#define DMSG_STR(str) Serial.println(str)
  11 +#define DMSG_HEX(num) Serial.print(' '); Serial.print(num, HEX)
  12 +#define DMSG_INT(num) Serial.print(' '); Serial.print(num)
  13 +#else
  14 +#define DMSG(args...)
  15 +#define DMSG_STR(str)
  16 +#define DMSG_HEX(num)
  17 +#define DMSG_INT(num)
  18 +#endif
  19 +
  20 +#endif
... ...
PN532/README.md 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +## NFC library for Arduino
  2 +
  3 +This is an Arduino library for PN532 to use NFC technology.
  4 +It works with
  5 +
  6 ++ [NFC Shield](http://goo.gl/Cac2OH)
  7 ++ [Xadow NFC](http://goo.gl/qBZMt0)
  8 ++ [PN532 NFC/RFID controller breakout board](http://goo.gl/tby9Sw)
  9 +
  10 +### Features
  11 ++ Support I2C, SPI and HSU of PN532
  12 ++ Read/write Mifare Classic Card
  13 ++ Works with [Don's NDEF Library](http://goo.gl/jDjsXl)
  14 ++ Support Peer to Peer communication(exchange data with android 4.0+)
  15 ++ Support [mbed platform](http://goo.gl/kGPovZ)
  16 +
  17 +### Getting Started
  18 +1. Download [zip file](http://goo.gl/F6beRM) and
  19 +extract the 4 folders(PN532, PN532_SPI, PN532_I2C and PN532_HSU) into Arduino's libraries.
  20 +2. Downlaod [Don's NDEF library](http://goo.gl/ewxeAe) and extract it intro Arduino's libraries.
  21 +3. Follow the examples of the two libraries.
  22 +
  23 +### To do
  24 ++ Card emulation
  25 +
  26 +### Contribution
  27 +It's based on [Adafruit_NFCShield_I2C](http://goo.gl/pk3FdB).
  28 +[Seeed Studio](http://goo.gl/zh1iQh) adds SPI interface and peer to peer communication support.
  29 +@Don writes the [NDEF library](http://goo.gl/jDjsXl) to make it more easy to use.
  30 +@JiapengLi adds HSU interface.
... ...
PN532/SPI.cpp 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +/*
  2 + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3 + * SPI Master library for arduino.
  4 + *
  5 + * This file is free software; you can redistribute it and/or modify
  6 + * it under the terms of either the GNU General Public License version 2
  7 + * or the GNU Lesser General Public License version 2.1, both as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#include "pins_arduino.h"
  12 +#include "SPI.h"
  13 +
  14 +SPIClass SPI;
  15 +
  16 +void SPIClass::begin() {
  17 +
  18 + // Set SS to high so a connected chip will be "deselected" by default
  19 + digitalWrite(SS, HIGH);
  20 +
  21 + // When the SS pin is set as OUTPUT, it can be used as
  22 + // a general purpose output port (it doesn't influence
  23 + // SPI operations).
  24 + pinMode(SS, OUTPUT);
  25 +
  26 + // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  27 + // automatically switches to Slave, so the data direction of
  28 + // the SS pin MUST be kept as OUTPUT.
  29 + SPCR |= _BV(MSTR);
  30 + SPCR |= _BV(SPE);
  31 +
  32 + // Set direction register for SCK and MOSI pin.
  33 + // MISO pin automatically overrides to INPUT.
  34 + // By doing this AFTER enabling SPI, we avoid accidentally
  35 + // clocking in a single bit since the lines go directly
  36 + // from "input" to SPI control.
  37 + // http://code.google.com/p/arduino/issues/detail?id=888
  38 + pinMode(SCK, OUTPUT);
  39 + pinMode(MOSI, OUTPUT);
  40 +}
  41 +
  42 +
  43 +void SPIClass::end() {
  44 + SPCR &= ~_BV(SPE);
  45 +}
  46 +
  47 +void SPIClass::setBitOrder(uint8_t bitOrder)
  48 +{
  49 + if(bitOrder == LSBFIRST) {
  50 + SPCR |= _BV(DORD);
  51 + } else {
  52 + SPCR &= ~(_BV(DORD));
  53 + }
  54 +}
  55 +
  56 +void SPIClass::setDataMode(uint8_t mode)
  57 +{
  58 + SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
  59 +}
  60 +
  61 +void SPIClass::setClockDivider(uint8_t rate)
  62 +{
  63 + SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
  64 + SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
  65 +}
  66 +
... ...
PN532/SPI.h 0 → 100644
... ... @@ -0,0 +1,70 @@
  1 +/*
  2 + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3 + * SPI Master library for arduino.
  4 + *
  5 + * This file is free software; you can redistribute it and/or modify
  6 + * it under the terms of either the GNU General Public License version 2
  7 + * or the GNU Lesser General Public License version 2.1, both as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#ifndef _SPI_H_INCLUDED
  12 +#define _SPI_H_INCLUDED
  13 +
  14 +#include <stdio.h>
  15 +#include <Arduino.h>
  16 +#include <avr/pgmspace.h>
  17 +
  18 +#define SPI_CLOCK_DIV4 0x00
  19 +#define SPI_CLOCK_DIV16 0x01
  20 +#define SPI_CLOCK_DIV64 0x02
  21 +#define SPI_CLOCK_DIV128 0x03
  22 +#define SPI_CLOCK_DIV2 0x04
  23 +#define SPI_CLOCK_DIV8 0x05
  24 +#define SPI_CLOCK_DIV32 0x06
  25 +//#define SPI_CLOCK_DIV64 0x07
  26 +
  27 +#define SPI_MODE0 0x00
  28 +#define SPI_MODE1 0x04
  29 +#define SPI_MODE2 0x08
  30 +#define SPI_MODE3 0x0C
  31 +
  32 +#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  33 +#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  34 +#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  35 +
  36 +class SPIClass {
  37 +public:
  38 + inline static byte transfer(byte _data);
  39 +
  40 + // SPI Configuration methods
  41 +
  42 + inline static void attachInterrupt();
  43 + inline static void detachInterrupt(); // Default
  44 +
  45 + static void begin(); // Default
  46 + static void end();
  47 +
  48 + static void setBitOrder(uint8_t);
  49 + static void setDataMode(uint8_t);
  50 + static void setClockDivider(uint8_t);
  51 +};
  52 +
  53 +extern SPIClass SPI;
  54 +
  55 +byte SPIClass::transfer(byte _data) {
  56 + SPDR = _data;
  57 + while (!(SPSR & _BV(SPIF)))
  58 + ;
  59 + return SPDR;
  60 +}
  61 +
  62 +void SPIClass::attachInterrupt() {
  63 + SPCR |= _BV(SPIE);
  64 +}
  65 +
  66 +void SPIClass::detachInterrupt() {
  67 + SPCR &= ~_BV(SPIE);
  68 +}
  69 +
  70 +#endif
... ...
PN532/emulatetag.cpp 0 → 100644
... ... @@ -0,0 +1,255 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + @file emulatetag.cpp
  4 + @author Armin Wieser
  5 + @license BSD
  6 +*/
  7 +/**************************************************************************/
  8 +
  9 +#include "emulatetag.h"
  10 +#include "PN532_debug.h"
  11 +
  12 +#include <string.h>
  13 +
  14 +#define MAX_TGREAD
  15 +
  16 +
  17 +// Command APDU
  18 +#define C_APDU_CLA 0
  19 +#define C_APDU_INS 1 // instruction
  20 +#define C_APDU_P1 2 // parameter 1
  21 +#define C_APDU_P2 3 // parameter 2
  22 +#define C_APDU_LC 4 // length command
  23 +#define C_APDU_DATA 5 // data
  24 +
  25 +#define C_APDU_P1_SELECT_BY_ID 0x00
  26 +#define C_APDU_P1_SELECT_BY_NAME 0x04
  27 +
  28 +// Response APDU
  29 +#define R_APDU_SW1_COMMAND_COMPLETE 0x90
  30 +#define R_APDU_SW2_COMMAND_COMPLETE 0x00
  31 +
  32 +#define R_APDU_SW1_NDEF_TAG_NOT_FOUND 0x6a
  33 +#define R_APDU_SW2_NDEF_TAG_NOT_FOUND 0x82
  34 +
  35 +#define R_APDU_SW1_FUNCTION_NOT_SUPPORTED 0x6A
  36 +#define R_APDU_SW2_FUNCTION_NOT_SUPPORTED 0x81
  37 +
  38 +#define R_APDU_SW1_MEMORY_FAILURE 0x65
  39 +#define R_APDU_SW2_MEMORY_FAILURE 0x81
  40 +
  41 +#define R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x62
  42 +#define R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES 0x82
  43 +
  44 +// ISO7816-4 commands
  45 +#define ISO7816_SELECT_FILE 0xA4
  46 +#define ISO7816_READ_BINARY 0xB0
  47 +#define ISO7816_UPDATE_BINARY 0xD6
  48 +
  49 +typedef enum { NONE, CC, NDEF } tag_file; // CC ... Compatibility Container
  50 +
  51 +bool EmulateTag::init(){
  52 + pn532.begin();
  53 + return pn532.SAMConfig();
  54 +}
  55 +
  56 +void EmulateTag::setNdefFile(const uint8_t* ndef, const int16_t ndefLength){
  57 + if(ndefLength > (NDEF_MAX_LENGTH -2)){
  58 + DMSG("ndef file too large (> NDEF_MAX_LENGHT -2) - aborting");
  59 + return;
  60 + }
  61 +
  62 + ndef_file[0] = ndefLength >> 8;
  63 + ndef_file[1] = ndefLength & 0xFF;
  64 + memcpy(ndef_file+2, ndef, ndefLength);
  65 +}
  66 +
  67 +void EmulateTag::setUid(uint8_t* uid){
  68 + uidPtr = uid;
  69 +}
  70 +
  71 +bool EmulateTag::emulate(const uint16_t tgInitAsTargetTimeout){
  72 +
  73 + uint8_t command[] = {
  74 + PN532_COMMAND_TGINITASTARGET,
  75 + 5, // MODE: PICC only, Passive only
  76 +
  77 + 0x04, 0x00, // SENS_RES
  78 + 0x00, 0x00, 0x00, // NFCID1
  79 + 0x20, // SEL_RES
  80 +
  81 + 0,0,0,0,0,0,0,0,
  82 + 0,0,0,0,0,0,0,0, // FeliCaParams
  83 + 0,0,
  84 +
  85 + 0,0,0,0,0,0,0,0,0,0, // NFCID3t
  86 +
  87 + 0, // length of general bytes
  88 + 0 // length of historical bytes
  89 + };
  90 +
  91 + if(uidPtr != 0){ // if uid is set copy 3 bytes to nfcid1
  92 + memcpy(command + 4, uidPtr, 3);
  93 + }
  94 +
  95 + if(1 != pn532.tgInitAsTarget(command,sizeof(command), tgInitAsTargetTimeout)){
  96 + DMSG("tgInitAsTarget failed or timed out!");
  97 + return false;
  98 + }
  99 +
  100 + uint8_t compatibility_container[] = {
  101 + 0, 0x0F,
  102 + 0x20,
  103 + 0, 0x54,
  104 + 0, 0xFF,
  105 + 0x04, // T
  106 + 0x06, // L
  107 + 0xE1, 0x04, // File identifier
  108 + ((NDEF_MAX_LENGTH & 0xFF00) >> 8), (NDEF_MAX_LENGTH & 0xFF), // maximum NDEF file size
  109 + 0x00, // read access 0x0 = granted
  110 + 0x00 // write access 0x0 = granted | 0xFF = deny
  111 + };
  112 +
  113 + if(tagWriteable == false){
  114 + compatibility_container[14] = 0xFF;
  115 + }
  116 +
  117 + tagWrittenByInitiator = false;
  118 +
  119 + uint8_t rwbuf[128];
  120 + uint8_t sendlen;
  121 + int16_t status;
  122 + tag_file currentFile = NONE;
  123 + uint16_t cc_size = sizeof(compatibility_container);
  124 + bool runLoop = true;
  125 +
  126 + while(runLoop){
  127 + status = pn532.tgGetData(rwbuf, sizeof(rwbuf));
  128 + if(status < 0){
  129 + DMSG("tgGetData failed!\n");
  130 + pn532.inRelease();
  131 + return true;
  132 + }
  133 +
  134 + uint8_t p1 = rwbuf[C_APDU_P1];
  135 + uint8_t p2 = rwbuf[C_APDU_P2];
  136 + uint8_t lc = rwbuf[C_APDU_LC];
  137 + uint16_t p1p2_length = ((int16_t) p1 << 8) + p2;
  138 +
  139 + switch(rwbuf[C_APDU_INS]){
  140 + case ISO7816_SELECT_FILE:
  141 + switch(p1){
  142 + case C_APDU_P1_SELECT_BY_ID:
  143 + if(p2 != 0x0c){
  144 + DMSG("C_APDU_P2 != 0x0c\n");
  145 + setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
  146 + } else if(lc == 2 && rwbuf[C_APDU_DATA] == 0xE1 && (rwbuf[C_APDU_DATA+1] == 0x03 || rwbuf[C_APDU_DATA+1] == 0x04)){
  147 + setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
  148 + if(rwbuf[C_APDU_DATA+1] == 0x03){
  149 + currentFile = CC;
  150 + } else if(rwbuf[C_APDU_DATA+1] == 0x04){
  151 + currentFile = NDEF;
  152 + }
  153 + } else {
  154 + setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
  155 + }
  156 + break;
  157 + case C_APDU_P1_SELECT_BY_NAME:
  158 + const uint8_t ndef_tag_application_name_v2[] = {0, 0x7, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
  159 + if(0 == memcmp(ndef_tag_application_name_v2, rwbuf + C_APDU_P2, sizeof(ndef_tag_application_name_v2))){
  160 + setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
  161 + } else{
  162 + DMSG("function not supported\n");
  163 + setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
  164 + }
  165 + break;
  166 + }
  167 + break;
  168 + case ISO7816_READ_BINARY:
  169 + switch(currentFile){
  170 + case NONE:
  171 + setResponse(TAG_NOT_FOUND, rwbuf, &sendlen);
  172 + break;
  173 + case CC:
  174 + if( p1p2_length > NDEF_MAX_LENGTH){
  175 + setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
  176 + }else {
  177 + memcpy(rwbuf,compatibility_container + p1p2_length, lc);
  178 + setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
  179 + }
  180 + break;
  181 + case NDEF:
  182 + if( p1p2_length > NDEF_MAX_LENGTH){
  183 + setResponse(END_OF_FILE_BEFORE_REACHED_LE_BYTES, rwbuf, &sendlen);
  184 + }else {
  185 + memcpy(rwbuf, ndef_file + p1p2_length, lc);
  186 + setResponse(COMMAND_COMPLETE, rwbuf + lc, &sendlen, lc);
  187 + }
  188 + break;
  189 + }
  190 + break;
  191 + case ISO7816_UPDATE_BINARY:
  192 + if(!tagWriteable){
  193 + setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
  194 + } else{
  195 + if( p1p2_length > NDEF_MAX_LENGTH){
  196 + setResponse(MEMORY_FAILURE, rwbuf, &sendlen);
  197 + }
  198 + else{
  199 + memcpy(ndef_file + p1p2_length, rwbuf + C_APDU_DATA, lc);
  200 + setResponse(COMMAND_COMPLETE, rwbuf, &sendlen);
  201 + tagWrittenByInitiator = true;
  202 +
  203 + uint16_t ndef_length = (ndef_file[0] << 8) + ndef_file[1];
  204 + if ((ndef_length > 0) && (updateNdefCallback != 0)) {
  205 + updateNdefCallback(ndef_file + 2, ndef_length);
  206 + }
  207 + }
  208 + }
  209 + break;
  210 + default:
  211 + DMSG("Command not supported!");
  212 + DMSG_HEX(rwbuf[C_APDU_INS]);
  213 + DMSG("\n");
  214 + setResponse(FUNCTION_NOT_SUPPORTED, rwbuf, &sendlen);
  215 + }
  216 + status = pn532.tgSetData(rwbuf, sendlen);
  217 + if(status < 0){
  218 + DMSG("tgSetData failed\n!");
  219 + pn532.inRelease();
  220 + return true;
  221 + }
  222 + }
  223 + pn532.inRelease();
  224 + return true;
  225 +}
  226 +
  227 +void EmulateTag::setResponse(responseCommand cmd, uint8_t* buf, uint8_t* sendlen, uint8_t sendlenOffset){
  228 + switch(cmd){
  229 + case COMMAND_COMPLETE:
  230 + buf[0] = R_APDU_SW1_COMMAND_COMPLETE;
  231 + buf[1] = R_APDU_SW2_COMMAND_COMPLETE;
  232 + *sendlen = 2 + sendlenOffset;
  233 + break;
  234 + case TAG_NOT_FOUND:
  235 + buf[0] = R_APDU_SW1_NDEF_TAG_NOT_FOUND;
  236 + buf[1] = R_APDU_SW2_NDEF_TAG_NOT_FOUND;
  237 + *sendlen = 2;
  238 + break;
  239 + case FUNCTION_NOT_SUPPORTED:
  240 + buf[0] = R_APDU_SW1_FUNCTION_NOT_SUPPORTED;
  241 + buf[1] = R_APDU_SW2_FUNCTION_NOT_SUPPORTED;
  242 + *sendlen = 2;
  243 + break;
  244 + case MEMORY_FAILURE:
  245 + buf[0] = R_APDU_SW1_MEMORY_FAILURE;
  246 + buf[1] = R_APDU_SW2_MEMORY_FAILURE;
  247 + *sendlen = 2;
  248 + break;
  249 + case END_OF_FILE_BEFORE_REACHED_LE_BYTES:
  250 + buf[0] = R_APDU_SW1_END_OF_FILE_BEFORE_REACHED_LE_BYTES;
  251 + buf[1] = R_APDU_SW2_END_OF_FILE_BEFORE_REACHED_LE_BYTES;
  252 + *sendlen= 2;
  253 + break;
  254 + }
  255 +}
... ...
PN532/emulatetag.h 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + @file emulatetag.h
  4 + @author Armin Wieser
  5 + @license BSD
  6 +
  7 + Implemented using NFC forum documents & library of libnfc
  8 +*/
  9 +/**************************************************************************/
  10 +
  11 +#ifndef __EMULATETAG_H__
  12 +#define __EMULATETAG_H__
  13 +
  14 +#include "PN532.h"
  15 +
  16 +#define NDEF_MAX_LENGTH 128 // altough ndef can handle up to 0xfffe in size, arduino cannot.
  17 +typedef enum {COMMAND_COMPLETE, TAG_NOT_FOUND, FUNCTION_NOT_SUPPORTED, MEMORY_FAILURE, END_OF_FILE_BEFORE_REACHED_LE_BYTES} responseCommand;
  18 +
  19 +class EmulateTag{
  20 +
  21 +public:
  22 +EmulateTag(PN532Interface &interface) : pn532(interface), uidPtr(0), tagWrittenByInitiator(false), tagWriteable(true), updateNdefCallback(0) { }
  23 +
  24 + bool init();
  25 +
  26 + bool emulate(const uint16_t tgInitAsTargetTimeout = 0);
  27 +
  28 + /*
  29 + * @param uid pointer to byte array of length 3 (uid is 4 bytes - first byte is fixed) or zero for uid
  30 + */
  31 + void setUid(uint8_t* uid = 0);
  32 +
  33 + void setNdefFile(const uint8_t* ndef, const int16_t ndefLength);
  34 +
  35 + void getContent(uint8_t** buf, uint16_t* length){
  36 + *buf = ndef_file + 2; // first 2 bytes = length
  37 + *length = (ndef_file[0] << 8) + ndef_file[1];
  38 + }
  39 +
  40 + bool writeOccured(){
  41 + return tagWrittenByInitiator;
  42 + }
  43 +
  44 + void setTagWriteable(bool setWriteable){
  45 + tagWriteable = setWriteable;
  46 + }
  47 +
  48 + uint8_t* getNdefFilePtr(){
  49 + return ndef_file;
  50 + }
  51 +
  52 + uint8_t getNdefMaxLength(){
  53 + return NDEF_MAX_LENGTH;
  54 + }
  55 +
  56 + void attach(void (*func)(uint8_t *buf, uint16_t length)) {
  57 + updateNdefCallback = func;
  58 + };
  59 +
  60 +private:
  61 + PN532 pn532;
  62 + uint8_t ndef_file[NDEF_MAX_LENGTH];
  63 + uint8_t* uidPtr;
  64 + bool tagWrittenByInitiator;
  65 + bool tagWriteable;
  66 + void (*updateNdefCallback)(uint8_t *ndef, uint16_t length);
  67 +
  68 + void setResponse(responseCommand cmd, uint8_t* buf, uint8_t* sendlen, uint8_t sendlenOffset = 0);
  69 +};
  70 +
  71 +#endif
... ...
PN532/examples/android_hce/android_hce.ino 0 → 100644
... ... @@ -0,0 +1,135 @@
  1 +#include <SPI.h>
  2 +#include <PN532_SPI.h>
  3 +#include <PN532Interface.h>
  4 +#include <PN532.h>
  5 +
  6 +PN532_SPI pn532spi(SPI, 10);
  7 +PN532 nfc(pn532spi);
  8 +
  9 +
  10 +void setup()
  11 +{
  12 + Serial.begin(115200);
  13 + Serial.println("-------Peer to Peer HCE--------");
  14 +
  15 + nfc.begin();
  16 +
  17 + uint32_t versiondata = nfc.getFirmwareVersion();
  18 + if (! versiondata) {
  19 + Serial.print("Didn't find PN53x board");
  20 + while (1); // halt
  21 + }
  22 +
  23 + // Got ok data, print it out!
  24 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  25 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  26 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  27 +
  28 + // Set the max number of retry attempts to read from a card
  29 + // This prevents us from waiting forever for a card, which is
  30 + // the default behaviour of the PN532.
  31 + //nfc.setPassiveActivationRetries(0xFF);
  32 +
  33 + // configure board to read RFID tags
  34 + nfc.SAMConfig();
  35 +}
  36 +
  37 +void loop()
  38 +{
  39 + bool success;
  40 +
  41 + uint8_t responseLength = 32;
  42 +
  43 + Serial.println("Waiting for an ISO14443A card");
  44 +
  45 + // set shield to inListPassiveTarget
  46 + success = nfc.inListPassiveTarget();
  47 +
  48 + if(success) {
  49 +
  50 + Serial.println("Found something!");
  51 +
  52 + uint8_t selectApdu[] = { 0x00, /* CLA */
  53 + 0xA4, /* INS */
  54 + 0x04, /* P1 */
  55 + 0x00, /* P2 */
  56 + 0x07, /* Length of AID */
  57 + 0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* AID defined on Android App */
  58 + 0x00 /* Le */ };
  59 +
  60 + uint8_t response[32];
  61 +
  62 + success = nfc.inDataExchange(selectApdu, sizeof(selectApdu), response, &responseLength);
  63 +
  64 + if(success) {
  65 +
  66 + Serial.print("responseLength: "); Serial.println(responseLength);
  67 +
  68 + nfc.PrintHexChar(response, responseLength);
  69 +
  70 + do {
  71 + uint8_t apdu[] = "Hello from Arduino";
  72 + uint8_t back[32];
  73 + uint8_t length = 32;
  74 +
  75 + success = nfc.inDataExchange(apdu, sizeof(apdu), back, &length);
  76 +
  77 + if(success) {
  78 +
  79 + Serial.print("responseLength: "); Serial.println(length);
  80 +
  81 + nfc.PrintHexChar(back, length);
  82 + }
  83 + else {
  84 +
  85 + Serial.println("Broken connection?");
  86 + }
  87 + }
  88 + while(success);
  89 + }
  90 + else {
  91 +
  92 + Serial.println("Failed sending SELECT AID");
  93 + }
  94 + }
  95 + else {
  96 +
  97 + Serial.println("Didn't find anything!");
  98 + }
  99 +
  100 + delay(1000);
  101 +}
  102 +
  103 +void printResponse(uint8_t *response, uint8_t responseLength) {
  104 +
  105 + String respBuffer;
  106 +
  107 + for (int i = 0; i < responseLength; i++) {
  108 +
  109 + if (response[i] < 0x10)
  110 + respBuffer = respBuffer + "0"; //Adds leading zeros if hex value is smaller than 0x10
  111 +
  112 + respBuffer = respBuffer + String(response[i], HEX) + " ";
  113 + }
  114 +
  115 + Serial.print("response: "); Serial.println(respBuffer);
  116 +}
  117 +
  118 +void setupNFC() {
  119 +
  120 + nfc.begin();
  121 +
  122 + uint32_t versiondata = nfc.getFirmwareVersion();
  123 + if (! versiondata) {
  124 + Serial.print("Didn't find PN53x board");
  125 + while (1); // halt
  126 + }
  127 +
  128 + // Got ok data, print it out!
  129 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  130 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  131 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  132 +
  133 + // configure board to read RFID tags
  134 + nfc.SAMConfig();
  135 +}
... ...
PN532/examples/emulate_tag_ndef/emulate_tag_ndef.ino 0 → 100644
... ... @@ -0,0 +1,69 @@
  1 +
  2 +#include "SPI.h"
  3 +#include "PN532_SPI.h"
  4 +#include "emulatetag.h"
  5 +#include "NdefMessage.h"
  6 +
  7 +PN532_SPI pn532spi(SPI, 10);
  8 +EmulateTag nfc(pn532spi);
  9 +
  10 +uint8_t ndefBuf[120];
  11 +NdefMessage message;
  12 +int messageSize;
  13 +
  14 +uint8_t uid[3] = { 0x12, 0x34, 0x56 };
  15 +
  16 +void setup()
  17 +{
  18 + Serial.begin(115200);
  19 + Serial.println("------- Emulate Tag --------");
  20 +
  21 + message = NdefMessage();
  22 + message.addUriRecord("http://www.seeedstudio.com");
  23 + messageSize = message.getEncodedSize();
  24 + if (messageSize > sizeof(ndefBuf)) {
  25 + Serial.println("ndefBuf is too small");
  26 + while (1) { }
  27 + }
  28 +
  29 + Serial.print("Ndef encoded message size: ");
  30 + Serial.println(messageSize);
  31 +
  32 + message.encode(ndefBuf);
  33 +
  34 + // comment out this command for no ndef message
  35 + nfc.setNdefFile(ndefBuf, messageSize);
  36 +
  37 + // uid must be 3 bytes!
  38 + nfc.setUid(uid);
  39 +
  40 + nfc.init();
  41 +}
  42 +
  43 +void loop(){
  44 + // uncomment for overriding ndef in case a write to this tag occured
  45 + //nfc.setNdefFile(ndefBuf, messageSize);
  46 +
  47 + // start emulation (blocks)
  48 + nfc.emulate();
  49 +
  50 + // or start emulation with timeout
  51 + /*if(!nfc.emulate(1000)){ // timeout 1 second
  52 + Serial.println("timed out");
  53 + }*/
  54 +
  55 + // deny writing to the tag
  56 + // nfc.setTagWriteable(false);
  57 +
  58 + if(nfc.writeOccured()){
  59 + Serial.println("\nWrite occured !");
  60 + uint8_t* tag_buf;
  61 + uint16_t length;
  62 +
  63 + nfc.getContent(&tag_buf, &length);
  64 + NdefMessage msg = NdefMessage(tag_buf, length);
  65 + msg.print();
  66 + }
  67 +
  68 + delay(1000);
  69 +}
... ...
PN532/examples/iso14443a_uid/iso14443a_uid.pde 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + This example will attempt to connect to an ISO14443A
  4 + card or tag and retrieve some basic information about it
  5 + that can be used to determine what type of card it is.
  6 +
  7 + Note that you need the baud rate to be 115200 because we need to print
  8 + out the data and read from the card at the same time!
  9 +
  10 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  11 +
  12 +*/
  13 +/**************************************************************************/
  14 +
  15 +#include <SPI.h>
  16 +#include <PN532_SPI.h>
  17 +#include "PN532.h"
  18 +
  19 +PN532_SPI pn532spi(SPI, 10);
  20 +PN532 nfc(pn532spi);
  21 +
  22 +void setup(void) {
  23 + Serial.begin(115200);
  24 + Serial.println("Hello!");
  25 +
  26 + nfc.begin();
  27 +
  28 + uint32_t versiondata = nfc.getFirmwareVersion();
  29 + if (! versiondata) {
  30 + Serial.print("Didn't find PN53x board");
  31 + while (1); // halt
  32 + }
  33 +
  34 + // Got ok data, print it out!
  35 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  36 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  37 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  38 +
  39 + // Set the max number of retry attempts to read from a card
  40 + // This prevents us from waiting forever for a card, which is
  41 + // the default behaviour of the PN532.
  42 + nfc.setPassiveActivationRetries(0xFF);
  43 +
  44 + // configure board to read RFID tags
  45 + nfc.SAMConfig();
  46 +
  47 + Serial.println("Waiting for an ISO14443A card");
  48 +}
  49 +
  50 +void loop(void) {
  51 + boolean success;
  52 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  53 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  54 +
  55 + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found
  56 + // 'uid' will be populated with the UID, and uidLength will indicate
  57 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  58 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  59 +
  60 + if (success) {
  61 + Serial.println("Found a card!");
  62 + Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  63 + Serial.print("UID Value: ");
  64 + for (uint8_t i=0; i < uidLength; i++)
  65 + {
  66 + Serial.print(" 0x");Serial.print(uid[i], HEX);
  67 + }
  68 + Serial.println("");
  69 + // Wait 1 second before continuing
  70 + delay(1000);
  71 + }
  72 + else
  73 + {
  74 + // PN532 probably timed out waiting for a card
  75 + Serial.println("Timed out waiting for a card");
  76 + }
  77 +}
0 78 \ No newline at end of file
... ...
PN532/examples/mifareclassic_formatndef/mifareclassic_formatndef.pde 0 → 100644
... ... @@ -0,0 +1,170 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + This example attempts to format a clean Mifare Classic 1K card as
  4 + an NFC Forum tag (to store NDEF messages that can be read by any
  5 + NFC enabled Android phone, etc.)
  6 +
  7 + Note that you need the baud rate to be 115200 because we need to print
  8 + out the data and read from the card at the same time!
  9 +
  10 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  11 +*/
  12 +/**************************************************************************/
  13 +
  14 +#include <SPI.h>
  15 +#include <PN532_SPI.h>
  16 +#include "PN532.h"
  17 +
  18 +PN532_SPI pn532spi(SPI, 10);
  19 +PN532 nfc(pn532spi);
  20 +
  21 +/*
  22 + We can encode many different kinds of pointers to the card,
  23 + from a URL, to an Email address, to a phone number, and many more
  24 + check the library header .h file to see the large # of supported
  25 + prefixes!
  26 +*/
  27 +// For a http://www. url:
  28 +const char * url = "seeedstudio.com";
  29 +uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT;
  30 +
  31 +// for an email address
  32 +//const char * url = "mail@example.com";
  33 +//uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO;
  34 +
  35 +// for a phone number
  36 +//const char * url = "+1 212 555 1212";
  37 +//uint8_t ndefprefix = NDEF_URIPREFIX_TEL;
  38 +
  39 +
  40 +void setup(void) {
  41 + Serial.begin(115200);
  42 + Serial.println("Looking for PN532...");
  43 +
  44 + nfc.begin();
  45 +
  46 + uint32_t versiondata = nfc.getFirmwareVersion();
  47 + if (! versiondata) {
  48 + Serial.print("Didn't find PN53x board");
  49 + while (1); // halt
  50 + }
  51 +
  52 + // Got ok data, print it out!
  53 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  54 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  55 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  56 +
  57 + // configure board to read RFID tags
  58 + nfc.SAMConfig();
  59 +}
  60 +
  61 +void loop(void) {
  62 + uint8_t success; // Flag to check if there was an error with the PN532
  63 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  64 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  65 + bool authenticated = false; // Flag to indicate if the sector is authenticated
  66 +
  67 + // Use the default key
  68 + uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  69 +
  70 + Serial.println("");
  71 + Serial.println("PLEASE NOTE: Formatting your card for NDEF records will change the");
  72 + Serial.println("authentication keys. To reformat your NDEF tag as a clean Mifare");
  73 + Serial.println("Classic tag, use the mifareclassic_ndeftoclassic example!");
  74 + Serial.println("");
  75 + Serial.println("Place your Mifare Classic card on the reader to format with NDEF");
  76 + Serial.println("and press any key to continue ...");
  77 + // Wait for user input before proceeding
  78 + while (!Serial.available());
  79 + // a key was pressed1
  80 + while (Serial.available()) Serial.read();
  81 +
  82 + // Wait for an ISO14443A type card (Mifare, etc.). When one is found
  83 + // 'uid' will be populated with the UID, and uidLength will indicate
  84 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  85 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  86 +
  87 + if (success)
  88 + {
  89 + // Display some basic information about the card
  90 + Serial.println("Found an ISO14443A card");
  91 + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  92 + Serial.print(" UID Value: ");
  93 + nfc.PrintHex(uid, uidLength);
  94 + for (uint8_t i = 0; i < uidLength; i++) {
  95 + Serial.print(uid[i], HEX);
  96 + Serial.print(' ');
  97 + }
  98 + Serial.println("");
  99 +
  100 + // Make sure this is a Mifare Classic card
  101 + if (uidLength != 4)
  102 + {
  103 + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
  104 + return;
  105 + }
  106 +
  107 + // We probably have a Mifare Classic card ...
  108 + Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
  109 +
  110 + // Try to format the card for NDEF data
  111 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya);
  112 + if (!success)
  113 + {
  114 + Serial.println("Unable to authenticate block 0 to enable card formatting!");
  115 + return;
  116 + }
  117 + success = nfc.mifareclassic_FormatNDEF();
  118 + if (!success)
  119 + {
  120 + Serial.println("Unable to format the card for NDEF");
  121 + return;
  122 + }
  123 +
  124 + Serial.println("Card has been formatted for NDEF data using MAD1");
  125 +
  126 + // Try to authenticate block 4 (first block of sector 1) using our key
  127 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keya);
  128 +
  129 + // Make sure the authentification process didn't fail
  130 + if (!success)
  131 + {
  132 + Serial.println("Authentication failed.");
  133 + return;
  134 + }
  135 +
  136 + // Try to write a URL
  137 + Serial.println("Writing URI to sector 1 as an NDEF Message");
  138 +
  139 + // Authenticated seems to have worked
  140 + // Try to write an NDEF record to sector 1
  141 + // Use 0x01 for the URI Identifier Code to prepend "http://www."
  142 + // to the url (and save some space). For information on URI ID Codes
  143 + // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef
  144 + if (strlen(url) > 38)
  145 + {
  146 + // The length is also checked in the WriteNDEFURI function, but lets
  147 + // warn users here just in case they change the value and it's bigger
  148 + // than it should be
  149 + Serial.println("URI is too long ... must be less than 38 characters long");
  150 + return;
  151 + }
  152 +
  153 + // URI is within size limits ... write it to the card and report success/failure
  154 + success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url);
  155 + if (success)
  156 + {
  157 + Serial.println("NDEF URI Record written to sector 1");
  158 + }
  159 + else
  160 + {
  161 + Serial.println("NDEF Record creation failed! :(");
  162 + }
  163 + }
  164 +
  165 + // Wait a bit before trying again
  166 + Serial.println("\n\nDone!");
  167 + delay(1000);
  168 + Serial.flush();
  169 + while(Serial.available()) Serial.read();
  170 +}
0 171 \ No newline at end of file
... ...
PN532/examples/mifareclassic_memdump/mifareclassic_memdump.pde 0 → 100644
... ... @@ -0,0 +1,157 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + This example attempts to dump the contents of a Mifare Classic 1K card
  4 +
  5 + Note that you need the baud rate to be 115200 because we need to print
  6 + out the data and read from the card at the same time!
  7 +
  8 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  9 +*/
  10 +/**************************************************************************/
  11 +
  12 +#include <SPI.h>
  13 +#include <PN532_SPI.h>
  14 +#include "PN532.h"
  15 +
  16 +PN532_SPI pn532spi(SPI, 10);
  17 +PN532 nfc(pn532spi);
  18 +
  19 +void setup(void) {
  20 + // has to be fast to dump the entire memory contents!
  21 + Serial.begin(115200);
  22 + Serial.println("Looking for PN532...");
  23 +
  24 + nfc.begin();
  25 +
  26 + uint32_t versiondata = nfc.getFirmwareVersion();
  27 + if (! versiondata) {
  28 + Serial.print("Didn't find PN53x board");
  29 + while (1); // halt
  30 + }
  31 + // Got ok data, print it out!
  32 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  33 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  34 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  35 +
  36 + // configure board to read RFID tags
  37 + nfc.SAMConfig();
  38 +
  39 + Serial.println("Waiting for an ISO14443A Card ...");
  40 +}
  41 +
  42 +
  43 +void loop(void) {
  44 + uint8_t success; // Flag to check if there was an error with the PN532
  45 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  46 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  47 + uint8_t currentblock; // Counter to keep track of which block we're on
  48 + bool authenticated = false; // Flag to indicate if the sector is authenticated
  49 + uint8_t data[16]; // Array to store block data during reads
  50 +
  51 + // Keyb on NDEF and Mifare Classic should be the same
  52 + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  53 +
  54 + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found
  55 + // 'uid' will be populated with the UID, and uidLength will indicate
  56 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  57 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  58 +
  59 + if (success) {
  60 + // Display some basic information about the card
  61 + Serial.println("Found an ISO14443A card");
  62 + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  63 + Serial.print(" UID Value: ");
  64 + for (uint8_t i = 0; i < uidLength; i++) {
  65 + Serial.print(uid[i], HEX);
  66 + Serial.print(' ');
  67 + }
  68 + Serial.println("");
  69 +
  70 + if (uidLength == 4)
  71 + {
  72 + // We probably have a Mifare Classic card ...
  73 + Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
  74 +
  75 + // Now we try to go through all 16 sectors (each having 4 blocks)
  76 + // authenticating each sector, and then dumping the blocks
  77 + for (currentblock = 0; currentblock < 64; currentblock++)
  78 + {
  79 + // Check if this is a new block so that we can reauthenticate
  80 + if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false;
  81 +
  82 + // If the sector hasn't been authenticated, do so first
  83 + if (!authenticated)
  84 + {
  85 + // Starting of a new sector ... try to to authenticate
  86 + Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------");
  87 + if (currentblock == 0)
  88 + {
  89 + // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!)
  90 + // or 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 for NDEF formatted cards using key a,
  91 + // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF)
  92 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
  93 + }
  94 + else
  95 + {
  96 + // This will be 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF for Mifare Classic (non-NDEF!)
  97 + // or 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7 for NDEF formatted cards using key a,
  98 + // but keyb should be the same for both (0xFF 0xFF 0xFF 0xFF 0xFF 0xFF)
  99 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
  100 + }
  101 + if (success)
  102 + {
  103 + authenticated = true;
  104 + }
  105 + else
  106 + {
  107 + Serial.println("Authentication error");
  108 + }
  109 + }
  110 + // If we're still not authenticated just skip the block
  111 + if (!authenticated)
  112 + {
  113 + Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate");
  114 + }
  115 + else
  116 + {
  117 + // Authenticated ... we should be able to read the block now
  118 + // Dump the data into the 'data' array
  119 + success = nfc.mifareclassic_ReadDataBlock(currentblock, data);
  120 + if (success)
  121 + {
  122 + // Read successful
  123 + Serial.print("Block ");Serial.print(currentblock, DEC);
  124 + if (currentblock < 10)
  125 + {
  126 + Serial.print(" ");
  127 + }
  128 + else
  129 + {
  130 + Serial.print(" ");
  131 + }
  132 + // Dump the raw data
  133 + nfc.PrintHexChar(data, 16);
  134 + }
  135 + else
  136 + {
  137 + // Oops ... something happened
  138 + Serial.print("Block ");Serial.print(currentblock, DEC);
  139 + Serial.println(" unable to read this block");
  140 + }
  141 + }
  142 + }
  143 + }
  144 + else
  145 + {
  146 + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
  147 + }
  148 + }
  149 + // Wait a bit before trying again
  150 + Serial.println("\n\nSend a character to run the mem dumper again!");
  151 + Serial.flush();
  152 + while (!Serial.available());
  153 + while (Serial.available()) {
  154 + Serial.read();
  155 + }
  156 + Serial.flush();
  157 +}
0 158 \ No newline at end of file
... ...
PN532/examples/mifareclassic_ndeftoclassic/mifareclassic_ndeftoclassic.pde 0 → 100644
... ... @@ -0,0 +1,172 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + This examples attempts to take a Mifare Classic 1K card that has been
  4 + formatted for NDEF messages using mifareclassic_formatndef, and resets
  5 + the authentication keys back to the Mifare Classic defaults
  6 +
  7 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  8 +*/
  9 +/**************************************************************************/
  10 +
  11 +#include <SPI.h>
  12 +#include <PN532_SPI.h>
  13 +#include "PN532.h"
  14 +
  15 +PN532_SPI pn532spi(SPI, 10);
  16 +PN532 nfc(pn532spi);
  17 +
  18 +
  19 +#define NR_SHORTSECTOR (32) // Number of short sectors on Mifare 1K/4K
  20 +#define NR_LONGSECTOR (8) // Number of long sectors on Mifare 4K
  21 +#define NR_BLOCK_OF_SHORTSECTOR (4) // Number of blocks in a short sector
  22 +#define NR_BLOCK_OF_LONGSECTOR (16) // Number of blocks in a long sector
  23 +
  24 +// Determine the sector trailer block based on sector number
  25 +#define BLOCK_NUMBER_OF_SECTOR_TRAILER(sector) (((sector)<NR_SHORTSECTOR)? \
  26 + ((sector)*NR_BLOCK_OF_SHORTSECTOR + NR_BLOCK_OF_SHORTSECTOR-1):\
  27 + (NR_SHORTSECTOR*NR_BLOCK_OF_SHORTSECTOR + (sector-NR_SHORTSECTOR)*NR_BLOCK_OF_LONGSECTOR + NR_BLOCK_OF_LONGSECTOR-1))
  28 +
  29 +// Determine the sector's first block based on the sector number
  30 +#define BLOCK_NUMBER_OF_SECTOR_1ST_BLOCK(sector) (((sector)<NR_SHORTSECTOR)? \
  31 + ((sector)*NR_BLOCK_OF_SHORTSECTOR):\
  32 + (NR_SHORTSECTOR*NR_BLOCK_OF_SHORTSECTOR + (sector-NR_SHORTSECTOR)*NR_BLOCK_OF_LONGSECTOR))
  33 +
  34 +// The default Mifare Classic key
  35 +static const uint8_t KEY_DEFAULT_KEYAB[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  36 +
  37 +void setup(void) {
  38 + Serial.begin(115200);
  39 + Serial.println("Looking for PN532...");
  40 +
  41 + nfc.begin();
  42 +
  43 + uint32_t versiondata = nfc.getFirmwareVersion();
  44 + if (! versiondata) {
  45 + Serial.print("Didn't find PN53x board");
  46 + while (1); // halt
  47 + }
  48 +
  49 + // Got ok data, print it out!
  50 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  51 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  52 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  53 +
  54 + // configure board to read RFID tags
  55 + nfc.SAMConfig();
  56 +}
  57 +
  58 +void loop(void) {
  59 + uint8_t success; // Flag to check if there was an error with the PN532
  60 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  61 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  62 + bool authenticated = false; // Flag to indicate if the sector is authenticated
  63 + uint8_t blockBuffer[16]; // Buffer to store block contents
  64 + uint8_t blankAccessBits[3] = { 0xff, 0x07, 0x80 };
  65 + uint8_t idx = 0;
  66 + uint8_t numOfSector = 16; // Assume Mifare Classic 1K for now (16 4-block sectors)
  67 +
  68 + Serial.println("Place your NDEF formatted Mifare Classic 1K card on the reader");
  69 + Serial.println("and press any key to continue ...");
  70 +
  71 + // Wait for user input before proceeding
  72 + while (!Serial.available());
  73 + while (Serial.available()) Serial.read();
  74 +
  75 + // Wait for an ISO14443A type card (Mifare, etc.). When one is found
  76 + // 'uid' will be populated with the UID, and uidLength will indicate
  77 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  78 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  79 +
  80 + if (success)
  81 + {
  82 + // We seem to have a tag ...
  83 + // Display some basic information about it
  84 + Serial.println("Found an ISO14443A card/tag");
  85 + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  86 + Serial.print(" UID Value: ");
  87 + nfc.PrintHex(uid, uidLength);
  88 + Serial.println("");
  89 +
  90 + // Make sure this is a Mifare Classic card
  91 + if (uidLength != 4)
  92 + {
  93 + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
  94 + return;
  95 + }
  96 +
  97 + Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
  98 + Serial.println("");
  99 + Serial.println("Reformatting card for Mifare Classic (please don't touch it!) ... ");
  100 +
  101 + // Now run through the card sector by sector
  102 + for (idx = 0; idx < numOfSector; idx++)
  103 + {
  104 + // Step 1: Authenticate the current sector using key B 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  105 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB);
  106 + if (!success)
  107 + {
  108 + Serial.print("Authentication failed for sector "); Serial.println(numOfSector);
  109 + return;
  110 + }
  111 +
  112 + // Step 2: Write to the other blocks
  113 + if (idx == 16)
  114 + {
  115 + memset(blockBuffer, 0, sizeof(blockBuffer));
  116 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer)))
  117 + {
  118 + Serial.print("Unable to write to sector "); Serial.println(numOfSector);
  119 + return;
  120 + }
  121 + }
  122 + if ((idx == 0) || (idx == 16))
  123 + {
  124 + memset(blockBuffer, 0, sizeof(blockBuffer));
  125 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
  126 + {
  127 + Serial.print("Unable to write to sector "); Serial.println(numOfSector);
  128 + return;
  129 + }
  130 + }
  131 + else
  132 + {
  133 + memset(blockBuffer, 0, sizeof(blockBuffer));
  134 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer)))
  135 + {
  136 + Serial.print("Unable to write to sector "); Serial.println(numOfSector);
  137 + return;
  138 + }
  139 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
  140 + {
  141 + Serial.print("Unable to write to sector "); Serial.println(numOfSector);
  142 + return;
  143 + }
  144 + }
  145 + memset(blockBuffer, 0, sizeof(blockBuffer));
  146 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer)))
  147 + {
  148 + Serial.print("Unable to write to sector "); Serial.println(numOfSector);
  149 + return;
  150 + }
  151 +
  152 + // Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  153 + memcpy(blockBuffer, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB));
  154 + memcpy(blockBuffer + 6, blankAccessBits, sizeof(blankAccessBits));
  155 + blockBuffer[9] = 0x69;
  156 + memcpy(blockBuffer + 10, KEY_DEFAULT_KEYAB, sizeof(KEY_DEFAULT_KEYAB));
  157 +
  158 + // Step 4: Write the trailer block
  159 + if (!(nfc.mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer)))
  160 + {
  161 + Serial.print("Unable to write trailer block of sector "); Serial.println(numOfSector);
  162 + return;
  163 + }
  164 + }
  165 + }
  166 +
  167 + // Wait a bit before trying again
  168 + Serial.println("\n\nDone!");
  169 + delay(1000);
  170 + Serial.flush();
  171 + while(Serial.available()) Serial.read();
  172 +}
0 173 \ No newline at end of file
... ...
PN532/examples/mifareclassic_updatendef/mifareclassic_updatendef.pde 0 → 100644
... ... @@ -0,0 +1,145 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + Updates a sector that is already formatted for NDEF (using
  4 + mifareclassic_formatndef.pde for example), inserting a new url
  5 +
  6 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  7 +*/
  8 +/**************************************************************************/
  9 +
  10 +#include <SPI.h>
  11 +#include <PN532_SPI.h>
  12 +#include "PN532.h"
  13 +
  14 +PN532_SPI pn532spi(SPI, 10);
  15 +PN532 nfc(pn532spi);
  16 +
  17 +
  18 +
  19 +/*
  20 + We can encode many different kinds of pointers to the card,
  21 + from a URL, to an Email address, to a phone number, and many more
  22 + check the library header .h file to see the large # of supported
  23 + prefixes!
  24 +*/
  25 +// For a http://www. url:
  26 +const char * url = "seeedstudio.com";
  27 +uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT;
  28 +
  29 +// for an email address
  30 +//const char * url = "mail@example.com";
  31 +//uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO;
  32 +
  33 +// for a phone number
  34 +//const char * url = "+1 212 555 1212";
  35 +//uint8_t ndefprefix = NDEF_URIPREFIX_TEL;
  36 +
  37 +
  38 +void setup(void) {
  39 + Serial.begin(115200);
  40 + Serial.println("Looking for PN532...");
  41 +
  42 + nfc.begin();
  43 +
  44 + uint32_t versiondata = nfc.getFirmwareVersion();
  45 + if (! versiondata) {
  46 + Serial.print("Didn't find PN53x board");
  47 + while (1); // halt
  48 + }
  49 +
  50 + // Got ok data, print it out!
  51 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  52 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  53 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  54 +
  55 + // configure board to read RFID tags
  56 + nfc.SAMConfig();
  57 +}
  58 +
  59 +void loop(void) {
  60 + uint8_t success; // Flag to check if there was an error with the PN532
  61 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  62 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  63 + bool authenticated = false; // Flag to indicate if the sector is authenticated
  64 +
  65 + // Use the default NDEF keys (these would have have set by mifareclassic_formatndef.pde!)
  66 + uint8_t keya[6] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
  67 + uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
  68 +
  69 + Serial.println("Place your NDEF formatted Mifare Classic card on the reader to update the");
  70 + Serial.println("NDEF record and press any key to continue ...");
  71 + // Wait for user input before proceeding
  72 + while (!Serial.available());
  73 + // a key was pressed1
  74 + while (Serial.available()) Serial.read();
  75 +
  76 + // Wait for an ISO14443A type card (Mifare, etc.). When one is found
  77 + // 'uid' will be populated with the UID, and uidLength will indicate
  78 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  79 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  80 +
  81 + if (success)
  82 + {
  83 + // Display some basic information about the card
  84 + Serial.println("Found an ISO14443A card");
  85 + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  86 + Serial.print(" UID Value: ");
  87 + nfc.PrintHex(uid, uidLength);
  88 + Serial.println("");
  89 +
  90 + // Make sure this is a Mifare Classic card
  91 + if (uidLength != 4)
  92 + {
  93 + Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
  94 + return;
  95 + }
  96 +
  97 + // We probably have a Mifare Classic card ...
  98 + Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
  99 +
  100 + // Check if this is an NDEF card (using first block of sector 1 from mifareclassic_formatndef.pde)
  101 + // Must authenticate on the first key using 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7
  102 + success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keyb);
  103 + if (!success)
  104 + {
  105 + Serial.println("Unable to authenticate block 4 ... is this card NDEF formatted?");
  106 + return;
  107 + }
  108 +
  109 + Serial.println("Authentication succeeded (seems to be an NDEF/NFC Forum tag) ...");
  110 +
  111 + // Authenticated seems to have worked
  112 + // Try to write an NDEF record to sector 1
  113 + // Use 0x01 for the URI Identifier Code to prepend "http://www."
  114 + // to the url (and save some space). For information on URI ID Codes
  115 + // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef
  116 + if (strlen(url) > 38)
  117 + {
  118 + // The length is also checked in the WriteNDEFURI function, but lets
  119 + // warn users here just in case they change the value and it's bigger
  120 + // than it should be
  121 + Serial.println("URI is too long ... must be less than 38 characters!");
  122 + return;
  123 + }
  124 +
  125 + Serial.println("Updating sector 1 with URI as NDEF Message");
  126 +
  127 + // URI is within size limits ... write it to the card and report success/failure
  128 + success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url);
  129 + if (success)
  130 + {
  131 + Serial.println("NDEF URI Record written to sector 1");
  132 + Serial.println("");
  133 + }
  134 + else
  135 + {
  136 + Serial.println("NDEF Record creation failed! :(");
  137 + }
  138 + }
  139 +
  140 + // Wait a bit before trying again
  141 + Serial.println("\n\nDone!");
  142 + delay(1000);
  143 + Serial.flush();
  144 + while(Serial.available()) Serial.read();
  145 +}
... ...
PN532/examples/p2p_raw/p2p_raw.ino 0 → 100644
... ... @@ -0,0 +1,51 @@
  1 +// snep_test.ino
  2 +// send a SNEP message to adnroid and get a message from android
  3 +
  4 +#include "SPI.h"
  5 +#include "PN532_SPI.h"
  6 +#include "llcp.h"
  7 +#include "snep.h"
  8 +
  9 +PN532_SPI pn532spi(SPI, 10);
  10 +SNEP nfc(pn532spi);
  11 +
  12 +void setup()
  13 +{
  14 + Serial.begin(115200);
  15 + Serial.println("-------Peer to Peer--------");
  16 +}
  17 +
  18 +uint8_t message[] = {
  19 +0xD2, 0xA, 0xB, 0x74,0x65, 0x78, 0x74, 0x2F, 0x70, 0x6C,
  20 +0x61, 0x69, 0x6E, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77,
  21 +0x6F, 0x72, 0x6C, 0x64};
  22 +
  23 +uint8_t buf[128];
  24 +
  25 +void loop()
  26 +{
  27 +
  28 + nfc.write(message, sizeof(message));
  29 + delay(3000);
  30 +
  31 + int16_t len = nfc.read(buf, sizeof(buf));
  32 + if (len > 0) {
  33 + Serial.println("get a SNEP message:");
  34 + for (uint8_t i = 0; i < len; i++) {
  35 + Serial.print(buf[i], HEX);
  36 + Serial.print(' ');
  37 + }
  38 + Serial.print('\n');
  39 + for (uint8_t i = 0; i < len; i++) {
  40 + char c = buf[i];
  41 + if (c <= 0x1f || c > 0x7f) {
  42 + Serial.print('.');
  43 + } else {
  44 + Serial.print(c);
  45 + }
  46 + }
  47 + Serial.print('\n');
  48 + }
  49 + delay(3000);
  50 +}
  51 +
... ...
PN532/examples/p2p_with_ndef_library/p2p_with_ndef_library.ino 0 → 100644
... ... @@ -0,0 +1,55 @@
  1 +// send a NDEF message to adnroid or get a NDEF message
  2 +//
  3 +// note: [NDEF library](https://github.com/Don/NDEF) is needed.
  4 +
  5 +#include "SPI.h"
  6 +#include "PN532_SPI.h"
  7 +#include "snep.h"
  8 +#include "NdefMessage.h"
  9 +
  10 +PN532_SPI pn532spi(SPI, 10);
  11 +SNEP nfc(pn532spi);
  12 +uint8_t ndefBuf[128];
  13 +
  14 +void setup()
  15 +{
  16 + Serial.begin(115200);
  17 + Serial.println("-------Peer to Peer--------");
  18 +}
  19 +
  20 +void loop()
  21 +{
  22 +#if 1
  23 + Serial.println("Send a message to Android");
  24 + NdefMessage message = NdefMessage();
  25 + message.addUriRecord("http://www.seeedstudio.com");
  26 + int messageSize = message.getEncodedSize();
  27 + if (messageSize > sizeof(ndefBuf)) {
  28 + Serial.println("ndefBuf is too small");
  29 + while (1) {
  30 + }
  31 +
  32 + }
  33 +
  34 + message.encode(ndefBuf);
  35 + if (0 >= nfc.write(ndefBuf, messageSize)) {
  36 + Serial.println("Failed");
  37 + } else {
  38 + Serial.println("Success");
  39 + }
  40 +
  41 + delay(3000);
  42 +#else
  43 + Serial.println("Get a message from Android");
  44 + int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
  45 + if (msgSize > 0) {
  46 + NdefMessage msg = NdefMessage(ndefBuf, msgSize);
  47 + msg.print();
  48 + Serial.println("\nSuccess");
  49 + } else {
  50 + Serial.println("failed");
  51 + }
  52 + delay(3000);
  53 +#endif
  54 +}
  55 +
... ...
PN532/examples/readMifare/readMifare.pde 0 → 100644
... ... @@ -0,0 +1,145 @@
  1 +/**************************************************************************/
  2 +/*!
  3 + This example will wait for any ISO14443A card or tag, and
  4 + depending on the size of the UID will attempt to read from it.
  5 +
  6 + If the card has a 4-byte UID it is probably a Mifare
  7 + Classic card, and the following steps are taken:
  8 +
  9 + - Authenticate block 4 (the first block of Sector 1) using
  10 + the default KEYA of 0XFF 0XFF 0XFF 0XFF 0XFF 0XFF
  11 + - If authentication succeeds, we can then read any of the
  12 + 4 blocks in that sector (though only block 4 is read here)
  13 +
  14 + If the card has a 7-byte UID it is probably a Mifare
  15 + Ultralight card, and the 4 byte pages can be read directly.
  16 + Page 4 is read by default since this is the first 'general-
  17 + purpose' page on the tags.
  18 +
  19 + To enable debug message, define DEBUG in PN532/PN532_debug.h
  20 +*/
  21 +/**************************************************************************/
  22 +
  23 +#include <SPI.h>
  24 +#include <PN532_SPI.h>
  25 +#include "PN532.h"
  26 +
  27 +PN532_SPI pn532spi(SPI, 10);
  28 +PN532 nfc(pn532spi);
  29 +
  30 +void setup(void) {
  31 + Serial.begin(115200);
  32 + Serial.println("Hello!");
  33 +
  34 + nfc.begin();
  35 +
  36 + uint32_t versiondata = nfc.getFirmwareVersion();
  37 + if (! versiondata) {
  38 + Serial.print("Didn't find PN53x board");
  39 + while (1); // halt
  40 + }
  41 + // Got ok data, print it out!
  42 + Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  43 + Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  44 + Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  45 +
  46 + // configure board to read RFID tags
  47 + nfc.SAMConfig();
  48 +
  49 + Serial.println("Waiting for an ISO14443A Card ...");
  50 +}
  51 +
  52 +
  53 +void loop(void) {
  54 + uint8_t success;
  55 + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  56 + uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  57 +
  58 + // Wait for an ISO14443A type cards (Mifare, etc.). When one is found
  59 + // 'uid' will be populated with the UID, and uidLength will indicate
  60 + // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  61 + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  62 +
  63 + if (success) {
  64 + // Display some basic information about the card
  65 + Serial.println("Found an ISO14443A card");
  66 + Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  67 + Serial.print(" UID Value: ");
  68 + nfc.PrintHex(uid, uidLength);
  69 + Serial.println("");
  70 +
  71 + if (uidLength == 4)
  72 + {
  73 + // We probably have a Mifare Classic card ...
  74 + Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
  75 +
  76 + // Now we need to try to authenticate it for read/write access
  77 + // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  78 + Serial.println("Trying to authenticate block 4 with default KEYA value");
  79 + uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  80 +
  81 + // Start with block 4 (the first block of sector 1) since sector 0
  82 + // contains the manufacturer data and it's probably better just
  83 + // to leave it alone unless you know what you're doing
  84 + success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
  85 +
  86 + if (success)
  87 + {
  88 + Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
  89 + uint8_t data[16];
  90 +
  91 + // If you want to write something to block 4 to test with, uncomment
  92 + // the following line and this text should be read back in a minute
  93 + // data = { 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0};
  94 + // success = nfc.mifareclassic_WriteDataBlock (4, data);
  95 +
  96 + // Try to read the contents of block 4
  97 + success = nfc.mifareclassic_ReadDataBlock(4, data);
  98 +
  99 + if (success)
  100 + {
  101 + // Data seems to have been read ... spit it out
  102 + Serial.println("Reading Block 4:");
  103 + nfc.PrintHexChar(data, 16);
  104 + Serial.println("");
  105 +
  106 + // Wait a bit before reading the card again
  107 + delay(1000);
  108 + }
  109 + else
  110 + {
  111 + Serial.println("Ooops ... unable to read the requested block. Try another key?");
  112 + }
  113 + }
  114 + else
  115 + {
  116 + Serial.println("Ooops ... authentication failed: Try another key?");
  117 + }
  118 + }
  119 +
  120 + if (uidLength == 7)
  121 + {
  122 + // We probably have a Mifare Ultralight card ...
  123 + Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");
  124 +
  125 + // Try to read the first general-purpose user page (#4)
  126 + Serial.println("Reading page 4");
  127 + uint8_t data[32];
  128 + success = nfc.mifareultralight_ReadPage (4, data);
  129 + if (success)
  130 + {
  131 + // Data seems to have been read ... spit it out
  132 + nfc.PrintHexChar(data, 4);
  133 + Serial.println("");
  134 +
  135 + // Wait a bit before reading the card again
  136 + delay(1000);
  137 + }
  138 + else
  139 + {
  140 + Serial.println("Ooops ... unable to read the requested page!?");
  141 + }
  142 + }
  143 + }
  144 +}
  145 +
... ...
PN532/license.txt 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +Software License Agreement (BSD License)
  2 +
  3 +Copyright (c) 2012, Adafruit Industries
  4 +Copyright (c) 2013, Seeed Technology Inc.
  5 +All rights reserved.
  6 +
  7 +Redistribution and use in source and binary forms, with or without
  8 +modification, are permitted provided that the following conditions are met:
  9 +1. Redistributions of source code must retain the above copyright
  10 +notice, this list of conditions and the following disclaimer.
  11 +2. Redistributions in binary form must reproduce the above copyright
  12 +notice, this list of conditions and the following disclaimer in the
  13 +documentation and/or other materials provided with the distribution.
  14 +3. Neither the name of the copyright holders nor the
  15 +names of its contributors may be used to endorse or promote products
  16 +derived from this software without specific prior written permission.
  17 +
  18 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
  19 +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  22 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25 +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
... ...
PN532/llcp.cpp 0 → 100644
... ... @@ -0,0 +1,309 @@
  1 +
  2 +#include "llcp.h"
  3 +#include "PN532_debug.h"
  4 +
  5 +// LLCP PDU Type Values
  6 +#define PDU_SYMM 0x00
  7 +#define PDU_PAX 0x01
  8 +#define PDU_CONNECT 0x04
  9 +#define PDU_DISC 0x05
  10 +#define PDU_CC 0x06
  11 +#define PDU_DM 0x07
  12 +#define PDU_I 0x0c
  13 +#define PDU_RR 0x0d
  14 +
  15 +uint8_t LLCP::SYMM_PDU[2] = {0, 0};
  16 +
  17 +inline uint8_t getPType(const uint8_t *buf)
  18 +{
  19 + return ((buf[0] & 0x3) << 2) + (buf[1] >> 6);
  20 +}
  21 +
  22 +inline uint8_t getSSAP(const uint8_t *buf)
  23 +{
  24 + return buf[1] & 0x3f;
  25 +}
  26 +
  27 +inline uint8_t getDSAP(const uint8_t *buf)
  28 +{
  29 + return buf[0] >> 2;
  30 +}
  31 +
  32 +int8_t LLCP::activate(uint16_t timeout)
  33 +{
  34 + return link.activateAsTarget(timeout);
  35 +}
  36 +
  37 +int8_t LLCP::waitForConnection(uint16_t timeout)
  38 +{
  39 + uint8_t type;
  40 +
  41 + mode = 1;
  42 + ns = 0;
  43 + nr = 0;
  44 +
  45 + // Get CONNECT PDU
  46 + DMSG("wait for a CONNECT PDU\n");
  47 + do {
  48 + if (2 > link.read(headerBuf, headerBufLen)) {
  49 + return -1;
  50 + }
  51 +
  52 + type = getPType(headerBuf);
  53 + if (PDU_CONNECT == type) {
  54 + break;
  55 + } else if (PDU_SYMM == type) {
  56 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  57 + return -2;
  58 + }
  59 + } else {
  60 + return -3;
  61 + }
  62 +
  63 + } while (1);
  64 +
  65 + // Put CC PDU
  66 + DMSG("put a CC(Connection Complete) PDU to response the CONNECT PDU\n");
  67 + ssap = getDSAP(headerBuf);
  68 + dsap = getSSAP(headerBuf);
  69 + headerBuf[0] = (dsap << 2) + ((PDU_CC >> 2) & 0x3);
  70 + headerBuf[1] = ((PDU_CC & 0x3) << 6) + ssap;
  71 + if (!link.write(headerBuf, 2)) {
  72 + return -2;
  73 + }
  74 +
  75 + return 1;
  76 +}
  77 +
  78 +int8_t LLCP::waitForDisconnection(uint16_t timeout)
  79 +{
  80 + uint8_t type;
  81 +
  82 + // Get DISC PDU
  83 + DMSG("wait for a DISC PDU\n");
  84 + do {
  85 + if (2 > link.read(headerBuf, headerBufLen)) {
  86 + return -1;
  87 + }
  88 +
  89 + type = getPType(headerBuf);
  90 + if (PDU_DISC == type) {
  91 + break;
  92 + } else if (PDU_SYMM == type) {
  93 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  94 + return -2;
  95 + }
  96 + } else {
  97 + return -3;
  98 + }
  99 +
  100 + } while (1);
  101 +
  102 + // Put DM PDU
  103 + DMSG("put a DM(Disconnect Mode) PDU to response the DISC PDU\n");
  104 + // ssap = getDSAP(headerBuf);
  105 + // dsap = getSSAP(headerBuf);
  106 + headerBuf[0] = (dsap << 2) + (PDU_DM >> 2);
  107 + headerBuf[1] = ((PDU_DM & 0x3) << 6) + ssap;
  108 + if (!link.write(headerBuf, 2)) {
  109 + return -2;
  110 + }
  111 +
  112 + return 1;
  113 +}
  114 +
  115 +int8_t LLCP::connect(uint16_t timeout)
  116 +{
  117 + uint8_t type;
  118 +
  119 + mode = 0;
  120 + dsap = LLCP_DEFAULT_DSAP;
  121 + ssap = LLCP_DEFAULT_SSAP;
  122 + ns = 0;
  123 + nr = 0;
  124 +
  125 + // try to get a SYMM PDU
  126 + if (2 > link.read(headerBuf, headerBufLen)) {
  127 + return -1;
  128 + }
  129 + type = getPType(headerBuf);
  130 + if (PDU_SYMM != type) {
  131 + return -1;
  132 + }
  133 +
  134 + // put a CONNECT PDU
  135 + headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_CONNECT >> 2);
  136 + headerBuf[1] = ((PDU_CONNECT & 0x03) << 6) + LLCP_DEFAULT_SSAP;
  137 + uint8_t body[] = " urn:nfc:sn:snep";
  138 + body[0] = 0x06;
  139 + body[1] = sizeof(body) - 2 - 1;
  140 + if (!link.write(headerBuf, 2, body, sizeof(body) - 1)) {
  141 + return -2;
  142 + }
  143 +
  144 + // wait for a CC PDU
  145 + DMSG("wait for a CC PDU\n");
  146 + do {
  147 + if (2 > link.read(headerBuf, headerBufLen)) {
  148 + return -1;
  149 + }
  150 +
  151 + type = getPType(headerBuf);
  152 + if (PDU_CC == type) {
  153 + break;
  154 + } else if (PDU_SYMM == type) {
  155 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  156 + return -2;
  157 + }
  158 + } else {
  159 + return -3;
  160 + }
  161 +
  162 + } while (1);
  163 +
  164 + return 1;
  165 +}
  166 +
  167 +int8_t LLCP::disconnect(uint16_t timeout)
  168 +{
  169 + uint8_t type;
  170 +
  171 + // try to get a SYMM PDU
  172 + if (2 > link.read(headerBuf, headerBufLen)) {
  173 + return -1;
  174 + }
  175 + type = getPType(headerBuf);
  176 + if (PDU_SYMM != type) {
  177 + return -1;
  178 + }
  179 +
  180 + // put a DISC PDU
  181 + headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_DISC >> 2);
  182 + headerBuf[1] = ((PDU_DISC & 0x03) << 6) + LLCP_DEFAULT_SSAP;
  183 + if (!link.write(headerBuf, 2)) {
  184 + return -2;
  185 + }
  186 +
  187 + // wait for a DM PDU
  188 + DMSG("wait for a DM PDU\n");
  189 + do {
  190 + if (2 > link.read(headerBuf, headerBufLen)) {
  191 + return -1;
  192 + }
  193 +
  194 + type = getPType(headerBuf);
  195 + if (PDU_CC == type) {
  196 + break;
  197 + } else if (PDU_DM == type) {
  198 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  199 + return -2;
  200 + }
  201 + } else {
  202 + return -3;
  203 + }
  204 +
  205 + } while (1);
  206 +
  207 + return 1;
  208 +}
  209 +
  210 +bool LLCP::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  211 +{
  212 + uint8_t type;
  213 + uint8_t buf[3];
  214 +
  215 + if (mode) {
  216 + // Get a SYMM PDU
  217 + if (2 != link.read(buf, sizeof(buf))) {
  218 + return false;
  219 + }
  220 + }
  221 +
  222 + if (headerBufLen < (hlen + 3)) {
  223 + return false;
  224 + }
  225 +
  226 + for (int8_t i = hlen - 1; i >= 0; i--) {
  227 + headerBuf[i + 3] = header[i];
  228 + }
  229 +
  230 + headerBuf[0] = (dsap << 2) + (PDU_I >> 2);
  231 + headerBuf[1] = ((PDU_I & 0x3) << 6) + ssap;
  232 + headerBuf[2] = (ns << 4) + nr;
  233 + if (!link.write(headerBuf, 3 + hlen, body, blen)) {
  234 + return false;
  235 + }
  236 +
  237 + ns++;
  238 +
  239 + // Get a RR PDU
  240 + int16_t status;
  241 + do {
  242 + status = link.read(headerBuf, headerBufLen);
  243 + if (2 > status) {
  244 + return false;
  245 + }
  246 +
  247 + type = getPType(headerBuf);
  248 + if (PDU_RR == type) {
  249 + break;
  250 + } else if (PDU_SYMM == type) {
  251 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  252 + return false;
  253 + }
  254 + } else {
  255 + return false;
  256 + }
  257 + } while (1);
  258 +
  259 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  260 + return false;
  261 + }
  262 +
  263 + return true;
  264 +}
  265 +
  266 +int16_t LLCP::read(uint8_t *buf, uint8_t length)
  267 +{
  268 + uint8_t type;
  269 + uint16_t status;
  270 +
  271 + // Get INFO PDU
  272 + do {
  273 + status = link.read(buf, length);
  274 + if (2 > status) {
  275 + return -1;
  276 + }
  277 +
  278 + type = getPType(buf);
  279 + if (PDU_I == type) {
  280 + break;
  281 + } else if (PDU_SYMM == type) {
  282 + if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
  283 + return -2;
  284 + }
  285 + } else {
  286 + return -3;
  287 + }
  288 +
  289 + } while (1);
  290 +
  291 + uint8_t len = status - 3;
  292 + ssap = getDSAP(buf);
  293 + dsap = getSSAP(buf);
  294 +
  295 + headerBuf[0] = (dsap << 2) + (PDU_RR >> 2);
  296 + headerBuf[1] = ((PDU_RR & 0x3) << 6) + ssap;
  297 + headerBuf[2] = (buf[2] >> 4) + 1;
  298 + if (!link.write(headerBuf, 3)) {
  299 + return -2;
  300 + }
  301 +
  302 + for (uint8_t i = 0; i < len; i++) {
  303 + buf[i] = buf[i + 3];
  304 + }
  305 +
  306 + nr++;
  307 +
  308 + return len;
  309 +}
... ...
PN532/llcp.h 0 → 100644
... ... @@ -0,0 +1,75 @@
  1 +
  2 +#ifndef __LLCP_H__
  3 +#define __LLCP_H__
  4 +
  5 +#include "mac_link.h"
  6 +
  7 +#define LLCP_DEFAULT_TIMEOUT 20000
  8 +#define LLCP_DEFAULT_DSAP 0x04
  9 +#define LLCP_DEFAULT_SSAP 0x20
  10 +
  11 +class LLCP {
  12 +public:
  13 + LLCP(PN532Interface &interface) : link(interface) {
  14 + headerBuf = link.getHeaderBuffer(&headerBufLen);
  15 + ns = 0;
  16 + nr = 0;
  17 + };
  18 +
  19 + /**
  20 + * @brief Actiave PN532 as a target
  21 + * @param timeout max time to wait, 0 means no timeout
  22 + * @return > 0 success
  23 + * = 0 timeout
  24 + * < 0 failed
  25 + */
  26 + int8_t activate(uint16_t timeout = 0);
  27 +
  28 + int8_t waitForConnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);
  29 +
  30 + int8_t waitForDisconnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);
  31 +
  32 + int8_t connect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);
  33 +
  34 + int8_t disconnect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);
  35 +
  36 + /**
  37 + * @brief write a packet, the packet should be less than (255 - 2) bytes
  38 + * @param header packet header
  39 + * @param hlen length of header
  40 + * @param body packet body
  41 + * @param blen length of body
  42 + * @return true success
  43 + * false failed
  44 + */
  45 + bool write(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  46 +
  47 + /**
  48 + * @brief read a packet, the packet will be less than (255 - 2) bytes
  49 + * @param buf the buffer to contain the packet
  50 + * @param len lenght of the buffer
  51 + * @return >=0 length of the packet
  52 + * <0 failed
  53 + */
  54 + int16_t read(uint8_t *buf, uint8_t len);
  55 +
  56 + uint8_t *getHeaderBuffer(uint8_t *len) {
  57 + uint8_t *buf = link.getHeaderBuffer(len);
  58 + len -= 3; // I PDU header has 3 bytes
  59 + return buf;
  60 + };
  61 +
  62 +private:
  63 + MACLink link;
  64 + uint8_t mode;
  65 + uint8_t ssap;
  66 + uint8_t dsap;
  67 + uint8_t *headerBuf;
  68 + uint8_t headerBufLen;
  69 + uint8_t ns; // Number of I PDU Sent
  70 + uint8_t nr; // Number of I PDU Received
  71 +
  72 + static uint8_t SYMM_PDU[2];
  73 +};
  74 +
  75 +#endif // __LLCP_H__
... ...
PN532/mac_link.cpp 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +
  2 +#include "mac_link.h"
  3 +#include "PN532_debug.h"
  4 +
  5 +int8_t MACLink::activateAsTarget(uint16_t timeout)
  6 +{
  7 + pn532.begin();
  8 + pn532.SAMConfig();
  9 + return pn532.tgInitAsTarget(timeout);
  10 +}
  11 +
  12 +bool MACLink::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  13 +{
  14 + return pn532.tgSetData(header, hlen, body, blen);
  15 +}
  16 +
  17 +int16_t MACLink::read(uint8_t *buf, uint8_t len)
  18 +{
  19 + return pn532.tgGetData(buf, len);
  20 +}
... ...
PN532/mac_link.h 0 → 100644
... ... @@ -0,0 +1,51 @@
  1 +
  2 +
  3 +#ifndef __MAC_LINK_H__
  4 +#define __MAC_LINK_H__
  5 +
  6 +#include "PN532.h"
  7 +
  8 +class MACLink {
  9 +public:
  10 + MACLink(PN532Interface &interface) : pn532(interface) {
  11 +
  12 + };
  13 +
  14 + /**
  15 + * @brief Activate PN532 as a target
  16 + * @param timeout max time to wait, 0 means no timeout
  17 + * @return > 0 success
  18 + * = 0 timeout
  19 + * < 0 failed
  20 + */
  21 + int8_t activateAsTarget(uint16_t timeout = 0);
  22 +
  23 + /**
  24 + * @brief write a PDU packet, the packet should be less than (255 - 2) bytes
  25 + * @param header packet header
  26 + * @param hlen length of header
  27 + * @param body packet body
  28 + * @param blen length of body
  29 + * @return true success
  30 + * false failed
  31 + */
  32 + bool write(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  33 +
  34 + /**
  35 + * @brief read a PDU packet, the packet will be less than (255 - 2) bytes
  36 + * @param buf the buffer to contain the PDU packet
  37 + * @param len lenght of the buffer
  38 + * @return >=0 length of the PDU packet
  39 + * <0 failed
  40 + */
  41 + int16_t read(uint8_t *buf, uint8_t len);
  42 +
  43 + uint8_t *getHeaderBuffer(uint8_t *len) {
  44 + return pn532.getBuffer(len);
  45 + };
  46 +
  47 +private:
  48 + PN532 pn532;
  49 +};
  50 +
  51 +#endif // __MAC_LINK_H__
... ...
PN532/snep.cpp 0 → 100644
... ... @@ -0,0 +1,106 @@
  1 +
  2 +#include "snep.h"
  3 +#include "PN532_debug.h"
  4 +
  5 +int8_t SNEP::write(const uint8_t *buf, uint8_t len, uint16_t timeout)
  6 +{
  7 + if (0 >= llcp.activate(timeout)) {
  8 + DMSG("failed to activate PN532 as a target\n");
  9 + return -1;
  10 + }
  11 +
  12 + if (0 >= llcp.connect(timeout)) {
  13 + DMSG("failed to set up a connection\n");
  14 + return -2;
  15 + }
  16 +
  17 + // response a success SNEP message
  18 + headerBuf[0] = SNEP_DEFAULT_VERSION;
  19 + headerBuf[1] = SNEP_REQUEST_PUT;
  20 + headerBuf[2] = 0;
  21 + headerBuf[3] = 0;
  22 + headerBuf[4] = 0;
  23 + headerBuf[5] = len;
  24 + if (0 >= llcp.write(headerBuf, 6, buf, len)) {
  25 + return -3;
  26 + }
  27 +
  28 + uint8_t rbuf[16];
  29 + if (6 > llcp.read(rbuf, sizeof(rbuf))) {
  30 + return -4;
  31 + }
  32 +
  33 + // check SNEP version
  34 + if (SNEP_DEFAULT_VERSION != rbuf[0]) {
  35 + DMSG("The received SNEP message's major version is different\n");
  36 + // To-do: send Unsupported Version response
  37 + return -4;
  38 + }
  39 +
  40 + // expect a put request
  41 + if (SNEP_RESPONSE_SUCCESS != rbuf[1]) {
  42 + DMSG("Expect a success response\n");
  43 + return -4;
  44 + }
  45 +
  46 + llcp.disconnect(timeout);
  47 +
  48 + return 1;
  49 +}
  50 +
  51 +int16_t SNEP::read(uint8_t *buf, uint8_t len, uint16_t timeout)
  52 +{
  53 + if (0 >= llcp.activate(timeout)) {
  54 + DMSG("failed to activate PN532 as a target\n");
  55 + return -1;
  56 + }
  57 +
  58 + if (0 >= llcp.waitForConnection(timeout)) {
  59 + DMSG("failed to set up a connection\n");
  60 + return -2;
  61 + }
  62 +
  63 + uint16_t status = llcp.read(buf, len);
  64 + if (6 > status) {
  65 + return -3;
  66 + }
  67 +
  68 +
  69 + // check SNEP version
  70 + if (SNEP_DEFAULT_VERSION != buf[0]) {
  71 + DMSG("The received SNEP message's major version is different\n");
  72 + // To-do: send Unsupported Version response
  73 + return -4;
  74 + }
  75 +
  76 + // expect a put request
  77 + if (SNEP_REQUEST_PUT != buf[1]) {
  78 + DMSG("Expect a put request\n");
  79 + return -4;
  80 + }
  81 +
  82 + // check message's length
  83 + uint32_t length = (buf[2] << 24) + (buf[3] << 16) + (buf[4] << 8) + buf[5];
  84 + // length should not be more than 244 (header + body < 255, header = 6 + 3 + 2)
  85 + if (length > (status - 6)) {
  86 + DMSG("The SNEP message is too large: ");
  87 + DMSG_INT(length);
  88 + DMSG_INT(status - 6);
  89 + DMSG("\n");
  90 + return -4;
  91 + }
  92 + for (uint8_t i = 0; i < length; i++) {
  93 + buf[i] = buf[i + 6];
  94 + }
  95 +
  96 + // response a success SNEP message
  97 + headerBuf[0] = SNEP_DEFAULT_VERSION;
  98 + headerBuf[1] = SNEP_RESPONSE_SUCCESS;
  99 + headerBuf[2] = 0;
  100 + headerBuf[3] = 0;
  101 + headerBuf[4] = 0;
  102 + headerBuf[5] = 0;
  103 + llcp.write(headerBuf, 6);
  104 +
  105 + return length;
  106 +}
... ...
PN532/snep.h 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +
  2 +
  3 +#ifndef __SNEP_H__
  4 +#define __SNEP_H__
  5 +
  6 +#include "llcp.h"
  7 +
  8 +#define SNEP_DEFAULT_VERSION 0x10 // Major: 1, Minor: 0
  9 +
  10 +#define SNEP_REQUEST_PUT 0x02
  11 +#define SNEP_REQUEST_GET 0x01
  12 +
  13 +#define SNEP_RESPONSE_SUCCESS 0x81
  14 +#define SNEP_RESPONSE_REJECT 0xFF
  15 +
  16 +class SNEP {
  17 +public:
  18 + SNEP(PN532Interface &interface) : llcp(interface) {
  19 + headerBuf = llcp.getHeaderBuffer(&headerBufLen);
  20 + };
  21 +
  22 + /**
  23 + * @brief write a SNEP packet, the packet should be less than (255 - 2 - 3) bytes
  24 + * @param buf the buffer to contain the packet
  25 + * @param len lenght of the buffer
  26 + * @param timeout max time to wait, 0 means no timeout
  27 + * @return >0 success
  28 + * =0 timeout
  29 + * <0 failed
  30 + */
  31 + int8_t write(const uint8_t *buf, uint8_t len, uint16_t timeout = 0);
  32 +
  33 + /**
  34 + * @brief read a SNEP packet, the packet will be less than (255 - 2 - 3) bytes
  35 + * @param buf the buffer to contain the packet
  36 + * @param len lenght of the buffer
  37 + * @param timeout max time to wait, 0 means no timeout
  38 + * @return >=0 length of the packet
  39 + * <0 failed
  40 + */
  41 + int16_t read(uint8_t *buf, uint8_t len, uint16_t timeout = 0);
  42 +
  43 +private:
  44 + LLCP llcp;
  45 + uint8_t *headerBuf;
  46 + uint8_t headerBufLen;
  47 +};
  48 +
  49 +#endif // __SNEP_H__
... ...
PN532_HSU/PN532_HSU.cpp 0 → 100644
... ... @@ -0,0 +1,196 @@
  1 +
  2 +#include "PN532_HSU.h"
  3 +#include "PN532_debug.h"
  4 +
  5 +
  6 +PN532_HSU::PN532_HSU(HardwareSerial &serial)
  7 +{
  8 + _serial = &serial;
  9 + command = 0;
  10 +}
  11 +
  12 +void PN532_HSU::begin()
  13 +{
  14 + _serial->begin(115200);
  15 +}
  16 +
  17 +void PN532_HSU::wakeup()
  18 +{
  19 + _serial->write(0x55);
  20 + _serial->write(0x55);
  21 + _serial->write(0);
  22 + _serial->write(0);
  23 + _serial->write(0);
  24 +
  25 + /** dump serial buffer */
  26 + if(_serial->available()){
  27 + DMSG("Dump serial buffer: ");
  28 + }
  29 + while(_serial->available()){
  30 + uint8_t ret = _serial->read();
  31 + DMSG_HEX(ret);
  32 + }
  33 +
  34 +}
  35 +
  36 +int8_t PN532_HSU::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  37 +{
  38 +
  39 + /** dump serial buffer */
  40 + if(_serial->available()){
  41 + DMSG("Dump serial buffer: ");
  42 + }
  43 + while(_serial->available()){
  44 + uint8_t ret = _serial->read();
  45 + DMSG_HEX(ret);
  46 + }
  47 +
  48 + command = header[0];
  49 +
  50 + _serial->write(PN532_PREAMBLE);
  51 + _serial->write(PN532_STARTCODE1);
  52 + _serial->write(PN532_STARTCODE2);
  53 +
  54 + uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
  55 + _serial->write(length);
  56 + _serial->write(~length + 1); // checksum of length
  57 +
  58 + _serial->write(PN532_HOSTTOPN532);
  59 + uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
  60 +
  61 + DMSG("\nWrite: ");
  62 +
  63 + _serial->write(header, hlen);
  64 + for (uint8_t i = 0; i < hlen; i++) {
  65 + sum += header[i];
  66 +
  67 + DMSG_HEX(header[i]);
  68 + }
  69 +
  70 + _serial->write(body, blen);
  71 + for (uint8_t i = 0; i < blen; i++) {
  72 + sum += body[i];
  73 +
  74 + DMSG_HEX(body[i]);
  75 + }
  76 +
  77 + uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
  78 + _serial->write(checksum);
  79 + _serial->write(PN532_POSTAMBLE);
  80 +
  81 + return readAckFrame();
  82 +}
  83 +
  84 +int16_t PN532_HSU::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
  85 +{
  86 + uint8_t tmp[3];
  87 +
  88 + DMSG("\nRead: ");
  89 +
  90 + /** Frame Preamble and Start Code */
  91 + if(receive(tmp, 3, timeout)<=0){
  92 + return PN532_TIMEOUT;
  93 + }
  94 + if(0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]){
  95 + DMSG("Preamble error");
  96 + return PN532_INVALID_FRAME;
  97 + }
  98 +
  99 + /** receive length and check */
  100 + uint8_t length[2];
  101 + if(receive(length, 2, timeout) <= 0){
  102 + return PN532_TIMEOUT;
  103 + }
  104 + if( 0 != (uint8_t)(length[0] + length[1]) ){
  105 + DMSG("Length error");
  106 + return PN532_INVALID_FRAME;
  107 + }
  108 + length[0] -= 2;
  109 + if( length[0] > len){
  110 + return PN532_NO_SPACE;
  111 + }
  112 +
  113 + /** receive command byte */
  114 + uint8_t cmd = command + 1; // response command
  115 + if(receive(tmp, 2, timeout) <= 0){
  116 + return PN532_TIMEOUT;
  117 + }
  118 + if( PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]){
  119 + DMSG("Command error");
  120 + return PN532_INVALID_FRAME;
  121 + }
  122 +
  123 + if(receive(buf, length[0], timeout) != length[0]){
  124 + return PN532_TIMEOUT;
  125 + }
  126 + uint8_t sum = PN532_PN532TOHOST + cmd;
  127 + for(uint8_t i=0; i<length[0]; i++){
  128 + sum += buf[i];
  129 + }
  130 +
  131 + /** checksum and postamble */
  132 + if(receive(tmp, 2, timeout) <= 0){
  133 + return PN532_TIMEOUT;
  134 + }
  135 + if( 0 != (uint8_t)(sum + tmp[0]) || 0 != tmp[1] ){
  136 + DMSG("Checksum error");
  137 + return PN532_INVALID_FRAME;
  138 + }
  139 +
  140 + return length[0];
  141 +}
  142 +
  143 +int8_t PN532_HSU::readAckFrame()
  144 +{
  145 + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
  146 + uint8_t ackBuf[sizeof(PN532_ACK)];
  147 +
  148 + DMSG("\nAck: ");
  149 +
  150 + if( receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0 ){
  151 + DMSG("Timeout\n");
  152 + return PN532_TIMEOUT;
  153 + }
  154 +
  155 + if( memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK)) ){
  156 + DMSG("Invalid\n");
  157 + return PN532_INVALID_ACK;
  158 + }
  159 + return 0;
  160 +}
  161 +
  162 +/**
  163 + @brief receive data .
  164 + @param buf --> return value buffer.
  165 + len --> length expect to receive.
  166 + timeout --> time of reveiving
  167 + @retval number of received bytes, 0 means no data received.
  168 +*/
  169 +int8_t PN532_HSU::receive(uint8_t *buf, int len, uint16_t timeout)
  170 +{
  171 + int read_bytes = 0;
  172 + int ret;
  173 + unsigned long start_millis;
  174 +
  175 + while (read_bytes < len) {
  176 + start_millis = millis();
  177 + do {
  178 + ret = _serial->read();
  179 + if (ret >= 0) {
  180 + break;
  181 + }
  182 + } while((timeout == 0) || ((millis()- start_millis ) < timeout));
  183 +
  184 + if (ret < 0) {
  185 + if(read_bytes){
  186 + return read_bytes;
  187 + }else{
  188 + return PN532_TIMEOUT;
  189 + }
  190 + }
  191 + buf[read_bytes] = (uint8_t)ret;
  192 + DMSG_HEX(ret);
  193 + read_bytes++;
  194 + }
  195 + return read_bytes;
  196 +}
... ...
PN532_HSU/PN532_HSU.h 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +
  2 +#ifndef __PN532_HSU_H__
  3 +#define __PN532_HSU_H__
  4 +
  5 +#include "PN532Interface.h"
  6 +#include "Arduino.h"
  7 +
  8 +#define PN532_HSU_DEBUG
  9 +
  10 +#define PN532_HSU_READ_TIMEOUT (1000)
  11 +
  12 +class PN532_HSU : public PN532Interface {
  13 +public:
  14 + PN532_HSU(HardwareSerial &serial);
  15 +
  16 + void begin();
  17 + void wakeup();
  18 + virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  19 + int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
  20 +
  21 +private:
  22 + HardwareSerial* _serial;
  23 + uint8_t command;
  24 +
  25 + int8_t readAckFrame();
  26 +
  27 + int8_t receive(uint8_t *buf, int len, uint16_t timeout=PN532_HSU_READ_TIMEOUT);
  28 +};
  29 +
  30 +#endif
... ...
PN532_I2C/PN532_I2C.cpp 0 → 100644
... ... @@ -0,0 +1,181 @@
  1 +
  2 +#include "PN532_I2C.h"
  3 +#include "PN532_debug.h"
  4 +#include "Arduino.h"
  5 +
  6 +#define PN532_I2C_ADDRESS (0x48 >> 1)
  7 +
  8 +
  9 +PN532_I2C::PN532_I2C(TwoWire &wire)
  10 +{
  11 + _wire = &wire;
  12 + command = 0;
  13 +}
  14 +
  15 +void PN532_I2C::begin()
  16 +{
  17 + _wire->begin();
  18 +}
  19 +
  20 +void PN532_I2C::wakeup()
  21 +{
  22 + _wire->beginTransmission(PN532_I2C_ADDRESS); // I2C start
  23 + delay(20);
  24 + _wire->endTransmission(); // I2C end
  25 +}
  26 +
  27 +int8_t PN532_I2C::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  28 +{
  29 + command = header[0];
  30 + _wire->beginTransmission(PN532_I2C_ADDRESS);
  31 +
  32 + write(PN532_PREAMBLE);
  33 + write(PN532_STARTCODE1);
  34 + write(PN532_STARTCODE2);
  35 +
  36 + uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
  37 + write(length);
  38 + write(~length + 1); // checksum of length
  39 +
  40 + write(PN532_HOSTTOPN532);
  41 + uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
  42 +
  43 + DMSG("write: ");
  44 +
  45 + for (uint8_t i = 0; i < hlen; i++) {
  46 + if (write(header[i])) {
  47 + sum += header[i];
  48 +
  49 + DMSG_HEX(header[i]);
  50 + } else {
  51 + DMSG("\nToo many data to send, I2C doesn't support such a big packet\n"); // I2C max packet: 32 bytes
  52 + return PN532_INVALID_FRAME;
  53 + }
  54 + }
  55 +
  56 + for (uint8_t i = 0; i < blen; i++) {
  57 + if (write(body[i])) {
  58 + sum += body[i];
  59 +
  60 + DMSG_HEX(body[i]);
  61 + } else {
  62 + DMSG("\nToo many data to send, I2C doesn't support such a big packet\n"); // I2C max packet: 32 bytes
  63 + return PN532_INVALID_FRAME;
  64 + }
  65 + }
  66 +
  67 + uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
  68 + write(checksum);
  69 + write(PN532_POSTAMBLE);
  70 +
  71 + _wire->endTransmission();
  72 +
  73 + DMSG('\n');
  74 +
  75 + return readAckFrame();
  76 +}
  77 +
  78 +int16_t PN532_I2C::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
  79 +{
  80 + uint16_t time = 0;
  81 +
  82 + do {
  83 + if (_wire->requestFrom(PN532_I2C_ADDRESS, len + 2)) {
  84 + if (read() & 1) { // check first byte --- status
  85 + break; // PN532 is ready
  86 + }
  87 + }
  88 +
  89 + delay(1);
  90 + time++;
  91 + if ((0 != timeout) && (time > timeout)) {
  92 + return -1;
  93 + }
  94 + } while (1);
  95 +
  96 + if (0x00 != read() || // PREAMBLE
  97 + 0x00 != read() || // STARTCODE1
  98 + 0xFF != read() // STARTCODE2
  99 + ) {
  100 +
  101 + return PN532_INVALID_FRAME;
  102 + }
  103 +
  104 + uint8_t length = read();
  105 + if (0 != (uint8_t)(length + read())) { // checksum of length
  106 + return PN532_INVALID_FRAME;
  107 + }
  108 +
  109 + uint8_t cmd = command + 1; // response command
  110 + if (PN532_PN532TOHOST != read() || (cmd) != read()) {
  111 + return PN532_INVALID_FRAME;
  112 + }
  113 +
  114 + length -= 2;
  115 + if (length > len) {
  116 + return PN532_NO_SPACE; // not enough space
  117 + }
  118 +
  119 + DMSG("read: ");
  120 + DMSG_HEX(cmd);
  121 +
  122 + uint8_t sum = PN532_PN532TOHOST + cmd;
  123 + for (uint8_t i = 0; i < length; i++) {
  124 + buf[i] = read();
  125 + sum += buf[i];
  126 +
  127 + DMSG_HEX(buf[i]);
  128 + }
  129 + DMSG('\n');
  130 +
  131 + uint8_t checksum = read();
  132 + if (0 != (uint8_t)(sum + checksum)) {
  133 + DMSG("checksum is not ok\n");
  134 + return PN532_INVALID_FRAME;
  135 + }
  136 + read(); // POSTAMBLE
  137 +
  138 + return length;
  139 +}
  140 +
  141 +int8_t PN532_I2C::readAckFrame()
  142 +{
  143 + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
  144 + uint8_t ackBuf[sizeof(PN532_ACK)];
  145 +
  146 + DMSG("wait for ack at : ");
  147 + DMSG(millis());
  148 + DMSG('\n');
  149 +
  150 + uint16_t time = 0;
  151 + do {
  152 + if (_wire->requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) {
  153 + if (read() & 1) { // check first byte --- status
  154 + break; // PN532 is ready
  155 + }
  156 + }
  157 +
  158 + delay(1);
  159 + time++;
  160 + if (time > PN532_ACK_WAIT_TIME) {
  161 + DMSG("Time out when waiting for ACK\n");
  162 + return PN532_TIMEOUT;
  163 + }
  164 + } while (1);
  165 +
  166 + DMSG("ready at : ");
  167 + DMSG(millis());
  168 + DMSG('\n');
  169 +
  170 +
  171 + for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
  172 + ackBuf[i] = read();
  173 + }
  174 +
  175 + if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) {
  176 + DMSG("Invalid ACK\n");
  177 + return PN532_INVALID_ACK;
  178 + }
  179 +
  180 + return 0;
  181 +}
... ...
PN532_I2C/PN532_I2C.h 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +
  2 +#ifndef __PN532_I2C_H__
  3 +#define __PN532_I2C_H__
  4 +
  5 +#include <Wire.h>
  6 +#include "PN532Interface.h"
  7 +
  8 +class PN532_I2C : public PN532Interface {
  9 +public:
  10 + PN532_I2C(TwoWire &wire);
  11 +
  12 + void begin();
  13 + void wakeup();
  14 + virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  15 + int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
  16 +
  17 +private:
  18 + TwoWire* _wire;
  19 + uint8_t command;
  20 +
  21 + int8_t readAckFrame();
  22 +
  23 + inline uint8_t write(uint8_t data) {
  24 + #if ARDUINO >= 100
  25 + return _wire->write(data);
  26 + #else
  27 + return _wire->send(data);
  28 + #endif
  29 + }
  30 +
  31 + inline uint8_t read() {
  32 + #if ARDUINO >= 100
  33 + return _wire->read();
  34 + #else
  35 + return _wire->receive();
  36 + #endif
  37 + }
  38 +};
  39 +
  40 +#endif
... ...
PN532_SPI/PN532_SPI.cpp 0 → 100644
... ... @@ -0,0 +1,217 @@
  1 +#include <util/delay.h>
  2 +#include "PN532_SPI.h"
  3 +#include "PN532_debug.h"
  4 +#include "Arduino.h"
  5 +
  6 +#define STATUS_READ 2
  7 +#define DATA_WRITE 1
  8 +#define DATA_READ 3
  9 +#define delay(a) _delay_ms(a)
  10 +
  11 +void send_serial(unsigned char);
  12 +
  13 +PN532_SPI::PN532_SPI(SPIClass &spi, uint8_t ss)
  14 +{
  15 + command = 0;
  16 + _spi = &spi;
  17 + _ss = ss;
  18 +}
  19 +
  20 +void PN532_SPI::begin()
  21 +{
  22 + pinMode(_ss, OUTPUT);
  23 +
  24 + _spi->begin();
  25 + _spi->setDataMode(SPI_MODE0); // PN532 only supports mode0
  26 + _spi->setBitOrder(LSBFIRST);
  27 +#ifndef __SAM3X8E__
  28 + _spi->setClockDivider(SPI_CLOCK_DIV8); // set clock 2MHz(max: 5MHz)
  29 +#else
  30 + /** DUE spi library does not support SPI_CLOCK_DIV8 macro */
  31 + _spi->setClockDivider(42); // set clock 2MHz(max: 5MHz)
  32 +#endif
  33 +
  34 +}
  35 +
  36 +void PN532_SPI::wakeup()
  37 +{
  38 + send_serial('Z');
  39 + digitalWrite(_ss, LOW);
  40 + send_serial('E');
  41 + delay(2);
  42 + send_serial('R');
  43 + digitalWrite(_ss, HIGH);
  44 + send_serial('T');
  45 +}
  46 +
  47 +
  48 +
  49 +int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  50 +{
  51 + command = header[0];
  52 + writeFrame(header, hlen, body, blen);
  53 +
  54 + uint8_t timeout = PN532_ACK_WAIT_TIME;
  55 + while (!isReady()) {
  56 + delay(1);
  57 + timeout--;
  58 + if (0 == timeout) {
  59 + DMSG("Time out when waiting for ACK\n");
  60 + return -2;
  61 + }
  62 + }
  63 + if (readAckFrame()) {
  64 + DMSG("Invalid ACK\n");
  65 + return PN532_INVALID_ACK;
  66 + }
  67 + return 0;
  68 +}
  69 +
  70 +int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
  71 +{
  72 + uint16_t time = 0;
  73 + while (!isReady()) {
  74 + delay(1);
  75 + time++;
  76 + if (timeout > 0 && time > timeout) {
  77 + return PN532_TIMEOUT;
  78 + }
  79 + }
  80 +
  81 + digitalWrite(_ss, LOW);
  82 + delay(1);
  83 +
  84 + int16_t result;
  85 + do {
  86 + write(DATA_READ);
  87 +
  88 + if (0x00 != read() || // PREAMBLE
  89 + 0x00 != read() || // STARTCODE1
  90 + 0xFF != read() // STARTCODE2
  91 + ) {
  92 +
  93 + result = PN532_INVALID_FRAME;
  94 + break;
  95 + }
  96 +
  97 + uint8_t length = read();
  98 + if (0 != (uint8_t)(length + read())) { // checksum of length
  99 + result = PN532_INVALID_FRAME;
  100 + break;
  101 + }
  102 +
  103 + uint8_t cmd = command + 1; // response command
  104 + if (PN532_PN532TOHOST != read() || (cmd) != read()) {
  105 + result = PN532_INVALID_FRAME;
  106 + break;
  107 + }
  108 +
  109 + DMSG("read: ");
  110 + DMSG_HEX(cmd);
  111 +
  112 + length -= 2;
  113 + if (length > len) {
  114 + for (uint8_t i = 0; i < length; i++) {
  115 + DMSG_HEX(read()); // dump message
  116 + }
  117 + DMSG("\nNot enough space\n");
  118 + read();
  119 + read();
  120 + result = PN532_NO_SPACE; // not enough space
  121 + break;
  122 + }
  123 +
  124 + uint8_t sum = PN532_PN532TOHOST + cmd;
  125 + for (uint8_t i = 0; i < length; i++) {
  126 + buf[i] = read();
  127 + sum += buf[i];
  128 +
  129 + DMSG_HEX(buf[i]);
  130 + }
  131 + DMSG('\n');
  132 +
  133 + uint8_t checksum = read();
  134 + if (0 != (uint8_t)(sum + checksum)) {
  135 + DMSG("checksum is not ok\n");
  136 + result = PN532_INVALID_FRAME;
  137 + break;
  138 + }
  139 + read(); // POSTAMBLE
  140 +
  141 + result = length;
  142 + } while (0);
  143 +
  144 + digitalWrite(_ss, HIGH);
  145 +
  146 + return result;
  147 +}
  148 +
  149 +boolean PN532_SPI::isReady()
  150 +{
  151 + digitalWrite(_ss, LOW);
  152 +
  153 + write(STATUS_READ);
  154 + uint8_t status = read() & 1;
  155 + digitalWrite(_ss, HIGH);
  156 + return status;
  157 +}
  158 +
  159 +void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
  160 +{
  161 + digitalWrite(_ss, LOW);
  162 + delay(2); // wake up PN532
  163 +
  164 + write(DATA_WRITE);
  165 + write(PN532_PREAMBLE);
  166 + write(PN532_STARTCODE1);
  167 + write(PN532_STARTCODE2);
  168 +
  169 + uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
  170 + write(length);
  171 + write(~length + 1); // checksum of length
  172 +
  173 + write(PN532_HOSTTOPN532);
  174 + uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
  175 +
  176 + DMSG("write: ");
  177 +
  178 + for (uint8_t i = 0; i < hlen; i++) {
  179 + write(header[i]);
  180 + sum += header[i];
  181 +
  182 + DMSG_HEX(header[i]);
  183 + }
  184 + for (uint8_t i = 0; i < blen; i++) {
  185 + write(body[i]);
  186 + sum += body[i];
  187 +
  188 + DMSG_HEX(body[i]);
  189 + }
  190 +
  191 + uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
  192 + write(checksum);
  193 + write(PN532_POSTAMBLE);
  194 +
  195 + digitalWrite(_ss, HIGH);
  196 +
  197 + DMSG('\n');
  198 +}
  199 +
  200 +int8_t PN532_SPI::readAckFrame()
  201 +{
  202 + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
  203 +
  204 + uint8_t ackBuf[sizeof(PN532_ACK)];
  205 +
  206 + digitalWrite(_ss, LOW);
  207 + delay(1);
  208 + write(DATA_READ);
  209 +
  210 + for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
  211 + ackBuf[i] = read();
  212 + }
  213 +
  214 + digitalWrite(_ss, HIGH);
  215 +
  216 + return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
  217 +}
... ...
PN532_SPI/PN532_SPI.h 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +
  2 +#ifndef __PN532_SPI_H__
  3 +#define __PN532_SPI_H__
  4 +
  5 +#include <SPI.h>
  6 +#include "PN532Interface.h"
  7 +
  8 +class PN532_SPI : public PN532Interface {
  9 +public:
  10 + PN532_SPI(SPIClass &spi, uint8_t ss);
  11 +
  12 + void begin();
  13 + void wakeup();
  14 + int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  15 +
  16 + int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
  17 +
  18 +private:
  19 + SPIClass* _spi;
  20 + uint8_t _ss;
  21 + uint8_t command;
  22 +
  23 + boolean isReady();
  24 + void writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
  25 + int8_t readAckFrame();
  26 +
  27 + inline void write(uint8_t data) {
  28 + _spi->transfer(data);
  29 + };
  30 +
  31 + inline uint8_t read() {
  32 + return _spi->transfer(0);
  33 + };
  34 +};
  35 +
  36 +#endif
... ...
tweekd_nfc.ino renamed to main.c
1   -#include <SPI.h>
2   -#include <PN532_SPI.h>
  1 +#include <util/delay.h>
  2 +#include <avr/io.h>
3 3 #include "PN532.h"
  4 +#include <PN532_SPI/PN532_SPI.h>
4 5  
5 6 #define MODEL_QUERY 0x80
6 7 #define SERIAL_ERROR 0x55
... ... @@ -8,9 +9,9 @@
8 9 #define NFC_TAGQUERY_UID 0x84
9 10 #define NFC_ARDUINO 0x02
10 11 #define NFC_NOTAG 0x81
11   -
12   -#define NFC_TYPE_PROFESSOR 0x00
  12 +#define NFC_TYPE_PROFESSOR 0x04
13 13 #define NFC_TYPE_STUDENT 0x01
  14 +#define CPU_FREQ 16000000L
14 15  
15 16 boolean tagDetected;
16 17 boolean tagType;
... ... @@ -18,33 +19,56 @@ boolean tagType;
18 19 PN532_SPI pn532spi(SPI, 10);
19 20 PN532 nfc(pn532spi);
20 21  
  22 +void init_serial(int speed)
  23 +{
  24 + UBRR0 = CPU_FREQ/(((unsigned long int)speed)<<4)-1;
  25 + UCSR0B = (1<<TXEN0 | 1<<RXEN0);
  26 + UCSR0C = (1<<UCSZ01 | 1<<UCSZ00);
  27 + UCSR0A &= ~(1 << U2X0);
  28 +}
  29 +
  30 +void send_serial(unsigned char c)
  31 +{
  32 + loop_until_bit_is_set(UCSR0A, UDRE0);
  33 + UDR0 = c;
  34 +}
  35 +
  36 +unsigned char get_serial(void)
  37 +{
  38 + loop_until_bit_is_set(UCSR0A, RXC0);
  39 + return UDR0;
  40 +}
  41 +
  42 +
21 43 void setup(void)
22 44 {
23 45 int ser;
24 46  
25   - Serial.begin(115200);
  47 + init_serial(9600);
26 48  
  49 + send_serial('1');
27 50 nfc.begin();
28 51  
  52 + send_serial('2');
29 53 uint32_t versiondata = nfc.getFirmwareVersion();
30 54 if(!versiondata)
31 55 {
32   - Serial.print(SERIAL_ERROR);
  56 + send_serial(SERIAL_ERROR);
33 57 while (1);
34 58 }
35 59  
  60 + send_serial('3');
36 61 nfc.SAMConfig();
37 62  
38 63 tagDetected = false;
39 64  
40 65 do
41 66 {
42   - while(!(Serial.available() > 0));
43   - ser = Serial.read();
  67 + ser = get_serial();
44 68 if(ser == MODEL_QUERY)
45   - Serial.print(NFC_ARDUINO);
  69 + send_serial(NFC_ARDUINO);
46 70 else
47   - Serial.print(SERIAL_ERROR);
  71 + send_serial(SERIAL_ERROR);
48 72 }while(ser != MODEL_QUERY);
49 73 }
50 74  
... ... @@ -56,7 +80,8 @@ void loop(void)
56 80 uint8_t uidLength;
57 81 uint8_t data1[16];
58 82 uint8_t data2[16];
59   - uint8_t dataf[8];
  83 + char professorTag[7];
  84 + char studentTag[9];
60 85 int ser;
61 86  
62 87 success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
... ... @@ -87,24 +112,24 @@ void loop(void)
87 112 data1[9] == data2[4])
88 113 {
89 114 tagType = NFC_TYPE_PROFESSOR;
90   - dataf[0] = data1[4];
91   - dataf[1] = data1[5];
92   - dataf[2] = data1[6];
93   - dataf[3] = data1[7];
94   - dataf[4] = data1[8];
95   - dataf[5] = data1[9];
  115 + professorTag[0] = (char) 48 + data1[4];
  116 + professorTag[1] = (char) 48 + data1[5];
  117 + professorTag[2] = (char) 48 + data1[6];
  118 + professorTag[3] = (char) 48 + data1[7];
  119 + professorTag[4] = (char) 48 + data1[8];
  120 + professorTag[5] = (char) 48 + data1[9];
96 121 }
97 122 else
98 123 {
99 124 tagType = NFC_TYPE_STUDENT;
100   - dataf[0] = data1[15];
101   - dataf[1] = data2[0];
102   - dataf[2] = data2[1];
103   - dataf[3] = data2[2];
104   - dataf[4] = data2[3];
105   - dataf[5] = data2[4];
106   - dataf[6] = data2[5];
107   - dataf[7] = data2[6];
  125 + studentTag[0] = (char) 48 + data1[15];
  126 + studentTag[1] = (char) 48 + data2[0];
  127 + studentTag[2] = (char) 48 + data2[1];
  128 + studentTag[3] = (char) 48 + data2[2];
  129 + studentTag[4] = (char) 48 + data2[3];
  130 + studentTag[5] = (char) 48 + data2[4];
  131 + studentTag[6] = (char) 48 + data2[5];
  132 + studentTag[7] = (char) 48 + data2[6];
108 133 }
109 134 }
110 135 }
... ... @@ -113,32 +138,53 @@ void loop(void)
113 138 }
114 139 else if(tagDetected)
115 140 {
116   - while(!(Serial.available() > 0));
117   - ser = Serial.read();
  141 + ser = get_serial();
118 142 if(ser == NFC_TAGQUERY)
119   - Serial.print(tagType);
  143 + send_serial(tagType);
120 144 else if(ser == NFC_TAGQUERY_UID)
121 145 {
122   - Serial.print((char) dataf[0]);
123   - Serial.print((char) dataf[1]);
124   - Serial.print((char) dataf[2]);
125   - Serial.print((char) dataf[3]);
126   - Serial.print((char) dataf[4]);
127   - Serial.print((char) dataf[5]);
128   - if(tagType == NFC_TYPE_STUDENT)
129   - {
130   - Serial.print((char) dataf[6]);
131   - Serial.print((char) dataf[7]);
132   - }
133   - tagDetected = false;
  146 + if(tagType == NFC_TYPE_STUDENT)
  147 + {/*
  148 + Serial.print((char) studentTag[0]);
  149 + Serial.print((char) studentTag[1]);
  150 + Serial.print((char) studentTag[2]);
  151 + Serial.print((char) studentTag[3]);
  152 + Serial.print((char) studentTag[4]);
  153 + Serial.print((char) studentTag[5]);
  154 + Serial.print((char) studentTag[6]);
  155 + Serial.print((char) studentTag[7]);*/
  156 + send_serial(0x10);
  157 + send_serial(0x20);
  158 + send_serial(0x30);
  159 + send_serial(0x40);
  160 + send_serial(0x50);
  161 + send_serial(0x60);
  162 + send_serial(0x70);
  163 + send_serial(0x80);
  164 + }
  165 + else
  166 + {
  167 + send_serial(professorTag[0]);
  168 + }
  169 + tagDetected = false;
134 170 }
135 171 else
136   - Serial.print(SERIAL_ERROR);
  172 + send_serial((char) SERIAL_ERROR);
137 173 }
138 174 else
139 175 {
140   - if(Serial.available() > 0)
141   - if(Serial.read() == NFC_TAGQUERY)
142   - Serial.print(NFC_NOTAG);
  176 + if(get_serial() == NFC_TAGQUERY)
  177 + send_serial(NFC_NOTAG);
143 178 }
144 179 }
  180 +
  181 +int main(void)
  182 +{
  183 + setup();
  184 +
  185 + while(1)
  186 + send_serial('Y');
  187 + //loop();
  188 +
  189 + return 0;
  190 +}
... ...