AppNearMe µNFC stack for the NXP PN532 chip License: You can use the stack free of charge to prototype with mbed; if you want to use the stack with your commercial product, get in touch!
Dependents: IOT_sensor_nfc AppNearMe_MuNFC_PN532_Test p2p_nfc_test NFCMoodLamp ... more
License
You can use the stack free of charge to prototype with mbed; if you want to use the stack with your commercial product, get in touch!
Revision 11:5be631376e5b, committed 2012-11-07
- Comitter:
- AppNearMe
- Date:
- Wed Nov 07 18:19:09 2012 +0000
- Parent:
- 10:2af578c635cd
- Child:
- 12:6eddbfe6b015
- Commit message:
- Updated library
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/EventCallback.cpp Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,47 @@ +/* + EventCallback.cpp + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#include "EventCallback.h" + +EventCallback::EventCallback() +{ + +} + +void EventCallback::init(void (*fn)(transaction_event_callback, void*)) +{ + fn(staticCallback, this); +} + +void EventCallback::attach(void (*fn)(NFCEvent, void*), void* arg) +{ + m_inst = NULL; + m_fn = fn; + m_arg = arg; +} + +void EventCallback::callback(transaction_event event, transaction_type type) +{ + if(m_inst) + { + m_caller(this, (NFCEvent)event); //At some point, should not cast event directly + } + else if(m_fn) + { + m_fn((NFCEvent)event, m_arg); + } +} + +/*static*/ void EventCallback::staticCallback(transaction_event event, transaction_type type, void* param) +{ + ((EventCallback*)(param))->callback(event, type); +} + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/EventCallback.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,65 @@ +/* + EventCallback.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef EVENTCALLBACK_H_ +#define EVENTCALLBACK_H_ + +#include "NFCEvent.h" + +#include "munfc/core/fwk.h" +#include "munfc/event/transaction_event.h" + +class EventCallback +{ +protected: + EventCallback(); + + void init( void (*fn)(transaction_event_callback, void*) ); //Callable by MuNFC + + void attach(void (*fn)(NFCEvent, void*), void* arg); + + template <class T> + void attach(T* inst, void (T::*member)(NFCEvent)) + { + m_fn = NULL; + m_inst = inst; + memcpy(m_pMember, (char*)&member, sizeof(member)); + m_caller = &EventCallback::memberCaller<T>; + } + + +private: + void callback(transaction_event event, transaction_type type); + + //Function + void(*m_fn)(NFCEvent, void*); + void* m_arg; + + + //Member of object instance + void* m_inst; + char m_pMember[16]; + void (*m_caller)(EventCallback*, NFCEvent); + + template <class T> + static inline void memberCaller(EventCallback* p, NFCEvent event) + { + T* inst = (T*) p->m_inst; + void (T::*member)(NFCEvent); + memcpy(&member, p->m_pMember, sizeof(member)); + (inst->*member)(event); + } + + static void staticCallback(transaction_event event, transaction_type type, void* param); + + friend class MuNFC; +}; + + + +#endif /* EVENTCALLBACK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/MuNFC.cpp Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,114 @@ +/* + MuNFC.cpp + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#include "MuNFC.h" +#include "MuNFCConfig.h" + +#include "mbed.h" +#if MUNFC_RTOS +#include "rtos/rtos.h" +#endif + +#include "munfc/core/fwk.h" +#include "munfc/event/transaction_event.h" +#include "munfc/target/target_nfctype2.h" +#include "munfc/target/target_nfctype4.h" +#include "munfc/ndef/appnearme_ndef.h" +#include "munfc/ndef/appnearme_ndef_tlv.h" + +#include <cstring> //For memcpy, strlen + +//TODO add handles in NFC stack to avoid ugly things like that +//extern DigitalIn* nfc_irq_pin_int; +extern InterruptIn* nfc_irq_pin_isr; +extern DigitalOut* nfc_cs_pin; +extern SPI* nfc_spi; + +#define SIGNAL_START 0x01 + +MuNFC::MuNFC(char appHash[16], uint32_t version, + PinName mosi, PinName miso, PinName sclk, PinName cs, PinName isr) : + /* m_irq_pin_int(isr),*/ m_irq_pin_isr(isr), m_cs_pin(cs), m_spi(mosi, miso, sclk) +#if MUNFC_RTOS + , m_pThread(NULL)//m_thread(MuNFC::staticCallback, (void*)this) +#endif +{ + //nfc_irq_pin_int = &m_irq_pin_int; + nfc_irq_pin_isr = &m_irq_pin_isr; + nfc_cs_pin = &m_cs_pin; + nfc_spi = &m_spi; + + appnearme_ndef_init(appHash, version); + m_eventCb.init(transaction_event_register_callback); + m_encodeCb.init(appnearme_ndef_register_encode_callback); + m_decodeCb.init(appnearme_ndef_register_decode_callback); +} + +MuNFC::~MuNFC() +{ + #if MUNFC_RTOS + if(m_pThread != NULL) + { + delete m_pThread; + } + #endif +} + +bool MuNFC::init() +{ + #if MUNFC_RTOS + if(m_pThread == NULL) + { + m_pThread = new Thread(MuNFC::staticCallback, (void*)this); + } + #endif + +#if NFC_CONTROLLER == PN512 + int ret = target_nfctype2_start(); +#elif NFC_CONTROLLER == PN532 + int ret = target_nfctype4_start(); +#endif + if(ret != OK) + { + return false; + } + return true; +} + +#if MUNFC_RTOS +void MuNFC::run() +{ + //Start NFC thread + m_pThread->signal_set(SIGNAL_START); +} + +void MuNFC::process() +{ + Thread::signal_wait(SIGNAL_START); + do + { + poll(-1); + } while(true); +} +#endif + +void MuNFC::poll(int timeoutMs) //TODO add Timeout +{ +#if NFC_CONTROLLER == PN512 + target_nfctype2_process(); +#elif NFC_CONTROLLER == PN532 + target_nfctype4_process(); +#endif +} + +#if MUNFC_RTOS + /*static*/ void MuNFC::staticCallback(void const* p) + { + ((MuNFC*)p)->process(); + } +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/MuNFC.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,178 @@ +/* + MuNFC.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef MUNFC_H_ +#define MUNFC_H_ + +#include "MuNFCConfig.h" + +#include <cstdint> //For uint_*t +#include <cstring> //For size_t + +using std::uint8_t; +using std::uint16_t; +using std::uint32_t; +using std::size_t; + +#include "NFCEvent.h" +#include "NdefCallback.h" +#include "EventCallback.h" +#include "TLVList.h" + +#include "mbed.h" +#if MUNFC_RTOS +#include "rtos/rtos.h" +#endif + +/** A library for embedded NFC applications using NXP's PN512/PN532 NFC transceivers. +* Visit http://www.appnearme.com/ +*/ +class MuNFC +{ +public: + + + /** Instantiate the µNFC stack for the following mobile app and using the following PN512/PN532 chip. + * @param appHash 16 chars-long hash of the corresponding mobile app + * @param version Minimum version of the mobile app to use in BCD format encoded as an uint32_t (0x01000000 is version 1.0.0.0) + * @param mosi MOSI pin of the SPI interface + * @param miso MISO pin of the SPI interface + * @param sclk SCLK pin of the SPI interface + * @param cs CS pin connected to the chip + * @param isr ISR pin connected to the chip + */ + MuNFC(char appHash[16], uint32_t version, + PinName mosi, PinName miso, PinName sclk, PinName cs, PinName isr); + + ~MuNFC(); + + /** Set Encode Callback. + * The encode callback will be called on each start of NFC transaction. + * to populate the data structure that will be transmitted to the reader + * @param fn pointer to the function to be called + * @param arg argument that will be passed to the callback + */ + inline void encode(void (*fn)(TLVList*, void*), void* arg) + { + m_encodeCb.attach(fn, arg); + } + + /** Set Encode Callback. + * The encode callback will be called on each start of NFC transaction. + * to populate the data structure that will be transmitted to the reader + * @param inst pointer to the object on which to call the member + * @param member pointer to the object's member to be called + */ + template <class T> + inline void encode(T* inst, void (T::*member)(TLVList*)) + { + m_encodeCb.attach(inst, member); + } + + /** Set Decode Callback. + * The decode callback will be called on each successful termination of NFC transaction. + * populated with the data structure that was transmitted by the reader + * @param fn pointer to the function to be called + * @param arg argument that will be passed to the callback + */ + inline void decode(void (*fn)(TLVList*, void*), void* arg) + { + m_decodeCb.attach(fn, arg); + } + + /** Set Decode Callback. + * The decode callback will be called on each successful termination of NFC transaction. + * populated with the data structure that was transmitted by the reader + * @param inst pointer to the object on which to call the member + * @param member pointer to the object's member to be called + */ + template <class T> + inline void decode(T* inst, void (T::*member)(TLVList*)) + { + m_decodeCb.attach(inst, member); + } + + /** Set Event Callback. + * The event callback will be called on each of the following event: + * - Transaction started + * - Transaction successful + * - Transaction failed + * @param fn pointer to the function to be called + * @param arg argument that will be passed to the callback + */ + inline void event(void (*fn)(NFCEvent, void*), void* arg) + { + m_eventCb.attach(fn, arg); + } + + /** Set Event Callback. + * The event callback will be called on each of the following event: + * - Transaction started + * - Transaction successful + * - Transaction failed + * @param fn pointer to the function to be called + * @param arg argument that will be passed to the callback + */ + template <class T> + inline void event(T* inst, void (T::*member)(NFCEvent)) + { + m_eventCb.attach(inst, member); + } + + /** Initialize stack. + * @return true if stack was initialized correctly, false otherwise + */ + bool init(); + +//#if MUNFC_RTOS -- flags must be disabled for proper doxygen support + /** Start NFC thread (threaded mode) + * + */ + void run(); +//#endif + +#if MUNFC_RTOS +protected: + /** NFC Thread + * + */ + void process(); +#endif + +#if MUNFC_RTOS + protected: +#else + public: +#endif + /** Poll for NFC reader (polling mode). + * @param timeoutMs (maximum polling time) + */ + void poll(int timeoutMs); + +private: +#if MUNFC_RTOS + static void staticCallback(void const* p); +#endif + + NdefCallback m_encodeCb; + NdefCallback m_decodeCb; + EventCallback m_eventCb; + + //DigitalIn m_irq_pin_int; + InterruptIn m_irq_pin_isr; + DigitalOut m_cs_pin; + SPI m_spi; + +#if MUNFC_RTOS + Thread* m_pThread; +#endif + +}; + + +#endif /* MUNFC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/MuNFCMbedPlatform.cpp Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,337 @@ +/* + MuNFCMbedPlatform.cpp + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ + */ + +#include "mbed.h" + +#include "MuNFCConfig.h" +#include "munfc/nfc_config.h" + +#if MUNFC_RTOS +#include "rtos/rtos.h" +#endif + +InterruptIn* nfc_irq_pin_isr; +DigitalOut* nfc_cs_pin; +SPI* nfc_spi; + +extern "C" +{ +#if NFC_CONTROLLER == PN512 +#include "munfc/platform/pn512_platform.h" +#elif NFC_CONTROLLER == PN532 +#include "munfc/platform/pn532_platform.h" +#endif +#include "munfc/platform/rtos.h" + +#if NFC_CONTROLLER == PN512 +void pn512_io_init() +{ + nfc_irq_pin_isr->rise(pn512_irq); + *nfc_cs_pin = 1; +} + +/* + * Get the IRQ pin's state + */ +bool pn512_irq_pin_get() +{ + //return (nfc_irq_pin_int->read() ? true : false); + return (nfc_irq_pin_isr->read() ? true : false); +} + +/* + * Set the CS pin to 0 (active low) + */ +void pn512_cs_set() +{ + *nfc_cs_pin = 0; +} + +/* + * Set the CS pin to 1 (active high) + */ +void pn512_cs_clear() +{ + *nfc_cs_pin = 1; +} + +/* + * You MUST call pn512_irq() on each raising front of IRQ pin + */ +#endif + +#if NFC_CONTROLLER == PN532 +/* + * Init + */ +void pn532_io_init(void) +{ + nfc_irq_pin_isr->mode(PullUp); + nfc_irq_pin_isr->fall(pn532_irq); + *nfc_cs_pin = 1; +} + +/* + * Get the IRQ pin's state + */ +bool pn532_irq_pin_get(void) +{ + return (nfc_irq_pin_isr->read() ? false : true); +} + +/* + * Set the CS pin to 0 (active low) + */ +void pn532_cs_set(void) +{ + *nfc_cs_pin = 0; +} + +/* + * Set the CS pin to 1 (active high) + */ +void pn532_cs_clear(void) +{ + *nfc_cs_pin = 1; +} + +/* + * You MUST call pn532_irq() on each falling front of IRQ pin + */ +#endif + +#if MUNFC_RTOS +struct rtos_semaphore //To be defined by impl +{ + Semaphore* s; +}; + +struct rtos_semaphore* rtos_semaphore_new() //Should return NULL if fails +{ + struct rtos_semaphore* pSem; + pSem = new struct rtos_semaphore; + pSem->s = new Semaphore(1); + pSem->s->wait(osWaitForever); + return pSem; +} + +int rtos_semaphore_produce(struct rtos_semaphore* pSem) +{ + pSem->s->release(); + return OK; +} + +int rtos_semaphore_consume(struct rtos_semaphore* pSem, int timeout) +{ + int resid; + if(timeout == -1) + { + resid = pSem->s->wait(osWaitForever); + } + else + { + resid = pSem->s->wait(timeout); + } + if(resid>0) + { + while( pSem->s->wait(0) > 0 ); + return OK; + } + else + { + return ERR_TIMEOUT; + } +} +#else +struct rtos_semaphore //To be defined by impl +{ + volatile int p; +}; + +struct rtos_semaphore* rtos_semaphore_new() //Should return NULL if fails +{ + struct rtos_semaphore* pSem; + pSem = new struct rtos_semaphore; + pSem->p = 1; + return pSem; +} + +//Will only be called from ISR +int rtos_semaphore_produce(struct rtos_semaphore* pSem) +{ + pSem->p++; + return OK; +} + +void ___voidf(void) +{ + +} + +int rtos_semaphore_consume(struct rtos_semaphore* pSem, int timeout) +{ + if(timeout == -1) + { + while(!pSem->p) + { + __WFI(); + } + pSem->p--; + } + else if(timeout == 0) + { + if(pSem->p) + { + pSem->p--; + } + else + { + return ERR_TIMEOUT; + } + } + else + { + Timer t; + t.start(); + Ticker t_isr; + t_isr.attach_us(&___voidf, 1000); //Just to generate an interrupt periodically + while(!pSem->p) + { + __WFI(); + if(t.read_ms()>=timeout) + { + return ERR_TIMEOUT; + } + } + pSem->p--; + } + return OK; +} +#endif + + +//These functions must be implemented for each platform + +#if NFC_CONTROLLER == PN512 +/* + * Initialize SPI + */ +int pn512_spi_init() +{ + nfc_spi->format(8, 3); + nfc_spi->frequency(10000000); //To change to 10000000 + return 0; +} +#endif + +#if NFC_CONTROLLER == PN532 +/* + * Initialize SPI + */ +int pn532_spi_init() +{ + nfc_spi->format(8, 0); + nfc_spi->frequency(5000000); + return 0; +} +#endif + +#define reverse(x) ( (x & 0x01) << 7 \ + | (x & 0x02) << 5 \ + | (x & 0x04) << 3 \ + | (x & 0x08) << 1 \ + | (x & 0x10) >> 1 \ + | (x & 0x20) >> 3 \ + | (x & 0x40) >> 5 \ + | (x & 0x80) >> 7 ) + +/* + * After skipping outSkip bytes, write outLen bytes + * After skipping inSkip bytes, read inLen bytes + * This will generate MAX(outSkip + outLen, inSkip + inLen) transfers on the SPI bus + */ +int spi_transfer(uint8_t* outBuf, size_t outLen, size_t outSkip, uint8_t* inBuf, + size_t inLen, size_t inSkip) +{ + int len; + int writeb; + int readb; + int outPos; + int inPos; + + outPos = inPos = 0; + + len = + (outSkip + outLen) > (inSkip + inLen) ? (outSkip + outLen) : + (inSkip + inLen); + + while (len--) + { + if (outSkip) + { + writeb = 0x00; + outSkip--; + } + else if (outPos < outLen) + { + writeb = outBuf[outPos]; + outPos++; + } + else + { + writeb = 0x00; + } + +#if NFC_CONTROLLER == PN532 + writeb = reverse(writeb); +#endif + + readb = nfc_spi->write(writeb); + +#if NFC_CONTROLLER == PN532 + readb = reverse(readb); +#endif + + if (inSkip) + { + inSkip--; + } + else if (inPos < inLen) + { + inBuf[inPos] = readb; + inPos++; + } + } + return 0; +} + +/* + * Write outLen bytes + */ +int spi_write(uint8_t* outBuf, size_t outLen) +{ + return spi_transfer(outBuf, outLen, 0, (uint8_t*) NULL, 0, 0); +} + +/* + * Read inLen bytes + */ +int spi_read(uint8_t* inBuf, size_t inLen) +{ + return spi_transfer((uint8_t*) NULL, 0, 0, inBuf, inLen, 0); +} + +/* + * Skip len bytes + */ +int spi_skip(size_t len) +{ + return spi_transfer((uint8_t*) NULL, 0, len, (uint8_t*) NULL, 0, len); +} + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/NFCEvent.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,25 @@ +/* + NFCEvent.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +/** \file NFCEvent.h +* NFC-related events +*/ + +#ifndef NFCEVENT_H_ +#define NFCEVENT_H_ + +/** NFC-related events + * + */ +enum NFCEvent +{ + NFC_TRANSACTION_STARTED, //!< Transaction with reader started (anticollision successful) + NFC_TRANSACTION_SUCCESSFUL, //!< Transaction with reader successful + NFC_TRANSACTION_FAILED //!< Transaction with reader failed +}; + +#endif /* NFCEVENT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/NdefCallback.cpp Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,46 @@ +/* + NdefCallback.cpp + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#include "NdefCallback.h" +#include "TLVList.h" + +NdefCallback::NdefCallback() +{ + +} + +void NdefCallback::init(void (*fn)(appnearme_ndef_callback, void*)) +{ + fn(staticCallback, this); +} + +void NdefCallback::attach(void (*fn)(TLVList*, void*), void* arg) +{ + m_inst = NULL; + m_fn = fn; + m_arg = arg; +} + +void NdefCallback::callback(tlv_list* payload) +{ + m_tlvList.wrap(payload); + if(m_inst) + { + m_caller(this, &m_tlvList); + } + else if(m_fn) + { + m_fn(&m_tlvList, m_arg); + } +} + +/*static*/ void NdefCallback::staticCallback(tlv_list* payload, void* param) +{ + ((NdefCallback*)(param))->callback(payload); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/NdefCallback.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,65 @@ +/* + NdefCallback.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef NDEFCALLBACK_H_ +#define NDEFCALLBACK_H_ + +#include "TLVList.h" + +#include "munfc/core/fwk.h" +#include "munfc/ndef/appnearme_ndef.h" + +class NdefCallback +{ +protected: + NdefCallback(); //Callable by MuNFC + + void init(void (*fn)(appnearme_ndef_callback, void*)); + + void attach(void (*fn)(TLVList*, void*), void* arg); + + template <class T> + void attach(T* inst, void (T::*member)(TLVList*)) + { + m_fn = NULL; + m_inst = inst; + memcpy(m_pMember, (char*)&member, sizeof(member)); + m_caller = &NdefCallback::memberCaller<T>; + } + +private: + void callback(tlv_list* payload); + + //Data + TLVList m_tlvList; + + //Function + void(*m_fn)(TLVList*, void*); + void* m_arg; + + //Member of object instance + void* m_inst; + char m_pMember[16]; + void (*m_caller)(NdefCallback*, TLVList*); + + template <class T> + static inline void memberCaller(NdefCallback* p, TLVList* tlvList) + { + T* inst = (T*) (p->m_inst); + void (T::*member)(TLVList*); + memcpy(&member, p->m_pMember, sizeof(member)); + (inst->*member)(tlvList); + } + + static void staticCallback(tlv_list* payload, void* param); + + friend class MuNFC; +}; + + +#endif /* NDEFCALLBACK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/TLVList.cpp Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,246 @@ +/* + TLVList.cpp + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#include "TLVList.h" + +#include "munfc/core/fwk.h" +#include "munfc/ndef/appnearme_ndef_tlv.h" + +#include <cstring> //For memcpy, strlen +using std::memcpy; +using std::strlen; + +TLVList::TLVList() : m_tlvList(NULL) +{ + +} + +void TLVList::wrap(tlv_list* payload) +{ + m_tlvList = payload; + m_space = true; + m_type = NONE; +} + + + +/* Getters */ + +/** Iterate to next item + * @return type if next item exists, NONE otherwise + */ +TLVList::TLVType TLVList::getNext() +{ + if(!m_tlvList) + { + return NONE; + } + + m_type = (TLVList::TLVType) appnearme_ndef_tlv_next_type(m_tlvList); //Explicit cast, this is the same enum + switch(m_type) + { + case UINT8: + m_arrayLen = 0; + m_uint8 = appnearme_ndef_tlv_get_uint8(m_tlvList); + break; + case UINT32: + m_arrayLen = 0; + m_uint32 = appnearme_ndef_tlv_get_uint32(m_tlvList); + break; + case UINT8_ARRAY: + //In this order, otherwise would break state-machine + m_arrayLen = appnearme_ndef_tlv_get_array_length(m_tlvList); + m_array = appnearme_ndef_tlv_get_array(m_tlvList); + break; + case STRING: + //In this order, otherwise would break state-machine + m_strLen = appnearme_ndef_tlv_get_string_length(m_tlvList); + m_str = appnearme_ndef_tlv_get_string(m_tlvList); + break; + } + return m_type; +} + +/** Get current item's type. +* @return type if item exists, NONE otherwise +*/ +TLVList::TLVType TLVList::getType() +{ + return m_type; +} + +/** Get uint8_t value + * If the current item's type is uint32_t, the value will be masked with 0xFF + * @return uint8_t value OR 0 if the type is incompatible + */ +uint8_t TLVList::getUInt8() +{ + switch(m_type) + { + case UINT8: + return m_uint8; + case UINT32: + return m_uint32 & 0xFF; + default: + return 0; + } +} + +/** Get uint32_t value + * If the current item's type is uint8_t, the value will be casted to uint32_t + * @return uint32_t value OR 0 if the type is incompatible + */ +uint32_t TLVList::getUInt32() +{ + switch(m_type) + { + case UINT32: + return m_uint32; + case UINT8: + return m_uint8 & 0xFF; + default: + return 0; + } +} + +/** Get array length + * @return bytes array length + */ +size_t TLVList::getArrayLength() +{ + switch(m_type) + { + case UINT8_ARRAY: + return m_arrayLen; + default: + return 0; + } +} + +/** Get array + * @param buf pointer to buffer's start + * @param maxLen maximum number of bytes to copy + * @return number of copied bytes + */ +size_t TLVList::getArray(uint8_t* buf, size_t maxLen) +{ + if(m_type != UINT8_ARRAY) + { + return 0; + } + size_t len = MIN(maxLen, m_arrayLen); + memcpy(buf, m_array, len); + return len; +} + +/** Get string length + * @return string length + */ +size_t TLVList::getStringLength() +{ + switch(m_type) + { + case STRING: + return m_strLen; + default: + return 0; + } +} + + +/** Get string + * Copy string to buffer (including null-terminating char) + * @param str pointer to string's start + * @param maxLen maximum number of chars to copy (not including null-terminating char) + * @return number of copied chars + */ +size_t TLVList::getString(char* str, size_t maxLen) +{ + if(m_type != STRING) + { + return 0; + } + size_t len = MIN(maxLen, m_strLen); + memcpy(str, m_str, len); + str[len] = '\0'; //Add null-terminating char + return len; +} + +/* Setters */ + +/** Check whether there is space left in list + * @return true if there is space left, false otherwise + */ +bool TLVList::isSpace() +{ + return m_space; +} + +/** Put uint8_t value + * @param value uint8_t value + * @return true on success, false if there is not enough space in buffer + */ +bool TLVList::putUInt8(uint8_t value) +{ + int res = appnearme_ndef_tlv_put_uint8(m_tlvList, value); + if( !res ) + { + m_space = false; + return false; + } + return true; +} + +/** Put uint32_t value + * @param value uint32_t value + * @return true on success, false if there is not enough space in buffer + */ +bool TLVList::putUInt32(uint32_t value) +{ + int res = appnearme_ndef_tlv_put_uint32(m_tlvList, value); + if( !res ) + { + m_space = false; + return false; + } + return true; +} + +/** Put array + * @param buf pointer to buffer's start + * @param len number of bytes to copy + * @return number of copied bytes + */ +size_t TLVList::putArray(uint8_t* buf, size_t len) +{ + int res = appnearme_ndef_tlv_put_array(m_tlvList, buf, len); + if( !res ) + { + m_space = false; + return 0; + } + return len; +} + +/** Put string + * @param str pointer to null-terminated string's start + * @return number of copied bytes + */ +size_t TLVList::putString(char* str) +{ + int res = appnearme_ndef_tlv_put_string(m_tlvList, str); + if( !res ) + { + m_space = false; + return 0; + } + return strlen(str); +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/TLVList.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,162 @@ +/* + TLVList.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +/** \file TLVList.h +* List of Type/Length/Values items +*/ + +#ifndef TLVLIST_H_ +#define TLVLIST_H_ + +#include <cstdint> //For uint_*t +#include <cstring> //For size_t + +using std::uint8_t; +using std::uint16_t; +using std::uint32_t; +using std::size_t; + +typedef struct __tlv_list tlv_list; + +/** A simple container +* List of Type/Length/Values items +*/ +class TLVList +{ +public: + + //getNext... + //get() + //put() + + + //typedef tlv_type TLVType; + /** Type of a TLV item + * + */ + enum TLVType + { + UINT8, //!< Unsigned char (byte) + UINT32, //!< Unsigned int + UINT8_ARRAY, ///< Byte array + STRING, //!<String + NONE, //!<End of packet + UNKNOWN //!< Unknown type + }; + + /* Getters */ + + /** Iterate to next item. + * @return type if next item exists, NONE otherwise + */ + TLVType getNext(); + + /** Get current item's type. + * @return type if item exists, NONE otherwise + */ + TLVType getType(); + + /** Get uint8_t value. + * If the current item's type is uint32_t, the value will be masked with 0xFF. + * @return uint8_t value OR 0 if the type is incompatible + */ + uint8_t getUInt8(); + + /** Get uint32_t value. + * If the current item's type is uint8_t, the value will be casted to uint32_t. + * @return uint32_t value OR 0 if the type is incompatible + */ + uint32_t getUInt32(); + + /** Get array length. + * @return bytes array length + */ + size_t getArrayLength(); + + /** Get array. + * @param buf pointer to buffer's start + * @param maxLen maximum number of bytes to copy + * @return number of copied bytes + */ + size_t getArray(uint8_t* buf, size_t maxLen); + + /** Get string length. + * @return string length + */ + size_t getStringLength(); + + /** Get string. + * Copy string to buffer (including null-terminating char). + * @param str pointer to string's start + * @param maxLen maximum number of chars to copy (not including null-terminating char) + * @return number of copied chars + */ + size_t getString(char* str, size_t maxLen); + + /* Setters */ + + /** Check whether there is space left in list. + * @return true if there is space left, false otherwise + */ + bool isSpace(); + + /** Put uint8_t value. + * @param value uint8_t value + * @return true on success, false if there is not enough space in buffer + */ + bool putUInt8(uint8_t value); + + /** Put uint32_t value. + * @param value uint32_t value + * @return true on success, false if there is not enough space in buffer + */ + bool putUInt32(uint32_t value); + + /** Put array. + * @param buf pointer to buffer's start + * @param len number of bytes to copy + * @return number of copied bytes + */ + size_t putArray(uint8_t* buf, size_t len); + + /** Put string. + * @param str pointer to null-terminated string's start + * @return number of copied bytes + */ + size_t putString(char* str); + +protected: + TLVList(); + + void wrap(tlv_list* payload); + +private: + tlv_list* m_tlvList; + + TLVType m_type; + + union + { + uint8_t m_uint8; + uint32_t m_uint32; + uint8_t* m_array; + char* m_str; + }; + + union + { + size_t m_arrayLen; + size_t m_strLen; + }; + + bool m_space; + + friend class NdefCallback; +}; + + +#endif /* TLVLIST_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/core/buffer.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,86 @@ +/* + buffer.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#ifndef BUFFER_H_ +#define BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" + +typedef struct __buffer +{ + uint8_t* bufdata; + size_t size; + + uint8_t* start; + size_t first_byte_length; //In bits + + uint8_t* end; + size_t last_byte_length; //In bits + + struct __buffer* next; + +} buffer; + +void buffer_init(buffer* pBuf, uint8_t* bufdata, size_t size); + +void buffer_byref(buffer* pBuf, uint8_t* bufdata, size_t length); //New buffer by ref on a size_t array, no malloc (useful on PIC for instance) + +buffer* buffer_new(size_t size); //malloc + +uint8_t* buffer_data(buffer* pBuf); + +void buffer_reset(buffer* pBuf); + +size_t buffer_size(buffer* pBuf); + +size_t buffer_length(buffer* pBuf); + +bool buffer_empty(buffer* pBuf); + +void buffer_set_length(buffer* pBuf, size_t length); + +size_t buffer_last_byte_length(buffer* pBuf); + +void buffer_set_last_byte_length(buffer* pBuf, size_t length); + +size_t buffer_bits_count(buffer* pBuf); + +void buffer_write_byte(buffer* pBuf, uint8_t b); + +void buffer_write_bit(buffer* pBuf, uint8_t b); + +#if 0 +size_t buffer_read_byte(buffer* pBuf, uint8_t b); + +size_t buffer_read_bit(buffer* pBuf, uint8_t b); +#endif + +buffer* buffer_next(buffer* pBuf); + +void buffer_set_next(buffer* pBuf, buffer* pNextBuf); + +void buffer_append(buffer* pBuf, buffer* pAppBuf); + +void buffer_unlink(buffer* pBuf, buffer* pLinkedBuf); + +size_t buffer_total_size(buffer* pBuf); + +size_t buffer_total_length(buffer* pBuf); + +void buffer_set_total_length(buffer* pBuf, size_t length); + +void buffer_free(buffer* pBuf); + +#ifdef __cplusplus +} +#endif + +#endif /* BUFFER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/core/debug.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,67 @@ +/* + debug.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#ifndef DEBUG_H_ +#define DEBUG_H_ + +#include "core/fwk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !DEBUG_DISABLED + +void debug(int level, const char* module, int line, const char* fmt, ...); +void debugx_enter(void); +void debugx(const char* fmt, ...); +void debugx_leave(void); + +#else +#ifdef __DEBUG__ +#undef __DEBUG__ +#define __DEBUG__ 0 +#endif + +#endif + +#if __DEBUG__ > 0 +#ifndef __MODULE__ +#error "__MODULE__ must be defined" +#endif +#endif + +#if __DEBUG__ >= 1 +#define ERR(...) do{ debug(1, __MODULE__, __LINE__, __VA_ARGS__); }while(0) +#else +#define ERR(...) +#endif + +#if __DEBUG__ >= 2 +#define WARN(...) do{ debug(2, __MODULE__, __LINE__, __VA_ARGS__); }while(0) +#else +#define WARN(...) +#endif + +#if __DEBUG__ >= 3 +#define DBG(...) do{ debug(3, __MODULE__, __LINE__, __VA_ARGS__); }while(0) +#define DBGX_ENTER() do{ debugx_enter(); }while(0); +#define DBGX(...) do{ debugx(__VA_ARGS__); }while(0) +#define DBGX_LEAVE() do{ debugx_leave(); }while(0); +#else +#define DBG(...) +#define DBGX_ENTER() +#define DBGX(...) +#define DBGX_LEAVE() +#endif + +#ifdef __cplusplus +} +#endif + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/core/errors.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,30 @@ +/* + errors.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#ifndef ERRORS_H_ +#define ERRORS_H_ + +#define OK 0 //No error + +#define ERR_UNKNOWN 1 +#define ERR_LENGTH 2 +#define ERR_NOT_FOUND 3 +#define ERR_UNSUPPORTED 4 +#define ERR_PARAMS 5 +#define ERR_BUFFER_TOO_SMALL 6 +#define ERR_TIMEOUT 7 +#define ERR_CRC 8 +#define ERR_NOCARD 9 +#define ERR_PARITY 10 +#define ERR_FIELD 11 //Lost RF field +#define ERR_COLLISION 12 +#define ERR_WRONG_COMM 13 +#define ERR_PROTOCOL 14 //Protocol is not conformant +#define ERR_BUSY 15 +#define ERR_CONTROLLER 16 //Controller failure + +#endif /* ERRORS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/core/fwk.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,51 @@ +/* + fwk.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef FWK_H_ +#define FWK_H_ + +#include "nfc_config.h" + +//Standard types definition +#include "stdint.h" + +#include "stddef.h" + +//Definition of size_t on 32-bit arch +#if !defined (__SIZE_TYPE__) +typedef uint32_t size_t; +#endif + +#ifndef __cplusplus +typedef uint8_t bool; //Define boolean type for pure-C functions +#define true 1 +#define false 0 +#endif + +//NULL pointer definition +#ifndef NULL +#define NULL ((void*)0) +#endif + +//Error codes +#include "errors.h" + +//RTOS abstraction +#include "platform/rtos.h" + +//Debugging +#include "debug.h" + +//Buffer +#include "buffer.h" + +//Macros +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#endif /* FWK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/drv/pn532/pn532.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,25 @@ +/* + pn532.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef PN532_H_ +#define PN532_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * To be called on each interrupt + */ +void pn532_irq(void); + +#ifdef __cplusplus +} +#endif + +#endif /* PN532_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/ndef/appnearme_ndef.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,39 @@ +/* + appnearme_ndef.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef APPNEARME_NDEF_H_ +#define APPNEARME_NDEF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" +#include "core/buffer.h" + +#include "appnearme_ndef_tlv.h" + +#define APPNEARME_HASH_SIZE 16 + +typedef void (*appnearme_ndef_callback)(tlv_list* payload, void* param); + +int appnearme_ndef_init(char app_hash[APPNEARME_HASH_SIZE], uint32_t version); + +void appnearme_ndef_register_encode_callback(appnearme_ndef_callback cb, void* param); + +void appnearme_ndef_register_decode_callback(appnearme_ndef_callback cb, void* param); + +int appnearme_ndef_encode_message(buffer* pMem); + +int appnearme_ndef_decode_message(buffer* pMem); + +#ifdef __cplusplus +} +#endif + +#endif /* APPNEARME_NDEF_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/ndef/appnearme_ndef_tlv.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,63 @@ +/* + appnearme_ndef_tlv.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#ifndef APPNEARME_NDEF_TLV_H_ +#define APPNEARME_NDEF_TLV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" +#include "core/buffer.h" + +typedef enum __tlv_type +{ + UINT8, + UINT32, + UINT8_ARRAY, + STRING, + NONE, //End of packet + UNKNOWN +} tlv_type; + +typedef struct __tlv_list +{ + buffer* buf; + size_t pos; + //bool writer_nreader; +} tlv_list; + +void appnearme_ndef_tlv_byref(tlv_list* pList, buffer* pBuf/*, bool writer_nreader*/); + +tlv_type appnearme_ndef_tlv_next_type(tlv_list* pList); + +uint8_t appnearme_ndef_tlv_get_uint8(tlv_list* pList); + +uint32_t appnearme_ndef_tlv_get_uint32(tlv_list* pList); + +size_t appnearme_ndef_tlv_get_array_length(tlv_list* pList); + +uint8_t* appnearme_ndef_tlv_get_array(tlv_list* pList); + +size_t appnearme_ndef_tlv_get_string_length(tlv_list* pList); + +char* appnearme_ndef_tlv_get_string(tlv_list* pList); + +int appnearme_ndef_tlv_put_uint8(tlv_list* pList, uint8_t b); //-1 if no space left + +int appnearme_ndef_tlv_put_uint32(tlv_list* pList, uint32_t b); + +int appnearme_ndef_tlv_put_array(tlv_list* pList, uint8_t* data, size_t len); + +int appnearme_ndef_tlv_put_string(tlv_list* pList, char* str); + +#ifdef __cplusplus +} +#endif + +#endif /* APPNEARME_NDEF_TLV_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/nfc_config.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,21 @@ +/* + nfc_config.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef NFC_CONFIG_H_ +#define NFC_CONFIG_H_ + +#define PN512 1 +#define PN532 2 + +#define DEBUG_DISABLED 0 +#define TARGET_HW_ANTICOLLISION 1 +//#define NFC_CONTROLLER PN532 //In Makefile +//#define APPNEARME_HASH "00000001aZSe2vF5" +//#define APPNEARME_VERSION 0x01000000 + +#endif /* NFC_CONFIG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/platform/pn532_platform.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,53 @@ +/* + pn532_platform.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef PN532_PLATFORM_H_ +#define PN532_PLATFORM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" + +#include "drv/pn532/pn532.h" + +/* + * Initialize SPI + */ +int pn532_spi_init(void); + +/* + * Init + */ +void pn532_io_init(void); + +/* + * Get the IRQ pin's state + */ +bool pn532_irq_pin_get(void); + +/* + * Set the CS pin to 0 (active low) + */ +void pn532_cs_set(void); + +/* + * Set the CS pin to 1 (active high) + */ +void pn532_cs_clear(void); + +/* + * You MUST call pn532_irq() on each falling front of IRQ pin + */ + +#ifdef __cplusplus +} +#endif + +#endif /* PN532_PLATFORM_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/platform/rtos.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,30 @@ +/* + rtos.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + + +#ifndef RTOS_H_ +#define RTOS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" + +struct rtos_semaphore; //To be defined by impl +typedef struct rtos_semaphore rtos_semaphore_t; + +rtos_semaphore_t* rtos_semaphore_new(void); //Should return NULL if fails + +int rtos_semaphore_produce(rtos_semaphore_t* pSem); +int rtos_semaphore_consume(rtos_semaphore_t* pSem, int timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* RTOS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PN532/munfc/platform/spi.h Wed Nov 07 18:19:09 2012 +0000 @@ -0,0 +1,45 @@ +/* + spi.h + Copyright (c) Donatien Garnier 2012 + donatien.garnier@appnearme.com + http://www.appnearme.com/ +*/ + +#ifndef SPI_H_ +#define SPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "core/fwk.h" + +//These functions must be implemented for each platform + +/* + * After skipping outSkip bytes, write outLen bytes + * After skipping inSkip bytes, read inLen bytes + * This will generate MAX(outSkip + outLen, inSkip + inLen) transfers on the SPI bus + */ +int spi_transfer( uint8_t* outBuf, size_t outLen, size_t outSkip, uint8_t* inBuf, size_t inLen, size_t inSkip ); + +/* + * Write outLen bytes + */ +int spi_write( uint8_t* outBuf, size_t outLen ); + +/* + * Read inLen bytes + */ +int spi_read( uint8_t* inBuf, size_t inLen ); + +/* + * Skip len bytes + */ +int spi_skip( size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* SPI_H_ */