Astyle formatting

pull/7822/head
Donatien Garnier 2018-08-21 15:19:51 +01:00
parent ce39e77f3d
commit 0e2484f7f3
74 changed files with 5018 additions and 5438 deletions

View File

@ -37,11 +37,10 @@ extern "C" {
#include "stddef.h" #include "stddef.h"
#include "stdbool.h" #include "stdbool.h"
typedef struct __ac_buffer typedef struct __ac_buffer {
{ const uint8_t *data;
const uint8_t* data; size_t size;
size_t size; struct __ac_buffer *pNext;
struct __ac_buffer* pNext;
} ac_buffer_t; } ac_buffer_t;
/** Initialize ac_buffer using underlying byte array, set ac_buffer's length to 0 (empty) /** Initialize ac_buffer using underlying byte array, set ac_buffer's length to 0 (empty)
@ -49,66 +48,66 @@ typedef struct __ac_buffer
* \param data byte array to use * \param data byte array to use
* \param size size of byte array * \param size size of byte array
*/ */
void ac_buffer_init(ac_buffer_t* pBuf, const uint8_t* data, size_t size); void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size);
/** Copy pBufIn to pBuf /** Copy pBufIn to pBuf
* \param pBuf pointer to ac_buffer_t structure to initialize * \param pBuf pointer to ac_buffer_t structure to initialize
* \param pBufIn the source buffer * \param pBufIn the source buffer
*/ */
void ac_buffer_dup(ac_buffer_t* pBuf, const ac_buffer_t* pBufIn); void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn);
/** Get buffer's underlying byte array /** Get buffer's underlying byte array
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
* \return underlying array * \return underlying array
*/ */
static inline const uint8_t* ac_buffer_data(const ac_buffer_t* pBuf) static inline const uint8_t *ac_buffer_data(const ac_buffer_t *pBuf)
{ {
return pBuf->data; return pBuf->data;
} }
/** Get buffer's size /** Get buffer's size
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
* \return buffer's size * \return buffer's size
*/ */
static inline size_t ac_buffer_size(const ac_buffer_t* pBuf) static inline size_t ac_buffer_size(const ac_buffer_t *pBuf)
{ {
return pBuf->size; return pBuf->size;
} }
/** Get next buffer in chain /** Get next buffer in chain
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
* \return pointer to next buffer * \return pointer to next buffer
*/ */
static inline ac_buffer_t* ac_buffer_next(const ac_buffer_t* pBuf) static inline ac_buffer_t *ac_buffer_next(const ac_buffer_t *pBuf)
{ {
return pBuf->pNext; return pBuf->pNext;
} }
/** Set next buffer in chain /** Set next buffer in chain
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
* \param pNextBuf pointer to next buffer (or NULL to break chain) * \param pNextBuf pointer to next buffer (or NULL to break chain)
*/ */
static inline void ac_buffer_set_next(ac_buffer_t* pBuf, ac_buffer_t* pNextBuf) static inline void ac_buffer_set_next(ac_buffer_t *pBuf, ac_buffer_t *pNextBuf)
{ {
pBuf->pNext = (ac_buffer_t*) pNextBuf; pBuf->pNext = (ac_buffer_t *) pNextBuf;
} }
/** Append buffer to end of chain /** Append buffer to end of chain
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
* \param pAppBuf pointer to buffer to append to chain * \param pAppBuf pointer to buffer to append to chain
*/ */
void ac_buffer_append(ac_buffer_t* pBuf, ac_buffer_t* pAppBuf); void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf);
/** Truncate pBuf to length bytes and save the remaining bytes in pEndBuf /** Truncate pBuf to length bytes and save the remaining bytes in pEndBuf
* \param pBuf The buffer to split (will be set to invalid state) * \param pBuf The buffer to split (will be set to invalid state)
* \param pStartBuf A new buffer at the head of the split * \param pStartBuf A new buffer at the head of the split
* \param pEndBuf A new buffer at the tail of the split * \param pEndBuf A new buffer at the tail of the split
* \param length How long pStartBuf should be (if longer than pBuf, then pStartBuf will be pBuf) * \param length How long pStartBuf should be (if longer than pBuf, then pStartBuf will be pBuf)
*/ */
void ac_buffer_split(ac_buffer_t* pStartBuf, ac_buffer_t* pEndBuf, ac_buffer_t* pBuf, size_t length); void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length);
//Debug //Debug
void ac_buffer_dump(ac_buffer_t* pBuf); void ac_buffer_dump(ac_buffer_t *pBuf);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -39,11 +39,10 @@ extern "C" {
#include "acore/buffer.h" #include "acore/buffer.h"
typedef struct __ac_buffer_builder typedef struct __ac_buffer_builder {
{ ac_buffer_t ac_buffer;
ac_buffer_t ac_buffer; uint8_t *data;
uint8_t* data; size_t size;
size_t size;
} ac_buffer_builder_t; } ac_buffer_builder_t;
/** Write data to big endian ac_buffer (on a LE architecture, byte order will be swapped) /** Write data to big endian ac_buffer (on a LE architecture, byte order will be swapped)
@ -51,14 +50,14 @@ typedef struct __ac_buffer_builder
* \param buf pointer to data * \param buf pointer to data
* \param size the data size * \param size the data size
*/ */
void ac_buffer_builder_write_be(ac_buffer_builder_t* pBuilder, const uint8_t* buf, size_t size); void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size);
/** Write data to little endian ac_buffer (on a LE architecture, byte order will be preserved) /** Write data to little endian ac_buffer (on a LE architecture, byte order will be preserved)
* \param pBuilder ac_buffer builder to use * \param pBuilder ac_buffer builder to use
* \param buf pointer to data * \param buf pointer to data
* \param size the data size * \param size the data size
*/ */
void ac_buffer_builder_write_le(ac_buffer_builder_t* pBuilder, const uint8_t* buf, size_t size); void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size);
/** Write data to big endian ac_buffer at specific position (on a LE architecture, byte order will be swapped) /** Write data to big endian ac_buffer at specific position (on a LE architecture, byte order will be swapped)
* \param pBuilder ac_buffer builder to use * \param pBuilder ac_buffer builder to use
@ -66,7 +65,7 @@ void ac_buffer_builder_write_le(ac_buffer_builder_t* pBuilder, const uint8_t* bu
* \param buf pointer to data * \param buf pointer to data
* \param size the data size * \param size the data size
*/ */
void ac_buffer_builder_write_be_at(ac_buffer_builder_t* pBuilder, size_t pos, const uint8_t* buf, size_t size); void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size);
/** Write data to little endian ac_buffer at specific position (on a LE architecture, byte order will be preserved) /** Write data to little endian ac_buffer at specific position (on a LE architecture, byte order will be preserved)
* \param pBuilder ac_buffer builder to use * \param pBuilder ac_buffer builder to use
@ -74,199 +73,190 @@ void ac_buffer_builder_write_be_at(ac_buffer_builder_t* pBuilder, size_t pos, co
* \param buf pointer to data * \param buf pointer to data
* \param size the data size * \param size the data size
*/ */
void ac_buffer_builder_write_le_at(ac_buffer_builder_t* pBuilder, size_t pos, const uint8_t* buf, size_t size); void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size);
/** Initialize ac_buffer builder /** Initialize ac_buffer builder
* \param pBuilder ac_buffer builder to init * \param pBuilder ac_buffer builder to init
* \param data pointer to byte array to use * \param data pointer to byte array to use
* \param size of byte array * \param size of byte array
*/ */
void ac_buffer_builder_init(ac_buffer_builder_t* pBuilder, uint8_t* data, size_t size); void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size);
/** Initialize ac_buffer builder from underlying ac_buffer /** Initialize ac_buffer builder from underlying ac_buffer
* \param pBuilder ac_buffer builder to init * \param pBuilder ac_buffer builder to init
*/ */
void ac_buffer_builder_from_ac_buffer(ac_buffer_builder_t* pBuilder); void ac_buffer_builder_from_ac_buffer(ac_buffer_builder_t *pBuilder);
/** Reset ac_buffer builder /** Reset ac_buffer builder
* \param pBuilder ac_buffer builder to reset * \param pBuilder ac_buffer builder to reset
*/ */
void ac_buffer_builder_reset(ac_buffer_builder_t* pBuilder); void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder);
/** Set ac_buffer builder's ac_buffer to full size /** Set ac_buffer builder's ac_buffer to full size
* \param pBuilder ac_buffer builder to set to full size * \param pBuilder ac_buffer builder to set to full size
*/ */
void ac_buffer_builder_set_full(ac_buffer_builder_t* pBuilder); void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder);
/** Get ac_buffer builder's length /** Get ac_buffer builder's length
* \param pBuilder ac_buffer builder to get length of * \param pBuilder ac_buffer builder to get length of
* \return number of valid bytes in ac_buffer * \return number of valid bytes in ac_buffer
*/ */
static inline size_t ac_buffer_builder_length(ac_buffer_builder_t* pBuilder) static inline size_t ac_buffer_builder_length(ac_buffer_builder_t *pBuilder)
{ {
return ac_buffer_size(&pBuilder->ac_buffer); return ac_buffer_size(&pBuilder->ac_buffer);
} }
/** Set ac_buffer builder's length /** Set ac_buffer builder's length
* \param pBuilder ac_buffer builder to set length of * \param pBuilder ac_buffer builder to set length of
* \param length number of valid bytes in ac_buffer * \param length number of valid bytes in ac_buffer
*/ */
static inline void ac_buffer_builder_set_length(ac_buffer_builder_t* pBuilder, size_t length) static inline void ac_buffer_builder_set_length(ac_buffer_builder_t *pBuilder, size_t length)
{ {
if( ac_buffer_data(&pBuilder->ac_buffer) + length > pBuilder->data + pBuilder->size ) if (ac_buffer_data(&pBuilder->ac_buffer) + length > pBuilder->data + pBuilder->size) {
{ return;
return; }
} pBuilder->ac_buffer.size = length;
pBuilder->ac_buffer.size = length;
} }
/** Get ac_buffer builder's pointer to write position /** Get ac_buffer builder's pointer to write position
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return pointer to write position * \return pointer to write position
*/ */
static inline uint8_t* ac_buffer_builder_write_position(ac_buffer_builder_t* pBuilder) static inline uint8_t *ac_buffer_builder_write_position(ac_buffer_builder_t *pBuilder)
{ {
return (uint8_t*)ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer); return (uint8_t *)ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer);
} }
/** Get ac_buffer builder's write offset /** Get ac_buffer builder's write offset
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return write offset * \return write offset
*/ */
static inline size_t ac_buffer_builder_write_offset(ac_buffer_builder_t* pBuilder) static inline size_t ac_buffer_builder_write_offset(ac_buffer_builder_t *pBuilder)
{ {
return ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer) - pBuilder->data; return ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer) - pBuilder->data;
} }
/** Set ac_buffer builder's write offset /** Set ac_buffer builder's write offset
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param off new write offset * \param off new write offset
*/ */
static inline void ac_buffer_builder_set_write_offset(ac_buffer_builder_t* pBuilder, size_t off) static inline void ac_buffer_builder_set_write_offset(ac_buffer_builder_t *pBuilder, size_t off)
{ {
if( off > pBuilder->size ) if (off > pBuilder->size) {
{ return;
return; }
} if (pBuilder->data + off > pBuilder->ac_buffer.data) {
if( pBuilder->data + off > pBuilder->ac_buffer.data ) pBuilder->ac_buffer.size = off - (pBuilder->ac_buffer.data - pBuilder->data);
{ } else {
pBuilder->ac_buffer.size = off - (pBuilder->ac_buffer.data - pBuilder->data); pBuilder->ac_buffer.size = 0;
} }
else
{
pBuilder->ac_buffer.size = 0;
}
} }
/** Get ac_buffer builder's read offset /** Get ac_buffer builder's read offset
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return read offset * \return read offset
*/ */
static inline size_t ac_buffer_builder_read_offset(ac_buffer_builder_t* pBuilder) static inline size_t ac_buffer_builder_read_offset(ac_buffer_builder_t *pBuilder)
{ {
return ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data; return ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data;
} }
/** Set ac_buffer builder's read offset /** Set ac_buffer builder's read offset
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param off new read offset * \param off new read offset
*/ */
static inline void ac_buffer_builder_set_read_offset(ac_buffer_builder_t* pBuilder, size_t off) static inline void ac_buffer_builder_set_read_offset(ac_buffer_builder_t *pBuilder, size_t off)
{ {
if( off > pBuilder->size ) if (off > pBuilder->size) {
{ return;
return; }
} if (pBuilder->data + off < pBuilder->ac_buffer.data + pBuilder->ac_buffer.size) {
if( pBuilder->data + off < pBuilder->ac_buffer.data + pBuilder->ac_buffer.size ) pBuilder->ac_buffer.size = pBuilder->ac_buffer.data - (pBuilder->data + off);
{ } else {
pBuilder->ac_buffer.size = pBuilder->ac_buffer.data - (pBuilder->data + off); pBuilder->ac_buffer.size = 0;
} }
else pBuilder->ac_buffer.data = pBuilder->data + off;
{
pBuilder->ac_buffer.size = 0;
}
pBuilder->ac_buffer.data = pBuilder->data + off;
} }
/** Get ac_buffer builder's underlying ac_buffer /** Get ac_buffer builder's underlying ac_buffer
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return ac_buffer * \return ac_buffer
*/ */
static inline ac_buffer_t* ac_buffer_builder_buffer(ac_buffer_builder_t* pBuilder) static inline ac_buffer_t *ac_buffer_builder_buffer(ac_buffer_builder_t *pBuilder)
{ {
return &pBuilder->ac_buffer; return &pBuilder->ac_buffer;
} }
/** Get space in ac_buffer builder /** Get space in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return number of free bytes in ac_buffer builder * \return number of free bytes in ac_buffer builder
*/ */
static inline size_t ac_buffer_builder_space(ac_buffer_builder_t* pBuilder) static inline size_t ac_buffer_builder_space(ac_buffer_builder_t *pBuilder)
{ {
return pBuilder->size - (ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data + ac_buffer_size(&pBuilder->ac_buffer)); return pBuilder->size - (ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data + ac_buffer_size(&pBuilder->ac_buffer));
} }
/** Is ac_buffer builder empty /** Is ac_buffer builder empty
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return true if ac_buffer builder is empty * \return true if ac_buffer builder is empty
*/ */
static inline bool ac_buffer_builder_empty(ac_buffer_builder_t* pBuilder) static inline bool ac_buffer_builder_empty(ac_buffer_builder_t *pBuilder)
{ {
return (ac_buffer_builder_length(pBuilder) == 0); return (ac_buffer_builder_length(pBuilder) == 0);
} }
/** Is ac_buffer builder full /** Is ac_buffer builder full
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return true if ac_buffer builder is full * \return true if ac_buffer builder is full
*/ */
static inline bool ac_buffer_full(ac_buffer_builder_t* pBuilder) static inline bool ac_buffer_full(ac_buffer_builder_t *pBuilder)
{ {
return (ac_buffer_builder_space(pBuilder) == 0); return (ac_buffer_builder_space(pBuilder) == 0);
} }
/** Write 8-bit value in ac_buffer builder /** Write 8-bit value in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param hu8 8-bit value to write * \param hu8 8-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu8(ac_buffer_builder_t* pBuilder, uint8_t hu8) static inline void ac_buffer_builder_write_nu8(ac_buffer_builder_t *pBuilder, uint8_t hu8)
{ {
ac_buffer_builder_write_be(pBuilder, &hu8, 1); ac_buffer_builder_write_be(pBuilder, &hu8, 1);
} }
/** Write 16-bit value in ac_buffer builder /** Write 16-bit value in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param hu16 16-bit value to write in big-endian format * \param hu16 16-bit value to write in big-endian format
*/ */
static inline void ac_buffer_builder_write_nu16(ac_buffer_builder_t* pBuilder, uint16_t hu16) static inline void ac_buffer_builder_write_nu16(ac_buffer_builder_t *pBuilder, uint16_t hu16)
{ {
ac_buffer_builder_write_be(pBuilder, (uint8_t*)&hu16, 2); ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu16, 2);
} }
/** Write 24-bit value in ac_buffer builder /** Write 24-bit value in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param hu24 24-bit value to write in big-endian format * \param hu24 24-bit value to write in big-endian format
*/ */
static inline void ac_buffer_builder_write_nu24(ac_buffer_builder_t* pBuilder, uint32_t hu24) static inline void ac_buffer_builder_write_nu24(ac_buffer_builder_t *pBuilder, uint32_t hu24)
{ {
ac_buffer_builder_write_be(pBuilder, (uint8_t*)&hu24, 3); ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu24, 3);
} }
/** Write 32-bit value in ac_buffer builder /** Write 32-bit value in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param hu32 32-bit value to write in big-endian format * \param hu32 32-bit value to write in big-endian format
*/ */
static inline void ac_buffer_builder_write_nu32(ac_buffer_builder_t* pBuilder, uint32_t hu32) static inline void ac_buffer_builder_write_nu32(ac_buffer_builder_t *pBuilder, uint32_t hu32)
{ {
ac_buffer_builder_write_be(pBuilder, (uint8_t*)&hu32, 4); ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu32, 4);
} }
/** Write 64-bit value in ac_buffer builder /** Write 64-bit value in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param hu64 64-bit value to write in big-endian format * \param hu64 64-bit value to write in big-endian format
*/ */
static inline void ac_buffer_builder_write_nu64(ac_buffer_builder_t* pBuilder, uint64_t hu64) static inline void ac_buffer_builder_write_nu64(ac_buffer_builder_t *pBuilder, uint64_t hu64)
{ {
ac_buffer_builder_write_be(pBuilder, (uint8_t*)&hu64, 8); ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu64, 8);
} }
/** Write n-bytes value in ac_buffer builder /** Write n-bytes value in ac_buffer builder
@ -274,9 +264,9 @@ static inline void ac_buffer_builder_write_nu64(ac_buffer_builder_t* pBuilder, u
* \param data data to write * \param data data to write
* \param size data length * \param size data length
*/ */
static inline void ac_buffer_builder_write_n_bytes(ac_buffer_builder_t* pBuilder, const uint8_t* data, size_t size) static inline void ac_buffer_builder_write_n_bytes(ac_buffer_builder_t *pBuilder, const uint8_t *data, size_t size)
{ {
ac_buffer_builder_write_le(pBuilder, data, size); ac_buffer_builder_write_le(pBuilder, data, size);
} }
/** Write 8-bit value in ac_buffer builder at specified position /** Write 8-bit value in ac_buffer builder at specified position
@ -284,9 +274,9 @@ static inline void ac_buffer_builder_write_n_bytes(ac_buffer_builder_t* pBuilder
* \param off offset at which to write * \param off offset at which to write
* \param hu8 8-bit value to write * \param hu8 8-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu8_at(ac_buffer_builder_t* pBuilder, size_t off, uint8_t hu8) static inline void ac_buffer_builder_write_nu8_at(ac_buffer_builder_t *pBuilder, size_t off, uint8_t hu8)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, &hu8, 1); ac_buffer_builder_write_be_at(pBuilder, off, &hu8, 1);
} }
/** Write 16-bit value in ac_buffer builder at specified position /** Write 16-bit value in ac_buffer builder at specified position
@ -294,9 +284,9 @@ static inline void ac_buffer_builder_write_nu8_at(ac_buffer_builder_t* pBuilder,
* \param off offset at which to write * \param off offset at which to write
* \param hu16 16-bit value to write * \param hu16 16-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu16_at(ac_buffer_builder_t* pBuilder, size_t off, uint16_t hu16) static inline void ac_buffer_builder_write_nu16_at(ac_buffer_builder_t *pBuilder, size_t off, uint16_t hu16)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t*)&hu16, 2); ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu16, 2);
} }
/** Write 24-bit value in ac_buffer builder at specified position /** Write 24-bit value in ac_buffer builder at specified position
@ -304,9 +294,9 @@ static inline void ac_buffer_builder_write_nu16_at(ac_buffer_builder_t* pBuilder
* \param off offset at which to write * \param off offset at which to write
* \param hu24 24-bit value to write * \param hu24 24-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu24_at(ac_buffer_builder_t* pBuilder, size_t off, uint32_t hu24) static inline void ac_buffer_builder_write_nu24_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu24)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t*)&hu24, 3); ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu24, 3);
} }
/** Write 32-bit value in ac_buffer builder at specified position /** Write 32-bit value in ac_buffer builder at specified position
@ -314,9 +304,9 @@ static inline void ac_buffer_builder_write_nu24_at(ac_buffer_builder_t* pBuilder
* \param off offset at which to write * \param off offset at which to write
* \param hu32 32-bit value to write * \param hu32 32-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu32_at(ac_buffer_builder_t* pBuilder, size_t off, uint32_t hu32) static inline void ac_buffer_builder_write_nu32_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu32)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t*)&hu32, 4); ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu32, 4);
} }
/** Write 64-bit value in ac_buffer builder at specified position /** Write 64-bit value in ac_buffer builder at specified position
@ -324,9 +314,9 @@ static inline void ac_buffer_builder_write_nu32_at(ac_buffer_builder_t* pBuilder
* \param off offset at which to write * \param off offset at which to write
* \param hu64 64-bit value to write * \param hu64 64-bit value to write
*/ */
static inline void ac_buffer_builder_write_nu64_at(ac_buffer_builder_t* pBuilder, size_t off, uint64_t hu64) static inline void ac_buffer_builder_write_nu64_at(ac_buffer_builder_t *pBuilder, size_t off, uint64_t hu64)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t*)&hu64, 8); ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu64, 8);
} }
/** Write n-bytes value in ac_buffer builder at specified position /** Write n-bytes value in ac_buffer builder at specified position
@ -335,37 +325,37 @@ static inline void ac_buffer_builder_write_nu64_at(ac_buffer_builder_t* pBuilder
* \param data data to write * \param data data to write
* \param size data length * \param size data length
*/ */
static inline void ac_buffer_builder_write_n_bytes_at(ac_buffer_builder_t* pBuilder, size_t off, const uint8_t* data, size_t size) static inline void ac_buffer_builder_write_n_bytes_at(ac_buffer_builder_t *pBuilder, size_t off, const uint8_t *data, size_t size)
{ {
ac_buffer_builder_write_be_at(pBuilder, off, data, size); ac_buffer_builder_write_be_at(pBuilder, off, data, size);
} }
/** Skip n-bytes in ac_buffer builder /** Skip n-bytes in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \param size number of bytes to skip * \param size number of bytes to skip
*/ */
void ac_buffer_builder_write_n_skip(ac_buffer_builder_t* pBuilder, size_t size); void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size);
/** Copy n bytes from buffer to builder /** Copy n bytes from buffer to builder
* \param pBuilderOut ac_buffer builder * \param pBuilderOut ac_buffer builder
* \param pBufIn the input buffer * \param pBufIn the input buffer
* \param size number of bytes to copy * \param size number of bytes to copy
*/ */
void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t* pBuilderOut, ac_buffer_t* pBufIn, size_t size); void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size);
/** Compact builder /** Compact builder
* Will move underlying buffer's byte to start of allocated buffer * Will move underlying buffer's byte to start of allocated buffer
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
*/ */
void ac_buffer_builder_compact(ac_buffer_builder_t* pBuilder); void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder);
/** Get number of writable bytes in ac_buffer builder /** Get number of writable bytes in ac_buffer builder
* \param pBuilder ac_buffer builder * \param pBuilder ac_buffer builder
* \return number of free bytes in ac_buffer builder * \return number of free bytes in ac_buffer builder
*/ */
static inline size_t ac_buffer_builder_writable(ac_buffer_builder_t* pBuilder) static inline size_t ac_buffer_builder_writable(ac_buffer_builder_t *pBuilder)
{ {
return ac_buffer_builder_space(pBuilder); return ac_buffer_builder_space(pBuilder);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -44,68 +44,68 @@ extern "C" {
* \param buf the array to write to * \param buf the array to write to
* \param size the number of bytes to read * \param size the number of bytes to read
*/ */
void ac_buffer_read_be(ac_buffer_t* pBuf, uint8_t* buf, size_t size); void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size);
/** Read n-bytes in little-endian format from buffer reader and advance read posiion /** Read n-bytes in little-endian format from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \param buf the array to write to * \param buf the array to write to
* \param size the number of bytes to read * \param size the number of bytes to read
*/ */
void ac_buffer_read_le(ac_buffer_t* pBuf, uint8_t* buf, size_t size); void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size);
/** Read 8-bit value from buffer reader and advance read posiion /** Read 8-bit value from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return 8-bit value read * \return 8-bit value read
*/ */
static inline uint8_t ac_buffer_read_nu8(ac_buffer_t* pBuf) static inline uint8_t ac_buffer_read_nu8(ac_buffer_t *pBuf)
{ {
uint8_t hu8; uint8_t hu8;
ac_buffer_read_be(pBuf, &hu8, 1); ac_buffer_read_be(pBuf, &hu8, 1);
return hu8; return hu8;
} }
/** Read BE 16-bit value from buffer reader and advance read posiion /** Read BE 16-bit value from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return 16-bit value read * \return 16-bit value read
*/ */
static inline uint16_t ac_buffer_read_nu16(ac_buffer_t* pBuf) static inline uint16_t ac_buffer_read_nu16(ac_buffer_t *pBuf)
{ {
uint16_t hu16; uint16_t hu16;
ac_buffer_read_be(pBuf, (uint8_t*)&hu16, 2); ac_buffer_read_be(pBuf, (uint8_t *)&hu16, 2);
return hu16; return hu16;
} }
/** Read BE 24-bit value from buffer reader and advance read posiion /** Read BE 24-bit value from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return 24-bit value read * \return 24-bit value read
*/ */
static inline uint32_t ac_buffer_read_nu24(ac_buffer_t* pBuf) static inline uint32_t ac_buffer_read_nu24(ac_buffer_t *pBuf)
{ {
uint32_t hu24; uint32_t hu24;
ac_buffer_read_be(pBuf, (uint8_t*)&hu24, 3); ac_buffer_read_be(pBuf, (uint8_t *)&hu24, 3);
return hu24; return hu24;
} }
/** Read BE 32-bit value from buffer reader and advance read posiion /** Read BE 32-bit value from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return 32-bit value read * \return 32-bit value read
*/ */
static inline uint32_t ac_buffer_read_nu32(ac_buffer_t* pBuf) static inline uint32_t ac_buffer_read_nu32(ac_buffer_t *pBuf)
{ {
uint32_t hu32; uint32_t hu32;
ac_buffer_read_be(pBuf, (uint8_t*)&hu32, 4); ac_buffer_read_be(pBuf, (uint8_t *)&hu32, 4);
return hu32; return hu32;
} }
/** Read BE 64-bit value from buffer reader and advance read posiion /** Read BE 64-bit value from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return 64-bit value read * \return 64-bit value read
*/ */
static inline uint64_t ac_buffer_read_nu64(ac_buffer_t* pBuf) static inline uint64_t ac_buffer_read_nu64(ac_buffer_t *pBuf)
{ {
uint64_t hu64; uint64_t hu64;
ac_buffer_read_be(pBuf, (uint8_t*)&hu64, 8); ac_buffer_read_be(pBuf, (uint8_t *)&hu64, 8);
return hu64; return hu64;
} }
/** Read n bytes from buffer reader and advance read posiion /** Read n bytes from buffer reader and advance read posiion
@ -113,34 +113,34 @@ static inline uint64_t ac_buffer_read_nu64(ac_buffer_t* pBuf)
* \param data the array to write bytes to * \param data the array to write bytes to
* \param size the number of bytes to read * \param size the number of bytes to read
*/ */
static inline void ac_buffer_read_n_bytes(ac_buffer_t* pBuf, uint8_t* data, size_t size) static inline void ac_buffer_read_n_bytes(ac_buffer_t *pBuf, uint8_t *data, size_t size)
{ {
ac_buffer_read_le(pBuf, data, size); ac_buffer_read_le(pBuf, data, size);
} }
/** Skip n bytes from buffer reader and advance read posiion /** Skip n bytes from buffer reader and advance read posiion
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \param size the number of bytes to skip * \param size the number of bytes to skip
*/ */
void ac_buffer_read_n_skip(ac_buffer_t* pBuf, size_t size); void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size);
/** Get number of bytes readable from buffer /** Get number of bytes readable from buffer
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return The number of bytes which can be read * \return The number of bytes which can be read
*/ */
size_t ac_buffer_reader_readable(const ac_buffer_t* pBuf); size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf);
/** Get a pointer to the current position within this buffer's current backing array /** Get a pointer to the current position within this buffer's current backing array
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return A pointer to the current position within the current backing array * \return A pointer to the current position within the current backing array
*/ */
const uint8_t* ac_buffer_reader_current_buffer_pointer(ac_buffer_t* pBuf); const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf);
/** Get the number of bytes readable within the current backing array /** Get the number of bytes readable within the current backing array
* \param pBuf the buffer to read from * \param pBuf the buffer to read from
* \return The number of bytes readable within the current backing array * \return The number of bytes readable within the current backing array
*/ */
size_t ac_buffer_reader_current_buffer_length(ac_buffer_t* pBuf); size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf);
/** Compare buffer with array (does not advance read position) /** Compare buffer with array (does not advance read position)
* \param pBuf the buffer to compare from * \param pBuf the buffer to compare from
@ -148,14 +148,14 @@ size_t ac_buffer_reader_current_buffer_length(ac_buffer_t* pBuf);
* \param length the array length * \param length the array length
* \return Whether the buffer is AT LEAST as long as the array AND the buffer and array have the same content * \return Whether the buffer is AT LEAST as long as the array AND the buffer and array have the same content
*/ */
bool ac_buffer_reader_cmp_bytes(const ac_buffer_t* pBuf, const uint8_t* bytes, size_t length); bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length);
/** Compare buffer with array (does not advance read position) /** Compare buffer with array (does not advance read position)
* \param pBuf1 the buffer to compare from * \param pBuf1 the buffer to compare from
* \param pBuf2 the buffer to compare with * \param pBuf2 the buffer to compare with
* \return Whether the buffers have the same length and content * \return Whether the buffers have the same length and content
*/ */
bool ac_buffer_reader_cmp(const ac_buffer_t* pBuf1, const ac_buffer_t* pBuf2); bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -39,32 +39,30 @@ typedef struct __ac_ostream ac_ostream_t;
#include "acore/buffer.h" #include "acore/buffer.h"
typedef void (*ac_istream_fn)(ac_buffer_t* pDataIn, bool* pClose, size_t maxLength, void* pUserParam); typedef void (*ac_istream_fn)(ac_buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam);
typedef void (*ac_ostream_fn)(ac_buffer_t* pDataOut, bool closed, void* pUserParam); typedef void (*ac_ostream_fn)(ac_buffer_t *pDataOut, bool closed, void *pUserParam);
//Input stream -- pulled by consumer //Input stream -- pulled by consumer
struct __ac_istream struct __ac_istream {
{ ac_istream_fn fn;
ac_istream_fn fn; void *pUserParam;
void* pUserParam;
}; };
//Output stream -- pushed by supplier //Output stream -- pushed by supplier
struct __ac_ostream struct __ac_ostream {
{ ac_ostream_fn fn;
ac_ostream_fn fn; void *pUserParam;
void* pUserParam;
}; };
//Called by supplier //Called by supplier
void ac_istream_init(ac_istream_t* pac_istream, ac_istream_fn fn, void* pUserParam); void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam);
//Called by consumer //Called by consumer
void ac_istream_pull(ac_istream_t* pac_istream, ac_buffer_t* pDataIn, bool* pClose, size_t maxLength); void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength);
//Called by consumer //Called by consumer
void ac_ostream_init(ac_ostream_t* pac_ostream, ac_ostream_fn fn, void* pUserParam); void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam);
//Called by supplier //Called by supplier
void ac_ostream_push(ac_ostream_t* pac_ostream, ac_buffer_t* pDataOut, bool closed); void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -29,77 +29,70 @@
#include "acore/debug.h" #include "acore/debug.h"
void ac_buffer_init(ac_buffer_t* pBuf, const uint8_t* data, size_t size) void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size)
{ {
pBuf->data = data; pBuf->data = data;
pBuf->size = size; pBuf->size = size;
pBuf->pNext = NULL; pBuf->pNext = NULL;
} }
void ac_buffer_dup(ac_buffer_t* pBuf, const ac_buffer_t* pBufIn) void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn)
{ {
if(pBuf != pBufIn) if (pBuf != pBufIn) {
{ memcpy(pBuf, pBufIn, sizeof(ac_buffer_t));
memcpy(pBuf, pBufIn, sizeof(ac_buffer_t)); }
}
} }
void ac_buffer_append(ac_buffer_t* pBuf, ac_buffer_t* pAppBuf) void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf)
{ {
while(pBuf->pNext != NULL) while (pBuf->pNext != NULL) {
{ pBuf = pBuf->pNext;
pBuf = pBuf->pNext; }
} pBuf->pNext = pAppBuf;
pBuf->pNext = pAppBuf;
} }
void ac_buffer_split(ac_buffer_t* pStartBuf, ac_buffer_t* pEndBuf, ac_buffer_t* pBuf, size_t length) void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length)
{ {
ac_buffer_dup(pStartBuf, pBuf); ac_buffer_dup(pStartBuf, pBuf);
ac_buffer_dup(pEndBuf, pBuf); ac_buffer_dup(pEndBuf, pBuf);
ac_buffer_read_n_skip(pEndBuf, length); ac_buffer_read_n_skip(pEndBuf, length);
while( length > ac_buffer_size(pStartBuf) ) while (length > ac_buffer_size(pStartBuf)) {
{ length -= pStartBuf->size;
length -= pStartBuf->size; pStartBuf = pStartBuf->pNext;
pStartBuf = pStartBuf->pNext; }
}
pStartBuf->size = length; pStartBuf->size = length;
pStartBuf->pNext = NULL; pStartBuf->pNext = NULL;
} }
/** Dump a ac_buffer's content to stdout (useful for debugging) /** Dump a ac_buffer's content to stdout (useful for debugging)
* \param pBuf pointer to ac_buffer_t structure * \param pBuf pointer to ac_buffer_t structure
*/ */
void ac_buffer_dump(ac_buffer_t* pBuf) void ac_buffer_dump(ac_buffer_t *pBuf)
{ {
#if !defined(NDEBUG) #if !defined(NDEBUG)
ACORE_STDIO_LOCK(); ACORE_STDIO_LOCK();
while(pBuf != NULL) while (pBuf != NULL) {
{ size_t r = ac_buffer_size(pBuf);
size_t r = ac_buffer_size(pBuf); size_t i = 0;
size_t i = 0; size_t j = 0;
size_t j = 0; while (i < r) {
while(i < r) for (j = i; j < MIN(i + 16, r); j++) {
{ ACORE_STDIO_PRINT("%02x ", ac_buffer_data(pBuf)[j]);
for(j = i; j < MIN(i + 16, r); j++) }
{ ACORE_STDIO_PRINT("\r\n");
ACORE_STDIO_PRINT("%02x ", ac_buffer_data(pBuf)[j]); i = j;
} }
ACORE_STDIO_PRINT("\r\n"); pBuf = ac_buffer_next(pBuf);
i = j; if (pBuf != NULL) {
ACORE_STDIO_PRINT("->\r\n");
}
} }
pBuf = ac_buffer_next(pBuf); ACORE_STDIO_UNLOCK();
if(pBuf != NULL)
{
ACORE_STDIO_PRINT("->\r\n");
}
}
ACORE_STDIO_UNLOCK();
#else #else
(void)pBuf; (void)pBuf;
#endif #endif
} }

View File

@ -29,91 +29,88 @@
#define VOID #define VOID
#define ENSURE_WRITE_LENGTH(pBuilder, n) do{ if( ac_buffer_builder_space(pBuilder) < n ) { return; } }while(0); #define ENSURE_WRITE_LENGTH(pBuilder, n) do{ if( ac_buffer_builder_space(pBuilder) < n ) { return; } }while(0);
void ac_buffer_builder_init(ac_buffer_builder_t* pBuilder, uint8_t* data, size_t size) void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size)
{ {
pBuilder->data = data; pBuilder->data = data;
pBuilder->size = size; pBuilder->size = size;
ac_buffer_init(&pBuilder->ac_buffer, data, 0); ac_buffer_init(&pBuilder->ac_buffer, data, 0);
} }
void ac_buffer_builder_from_ac_buffer(ac_buffer_builder_t* pBuilder) void ac_buffer_builder_from_ac_buffer(ac_buffer_builder_t *pBuilder)
{ {
pBuilder->data = (uint8_t*)pBuilder->ac_buffer.data; pBuilder->data = (uint8_t *)pBuilder->ac_buffer.data;
pBuilder->size = pBuilder->ac_buffer.size; pBuilder->size = pBuilder->ac_buffer.size;
pBuilder->ac_buffer.size = 0; pBuilder->ac_buffer.size = 0;
} }
void ac_buffer_builder_reset(ac_buffer_builder_t* pBuilder) void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder)
{ {
ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, 0); ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, 0);
} }
void ac_buffer_builder_set_full(ac_buffer_builder_t* pBuilder) void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder)
{ {
ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, pBuilder->size); ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, pBuilder->size);
} }
void ac_buffer_builder_write_be(ac_buffer_builder_t* pBuilder, const uint8_t* buf, size_t size) void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size)
{ {
ENSURE_WRITE_LENGTH(pBuilder, size); ENSURE_WRITE_LENGTH(pBuilder, size);
buf += size; buf += size;
while(size > 0) while (size > 0) {
{ buf--;
buf--; *ac_buffer_builder_write_position(pBuilder) = *buf;
*ac_buffer_builder_write_position(pBuilder) = *buf; pBuilder->ac_buffer.size++;
pBuilder->ac_buffer.size++; size--;
size--; }
}
} }
void ac_buffer_builder_write_le(ac_buffer_builder_t* pBuilder, const uint8_t* buf, size_t size) void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size)
{ {
ENSURE_WRITE_LENGTH(pBuilder, size); ENSURE_WRITE_LENGTH(pBuilder, size);
memcpy(ac_buffer_builder_write_position(pBuilder), buf, size); memcpy(ac_buffer_builder_write_position(pBuilder), buf, size);
pBuilder->ac_buffer.size+=size; pBuilder->ac_buffer.size += size;
} }
void ac_buffer_builder_write_be_at(ac_buffer_builder_t* pBuilder, size_t pos, const uint8_t* buf, size_t size) void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size)
{ {
size_t currentPos = pBuilder->ac_buffer.size; size_t currentPos = pBuilder->ac_buffer.size;
pBuilder->ac_buffer.size = pos; pBuilder->ac_buffer.size = pos;
ac_buffer_builder_write_be(pBuilder, buf, size); ac_buffer_builder_write_be(pBuilder, buf, size);
pBuilder->ac_buffer.size = currentPos; pBuilder->ac_buffer.size = currentPos;
} }
void ac_buffer_builder_write_le_at(ac_buffer_builder_t* pBuilder, size_t pos, const uint8_t* buf, size_t size) void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size)
{ {
size_t currentPos = pBuilder->ac_buffer.size; size_t currentPos = pBuilder->ac_buffer.size;
pBuilder->ac_buffer.size = pos; pBuilder->ac_buffer.size = pos;
ac_buffer_builder_write_le(pBuilder, buf, size); ac_buffer_builder_write_le(pBuilder, buf, size);
pBuilder->ac_buffer.size = currentPos; pBuilder->ac_buffer.size = currentPos;
} }
void ac_buffer_builder_write_n_skip(ac_buffer_builder_t* pBuilder, size_t size) void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size)
{ {
ENSURE_WRITE_LENGTH(pBuilder, size); ENSURE_WRITE_LENGTH(pBuilder, size);
pBuilder->ac_buffer.size += size; pBuilder->ac_buffer.size += size;
} }
void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t* pBuilderOut, ac_buffer_t* pBufIn, size_t size) void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size)
{ {
ENSURE_WRITE_LENGTH(pBuilderOut, size); ENSURE_WRITE_LENGTH(pBuilderOut, size);
if( ac_buffer_reader_readable(pBufIn) < size ) if (ac_buffer_reader_readable(pBufIn) < size) {
{ return;
return; }
} while (size > 0) {
while(size > 0) size_t cpy = ac_buffer_reader_current_buffer_length(pBufIn);
{ cpy = MIN(cpy, size);
size_t cpy = ac_buffer_reader_current_buffer_length(pBufIn); ac_buffer_builder_write_n_bytes(pBuilderOut, ac_buffer_reader_current_buffer_pointer(pBufIn), cpy);
cpy = MIN(cpy, size); ac_buffer_read_n_skip(pBufIn, cpy);
ac_buffer_builder_write_n_bytes(pBuilderOut, ac_buffer_reader_current_buffer_pointer(pBufIn), cpy); size -= cpy;
ac_buffer_read_n_skip(pBufIn, cpy); }
size -= cpy;
}
} }
void ac_buffer_builder_compact(ac_buffer_builder_t* pBuilder) void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder)
{ {
memmove(pBuilder->data, ac_buffer_data(&pBuilder->ac_buffer), ac_buffer_size(&pBuilder->ac_buffer)); memmove(pBuilder->data, ac_buffer_data(&pBuilder->ac_buffer), ac_buffer_size(&pBuilder->ac_buffer));
pBuilder->ac_buffer.data = pBuilder->data; pBuilder->ac_buffer.data = pBuilder->data;
} }

View File

@ -28,156 +28,139 @@
#define VOID #define VOID
#define ENSURE_READ_LENGTH(pBuf, n) do{ if( ac_buffer_reader_readable(pBuf) < n ) { return; } }while(0); #define ENSURE_READ_LENGTH(pBuf, n) do{ if( ac_buffer_reader_readable(pBuf) < n ) { return; } }while(0);
static inline void update_buf(ac_buffer_t* pBuf) static inline void update_buf(ac_buffer_t *pBuf)
{ {
while( ac_buffer_size(pBuf) == 0 ) while (ac_buffer_size(pBuf) == 0) {
{ if (ac_buffer_next(pBuf) != NULL) {
if( ac_buffer_next(pBuf) != NULL ) ac_buffer_t *pNext = ac_buffer_next(pBuf);
{ ac_buffer_init(pBuf, ac_buffer_data(pNext), ac_buffer_size(pNext));
ac_buffer_t* pNext = ac_buffer_next(pBuf); pBuf->pNext = ac_buffer_next(pNext);
ac_buffer_init(pBuf, ac_buffer_data(pNext), ac_buffer_size(pNext)); } else if (pBuf->data != NULL) {
pBuf->pNext = ac_buffer_next(pNext); ac_buffer_init(pBuf, NULL, 0);
} else {
return;
}
} }
else if( pBuf->data != NULL )
{
ac_buffer_init(pBuf, NULL, 0);
}
else
{
return;
}
}
} }
void ac_buffer_read_be(ac_buffer_t* pBuf, uint8_t* buf, size_t size) void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size)
{
ENSURE_READ_LENGTH(pBuf, size);
buf += size;
while (size > 0) {
buf--;
*buf = *ac_buffer_data(pBuf);
pBuf->data++;
pBuf->size--;
update_buf(pBuf);
size--;
}
}
void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size)
{
ENSURE_READ_LENGTH(pBuf, size);
while (size > 0) {
size_t cpy = ac_buffer_size(pBuf);
cpy = MIN(cpy, size);
memcpy(buf, ac_buffer_data(pBuf), cpy);
pBuf->data += cpy;
pBuf->size -= cpy;
update_buf(pBuf);
size -= cpy;
buf += cpy;
}
}
void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size)
{
ENSURE_READ_LENGTH(pBuf, size);
while (size > 0) {
size_t cpy = ac_buffer_size(pBuf);
cpy = MIN(cpy, size);
pBuf->data += cpy;
pBuf->size -= cpy;
update_buf(pBuf);
size -= cpy;
}
}
size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf)
{
size_t r = 0;
while (pBuf != NULL) {
r += ac_buffer_size(pBuf);
pBuf = ac_buffer_next(pBuf);
}
return r;
}
const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf)
{ {
ENSURE_READ_LENGTH(pBuf, size);
buf += size;
while(size > 0)
{
buf--;
*buf = *ac_buffer_data(pBuf);
pBuf->data++;
pBuf->size--;
update_buf(pBuf); update_buf(pBuf);
size--; return ac_buffer_data(pBuf);
}
} }
void ac_buffer_read_le(ac_buffer_t* pBuf, uint8_t* buf, size_t size) size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf)
{ {
ENSURE_READ_LENGTH(pBuf, size);
while(size > 0)
{
size_t cpy = ac_buffer_size(pBuf);
cpy = MIN(cpy, size);
memcpy(buf, ac_buffer_data(pBuf), cpy);
pBuf->data+=cpy;
pBuf->size-=cpy;
update_buf(pBuf); update_buf(pBuf);
size-=cpy; return ac_buffer_size(pBuf);
buf+=cpy;
}
} }
void ac_buffer_read_n_skip(ac_buffer_t* pBuf, size_t size) bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length)
{ {
ENSURE_READ_LENGTH(pBuf, size); ac_buffer_t reader;
while(size > 0)
{
size_t cpy = ac_buffer_size(pBuf);
cpy = MIN(cpy, size);
pBuf->data+=cpy;
pBuf->size-=cpy;
update_buf(pBuf);
size-=cpy;
}
}
size_t ac_buffer_reader_readable(const ac_buffer_t* pBuf) if (length > ac_buffer_reader_readable(pBuf)) {
{ return false;
size_t r = 0;
while( pBuf != NULL )
{
r += ac_buffer_size(pBuf);
pBuf = ac_buffer_next(pBuf);
}
return r;
}
const uint8_t* ac_buffer_reader_current_buffer_pointer(ac_buffer_t* pBuf)
{
update_buf(pBuf);
return ac_buffer_data(pBuf);
}
size_t ac_buffer_reader_current_buffer_length(ac_buffer_t* pBuf)
{
update_buf(pBuf);
return ac_buffer_size(pBuf);
}
bool ac_buffer_reader_cmp_bytes(const ac_buffer_t* pBuf, const uint8_t* bytes, size_t length)
{
ac_buffer_t reader;
if( length > ac_buffer_reader_readable(pBuf) )
{
return false;
}
ac_buffer_dup(&reader, pBuf);
while(length > 0)
{
size_t sz = ac_buffer_reader_current_buffer_length(&reader);
if( sz > length )
{
sz = length;
} }
int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader), bytes, sz);
if(c)
{
return false;
}
length -= sz;
bytes += sz;
ac_buffer_read_n_skip(&reader, sz);
}
return true; ac_buffer_dup(&reader, pBuf);
while (length > 0) {
size_t sz = ac_buffer_reader_current_buffer_length(&reader);
if (sz > length) {
sz = length;
}
int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader), bytes, sz);
if (c) {
return false;
}
length -= sz;
bytes += sz;
ac_buffer_read_n_skip(&reader, sz);
}
return true;
} }
bool ac_buffer_reader_cmp(const ac_buffer_t* pBuf1, const ac_buffer_t* pBuf2) bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2)
{ {
ac_buffer_t reader1; ac_buffer_t reader1;
ac_buffer_t reader2; ac_buffer_t reader2;
if( ac_buffer_reader_readable(pBuf1) != ac_buffer_reader_readable(pBuf2) ) if (ac_buffer_reader_readable(pBuf1) != ac_buffer_reader_readable(pBuf2)) {
{ return false;
return false;
}
ac_buffer_dup(&reader1, pBuf1);
ac_buffer_dup(&reader2, pBuf2);
size_t length = ac_buffer_reader_readable(pBuf1);
while(length > 0)
{
size_t sz1 = ac_buffer_reader_current_buffer_length(&reader1);
size_t sz2 = ac_buffer_reader_current_buffer_length(&reader2);
size_t sz = MIN(sz1, sz2);
int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader1), ac_buffer_reader_current_buffer_pointer(&reader2), sz);
if(c)
{
return false;
} }
length -= sz;
ac_buffer_read_n_skip(&reader1, sz);
ac_buffer_read_n_skip(&reader2, sz);
}
return true; ac_buffer_dup(&reader1, pBuf1);
ac_buffer_dup(&reader2, pBuf2);
size_t length = ac_buffer_reader_readable(pBuf1);
while (length > 0) {
size_t sz1 = ac_buffer_reader_current_buffer_length(&reader1);
size_t sz2 = ac_buffer_reader_current_buffer_length(&reader2);
size_t sz = MIN(sz1, sz2);
int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader1), ac_buffer_reader_current_buffer_pointer(&reader2), sz);
if (c) {
return false;
}
length -= sz;
ac_buffer_read_n_skip(&reader1, sz);
ac_buffer_read_n_skip(&reader2, sz);
}
return true;
} }

View File

@ -24,27 +24,27 @@
#include "acore/macros.h" #include "acore/macros.h"
//Called by supplier //Called by supplier
void ac_istream_init(ac_istream_t* pac_istream, ac_istream_fn fn, void* pUserParam) void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam)
{ {
pac_istream->fn = fn; pac_istream->fn = fn;
pac_istream->pUserParam = pUserParam; pac_istream->pUserParam = pUserParam;
} }
//Called by consumer //Called by consumer
void ac_istream_pull(ac_istream_t* pac_istream, ac_buffer_t* pDataIn, bool* pClose, size_t maxLength) void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength)
{ {
pac_istream->fn(pDataIn, pClose, maxLength, pac_istream->pUserParam); pac_istream->fn(pDataIn, pClose, maxLength, pac_istream->pUserParam);
} }
//Called by consumer //Called by consumer
void ac_ostream_init(ac_ostream_t* pac_ostream, ac_ostream_fn fn, void* pUserParam) void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam)
{ {
pac_ostream->fn = fn; pac_ostream->fn = fn;
pac_ostream->pUserParam = pUserParam; pac_ostream->pUserParam = pUserParam;
} }
//Called by supplier //Called by supplier
void ac_ostream_push(ac_ostream_t* pac_ostream, ac_buffer_t* pDataOut, bool closed) void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed)
{ {
pac_ostream->fn(pDataOut, closed, pac_ostream->pUserParam); pac_ostream->fn(pDataOut, closed, pac_ostream->pUserParam);
} }

View File

@ -25,21 +25,21 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
struct PN512TransportDriver; struct PN512TransportDriver;
class PN512Driver : public NFCControllerDriver, private PN512TransportDriver::Delegate { class PN512Driver : public NFCControllerDriver, private PN512TransportDriver::Delegate {
public: public:
PN512Driver(PN512TransportDriver* transport_driver); PN512Driver(PN512TransportDriver *transport_driver);
virtual nfc_transceiver_t* initialize(nfc_scheduler_timer_t* scheduler_timer); virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer);
virtual void get_supported_nfc_techs(nfc_tech_t* initiator, nfc_tech_t* target) const; virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const;
private: private:
// PN512TransportDriver::Delegate implementation // PN512TransportDriver::Delegate implementation
void on_hw_interrupt(); void on_hw_interrupt();
PN512TransportDriver* _transport_driver; PN512TransportDriver *_transport_driver;
pn512_t _pn512; pn512_t _pn512;
}; };
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -26,29 +26,29 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
class PN512SPITransportDriver : public PN512TransportDriver {
public:
PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst);
private: class PN512SPITransportDriver : public PN512TransportDriver {
virtual void initialize(); public:
virtual nfc_transport_t* get_transport() const; PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst);
void transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen ); private:
void transport_read( uint8_t address, uint8_t* inBuf, size_t inLen ); virtual void initialize();
virtual nfc_transport_t *get_transport() const;
// Callbacks from munfc void transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen);
static void s_transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen, void* pUser ); void transport_read(uint8_t address, uint8_t *inBuf, size_t inLen);
static void s_transport_read( uint8_t address, uint8_t* inBuf, size_t inLen, void* pUser );
// Callbacks from munfc
static void s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser);
static void s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser);
nfc_transport_t _nfc_transport;
SPI _spi;
DigitalOut _ssel;
InterruptIn _irq;
DigitalOut _rst;
};
nfc_transport_t _nfc_transport;
SPI _spi;
DigitalOut _ssel;
InterruptIn _irq;
DigitalOut _rst;
};
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -23,55 +23,55 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* The PN512 supports multiple transport mechanisms (SPI, I2C, UART): this class provides a unified API across these transports
*/
class PN512TransportDriver {
public:
/** /**
* The PN512 supports multiple transport mechanisms (SPI, I2C, UART): this class provides a unified API across these transports * The PN512TransportDriver delegate
*/ */
class PN512TransportDriver { struct Delegate {
public:
/** /**
* The PN512TransportDriver delegate * Called when the PN512 asserts the interrupt line
*/ */
struct Delegate { void on_hw_interrupt();
/**
* Called when the PN512 asserts the interrupt line
*/
void on_hw_interrupt();
};
/**
* Create a PN512TransportDriver instance
*/
PN512TransportDriver();
/**
* Initialize transport driver and perform a chip reset
*/
virtual void initialize() = 0;
/**
* Retrieve the nfc_transport_t struct for the stack to use
*
* @return a pointer to a nfc_transport_t struct
*/
virtual nfc_transport_t* get_transport() const = 0;
/**
* Set this instance's delegate
*
* @param[in] delegate the delegate instance to use
*/
void set_delegate(Delegate* delegate);
protected:
/**
* An implementation must call this function (can be called from interrupt context)
* when the PN512 asserts its interrupt line
*/
void hw_interrupt();
private:
Delegate* _delegate;
}; };
/**
* Create a PN512TransportDriver instance
*/
PN512TransportDriver();
/**
* Initialize transport driver and perform a chip reset
*/
virtual void initialize() = 0;
/**
* Retrieve the nfc_transport_t struct for the stack to use
*
* @return a pointer to a nfc_transport_t struct
*/
virtual nfc_transport_t *get_transport() const = 0;
/**
* Set this instance's delegate
*
* @param[in] delegate the delegate instance to use
*/
void set_delegate(Delegate *delegate);
protected:
/**
* An implementation must call this function (can be called from interrupt context)
* when the PN512 asserts its interrupt line
*/
void hw_interrupt();
private:
Delegate *_delegate;
};
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -25,111 +25,109 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
class Type4RemoteInitiator;
/**
* This base class represents an ISO7816-4 application.
*/
class ISO7816App {
/** /**
* @addtogroup nfc * This class describes an ISO7816-4 exchange (Command/Response).
* @{
*/ */
class Exchange {
class Type4RemoteInitiator; public:
/**
* This base class represents an ISO7816-4 application.
*/
class ISO7816App {
/** /**
* This class describes an ISO7816-4 exchange (Command/Response). * A Command APDU (Application Protocol Data Unit) .
*/ */
class Exchange { struct CAPDU {
public: uint8_t cla; ///< CLA - Instruction class
/** uint8_t ins; ///< INS - Instruction code
* A Command APDU (Application Protocol Data Unit) . uint8_t p1; ///< P1 - First parameter
*/ uint8_t p2; ///< P2 - Second parameter
struct CAPDU ac_buffer_t dataIn; ///< Command data
{ size_t maxRespLength; ///< Maximum response length
uint8_t cla; ///< CLA - Instruction class
uint8_t ins; ///< INS - Instruction code
uint8_t p1; ///< P1 - First parameter
uint8_t p2; ///< P2 - Second parameter
ac_buffer_t dataIn; ///< Command data
size_t maxRespLength; ///< Maximum response length
};
/**
* A Response APDU (Application Protocol Data Unit)
*/
struct RAPDU
{
ac_buffer_t dataOut; ///< Response data
uint16_t sw; ///< Status word
};
/**
* Access Command APDU.
*
* @return a const reference to the Command ADPU
*/
const CAPDU& command() const;
/**
* Access Response APDU.
*
* @return a mutable reference to the Command ADPU
*/
RAPDU& response();
/**
* Respond to command.
*
* @return NFC_OK if the response could be sent back successfully, or an error code otherwise
*/
nfc_err_t respond();
private:
CAPDU _command;
RAPDU _response;
ISO7816App* _iso7816_app;
}; };
/** /**
* Construct ISO7816 app instance * A Response APDU (Application Protocol Data Unit)
*/ */
ISO7816App(); struct RAPDU {
ac_buffer_t dataOut; ///< Response data
uint16_t sw; ///< Status word
};
/**
* Access Command APDU.
*
* @return a const reference to the Command ADPU
*/
const CAPDU &command() const;
/**
* Access Response APDU.
*
* @return a mutable reference to the Command ADPU
*/
RAPDU &response();
/**
* Respond to command.
*
* @return NFC_OK if the response could be sent back successfully, or an error code otherwise
*/
nfc_err_t respond();
private: private:
friend class Type4RemoteInitiator; CAPDU _command;
RAPDU _response;
/** ISO7816App *_iso7816_app;
* Retrieve the application's identifier (AID).
* AIDs are composed of a RID (Registered Application Provider Identifier) that needs to be registered and a custom suffix.
*
* @return a pointer to a const buffer containing the application's identifier (AID).
*/
virtual const ac_buffer_t* get_aid() const = 0;
/**
* Called when the application is selected and before any exchange is performed.
*/
virtual void on_selected() = 0;
/**
* Called when the application is deselected (or link is lost).
*/
virtual void on_deselected() = 0;
/**
* Called when an exchange is performed.
* The application must respond using the respond() method of the Exchange class.
*
* @param[in] exchange an instance of the Exchange class populated with the C-APDU which was received
*/
virtual void on_exchange(Exchange* exchange) = 0;
nfc_tech_iso7816_app_t iso7816_app;
}; };
/** /**
* @} * Construct ISO7816 app instance
*/ */
ISO7816App();
private:
friend class Type4RemoteInitiator;
/**
* Retrieve the application's identifier (AID).
* AIDs are composed of a RID (Registered Application Provider Identifier) that needs to be registered and a custom suffix.
*
* @return a pointer to a const buffer containing the application's identifier (AID).
*/
virtual const ac_buffer_t *get_aid() const = 0;
/**
* Called when the application is selected and before any exchange is performed.
*/
virtual void on_selected() = 0;
/**
* Called when the application is deselected (or link is lost).
*/
virtual void on_deselected() = 0;
/**
* Called when an exchange is performed.
* The application must respond using the respond() method of the Exchange class.
*
* @param[in] exchange an instance of the Exchange class populated with the C-APDU which was received
*/
virtual void on_exchange(Exchange *exchange) = 0;
nfc_tech_iso7816_app_t iso7816_app;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -27,155 +27,155 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
class NFCRemoteInitiator; class NFCRemoteInitiator;
class NFCRemoteTarget; class NFCRemoteTarget;
class NFCControllerDriver; class NFCControllerDriver;
/**
* @addtogroup nfc
* @{
*/
/**
* This class represents a NFC Controller.
*
* A controller can be in one of three different states:
* * Idle/sleep state
* * Discovery state: The controller tries to discover a remote endpoint (initiator or target)
* * Connected state: The controller exchanges data with an endpoint (initiator or target)
*
* A NFCController instance needs to be initialized with a NFCControllerDriver instance which abstracts the specific controller being used.
* A delegate needs to be set by the user to receive discovery events.
*/
class NFCController : private NFCControllerDriver::Delegate {
public:
/** /**
* @addtogroup nfc * The NFCController delegate. Users of the NFCController class need to implement this delegate's methods to receive events.
* @{
*/ */
struct Delegate {
/**
* This class represents a NFC Controller.
*
* A controller can be in one of three different states:
* * Idle/sleep state
* * Discovery state: The controller tries to discover a remote endpoint (initiator or target)
* * Connected state: The controller exchanges data with an endpoint (initiator or target)
*
* A NFCController instance needs to be initialized with a NFCControllerDriver instance which abstracts the specific controller being used.
* A delegate needs to be set by the user to receive discovery events.
*/
class NFCController : private NFCControllerDriver::Delegate {
public:
/** /**
* The NFCController delegate. Users of the NFCController class need to implement this delegate's methods to receive events. * A enumeration of causes for the discovery process terminating.
*/ */
struct Delegate { enum nfc_discovery_terminated_reason_t {
/** nfc_discovery_terminated_completed = 0, ///< Process completed, at least one endpoint was discovered
* A enumeration of causes for the discovery process terminating. nfc_discovery_terminated_canceled, ///< Process was canceled by the user
*/ nfc_discovery_terminated_rf_error ///< An unexpected error was encountered during an exchange on the air interface
enum nfc_discovery_terminated_reason_t {
nfc_discovery_terminated_completed = 0, ///< Process completed, at least one endpoint was discovered
nfc_discovery_terminated_canceled, ///< Process was canceled by the user
nfc_discovery_terminated_rf_error ///< An unexpected error was encountered during an exchange on the air interface
};
/**
* The discovery process terminated.
* @param[in] reason the cause for the termination
*/
virtual void on_discovery_terminated(nfc_discovery_terminated_reason_t reason) {}
/**
* A remote initiator was discovered (the local controller is in target mode).
* @param[in] the NFCRemoteInitiator instance
*/
virtual void on_nfc_initiator_discovered(const SharedPtr<NFCRemoteInitiator>& nfc_initiator) {}
/**
* A remote target was discovered (the local controller is in initiator mode).
* @param[in] the NFCRemoteTarget instance
*/
virtual void on_nfc_target_discovered(const SharedPtr<NFCRemoteTarget>& nfc_target) {}
}; };
/** /**
* Construct a NFCController instance. * The discovery process terminated.
* * @param[in] reason the cause for the termination
* @param[in] driver a pointer to a NFCControllerDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer a bytes array used to store NDEF messages
* @param[in] ndef_buffer_sz the array size in bytes
*/ */
NFCController(NFCControllerDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz); virtual void on_discovery_terminated(nfc_discovery_terminated_reason_t reason) {}
/** /**
* Initialize the NFC controller * A remote initiator was discovered (the local controller is in target mode).
* * @param[in] the NFCRemoteInitiator instance
* This method must be called before any other method call.
*
* @return NFC_OK, or an error.
*/ */
nfc_err_t initialize(); virtual void on_nfc_initiator_discovered(const SharedPtr<NFCRemoteInitiator> &nfc_initiator) {}
/**
* Set the delegate that will receive events generated by this controller.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_delegate(Delegate* delegate);
/** /**
* Get the list of RF protocols supported by this controller. * A remote target was discovered (the local controller is in initiator mode).
* * @param[in] the NFCRemoteTarget instance
* @return a bitmask of RF protocols supported by the controller
*/ */
nfc_rf_protocols_bitmask_t get_supported_rf_protocols() const; virtual void on_nfc_target_discovered(const SharedPtr<NFCRemoteTarget> &nfc_target) {}
/**
* Set the list of RF protocols to look for during discovery.
*
* @param[in] rf_protocols the relevant bitmask
* @return NFC_OK on success, or
* NFC_ERR_UNSUPPORTED if a protocol is not supported by the controller,
* NFC_ERR_BUSY if the discovery process is already running
*/
nfc_err_t configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols);
/**
* Start the discovery process using the protocols configured previously.
*
* If remote endpoints are connected when this is called, they will be disconnected.
*
* @return NFC_OK on success, or
* NFC_ERR_BUSY if the discovery process is already running
*/
nfc_err_t start_discovery();
/**
* Cancel/stop a running discovery process.
*
* @return NFC_OK
*/
nfc_err_t cancel_discovery();
private:
friend class NFCRemoteEndpoint;
friend class NFCRemoteInitiator;
friend class Type4RemoteInitiator;
nfc_transceiver_t* transceiver() const;
void polling_callback(nfc_err_t ret);
// NFC Stack scheduler
void scheduler_process(bool hw_interrupt);
// Callbacks from NFC stack
static void s_polling_callback(nfc_transceiver_t* pTransceiver, nfc_err_t ret, void* pUserData);
// Implementation of NFCControllerDriver::Delegate
void on_hw_interrupt();
// Triggers when scheduler must be run again
void on_timeout();
NFCControllerDriver* _driver;
events::EventQueue* _queue;
nfc_transceiver_t* _transceiver;
nfc_scheduler_t* _scheduler;
Timer _timer;
Timeout _timeout;
Delegate* _delegate;
bool _discovery_running;
uint8_t* _ndef_buffer;
size_t _ndef_buffer_sz;
}; };
/** /**
* @} * Construct a NFCController instance.
*
* @param[in] driver a pointer to a NFCControllerDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer a bytes array used to store NDEF messages
* @param[in] ndef_buffer_sz the array size in bytes
*/ */
NFCController(NFCControllerDriver *driver, events::EventQueue *queue, uint8_t *ndef_buffer, size_t ndef_buffer_sz);
/**
* Initialize the NFC controller
*
* This method must be called before any other method call.
*
* @return NFC_OK, or an error.
*/
nfc_err_t initialize();
/**
* Set the delegate that will receive events generated by this controller.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_delegate(Delegate *delegate);
/**
* Get the list of RF protocols supported by this controller.
*
* @return a bitmask of RF protocols supported by the controller
*/
nfc_rf_protocols_bitmask_t get_supported_rf_protocols() const;
/**
* Set the list of RF protocols to look for during discovery.
*
* @param[in] rf_protocols the relevant bitmask
* @return NFC_OK on success, or
* NFC_ERR_UNSUPPORTED if a protocol is not supported by the controller,
* NFC_ERR_BUSY if the discovery process is already running
*/
nfc_err_t configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols);
/**
* Start the discovery process using the protocols configured previously.
*
* If remote endpoints are connected when this is called, they will be disconnected.
*
* @return NFC_OK on success, or
* NFC_ERR_BUSY if the discovery process is already running
*/
nfc_err_t start_discovery();
/**
* Cancel/stop a running discovery process.
*
* @return NFC_OK
*/
nfc_err_t cancel_discovery();
private:
friend class NFCRemoteEndpoint;
friend class NFCRemoteInitiator;
friend class Type4RemoteInitiator;
nfc_transceiver_t *transceiver() const;
void polling_callback(nfc_err_t ret);
// NFC Stack scheduler
void scheduler_process(bool hw_interrupt);
// Callbacks from NFC stack
static void s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData);
// Implementation of NFCControllerDriver::Delegate
void on_hw_interrupt();
// Triggers when scheduler must be run again
void on_timeout();
NFCControllerDriver *_driver;
events::EventQueue *_queue;
nfc_transceiver_t *_transceiver;
nfc_scheduler_t *_scheduler;
Timer _timer;
Timeout _timeout;
Delegate *_delegate;
bool _discovery_running;
uint8_t *_ndef_buffer;
size_t _ndef_buffer_sz;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -27,67 +27,67 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* The abstraction for a NFC controller driver.
* Implementers need to derive from this class and implement its methods.
*/
class NFCControllerDriver {
/** /**
* @addtogroup nfc * Instantiate a NFCControllerDriver
* @{
*/ */
NFCControllerDriver();
/** /**
* The abstraction for a NFC controller driver. * The NFCControllerDriver delegate
* Implementers need to derive from this class and implement its methods. */
*/ struct Delegate {
class NFCControllerDriver {
/** /**
* Instantiate a NFCControllerDriver * Called when the controller asserts the interrupt line
*/ */
NFCControllerDriver(); virtual void on_hw_interrupt() {}
/**
* The NFCControllerDriver delegate
*/
struct Delegate {
/**
* Called when the controller asserts the interrupt line
*/
virtual void on_hw_interrupt() {}
};
/**
* Initialize the driver and retrieve the interface to the controller.
*
* @param[in] scheduler_timer a timer to initialize the controller's scheduler instance with
* @return an initialized MicroNFC nfc_transceiver_t instance
*/
virtual nfc_transceiver_t* initialize(nfc_scheduler_timer_t* scheduler_timer) = 0;
/**
* Retrieve list of technologies supported by the controller
* @param[out] initiator bitmask of technologies supported when the controller is in initiator mode
* @param[out] target bitmask of technologies supported when the controller is in target mode
*/
virtual void get_supported_nfc_techs(nfc_tech_t* initiator, nfc_tech_t* target) const = 0;
/**
* Set this instance's delegate
*
* @param[in] delegate the delegate instance to use
*/
void set_delegate(Delegate* delegate);
protected:
/**
* An implementation must call this function (can be called from interrupt context)
* when the controller asserts its interrupt line
*/
void hw_interrupt();
private:
Delegate* _delegate;
}; };
/** /**
* @} * Initialize the driver and retrieve the interface to the controller.
*
* @param[in] scheduler_timer a timer to initialize the controller's scheduler instance with
* @return an initialized MicroNFC nfc_transceiver_t instance
*/ */
virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer) = 0;
/**
* Retrieve list of technologies supported by the controller
* @param[out] initiator bitmask of technologies supported when the controller is in initiator mode
* @param[out] target bitmask of technologies supported when the controller is in target mode
*/
virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const = 0;
/**
* Set this instance's delegate
*
* @param[in] delegate the delegate instance to use
*/
void set_delegate(Delegate *delegate);
protected:
/**
* An implementation must call this function (can be called from interrupt context)
* when the controller asserts its interrupt line
*/
void hw_interrupt();
private:
Delegate *_delegate;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -24,31 +24,30 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
struct nfc_rf_protocols_bitmask_t struct nfc_rf_protocols_bitmask_t {
{ uint8_t initiator_t1t : 1;
uint8_t initiator_t1t : 1; uint8_t initiator_t2t : 1;
uint8_t initiator_t2t : 1; uint8_t initiator_t3t : 1;
uint8_t initiator_t3t : 1; uint8_t initiator_iso_dep : 1;
uint8_t initiator_iso_dep : 1; uint8_t initiator_nfc_dep : 1;
uint8_t initiator_nfc_dep : 1; uint8_t initiator_t5t : 1;
uint8_t initiator_t5t : 1;
uint8_t target_t1t : 1; uint8_t target_t1t : 1;
uint8_t target_t2t : 1; uint8_t target_t2t : 1;
uint8_t target_t3t : 1; uint8_t target_t3t : 1;
uint8_t target_iso_dep : 1; uint8_t target_iso_dep : 1;
uint8_t target_nfc_dep : 1; uint8_t target_nfc_dep : 1;
uint8_t target_t5t : 1; uint8_t target_t5t : 1;
}; };
enum nfc_tag_type_t { enum nfc_tag_type_t {
nfc_tag_type_1, nfc_tag_type_1,
nfc_tag_type_2, nfc_tag_type_2,
nfc_tag_type_3, nfc_tag_type_3,
nfc_tag_type_4a, nfc_tag_type_4a,
nfc_tag_type_4b, nfc_tag_type_4b,
nfc_tag_type_5 nfc_tag_type_5
}; };
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -26,110 +26,110 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* The NFC EEPROM class represents a NFC target device connected using a wired
* link (I2C, SPI, etc).
*
* These EEPROMs essentially provide addressable memory that can be accessed
* using either a wired or NFC interface.
*
* In NFC mode these most often conform to one of the NFC tag types defined
* by the NFC Forum, therefore encoding NDEF data in these EEPROMs will
* ensure that it is understandable by a NFC reader.
*/
class NFCEEPROM : public NFCTarget, public NFCEEPROMDriver::Delegate {
public:
/** /**
* @addtogroup nfc * Construct a NFCEEPROM instance.
* @{ *
* @param[in] driver a pointer to a NFCEEPROMDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer a bytes array used to store NDEF messages
* @param[in] ndef_buffer_sz the array size in bytes
*/ */
NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, uint8_t *ndef_buffer, size_t ndef_buffer_sz);
/** /**
* The NFC EEPROM class represents a NFC target device connected using a wired * The NFCEEPROM delegate. Users of the NFCEEPROM class need to implement this delegate's methods to receive events.
* link (I2C, SPI, etc). */
* struct Delegate : NFCTarget::Delegate {
* These EEPROMs essentially provide addressable memory that can be accessed
* using either a wired or NFC interface.
*
* In NFC mode these most often conform to one of the NFC tag types defined
* by the NFC Forum, therefore encoding NDEF data in these EEPROMs will
* ensure that it is understandable by a NFC reader.
*/
class NFCEEPROM : public NFCTarget, public NFCEEPROMDriver::Delegate {
public:
/**
* Construct a NFCEEPROM instance.
*
* @param[in] driver a pointer to a NFCEEPROMDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer a bytes array used to store NDEF messages
* @param[in] ndef_buffer_sz the array size in bytes
*/
NFCEEPROM(NFCEEPROMDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz);
/**
* The NFCEEPROM delegate. Users of the NFCEEPROM class need to implement this delegate's methods to receive events.
*/
struct Delegate : NFCTarget::Delegate {
};
/**
* Initialize the NFC EEPROM
*
* This method must be called before any other method call.
*
* @return NFC_OK, or an error.
*/
nfc_err_t initialize();
/**
* Set the delegate that will receive events generated by this EEPROM.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_delegate(Delegate* delegate);
private:
// Implementation of NFCTarget
virtual void write_ndef_message();
virtual void read_ndef_message();
virtual void erase_ndef_message();
// Implementation of NFCEEPROMDriver::Delegate
virtual void on_session_started(bool success);
virtual void on_session_ended(bool success);
virtual void on_bytes_read(size_t count);
virtual void on_bytes_written(size_t count);
virtual void on_size_written(bool success);
virtual void on_size_read(bool success, size_t size);
virtual void on_bytes_erased(size_t count);
virtual void on_event();
void handle_error(nfc_err_t ret);
void continue_write();
void continue_read();
void continue_erase();
enum class nfc_eeprom_operation_t {
nfc_eeprom_idle,
nfc_eeprom_write_start_session,
nfc_eeprom_write_write_bytes,
nfc_eeprom_write_write_size,
nfc_eeprom_write_end_session,
nfc_eeprom_write_start_session,
nfc_eeprom_read_read_size,
nfc_eeprom_read_read_bytes,
nfc_eeprom_read_end_session,
nfc_eeprom_erase_start_session,
nfc_eeprom_erase_erase_bytes,
nfc_eeprom_erase_write_size,
nfc_eeprom_erase_end_session
};
NFCEEPROMDriver* _driver;
events::EventQueue* _queue;
bool _initialized;
nfc_eeprom_operation_t _current_op;
buffer_t _ndef_buffer_reader;
size_t _ndef_buffer_read_sz;
uint32_t _eeprom_address;
nfc_err_t _operation_result;
}; };
/** /**
* @} * Initialize the NFC EEPROM
*
* This method must be called before any other method call.
*
* @return NFC_OK, or an error.
*/ */
nfc_err_t initialize();
/**
* Set the delegate that will receive events generated by this EEPROM.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_delegate(Delegate *delegate);
private:
// Implementation of NFCTarget
virtual void write_ndef_message();
virtual void read_ndef_message();
virtual void erase_ndef_message();
// Implementation of NFCEEPROMDriver::Delegate
virtual void on_session_started(bool success);
virtual void on_session_ended(bool success);
virtual void on_bytes_read(size_t count);
virtual void on_bytes_written(size_t count);
virtual void on_size_written(bool success);
virtual void on_size_read(bool success, size_t size);
virtual void on_bytes_erased(size_t count);
virtual void on_event();
void handle_error(nfc_err_t ret);
void continue_write();
void continue_read();
void continue_erase();
enum class nfc_eeprom_operation_t {
nfc_eeprom_idle,
nfc_eeprom_write_start_session,
nfc_eeprom_write_write_bytes,
nfc_eeprom_write_write_size,
nfc_eeprom_write_end_session,
nfc_eeprom_write_start_session,
nfc_eeprom_read_read_size,
nfc_eeprom_read_read_bytes,
nfc_eeprom_read_end_session,
nfc_eeprom_erase_start_session,
nfc_eeprom_erase_erase_bytes,
nfc_eeprom_erase_write_size,
nfc_eeprom_erase_end_session
};
NFCEEPROMDriver *_driver;
events::EventQueue *_queue;
bool _initialized;
nfc_eeprom_operation_t _current_op;
buffer_t _ndef_buffer_reader;
size_t _ndef_buffer_read_sz;
uint32_t _eeprom_address;
nfc_err_t _operation_result;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc

View File

@ -26,173 +26,173 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* The abstraction for a NFC EEPROM driver.
* Implementers need to derive from this class and implement its methods.
*/
class NFCEEPROMDriver {
public:
/** /**
* @addtogroup nfc * Construct a NFCEEPROM driver instance.
* @{
*/ */
NFCEEPROMDriver();
/** /**
* The abstraction for a NFC EEPROM driver. * The NFCEEPROMDriver delegate.
* Implementers need to derive from this class and implement its methods. * Methods in this class are called by the driver on completion of long-running operations.
*/ */
class NFCEEPROMDriver { struct Delegate {
public:
/** /**
* Construct a NFCEEPROM driver instance. * Completion of session start operation.
*
* @param[in] success whether this operation succeeded
*/ */
NFCEEPROMDriver(); virtual void on_session_started(bool success) = 0;
/** /**
* The NFCEEPROMDriver delegate. * Completion of session end operation.
* Methods in this class are called by the driver on completion of long-running operations. *
* @param[in] success whether this operation succeeded
*/ */
struct Delegate { virtual void on_session_ended(bool success) = 0;
/**
* Completion of session start operation.
*
* @param[in] success whether this operation succeeded
*/
virtual void on_session_started(bool success) = 0;
/**
* Completion of session end operation.
*
* @param[in] success whether this operation succeeded
*/
virtual void on_session_ended(bool success) = 0;
/**
* Completion of read operation.
*
* @param[in] count number of bytes actually read
*/
virtual void on_bytes_read(size_t count) = 0;
/**
* Completion of write operation.
*
* @param[in] count number of bytes actually written
*/
virtual void on_bytes_written(size_t count) = 0;
/**
* Completion of size retrieval operation.
*
* @param[in] success whether this operation succeeded
* @param[out] the current addressable memory size
*/
virtual void on_size_read(bool success, size_t size) = 0;
/**
* Completion of size setting operation.
*
* @param[in] success whether this operation succeeded
*/
virtual void on_size_written(bool success) = 0;
/**
* Completion of erasing operation.
*
* @param[in] count number of bytes actually erased
*/
virtual void on_bytes_erased(size_t count) = 0;
/**
* Signal the user that the process_events() need to be called
*
* @note this function can be called in interrupt context
*/
virtual void on_event() = 0;
};
/**
* Set the delegate that will receive events generated by this EEPROM.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_delegate(Delegate* delegate);
/**
* Reset and initialize the EEPROM.
* This method should complete synchronously.
*/
virtual void reset() = 0;
/** /**
* Process events raised by the driver in interrupt context. * Completion of read operation.
*/ *
virtual void process_events(); * @param[in] count number of bytes actually read
*/
virtual void on_bytes_read(size_t count) = 0;
/** /**
* Get the maximum memory size addressable by the EEPROM. * Completion of write operation.
*/ *
virtual size_t get_max_size() = 0; * @param[in] count number of bytes actually written
*/
virtual void on_bytes_written(size_t count) = 0;
/** /**
* Start a session of operations (reads, writes, erases, size gets/sets). * Completion of size retrieval operation.
* This method is called prior to any memory access to allow the underlying implementation *
* to disable the RF interface or abort the transaction if it's being used. * @param[in] success whether this operation succeeded
* This method should complete asynchronously by calling has_started_session(). * @param[out] the current addressable memory size
*/ */
virtual void start_session() = 0; // This could lock the chip's RF interface virtual void on_size_read(bool success, size_t size) = 0;
/** /**
* End a session. * Completion of size setting operation.
* This method should complete asynchronously by calling has_ended_session(). *
*/ * @param[in] success whether this operation succeeded
virtual void end_session() = 0; */
virtual void on_size_written(bool success) = 0;
/** /**
* Read bytes from memory. * Completion of erasing operation.
* @param[in] address the virtual address (starting from 0) from which to start the read. *
* @param[out] bytes a buffer in which the read bytes will be stored. * @param[in] count number of bytes actually erased
* This buffer should remain valid till the callback is called. */
* @oaram[in] count the number of bytes to read. virtual void on_bytes_erased(size_t count) = 0;
* This method should complete asynchronously by calling has_read_bytes().
*/
virtual void read_bytes(uint32_t address, uint8_t* bytes, size_t count) = 0;
/** /**
* Write bytes to memory. * Signal the user that the process_events() need to be called
* @param[in] address the virtual address (starting from 0) from which to start the write. *
* @param[in] bytes a buffer from to copy. * @note this function can be called in interrupt context
* This buffer should remain valid till the callback is called. */
* @oaram[in] count the number of bytes to write. virtual void on_event() = 0;
* This method should complete asynchronously by calling has_written_bytes().
*/
virtual void write_bytes(uint32_t address, const uint8_t* bytes, size_t count) = 0;
/**
* Retrieve the size of the addressable memory.
* This method should complete asynchronously by calling has_gotten_size().
*/
virtual void read_size() = 0;
/**
* Set the size of the addressable memory.
* @oaram[in] count the number of addressable bytes.
* This method should complete asynchronously by calling has_set_size().
*/
virtual void write_size(size_t count) = 0;
/**
* Erase bytes from memory.
* @param[in] address the virtual address (starting from 0) from which to start erasing.
* @oaram[in] count the number of bytes to erase.
* This method should complete asynchronously by calling has_erased_bytes().
*/
virtual void erase_bytes(uint32_t address, size_t size) = 0;
protected:
Delegate* delegate();
private:
Delegate* _delegate;
}; };
/** /**
* @} * Set the delegate that will receive events generated by this EEPROM.
*
* @oaram[in] delegate the delegate instance to use
*/ */
void set_delegate(Delegate *delegate);
/**
* Reset and initialize the EEPROM.
* This method should complete synchronously.
*/
virtual void reset() = 0;
/**
* Process events raised by the driver in interrupt context.
*/
virtual void process_events();
/**
* Get the maximum memory size addressable by the EEPROM.
*/
virtual size_t get_max_size() = 0;
/**
* Start a session of operations (reads, writes, erases, size gets/sets).
* This method is called prior to any memory access to allow the underlying implementation
* to disable the RF interface or abort the transaction if it's being used.
* This method should complete asynchronously by calling has_started_session().
*/
virtual void start_session() = 0; // This could lock the chip's RF interface
/**
* End a session.
* This method should complete asynchronously by calling has_ended_session().
*/
virtual void end_session() = 0;
/**
* Read bytes from memory.
* @param[in] address the virtual address (starting from 0) from which to start the read.
* @param[out] bytes a buffer in which the read bytes will be stored.
* This buffer should remain valid till the callback is called.
* @oaram[in] count the number of bytes to read.
* This method should complete asynchronously by calling has_read_bytes().
*/
virtual void read_bytes(uint32_t address, uint8_t *bytes, size_t count) = 0;
/**
* Write bytes to memory.
* @param[in] address the virtual address (starting from 0) from which to start the write.
* @param[in] bytes a buffer from to copy.
* This buffer should remain valid till the callback is called.
* @oaram[in] count the number of bytes to write.
* This method should complete asynchronously by calling has_written_bytes().
*/
virtual void write_bytes(uint32_t address, const uint8_t *bytes, size_t count) = 0;
/**
* Retrieve the size of the addressable memory.
* This method should complete asynchronously by calling has_gotten_size().
*/
virtual void read_size() = 0;
/**
* Set the size of the addressable memory.
* @oaram[in] count the number of addressable bytes.
* This method should complete asynchronously by calling has_set_size().
*/
virtual void write_size(size_t count) = 0;
/**
* Erase bytes from memory.
* @param[in] address the virtual address (starting from 0) from which to start erasing.
* @oaram[in] count the number of bytes to erase.
* This method should complete asynchronously by calling has_erased_bytes().
*/
virtual void erase_bytes(uint32_t address, size_t size) = 0;
protected:
Delegate *delegate();
private:
Delegate *_delegate;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -24,93 +24,99 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* The base class for all endpoints that can support NDEF content.
*/
class NFCNDEFCapable {
public:
/** /**
* @addtogroup nfc * Construct a NFCNDEFCapable instance.
* @{ * @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/ */
NFCNDEFCapable(uint8_t *buffer, size_t buffer_size);
/** /**
* The base class for all endpoints that can support NDEF content. * Check if this instance actually supports NDEF content.
*/ *
class NFCNDEFCapable { * @return whether NDEF content is supported
public: */
/** virtual bool is_ndef_supported() const
* Construct a NFCNDEFCapable instance. {
* @param[in] buffer a bytes array used to store NDEF messages return false;
* @param[in] buffer_size the array size in bytes }
*/
NFCNDEFCapable(uint8_t* buffer, size_t buffer_size);
/** struct Delegate {
* Check if this instance actually supports NDEF content.
*
* @return whether NDEF content is supported
*/
virtual bool is_ndef_supported() const { return false; }
struct Delegate {
/**
* Parse a NDEF message.
*
* @param[in] buffer a buffer containing the message to parse
* @param[in] size the buffer's size
*/
virtual void parse_ndef_message(const uint8_t* buffer, size_t size) { }
/**
* Build a NDEF message.
*
* @param[in] buffer a mutable buffer in which the message should be stored
* @param[in] capacity the buffer's capacity
* @return the number of bytes actually used
*/
virtual size_t build_ndef_message(uint8_t* buffer, size_t capacity) { return 0; }
};
/**
* Set the delegate that will receive events generated by this class.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_ndef_delegate(Delegate* delegate);
protected:
/** /**
* Parse a NDEF message. * Parse a NDEF message.
* *
* @param[in] a buffer containing a NDEF message * @param[in] buffer a buffer containing the message to parse
*/ * @param[in] size the buffer's size
void parse_ndef_message(const ac_buffer_t& buffer); */
virtual void parse_ndef_message(const uint8_t *buffer, size_t size) { }
/** /**
* Build NDEF message. * Build a NDEF message.
* *
* @param[in,out] a buffer builder in which to create the NDEF message. * @param[in] buffer a mutable buffer in which the message should be stored
* The backing buffer is guaranteed to be continuous. * @param[in] capacity the buffer's capacity
*/ * @return the number of bytes actually used
void build_ndef_message(ac_buffer_builder_t& buffer_builder); */
virtual size_t build_ndef_message(uint8_t *buffer, size_t capacity)
/** {
* Retrieve underlying NDEF message instance return 0;
* @return pointer to NDEF message instance }
*/
ndef_msg_t* ndef_message();
private:
// Callbacks from NDEF stack
static nfc_err_t s_ndef_encode(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData);
static nfc_err_t s_ndef_decode(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData);
nfc_err_t ndef_encode(buffer_builder_t* pBufferBldr);
nfc_err_t ndef_decode(buffer_t* pBuffer);
Delegate* _delegate;
ndef_msg_t _ndef_message;
}; };
/** /**
* @} * Set the delegate that will receive events generated by this class.
*
* @oaram[in] delegate the delegate instance to use
*/ */
void set_ndef_delegate(Delegate *delegate);
protected:
/**
* Parse a NDEF message.
*
* @param[in] a buffer containing a NDEF message
*/
void parse_ndef_message(const ac_buffer_t &buffer);
/**
* Build NDEF message.
*
* @param[in,out] a buffer builder in which to create the NDEF message.
* The backing buffer is guaranteed to be continuous.
*/
void build_ndef_message(ac_buffer_builder_t &buffer_builder);
/**
* Retrieve underlying NDEF message instance
* @return pointer to NDEF message instance
*/
ndef_msg_t *ndef_message();
private:
// Callbacks from NDEF stack
static nfc_err_t s_ndef_encode(ndef_msg_t *pTag, buffer_builder_t *pBufferBldr, void *pUserData);
static nfc_err_t s_ndef_decode(ndef_msg_t *pTag, buffer_t *pBuffer, void *pUserData);
nfc_err_t ndef_encode(buffer_builder_t *pBufferBldr);
nfc_err_t ndef_decode(buffer_t *pBuffer);
Delegate *_delegate;
ndef_msg_t _ndef_message;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -24,83 +24,83 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
class NFCController;
/**
* This is the base class for all remote endpoints (initiators and targets)
* addressable over the air interface.
*/
class NFCRemoteEndpoint {
public:
NFCRemoteEndpoint();
/** /**
* @addtogroup nfc * The NFCRemoteEndpoint base delegate.
* @{
*/ */
struct Delegate {
class NFCController;
/**
* This is the base class for all remote endpoints (initiators and targets)
* addressable over the air interface.
*/
class NFCRemoteEndpoint {
public:
NFCRemoteEndpoint();
/** /**
* The NFCRemoteEndpoint base delegate. * This method is called when the endpoint is connected
*/ */
struct Delegate { virtual void on_connected() {};
/**
* This method is called when the endpoint is connected
*/
virtual void on_connected() {};
/**
* This method is called when the endpoint is lost (air interface link disconnnected)
*/
virtual void on_disconnected() {};
};
/** /**
* Connect the remote endpoint * This method is called when the endpoint is lost (air interface link disconnnected)
*
* @return NFC_OK or an error code
*/ */
virtual nfc_err_t connect() = 0; virtual void on_disconnected() {};
/**
* Disconnect the remote endpoint
*
* @return NFC_OK or an error code
*/
virtual nfc_err_t disconnect() = 0;
/**
* Check if the endpoint is connected.
* @return whether the endpoint is connected
*/
virtual bool is_connected() const = 0;
/**
* Check if the endpoint is disconnected/lost.
* @return whether the endpoint has been disconnected
*/
virtual bool is_disconnected() const = 0;
/**
* Get the list of RF protocols supported and activated over the air interface.
* @return a bitmask of activated protocols
*/
virtual nfc_rf_protocols_bitmask_t rf_protocols() = 0;
protected:
/**
* Mark endpoint as connected
*/
void connected();
/**
* Mark endpoint as disconnected
*/
void disconnected();
}; };
/** /**
* @} * Connect the remote endpoint
*
* @return NFC_OK or an error code
*/ */
virtual nfc_err_t connect() = 0;
/**
* Disconnect the remote endpoint
*
* @return NFC_OK or an error code
*/
virtual nfc_err_t disconnect() = 0;
/**
* Check if the endpoint is connected.
* @return whether the endpoint is connected
*/
virtual bool is_connected() const = 0;
/**
* Check if the endpoint is disconnected/lost.
* @return whether the endpoint has been disconnected
*/
virtual bool is_disconnected() const = 0;
/**
* Get the list of RF protocols supported and activated over the air interface.
* @return a bitmask of activated protocols
*/
virtual nfc_rf_protocols_bitmask_t rf_protocols() = 0;
protected:
/**
* Mark endpoint as connected
*/
void connected();
/**
* Mark endpoint as disconnected
*/
void disconnected();
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -26,70 +26,70 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
class NFCController;
/**
* This class represents a remote NFC initiator (the local controller being in target mode).
*
* An initiator can be a NFC reader, a NFC-enabled phone or other NFC device capable of generating a RF field.
*/
class NFCRemoteInitiator : public NFCRemoteEndpoint, public NFCNDEFCapable {
public:
/** /**
* @addtogroup nfc * Create a NFCRemoteInitiator.
* @{ * @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/ */
NFCRemoteInitiator(uint8_t *buffer, size_t buffer_size);
virtual ~NFCRemoteInitiator();
class NFCController;
/** /**
* This class represents a remote NFC initiator (the local controller being in target mode). * The NFCRemoteInitiator delegate. Users of the NFCRemoteInitiator class need to implement this delegate's methods to receive events.
* */
* An initiator can be a NFC reader, a NFC-enabled phone or other NFC device capable of generating a RF field. struct Delegate : NFCEndpoint::Delegate, NFCNDEFCapable::Delegate {
*/
class NFCRemoteInitiator : public NFCRemoteEndpoint, public NFCNDEFCapable {
public:
/**
* Create a NFCRemoteInitiator.
* @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/
NFCRemoteInitiator(uint8_t* buffer, size_t buffer_size);
virtual ~NFCRemoteInitiator();
/**
* The NFCRemoteInitiator delegate. Users of the NFCRemoteInitiator class need to implement this delegate's methods to receive events.
*/
struct Delegate : NFCEndpoint::Delegate, NFCNDEFCapable::Delegate {
};
/**
* Set the delegate that will receive events generated by the initiator.
*
* @oaram[in] delegate the delegate instance to use
*/
void set_remote_initiator_delegate(Delegate* delegate);
/**
* Retrieve the NFC tag type exposed by the controller to communicate with the initiator.
*
* @return the relevant NFC tag type
*/
virtual nfc_tag_type_t nfc_tag_type() const = 0;
/**
* Retrieve whether ISO7816 applications are supported by the underlying technology.
*
* @return whether ISO7816 applications are supported
*/
virtual bool is_iso7816_supported() const = 0;
/**
* Register an ISO7816 application to be used by the initiator.
*
* @param[in] application a pointer to an ISO7816App instance
*/
virtual void add_iso7816_application(ISO7816App* application) = 0;
private:
Delegate* _delegate;
}; };
/** /**
* @} * Set the delegate that will receive events generated by the initiator.
*
* @oaram[in] delegate the delegate instance to use
*/ */
void set_remote_initiator_delegate(Delegate *delegate);
/**
* Retrieve the NFC tag type exposed by the controller to communicate with the initiator.
*
* @return the relevant NFC tag type
*/
virtual nfc_tag_type_t nfc_tag_type() const = 0;
/**
* Retrieve whether ISO7816 applications are supported by the underlying technology.
*
* @return whether ISO7816 applications are supported
*/
virtual bool is_iso7816_supported() const = 0;
/**
* Register an ISO7816 application to be used by the initiator.
*
* @param[in] application a pointer to an ISO7816App instance
*/
virtual void add_iso7816_application(ISO7816App *application) = 0;
private:
Delegate *_delegate;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -26,75 +26,75 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* This class represents a NFC target (either a remote target when the local controller in in initiator mode, or a target connected through a wired connection).
*
* A target can be a NFC tag/card, a NFC-enabled phone or other NFC device capable of modulating a RF field.
*/
class NFCTarget : public NFCNDEFCapable {
public:
/** /**
* @addtogroup nfc * Create a NFCTarget.
* @{ *
* @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/ */
NFCTarget(uint8_t *buffer, size_t buffer_size);
/** virtual ~NFCTarget();
* This class represents a NFC target (either a remote target when the local controller in in initiator mode, or a target connected through a wired connection).
* struct Delegate {
* A target can be a NFC tag/card, a NFC-enabled phone or other NFC device capable of modulating a RF field.
*/
class NFCTarget : public NFCNDEFCapable {
public:
/** /**
* Create a NFCTarget. * The NDEF message erasing request completed.
* *
* @param[in] buffer a bytes array used to store NDEF messages * @param[in] result NFC_OK or an error code on failure
* @param[in] buffer_size the array size in bytes */
*/ virtual void on_ndef_message_erased(nfc_err_t result) {}
NFCTarget(uint8_t* buffer, size_t buffer_size);
virtual ~NFCTarget();
struct Delegate {
/**
* The NDEF message erasing request completed.
*
* @param[in] result NFC_OK or an error code on failure
*/
virtual void on_ndef_message_erased(nfc_err_t result) {}
/**
* The NDEF message writing request completed.
*
* @param[in] result NFC_OK or an error code on failure
*/
virtual void on_ndef_message_written(nfc_err_t result) {}
/**
* The NDEF message reading request completed.
*
* @param[in] result NFC_OK or an error code on failure
*/
virtual void on_ndef_message_read(nfc_err_t result) {}
};
/** /**
* Write a NDEF message to the target. * The NDEF message writing request completed.
* *
* on_ndef_message_written() will be called on completion. * @param[in] result NFC_OK or an error code on failure
*/ */
virtual void write_ndef_message() = 0; virtual void on_ndef_message_written(nfc_err_t result) {}
/** /**
* Read a NDEF message from the target. * The NDEF message reading request completed.
* *
* on_ndef_message_read() will be called on completion. * @param[in] result NFC_OK or an error code on failure
*/ */
virtual void read_ndef_message() = 0; virtual void on_ndef_message_read(nfc_err_t result) {}
/**
* Erase the NDEF message in the target.
*
* on_ndef_message_erased() will be called on completion.
*/
virtual void erase_ndef_message() = 0;
}; };
/** /**
* @} * Write a NDEF message to the target.
*
* on_ndef_message_written() will be called on completion.
*/ */
virtual void write_ndef_message() = 0;
/**
* Read a NDEF message from the target.
*
* on_ndef_message_read() will be called on completion.
*/
virtual void read_ndef_message() = 0;
/**
* Erase the NDEF message in the target.
*
* on_ndef_message_erased() will be called on completion.
*/
virtual void erase_ndef_message() = 0;
};
/**
* @}
*/
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -29,54 +29,54 @@
namespace mbed { namespace mbed {
namespace nfc { namespace nfc {
/**
* @addtogroup nfc
* @{
*/
/**
* This class is an implementation of the Type 4 tag application.
*/
class Type4RemoteInitiator : public NFCRemoteInitiator {
private:
/** /**
* @addtogroup nfc * Create a Type4RemoteInitiator.
* @{ *
* @param[in] controller pointer to the NFCController instance that created this object
* @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/ */
Type4RemoteInitiator(NFCController *controller, uint8_t *buffer, size_t buffer_size);
/**
* This class is an implementation of the Type 4 tag application.
*/
class Type4RemoteInitiator : public NFCRemoteInitiator {
private:
/**
* Create a Type4RemoteInitiator.
*
* @param[in] controller pointer to the NFCController instance that created this object
* @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/
Type4RemoteInitiator(NFCController* controller, uint8_t* buffer, size_t buffer_size);
// NFCRemoteEndpoint implementation // NFCRemoteEndpoint implementation
virtual nfc_err_t connect(); virtual nfc_err_t connect();
virtual nfc_err_t disconnect(); virtual nfc_err_t disconnect();
virtual bool is_connected(); virtual bool is_connected();
virtual bool is_disconnected(); virtual bool is_disconnected();
virtual nfc_rf_protocols_bitmask_t rf_protocols(); virtual nfc_rf_protocols_bitmask_t rf_protocols();
// NFCRemoteInitiator implementation // NFCRemoteInitiator implementation
virtual nfc_tag_type_t nfc_tag_type() const; virtual nfc_tag_type_t nfc_tag_type() const;
virtual bool is_iso7816_supported() const; virtual bool is_iso7816_supported() const;
virtual void add_iso7816_application(ISO7816App* application); virtual void add_iso7816_application(ISO7816App *application);
// NFCNDEFCapable implementation // NFCNDEFCapable implementation
virtual bool is_ndef_supported() const; virtual bool is_ndef_supported() const;
// Callbacks from NFC stack // Callbacks from NFC stack
void disconnected_callback(bool deselected); void disconnected_callback(bool deselected);
static void s_disconnected_callback(nfc_tech_iso7816_t* pIso7816, bool deselected, void* pUserData); static void s_disconnected_callback(nfc_tech_iso7816_t *pIso7816, bool deselected, void *pUserData);
NFCController* _controller; NFCController *_controller;
bool _is_connected; bool _is_connected;
bool _is_disconnected; bool _is_disconnected;
nfc_tech_iso7816_t _iso7816; nfc_tech_iso7816_t _iso7816;
nfc_tech_type4_target_t _type4; nfc_tech_type4_target_t _type4;
}; };
/** /**
* @} * @}
*/ */
} // namespace nfc } // namespace nfc
} // namespace mbed } // namespace mbed

View File

@ -16,17 +16,18 @@
#include "PN512Driver.h" #include "PN512Driver.h"
PN512Driver::PN512Driver(PN512TransportDriver* transport_driver) : NFCControllerDriver(), _transport_driver(transport_driver) { PN512Driver::PN512Driver(PN512TransportDriver *transport_driver) : NFCControllerDriver(), _transport_driver(transport_driver)
{
_transport_driver->set_delegate(this); _transport_driver->set_delegate(this);
} }
nfc_transceiver_t* PN512Driver::initialize(nfc_scheduler_timer_t* scheduler_timer) { nfc_transceiver_t *PN512Driver::initialize(nfc_scheduler_timer_t *scheduler_timer)
{
// Initialize transport // Initialize transport
_transport_driver->initialize(); _transport_driver->initialize();
nfc_err_t ret = pn512_init(&pn512, _transport_driver->get_transport(), scheduler_timer); nfc_err_t ret = pn512_init(&pn512, _transport_driver->get_transport(), scheduler_timer);
if( ret != NFC_OK ) if (ret != NFC_OK) {
{
NFC_ERR("PN512 init error (%d)", ret); NFC_ERR("PN512 init error (%d)", ret);
return NULL; return NULL;
} }
@ -35,7 +36,8 @@ nfc_transceiver_t* PN512Driver::initialize(nfc_scheduler_timer_t* scheduler_time
return pn512_get_transceiver(&pn512); return pn512_get_transceiver(&pn512);
} }
void PN512Driver::get_supported_nfc_techs(nfc_tech_t* initiator, nfc_tech_t* target) const { void PN512Driver::get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const
{
initiator->nfc_type1 = 0; initiator->nfc_type1 = 0;
initiator->nfc_type2 = 1; initiator->nfc_type2 = 1;
initiator->nfc_type3 = 1; initiator->nfc_type3 = 1;
@ -55,6 +57,7 @@ void PN512Driver::get_supported_nfc_techs(nfc_tech_t* initiator, nfc_tech_t* tar
target->nfc_nfc_dep_f_424 = 1; target->nfc_nfc_dep_f_424 = 1;
} }
void PN512Driver::on_hw_interrupt() { void PN512Driver::on_hw_interrupt()
{
hw_interrupt(); // Propagate interrupt signal hw_interrupt(); // Propagate interrupt signal
} }

View File

@ -22,12 +22,13 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst)) : PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst)) :
_spi(mosi, miso, sclk), _spi(mosi, miso, sclk),
_ssel(ssel, 1), _ssel(ssel, 1),
_irq(irq, PullNone), _irq(irq, PullNone),
_rst(rst, 1) { _rst(rst, 1)
{
// Use SPI mode 0 // Use SPI mode 0
_spi.format(8, 0); _spi.format(8, 0);
@ -38,7 +39,8 @@ PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, Pin
nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this); nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this);
} }
void PN512SPITransportDriver::initialize() { void PN512SPITransportDriver::initialize()
{
// Deactivate IRQ // Deactivate IRQ
_irq.rise(callback(NULL)); _irq.rise(callback(NULL));
@ -53,12 +55,14 @@ void PN512SPITransportDriver::initialize() {
_irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt)); _irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt));
} }
nfc_transport_t* PN512SPITransportDriver::get_transport() const { nfc_transport_t *PN512SPITransportDriver::get_transport() const
{
return &_nfc_transport; return &_nfc_transport;
} }
void PN512SPITransportDriver::transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen ) { void PN512SPITransportDriver::transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen)
if( outLen == 0 ) { {
if (outLen == 0) {
return; return;
} }
@ -70,19 +74,20 @@ void PN512SPITransportDriver::transport_write( uint8_t address, const uint8_t* o
_ssel = 1; _ssel = 1;
} }
void PN512SPITransportDriver::transport_read( uint8_t address, uint8_t* inBuf, size_t inLen ) { void PN512SPITransportDriver::transport_read(uint8_t address, uint8_t *inBuf, size_t inLen)
if( inLen == 0 ) { {
if (inLen == 0) {
return; return;
} }
// Address byte is (address << 1) | 0x80 for a read // Address byte is (address << 1) | 0x80 for a read
// This should be repeated accross the transfer, except for the last byte which should be 0 // This should be repeated accross the transfer, except for the last byte which should be 0
address = (address << 1) | 0x80; address = (address << 1) | 0x80;
// Set this byte across inBuf so that it's repeated accross the transfer // Set this byte across inBuf so that it's repeated accross the transfer
// Bit cheeky, but will work // Bit cheeky, but will work
memset(inBuf, address, inLen - 1); memset(inBuf, address, inLen - 1);
// Also terminate with 0 so that it's a no-op // Also terminate with 0 so that it's a no-op
inBuf[inLen - 1] = 0; inBuf[inLen - 1] = 0;
@ -93,12 +98,14 @@ void PN512SPITransportDriver::transport_read( uint8_t address, uint8_t* inBuf, s
} }
// Callbacks from munfc // Callbacks from munfc
static void PN512SPITransportDriver::s_transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen, void* pUser ) { static void PN512SPITransportDriver::s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser)
PN512SPITransportDriver* self = (PN512SPITransportDriver*)pUser; {
PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser;
self->transport_write(address, outBuf, outLen); self->transport_write(address, outBuf, outLen);
} }
static void PN512SPITransportDriver::s_transport_read( uint8_t address, uint8_t* inBuf, size_t inLen, void* pUser ) { static void PN512SPITransportDriver::s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser)
PN512SPITransportDriver* self = (PN512SPITransportDriver*)pUser; {
PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser;
self->transport_read(address, inBuf, inLen); self->transport_read(address, inBuf, inLen);
} }

View File

@ -19,16 +19,19 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
PN512TransportDriver::PN512TransportDriver() : _delegate(NULL) { PN512TransportDriver::PN512TransportDriver() : _delegate(NULL)
{
} }
void PN512TransportDriver::set_delegate(Delegate* delegate) { void PN512TransportDriver::set_delegate(Delegate *delegate)
{
_delegate = delegate; _delegate = delegate;
} }
void PN512TransportDriver::hw_interrupt() { void PN512TransportDriver::hw_interrupt()
if(_delegate != NULL) { {
if (_delegate != NULL) {
_delegate->on_hw_interrupt(); _delegate->on_hw_interrupt();
} }
} }

View File

@ -23,7 +23,7 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCController::NFCController(NFCControllerDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz) : NFCController::NFCController(NFCControllerDriver *driver, events::EventQueue *queue, uint8_t *ndef_buffer, size_t ndef_buffer_sz) :
_driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer_sz(ndef_buffer_sz) _driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer_sz(ndef_buffer_sz)
{ {
_driver->set_delegate(this); _driver->set_delegate(this);
@ -32,9 +32,9 @@ NFCController::NFCController(NFCControllerDriver* driver, events::EventQueue* qu
nfc_err_t NFCController::initialize() nfc_err_t NFCController::initialize()
{ {
MBED_ASSERT(_transceiver == NULL); // Initialize should only be called once MBED_ASSERT(_transceiver == NULL); // Initialize should only be called once
_transceiver = _driver->initialize((nfc_scheduler_timer_t*)&_timer); // See implementation below _transceiver = _driver->initialize((nfc_scheduler_timer_t *)&_timer); // See implementation below
if( _transceiver == NULL ) { if (_transceiver == NULL) {
// Initialization error // Initialization error
return NFC_ERR_CONTROLLER; // Controller error return NFC_ERR_CONTROLLER; // Controller error
} }
@ -46,7 +46,7 @@ nfc_err_t NFCController::initialize()
_queue->call(this, NFCController::scheduler_process, false); _queue->call(this, NFCController::scheduler_process, false);
} }
void NFCController::set_delegate(Delegate* delegate) void NFCController::set_delegate(Delegate *delegate)
{ {
_delegate = delegate; _delegate = delegate;
} }
@ -69,19 +69,19 @@ nfc_rf_protocols_bitmask_t NFCController::get_supported_rf_protocols() const
// rf_protocols.initiator_t3t = initiator_tech.nfc_type3; // rf_protocols.initiator_t3t = initiator_tech.nfc_type3;
// rf_protocols.initiator_iso_dep = initiator_tech.nfc_iso_dep_a || initiator_tech.nfc_iso_dep_b; // rf_protocols.initiator_iso_dep = initiator_tech.nfc_iso_dep_a || initiator_tech.nfc_iso_dep_b;
// rf_protocols.initiator_nfc_dep = initiator_tech.nfc_nfc_dep_a || initiator_tech.nfc_nfc_dep_f_212 || initiator_tech.nfc_nfc_dep_f_424; // rf_protocols.initiator_nfc_dep = initiator_tech.nfc_nfc_dep_a || initiator_tech.nfc_nfc_dep_f_212 || initiator_tech.nfc_nfc_dep_f_424;
// rf_protocols.target_t1t = target_tech.nfc_type1; // rf_protocols.target_t1t = target_tech.nfc_type1;
// rf_protocols.target_t2t = target_tech.nfc_type2; // rf_protocols.target_t2t = target_tech.nfc_type2;
// rf_protocols.target_t3t = target_tech.nfc_type3; // rf_protocols.target_t3t = target_tech.nfc_type3;
rf_protocols.target_iso_dep = target_tech.nfc_iso_dep_a || target_tech.nfc_iso_dep_b; rf_protocols.target_iso_dep = target_tech.nfc_iso_dep_a || target_tech.nfc_iso_dep_b;
// rf_protocols.target_nfc_dep = target_tech.nfc_nfc_dep_a || target_tech.nfc_nfc_dep_f_212 || target_tech.nfc_nfc_dep_f_424; // rf_protocols.target_nfc_dep = target_tech.nfc_nfc_dep_a || target_tech.nfc_nfc_dep_f_212 || target_tech.nfc_nfc_dep_f_424;
return rf_protocols; return rf_protocols;
} }
nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols) nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols)
{ {
if( _discovery_running ) { if (_discovery_running) {
// Cannot configure RF protocols if discovery is running // Cannot configure RF protocols if discovery is running
return NFC_ERR_BUSY; return NFC_ERR_BUSY;
} }
@ -103,7 +103,7 @@ nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_pr
nfc_err_t NFCController::start_discovery() nfc_err_t NFCController::start_discovery()
{ {
if( _discovery_running ) { if (_discovery_running) {
// Cannot start discovery if it's already running // Cannot start discovery if it's already running
return NFC_ERR_BUSY; return NFC_ERR_BUSY;
} }
@ -113,14 +113,14 @@ nfc_err_t NFCController::start_discovery()
nfc_err_t NFCController::cancel_discovery() nfc_err_t NFCController::cancel_discovery()
{ {
if( !_discovery_running ) { if (!_discovery_running) {
return NFC_OK; return NFC_OK;
} }
transceiver_abort(_transceiver); transceiver_abort(_transceiver);
} }
nfc_transceiver_t* NFCController::transceiver() const nfc_transceiver_t *NFCController::transceiver() const
{ {
return _transceiver; return _transceiver;
} }
@ -130,16 +130,16 @@ void NFCController::polling_callback(nfc_err_t ret)
// Polling has completed // Polling has completed
_discovery_running = false; _discovery_running = false;
if( ret == NFC_OK ) { if (ret == NFC_OK) {
// Check if a remote initiator was detected and if so, instantiate it // Check if a remote initiator was detected and if so, instantiate it
if( !transceiver_is_initiator_mode(_transceiver) ) { if (!transceiver_is_initiator_mode(_transceiver)) {
nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver); nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
if( active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b ) { if (active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b) {
Type4RemoteInitiator type4_remote_initiator_ptr = new (std::nothrow) Type4RemoteInitiator(_transceiver, _ndef_buffer, _ndef_buffer_sz); Type4RemoteInitiator type4_remote_initiator_ptr = new (std::nothrow) Type4RemoteInitiator(_transceiver, _ndef_buffer, _ndef_buffer_sz);
if( type4_remote_initiator_ptr == NULL ) { if (type4_remote_initiator_ptr == NULL) {
// No memory :( // No memory :(
SharedPtr<Type4RemoteInitiator> type4_remote_initiator( type4_remote_initiator_ptr ); SharedPtr<Type4RemoteInitiator> type4_remote_initiator(type4_remote_initiator_ptr);
if( _delegate != NULL ) { if (_delegate != NULL) {
_delegate->on_nfc_initiator_discovered(type4_remote_initiator); _delegate->on_nfc_initiator_discovered(type4_remote_initiator);
} }
} }
@ -147,11 +147,11 @@ void NFCController::polling_callback(nfc_err_t ret)
} }
} }
if( _delegate != NULL ) { if (_delegate != NULL) {
nfc_discovery_terminated_reason_t reason; nfc_discovery_terminated_reason_t reason;
// Map reason // Map reason
switch(ret) { switch (ret) {
case NFC_OK: case NFC_OK:
reason = nfc_discovery_terminated_completed; reason = nfc_discovery_terminated_completed;
break; break;
@ -168,53 +168,61 @@ void NFCController::polling_callback(nfc_err_t ret)
} }
} }
void NFCController::scheduler_process(bool hw_interrupt) { void NFCController::scheduler_process(bool hw_interrupt)
{
_timer.detach(); // Cancel timeout - if it triggers, it's ok as we'll have an "early" iteration which will likely be a no-op _timer.detach(); // Cancel timeout - if it triggers, it's ok as we'll have an "early" iteration which will likely be a no-op
// Process stack events // Process stack events
uint32_t timeout = nfc_scheduler_iteration(_scheduler, hw_interrupt?EVENT_HW_INTERRUPT:EVENT_NONE); uint32_t timeout = nfc_scheduler_iteration(_scheduler, hw_interrupt ? EVENT_HW_INTERRUPT : EVENT_NONE);
_timer.attach(callback(this, &NFCController::on_timeout)); _timer.attach(callback(this, &NFCController::on_timeout));
} }
void NFCController::on_hw_interrupt() { void NFCController::on_hw_interrupt()
{
// Run scheduler - this is called in interrupt context // Run scheduler - this is called in interrupt context
_timer.detach(); // Cancel timeout - if it triggers anyways, it's ok _timer.detach(); // Cancel timeout - if it triggers anyways, it's ok
_queue->call(this, NFCController::scheduler_process, true); _queue->call(this, NFCController::scheduler_process, true);
} }
void NFCController::on_timeout() { void NFCController::on_timeout()
{
// Run scheduler - this is called in interrupt context // Run scheduler - this is called in interrupt context
_queue->call(this, NFCController::scheduler_process, false); _queue->call(this, NFCController::scheduler_process, false);
} }
static void NFCController::s_polling_callback(nfc_transceiver_t* pTransceiver, nfc_err_t ret, void* pUserData) static void NFCController::s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData)
{ {
NFCController* self = (NFCController*) pUserData; NFCController *self = (NFCController *) pUserData;
self->polling_callback(ret); self->polling_callback(ret);
} }
// Implementation nfc_scheduler_timer_t // Implementation nfc_scheduler_timer_t
void nfc_scheduler_timer_init(nfc_scheduler_timer_t* timer) { void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer)
{
(void)timer; // This is a no-op (void)timer; // This is a no-op
} }
void nfc_scheduler_timer_start(nfc_scheduler_timer_t* timer) { void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer)
Timer* mbed_timer = (Timer*)timer; {
Timer *mbed_timer = (Timer *)timer;
mbed_timer->start(); mbed_timer->start();
} }
uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t* timer) { uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer)
Timer* mbed_timer = (Timer*)timer; {
Timer *mbed_timer = (Timer *)timer;
return (uint32_t)mbed_timer->read_ms(); return (uint32_t)mbed_timer->read_ms();
} }
void nfc_scheduler_timer_stop(nfc_scheduler_timer_t* timer) { void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer)
Timer* mbed_timer = (Timer*)timer; {
Timer *mbed_timer = (Timer *)timer;
mbed_timer->stop(); mbed_timer->stop();
} }
void nfc_scheduler_timer_reset(nfc_scheduler_timer_t* timer) { void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer)
Timer* mbed_timer = (Timer*)timer; {
Timer *mbed_timer = (Timer *)timer;
mbed_timer->reset(); mbed_timer->reset();
} }

View File

@ -19,16 +19,19 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCControllerDriver::NFCControllerDriver() : _delegate(NULL) { NFCControllerDriver::NFCControllerDriver() : _delegate(NULL)
{
} }
void NFCControllerDriver::set_delegate(Delegate* delegate) { void NFCControllerDriver::set_delegate(Delegate *delegate)
{
_delegate = delegate; _delegate = delegate;
} }
void NFCControllerDriver::hw_interrupt() { void NFCControllerDriver::hw_interrupt()
if(_delegate != NULL) { {
if (_delegate != NULL) {
_delegate->on_hw_interrupt(); _delegate->on_hw_interrupt();
} }
} }

View File

@ -20,13 +20,14 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCEEPROM(NFCEEPROMDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz) : NFCTarget( ndef_buffer, ndef_buffer_sz ) NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, uint8_t *ndef_buffer, size_t ndef_buffer_sz) : NFCTarget(ndef_buffer, ndef_buffer_sz)
_driver(driver), _queue(queue), _initialized(false), _current_op(nfc_eeprom_idle), _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN) _driver(driver), _queue(queue), _initialized(false), _current_op(nfc_eeprom_idle), _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN)
{ {
_driver->set_delegate(this); _driver->set_delegate(this);
} }
nfc_err_t NFCEEPROM::initialize() { nfc_err_t NFCEEPROM::initialize()
{
MBED_ASSERT(_initialized == false); // Initialize should only be called once MBED_ASSERT(_initialized == false); // Initialize should only be called once
// Initialize driver // Initialize driver
@ -34,14 +35,16 @@ nfc_err_t NFCEEPROM::initialize() {
_initialized = true; _initialized = true;
} }
void NFCEEPROM::set_delegate(NFCEEPROM::Delegate* delegate) { void NFCEEPROM::set_delegate(NFCEEPROM::Delegate *delegate)
{
_delegate = delegate; _delegate = delegate;
} }
void NFCEEPROM::write_ndef_message() { void NFCEEPROM::write_ndef_message()
{
MBED_ASSERT(_initialized == true); MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) { if (_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) { if (_delegate != NULL) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY); _delegate->on_ndef_message_written(NFC_ERR_BUSY);
} }
return; return;
@ -51,32 +54,33 @@ void NFCEEPROM::write_ndef_message() {
ndef_msg_encode(ndef_message()); ndef_msg_encode(ndef_message());
_current_op = nfc_eeprom_write_start_session; _current_op = nfc_eeprom_write_start_session;
// Retrieve reader
ac_buffer_dup(&_ndef_buffer_reader, ac_buffer_builder_buffer(ndef_msg_buffer_builder(ndef_message()) );
// Check that NDEF message is not too big // Retrieve reader
if( ac_buffer_reader_readable(&_ndef_buffer_reader) > _driver->get_max_size() ) { ac_buffer_dup(&_ndef_buffer_reader, ac_buffer_builder_buffer(ndef_msg_buffer_builder(ndef_message()));
handle_error(NFC_ERR_BUFFER_TOO_SMALL);
// Check that NDEF message is not too big
if (ac_buffer_reader_readable(&_ndef_buffer_reader) > _driver->get_max_size()) {
handle_error(NFC_ERR_BUFFER_TOO_SMALL);
return; return;
} }
// Reset EEPROM address // Reset EEPROM address
_eeprom_address = 0; _eeprom_address = 0;
// Go through the steps! // Go through the steps!
_driver->start_session(); _driver->start_session();
// 1 - Start session // 1 - Start session
// 2 - Write bytes (can be repeated) // 2 - Write bytes (can be repeated)
// 3 - Set NDEF message size // 3 - Set NDEF message size
// 4 - End session // 4 - End session
} }
void NFCEEPROM::read_ndef_message() { void NFCEEPROM::read_ndef_message()
{
MBED_ASSERT(_initialized == true); MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) { if (_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) { if (_delegate != NULL) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY); _delegate->on_ndef_message_written(NFC_ERR_BUSY);
} }
return; return;
@ -96,13 +100,14 @@ void NFCEEPROM::read_ndef_message() {
// 4 - End session // 4 - End session
} }
void NFCEEPROM::erase_ndef_message() { void NFCEEPROM::erase_ndef_message()
{
// We don't want to take any risks, so erase the whole address space // We don't want to take any risks, so erase the whole address space
// And set the message size to 0 // And set the message size to 0
MBED_ASSERT(_initialized == true); MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) { if (_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) { if (_delegate != NULL) {
_delegate->on_ndef_message_erased(NFC_ERR_BUSY); _delegate->on_ndef_message_erased(NFC_ERR_BUSY);
} }
return; return;
@ -122,10 +127,11 @@ void NFCEEPROM::erase_ndef_message() {
// 4 - End session // 4 - End session
} }
void NFCEEPROM::on_session_started(bool success) { void NFCEEPROM::on_session_started(bool success)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_write_start_session: case nfc_eeprom_write_start_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); // An EEPROM is not really a controller but close enough handle_error(NFC_ERR_CONTROLLER); // An EEPROM is not really a controller but close enough
return; return;
} }
@ -134,7 +140,7 @@ void NFCEEPROM::on_session_started(bool success) {
break; break;
case nfc_eeprom_read_start_session: case nfc_eeprom_read_start_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -143,7 +149,7 @@ void NFCEEPROM::on_session_started(bool success) {
break; break;
case nfc_eeprom_erase_start_session: case nfc_eeprom_erase_start_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -158,21 +164,22 @@ void NFCEEPROM::on_session_started(bool success) {
} }
} }
void NFCEEPROM::on_session_ended(bool success) { void NFCEEPROM::on_session_ended(bool success)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_write_end_session: case nfc_eeprom_write_end_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
_current_op = nfc_eeprom_idle; _current_op = nfc_eeprom_idle;
if( _delegate != NULL ) { if (_delegate != NULL) {
_driver->on_ndef_message_written(_operation_result); _driver->on_ndef_message_written(_operation_result);
} }
break; break;
case nfc_eeprom_read_end_session: case nfc_eeprom_read_end_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -181,18 +188,18 @@ void NFCEEPROM::on_session_ended(bool success) {
// Try to parse the NDEF message // Try to parse the NDEF message
ndef_msg_decode(ndef_message()); ndef_msg_decode(ndef_message());
if( _delegate != NULL ) { if (_delegate != NULL) {
_driver->on_ndef_message_read(_operation_result); _driver->on_ndef_message_read(_operation_result);
} }
break; break;
case nfc_eeprom_erase_end_session: case nfc_eeprom_erase_end_session:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
_current_op = nfc_eeprom_idle; _current_op = nfc_eeprom_idle;
if( _delegate != NULL ) { if (_delegate != NULL) {
_driver->on_ndef_message_erased(_operation_result); _driver->on_ndef_message_erased(_operation_result);
} }
break; break;
@ -204,17 +211,18 @@ void NFCEEPROM::on_session_ended(bool success) {
} }
} }
void NFCEEPROM::on_bytes_read(size_t count) { void NFCEEPROM::on_bytes_read(size_t count)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_read_read_bytes: case nfc_eeprom_read_read_bytes:
if(count == 0) { if (count == 0) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
// Discard bytes that were actually read and update address // Discard bytes that were actually read and update address
_eeprom_address += count; _eeprom_address += count;
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message()); ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
ac_buffer_builder_write_n_skip(buffer_builder, count); ac_buffer_builder_write_n_skip(buffer_builder, count);
// Continue reading // Continue reading
@ -227,10 +235,11 @@ void NFCEEPROM::on_bytes_read(size_t count) {
} }
} }
void NFCEEPROM::on_bytes_written(size_t count) { void NFCEEPROM::on_bytes_written(size_t count)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_write_write_bytes: case nfc_eeprom_write_write_bytes:
if(count == 0) { if (count == 0) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -249,10 +258,11 @@ void NFCEEPROM::on_bytes_written(size_t count) {
} }
} }
void NFCEEPROM::on_size_written(bool success) { void NFCEEPROM::on_size_written(bool success)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_write_write_size: case nfc_eeprom_write_write_size:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -263,7 +273,7 @@ void NFCEEPROM::on_size_written(bool success) {
_driver->end_session(); _driver->end_session();
break; break;
case nfc_eeprom_erase_write_size: case nfc_eeprom_erase_write_size:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -280,21 +290,21 @@ void NFCEEPROM::on_size_written(bool success) {
} }
} }
void NFCEEPROM::on_size_read(bool success, size_t size) { void NFCEEPROM::on_size_read(bool success, size_t size)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_read_read_size: case nfc_eeprom_read_read_size:
if(!success) { if (!success) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
// Reset NDEF message buffer builder // Reset NDEF message buffer builder
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message()); ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
ac_buffer_builder_reset( buffer_builder ); ac_buffer_builder_reset(buffer_builder);
// Check that we have a big enough buffer to read the message // Check that we have a big enough buffer to read the message
if( size > ac_buffer_builder_writable(buffer_builder) ) if (size > ac_buffer_builder_writable(buffer_builder)) {
{
// Not enough space, close session // Not enough space, close session
_current_op = nfc_eeprom_read_end_session; _current_op = nfc_eeprom_read_end_session;
_operation_result = NFC_ERR_BUFFER_TOO_SMALL; _operation_result = NFC_ERR_BUFFER_TOO_SMALL;
@ -317,10 +327,11 @@ void NFCEEPROM::on_size_read(bool success, size_t size) {
} }
} }
void NFCEEPROM::on_bytes_erased(size_t count) { void NFCEEPROM::on_bytes_erased(size_t count)
switch(_current_op) { {
switch (_current_op) {
case nfc_eeprom_erase_erase_bytes: case nfc_eeprom_erase_erase_bytes:
if(count == 0) { if (count == 0) {
handle_error(NFC_ERR_CONTROLLER); handle_error(NFC_ERR_CONTROLLER);
return; return;
} }
@ -338,61 +349,61 @@ void NFCEEPROM::on_bytes_erased(size_t count) {
} }
} }
void NFCEEPROM::on_event() { void NFCEEPROM::on_event()
{
// Just schedule a task on event queue // Just schedule a task on event queue
_queue->call(_driver, NFCEEPROMDriver::process_events); _queue->call(_driver, NFCEEPROMDriver::process_events);
} }
void NFCEEPROM::continue_write() { void NFCEEPROM::continue_write()
if( ac_buffer_reader_readable(&_ndef_buffer_reader) > 0 ) { {
if (ac_buffer_reader_readable(&_ndef_buffer_reader) > 0) {
// Continue writing // Continue writing
_driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader)); _driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader));
} } else {
else {
// Now update size // Now update size
_current_op = nfc_eeprom_write_write_size; _current_op = nfc_eeprom_write_write_size;
_driver->write_size(_eeprom_address); _driver->write_size(_eeprom_address);
} }
} }
void NFCEEPROM::continue_erase() { void NFCEEPROM::continue_erase()
if( _eeprom_address < _driver->get_max_size() ) { {
if (_eeprom_address < _driver->get_max_size()) {
// Continue erasing // Continue erasing
_driver->erase_bytes(_eeprom_address, _driver->get_max_size() - _eeprom_address); _driver->erase_bytes(_eeprom_address, _driver->get_max_size() - _eeprom_address);
} } else {
else {
// Now update size // Now update size
_current_op = nfc_eeprom_erase_write_size; _current_op = nfc_eeprom_erase_write_size;
_driver->write_size(0); _driver->write_size(0);
} }
} }
void NFCEEPROM::continue_read() { void NFCEEPROM::continue_read()
if( _eeprom_address < _ndef_buffer_read_sz ) { {
if (_eeprom_address < _ndef_buffer_read_sz) {
// Continue reading // Continue reading
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message()); ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
_driver->read_bytes(_eeprom_address, ac_buffer_builder_write_position(buffer_builder), _ndef_buffer_read_sz - _eeprom_address); _driver->read_bytes(_eeprom_address, ac_buffer_builder_write_position(buffer_builder), _ndef_buffer_read_sz - _eeprom_address);
} } else {
else {
// Done, close session // Done, close session
_operation_result = NFC_OK; _operation_result = NFC_OK;
_driver->end_session(); _driver->end_session();
} }
} }
void NFCEEPROM::handle_error(nfc_err_t ret) { void NFCEEPROM::handle_error(nfc_err_t ret)
{
// Save & reset current op // Save & reset current op
nfc_eeprom_operation_t last_op = _current_op; nfc_eeprom_operation_t last_op = _current_op;
_current_op = nfc_eeprom_idle; _current_op = nfc_eeprom_idle;
if(_delegate != NULL) { if (_delegate != NULL) {
if(last_op <= nfc_eeprom_write_end_session) { if (last_op <= nfc_eeprom_write_end_session) {
_delegate->on_ndef_message_written(ret); _delegate->on_ndef_message_written(ret);
} } else if (last_op <= nfc_eeprom_read_end_session) {
else if(last_op <= nfc_eeprom_read_end_session) {
_delegate->on_ndef_message_read(ret); _delegate->on_ndef_message_read(ret);
} } else if (last_op <= nfc_eeprom_erase_end_session) {
else if(last_op <= nfc_eeprom_erase_end_session) {
_delegate->on_ndef_message_erased(ret); _delegate->on_ndef_message_erased(ret);
} }
} }

View File

@ -19,10 +19,12 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCEEPROMDriver::NFCEEPROMDriver() : _delegate(NULL) { NFCEEPROMDriver::NFCEEPROMDriver() : _delegate(NULL)
{
} }
void NFCEEPROMDriver::set_delegate(Delegate* delegate) { void NFCEEPROMDriver::set_delegate(Delegate *delegate)
{
_delegate = delegate; _delegate = delegate;
} }

View File

@ -25,49 +25,53 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCNDEFCapable::NFCNDEFCapable(uint8_t* buffer, size_t buffer_size) : _delegate(NULL) NFCNDEFCapable::NFCNDEFCapable(uint8_t *buffer, size_t buffer_size) : _delegate(NULL)
{ {
ndef_msg_init(&_ndef_message, s_encode_callback, s_decode_callback); ndef_msg_init(&_ndef_message, s_encode_callback, s_decode_callback);
} }
void NFCNDEFCapable::set_ndef_delegate(NFCNDEFCapable::Delegate* delegate) void NFCNDEFCapable::set_ndef_delegate(NFCNDEFCapable::Delegate *delegate)
{ {
_delegate = delegate; _delegate = delegate;
} }
void NFCNDEFCapable::parse_ndef_message(const ac_buffer_t& buffer) void NFCNDEFCapable::parse_ndef_message(const ac_buffer_t &buffer)
{ {
ac_buffer_t reader; ac_buffer_t reader;
ac_buffer_dup(&reader, &buffer); ac_buffer_dup(&reader, &buffer);
if(_delegate != NULL) { if (_delegate != NULL) {
_delegate->parse_ndef_message(ac_buffer_reader_current_buffer_pointer(&reader), ac_buffer_reader_current_buffer_length(&reader)); _delegate->parse_ndef_message(ac_buffer_reader_current_buffer_pointer(&reader), ac_buffer_reader_current_buffer_length(&reader));
} }
} }
void NFCNDEFCapable::build_ndef_message(ac_buffer_builder_t& buffer_builder) void NFCNDEFCapable::build_ndef_message(ac_buffer_builder_t &buffer_builder)
{ {
if(_delegate != NULL) { if (_delegate != NULL) {
size_t count = _delegate->build_ndef_message( ac_buffer_builder_write_position(&buffer_builder), ac_buffer_builder_writable(&buffer_builder) ); size_t count = _delegate->build_ndef_message(ac_buffer_builder_write_position(&buffer_builder), ac_buffer_builder_writable(&buffer_builder));
ac_buffer_builder_write_n_skip(&buffer_builder, count); ac_buffer_builder_write_n_skip(&buffer_builder, count);
} }
} }
nfc_err_t NFCNDEFCapable::s_ndef_encode(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData) { nfc_err_t NFCNDEFCapable::s_ndef_encode(ndef_msg_t *pTag, buffer_builder_t *pBufferBldr, void *pUserData)
NFCNDEFCapable* self = (NFCNDEFCapable*)pUserData; {
NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData;
self->ndef_encode(pBufferBldr); self->ndef_encode(pBufferBldr);
} }
nfc_err_t NFCNDEFCapable::s_ndef_decode(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData) { nfc_err_t NFCNDEFCapable::s_ndef_decode(ndef_msg_t *pTag, buffer_t *pBuffer, void *pUserData)
NFCNDEFCapable* self = (NFCNDEFCapable*)pUserData; {
NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData;
self->ndef_decode(pBuffer); self->ndef_decode(pBuffer);
} }
nfc_err_t NFCNDEFCapable::ndef_encode(buffer_builder_t* pBufferBldr) { nfc_err_t NFCNDEFCapable::ndef_encode(buffer_builder_t *pBufferBldr)
{
build_ndef_message(buffer_builder); build_ndef_message(buffer_builder);
return NFC_OK; return NFC_OK;
} }
nfc_err_t NFCNDEFCapable::ndef_decode(buffer_t* pBuffer) { nfc_err_t NFCNDEFCapable::ndef_decode(buffer_t *pBuffer)
{
parse_ndef_message(pBuffer); parse_ndef_message(pBuffer);
return NFC_OK; return NFC_OK;
} }

View File

@ -25,19 +25,21 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCRemoteEndpoint::NFCRemoteEndpoint(NFCController* controller) : _controller(controller), _is_lost(false) { NFCRemoteEndpoint::NFCRemoteEndpoint(NFCController *controller) : _controller(controller), _is_lost(false)
{
} }
bool NFCRemoteEndpoint::is_lost() const { bool NFCRemoteEndpoint::is_lost() const
{
return _is_lost; return _is_lost;
} }
nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols() { nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols()
{
nfc_rf_protocols_bitmask_t rf_protocols = {0}; nfc_rf_protocols_bitmask_t rf_protocols = {0};
nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver); nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
if(!transceiver_is_initiator_mode(_transceiver)) if (!transceiver_is_initiator_mode(_transceiver)) {
{
// Note: We only support ISO-DEP for now // Note: We only support ISO-DEP for now
rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b;
} }
@ -45,11 +47,13 @@ nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols() {
return rf_protocols; return rf_protocols;
} }
void NFCRemoteEndpoint::set_lost() { void NFCRemoteEndpoint::set_lost()
{
_is_lost = true; _is_lost = true;
} }
NFCController* NFCRemoteEndpoint::nfc_controller() const { NFCController *NFCRemoteEndpoint::nfc_controller() const
{
return _controller; return _controller;
} }

View File

@ -19,17 +19,19 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCRemoteInitiator::NFCRemoteInitiator(NFCController* controller, uint8_t* buffer, size_t buffer_size) : NFCRemoteInitiator::NFCRemoteInitiator(NFCController *controller, uint8_t *buffer, size_t buffer_size) :
NFCRemoteEndpoint(controller), NFCNDEFCapable(buffer, buffer_size) { NFCRemoteEndpoint(controller), NFCNDEFCapable(buffer, buffer_size)
{
} }
NFCRemoteInitiator::~NFCRemoteInitiator() { NFCRemoteInitiator::~NFCRemoteInitiator()
{
} }
void NFCRemoteInitiator::set_remote_initiator_delegate(Delegate* delegate) void NFCRemoteInitiator::set_remote_initiator_delegate(Delegate *delegate)
{ {
_delegate = delegate; _delegate = delegate;
} }

View File

@ -19,11 +19,13 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
NFCTarget::NFCTarget(uint8_t* buffer, size_t buffer_size) : NFCTarget::NFCTarget(uint8_t *buffer, size_t buffer_size) :
NFCNDEFCapable(buffer, buffer_size) { NFCNDEFCapable(buffer, buffer_size)
{
} }
NFCTarget::~NFCTarget() { NFCTarget::~NFCTarget()
{
} }

View File

@ -28,22 +28,24 @@
using namespace mbed; using namespace mbed;
using namespace mbed::nfc; using namespace mbed::nfc;
Type4RemoteInitiator::Type4RemoteInitiator(NFCController* controller, uint8_t* buffer, size_t buffer_size) : Type4RemoteInitiator::Type4RemoteInitiator(NFCController *controller, uint8_t *buffer, size_t buffer_size) :
NFCRemoteInitiator(ndef_buffer, ndef_buffer_sz), NFCRemoteInitiator(ndef_buffer, ndef_buffer_sz),
_controller(controller), _is_connected(false) , _is_disconnected(false), _apps(NULL) { _controller(controller), _is_connected(false), _is_disconnected(false), _apps(NULL)
{
// Init ISO7816 // Init ISO7816
nfc_tech_iso7816_init(&_iso7816, _controller->transceiver(), &Type4RemoteInitiator::s_disconnected_callback, this); nfc_tech_iso7816_init(&_iso7816, _controller->transceiver(), &Type4RemoteInitiator::s_disconnected_callback, this);
// Init Type 4 app // Init Type 4 app
nfc_tech_type4_target_init(&_type4, &_iso7816, ndef_message()); nfc_tech_type4_target_init(&_type4, &_iso7816, ndef_message());
} }
nfc_err_t Type4RemoteInitiator::connect() { nfc_err_t Type4RemoteInitiator::connect()
if(_is_connected) { {
if (_is_connected) {
return NFC_BUSY; return NFC_BUSY;
} }
if(_is_disconnected) { if (_is_disconnected) {
return NFC_ERR_DISCONNECTED; return NFC_ERR_DISCONNECTED;
} }
@ -54,12 +56,13 @@ nfc_err_t Type4RemoteInitiator::connect() {
connected(); connected();
} }
nfc_err_t Type4RemoteInitiator::disconnect() { nfc_err_t Type4RemoteInitiator::disconnect()
if(!_is_connected) { {
if (!_is_connected) {
return NFC_OK; return NFC_OK;
} }
if(_is_disconnected) { if (_is_disconnected) {
return NFC_OK; return NFC_OK;
} }
@ -67,19 +70,21 @@ nfc_err_t Type4RemoteInitiator::disconnect() {
nfc_tech_iso7816_disconnect(&_iso7816); nfc_tech_iso7816_disconnect(&_iso7816);
} }
bool Type4RemoteInitiator::is_connected() const { bool Type4RemoteInitiator::is_connected() const
{
return _is_connected; return _is_connected;
} }
bool Type4RemoteInitiator::is_disconnected() const { bool Type4RemoteInitiator::is_disconnected() const
{
return _is_disconnected; return _is_disconnected;
} }
nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols() { nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols()
{
nfc_rf_protocols_bitmask_t rf_protocols = {0}; nfc_rf_protocols_bitmask_t rf_protocols = {0};
nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver); nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
if(!transceiver_is_initiator_mode(_transceiver)) if (!transceiver_is_initiator_mode(_transceiver)) {
{
// We only support ISO-DEP // We only support ISO-DEP
rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b;
} }
@ -87,24 +92,27 @@ nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols() {
return rf_protocols; return rf_protocols;
} }
virtual nfc_tag_type_t Type4RemoteInitiator::nfc_tag_type() const { virtual nfc_tag_type_t Type4RemoteInitiator::nfc_tag_type() const
{
nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver); nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
if(active_tech.nfc_iso_dep_a) { if (active_tech.nfc_iso_dep_a) {
return nfc_tag_type_4a; return nfc_tag_type_4a;
} } else { // if(active_tech.nfc_iso_dep_b)
else { // if(active_tech.nfc_iso_dep_b)
return nfc_tag_type_4b; return nfc_tag_type_4b;
} }
} }
virtual bool Type4RemoteInitiator::is_iso7816_supported() const { virtual bool Type4RemoteInitiator::is_iso7816_supported() const
{
return true; return true;
} }
virtual void Type4RemoteInitiator::add_iso7816_application(ISO7816App* application) { virtual void Type4RemoteInitiator::add_iso7816_application(ISO7816App *application)
{
nfc_tech_iso7816_add_app(&_iso7816, application->_iso7816_app); nfc_tech_iso7816_add_app(&_iso7816, application->_iso7816_app);
} }
virtual bool Type4RemoteInitiator::is_ndef_supported() const { virtual bool Type4RemoteInitiator::is_ndef_supported() const
{
return true; return true;
} }

View File

@ -39,12 +39,12 @@
* \param buffer_size size of the underlying buffer * \param buffer_size size of the underlying buffer
* \param pImpl pointer to actual implementation * \param pImpl pointer to actual implementation
*/ */
void ndef_msg_init( ndef_msg_t* pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t* data, size_t size, void* pUserData ) void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData)
{ {
pNdef->encode = encode; pNdef->encode = encode;
pNdef->decode = decode; pNdef->decode = decode;
buffer_builder_init(&pNdef->bufferBldr, data, size); buffer_builder_init(&pNdef->bufferBldr, data, size);
pNdef->pUserData = pUserData; pNdef->pUserData = pUserData;
} }
/** Get NDEF tag implementation /** Get NDEF tag implementation

View File

@ -43,45 +43,42 @@ typedef struct __ndef_msg ndef_msg_t;
* \param pTag pointer to ndef_tag_t instance * \param pTag pointer to ndef_tag_t instance
* \param type pMem buffer in which to store the generated content * \param type pMem buffer in which to store the generated content
*/ */
typedef nfc_err_t (*ndef_encode_fn_t)(ndef_msg_t* pTag, buffer_builder_t* pBufferBldr, void* pUserData); typedef nfc_err_t (*ndef_encode_fn_t)(ndef_msg_t *pTag, buffer_builder_t *pBufferBldr, void *pUserData);
/** Function called to decode the tag's content on write (target mode) or read (reader mode) /** Function called to decode the tag's content on write (target mode) or read (reader mode)
* \param pTag pointer to ndef_tag_t instance * \param pTag pointer to ndef_tag_t instance
* \param type pMem buffer containing the tag's content * \param type pMem buffer containing the tag's content
*/ */
typedef nfc_err_t (*ndef_decode_fn_t)(ndef_msg_t* pTag, buffer_t* pBuffer, void* pUserData); typedef nfc_err_t (*ndef_decode_fn_t)(ndef_msg_t *pTag, buffer_t *pBuffer, void *pUserData);
typedef struct __ndef_msg typedef struct __ndef_msg {
{ ndef_encode_fn_t encode;
ndef_encode_fn_t encode; ndef_decode_fn_t decode;
ndef_decode_fn_t decode; buffer_builder_t bufferBldr;
buffer_builder_t bufferBldr; void *pUserData;
void* pUserData;
} ndef_msg_t; } ndef_msg_t;
void ndef_msg_init( ndef_msg_t* pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t* data, size_t size, void* pUserData ); void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData);
static inline nfc_err_t ndef_msg_encode(ndef_msg_t* pNdef) static inline nfc_err_t ndef_msg_encode(ndef_msg_t *pNdef)
{ {
if(pNdef->encode == NULL) if (pNdef->encode == NULL) {
{ return NFC_OK;
return NFC_OK; }
} return pNdef->encode(pNdef, &pNdef->bufferBldr, pNdef->pUserData);
return pNdef->encode(pNdef, &pNdef->bufferBldr, pNdef->pUserData);
} }
static inline nfc_err_t ndef_msg_decode(ndef_msg_t* pNdef) static inline nfc_err_t ndef_msg_decode(ndef_msg_t *pNdef)
{ {
if(pNdef->decode == NULL) if (pNdef->decode == NULL) {
{ return NFC_OK;
return NFC_OK; }
} return pNdef->decode(pNdef, buffer_builder_buffer(&pNdef->bufferBldr), pNdef->pUserData);
return pNdef->decode(pNdef, buffer_builder_buffer(&pNdef->bufferBldr), pNdef->pUserData);
} }
static inline buffer_builder_t* ndef_msg_buffer_builder(ndef_msg_t* pNdef) static inline buffer_builder_t *ndef_msg_buffer_builder(ndef_msg_t *pNdef)
{ {
return &pNdef->bufferBldr; return &pNdef->bufferBldr;
} }
//void* ndef_tag_impl(ndef_tag_t* pNdefTag); //void* ndef_tag_impl(ndef_tag_t* pNdefTag);

View File

@ -21,7 +21,8 @@
#if NFC_DEBUG && !defined(NDEBUG) #if NFC_DEBUG && !defined(NDEBUG)
#include "stdio.h" #include "stdio.h"
#include "stdarg.h" #include "stdarg.h"
static inline void nfc_dbg_print(const char* type, const char* module, unsigned int line, const char* fmt, ...) { static inline void nfc_dbg_print(const char *type, const char *module, unsigned int line, const char *fmt, ...)
{
#if !defined(NDEBUG) #if !defined(NDEBUG)
printf("NFC [%s] %s:%u ", type, module, line); printf("NFC [%s] %s:%u ", type, module, line);
va_list args; va_list args;

View File

@ -27,182 +27,158 @@
#include "platform/nfc_scheduler.h" #include "platform/nfc_scheduler.h"
void nfc_scheduler_init(nfc_scheduler_t* pScheduler, nfc_scheduler_timer_t* pTimer) void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer)
{ {
pScheduler->pNext = NULL; pScheduler->pNext = NULL;
pScheduler->pTimer = pTimer; pScheduler->pTimer = pTimer;
//Start timer //Start timer
nfc_scheduler_timer_start(pTimer); nfc_scheduler_timer_start(pTimer);
} }
#define MAX_TIMEOUT UINT32_MAX #define MAX_TIMEOUT UINT32_MAX
uint32_t nfc_scheduler_iteration(nfc_scheduler_t* pScheduler, uint32_t events) uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events)
{ {
bool triggered = false; bool triggered = false;
while(true) while (true) {
{ nfc_task_t *pPrioTask = NULL;
nfc_task_t* pPrioTask = NULL; nfc_task_t *pPrioTaskPrevious = NULL;
nfc_task_t* pPrioTaskPrevious = NULL; uint32_t prioTaskEvent = 0;
uint32_t prioTaskEvent = 0; int64_t timeout;
int64_t timeout; nfc_task_t *pPreviousTask = NULL;
nfc_task_t* pPreviousTask = NULL; nfc_task_t *pTask = pScheduler->pNext;
nfc_task_t* pTask = pScheduler->pNext;
if( pTask == NULL ) if (pTask == NULL) {
{ NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer));
NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer)); //Empty queue, return
//Empty queue, return return MAX_TIMEOUT;
return MAX_TIMEOUT; }
}
//Get timer value //Get timer value
uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer); uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer);
NFC_DBG("%lu ms elapsed", timeElapsed); NFC_DBG("%lu ms elapsed", timeElapsed);
nfc_scheduler_timer_reset(pScheduler->pTimer); nfc_scheduler_timer_reset(pScheduler->pTimer);
do do {
{ //Apply timeouts
//Apply timeouts if (pTask->events & EVENT_TIMEOUT) {
if( pTask->events & EVENT_TIMEOUT ) pTask->timeout -= timeElapsed;
{ }
pTask->timeout -= timeElapsed; pPreviousTask = pTask;
} pTask = pTask->pNext;
pPreviousTask = pTask; } while (pTask != NULL);
pTask = pTask->pNext;
} while( pTask != NULL );
pTask = pScheduler->pNext; pTask = pScheduler->pNext;
pPreviousTask = NULL; pPreviousTask = NULL;
timeout = MAX_TIMEOUT; timeout = MAX_TIMEOUT;
do do {
{ //Check which task should be woken up first
//Check which task should be woken up first if ((events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT)) {
if( (events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT) ) //Hardware interrupts have prio
{ pPrioTask = pTask;
//Hardware interrupts have prio pPrioTaskPrevious = pPreviousTask;
pPrioTask = pTask; timeout = 0;
pPrioTaskPrevious = pPreviousTask; events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event
timeout = 0; prioTaskEvent = EVENT_HW_INTERRUPT;
break;
} else if ((pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout)) {
pPrioTask = pTask;
pPrioTaskPrevious = pPreviousTask;
timeout = pTask->timeout;
prioTaskEvent = EVENT_TIMEOUT;
}
pPreviousTask = pTask;
pTask = pTask->pNext;
} while (pTask != NULL);
if (pPrioTask == NULL) {
//No task to wake up, exit
NFC_DBG("No task to wake up");
return MAX_TIMEOUT;
}
if (timeout > 0) {
//No task to wake up yet
if (timeout > MAX_TIMEOUT) {
NFC_DBG("No task to wake up");
return MAX_TIMEOUT;
} else {
NFC_DBG("No task to wake up, wait %lu ms", timeout);
return timeout;
}
}
//Dequeue task
if (pPrioTaskPrevious == NULL) {
pScheduler->pNext = pPrioTask->pNext;
} else {
pPrioTaskPrevious->pNext = pPrioTask->pNext;
}
pPrioTask->pNext = NULL;
//Execute task
NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent);
pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData);
events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event
prioTaskEvent = EVENT_HW_INTERRUPT; triggered = true;
break;
}
else if( (pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout) )
{
pPrioTask = pTask;
pPrioTaskPrevious = pPreviousTask;
timeout = pTask->timeout;
prioTaskEvent = EVENT_TIMEOUT;
}
pPreviousTask = pTask;
pTask = pTask->pNext;
} while( pTask != NULL );
if( pPrioTask == NULL )
{
//No task to wake up, exit
NFC_DBG("No task to wake up");
return MAX_TIMEOUT;
} }
return MAX_TIMEOUT;
if( timeout > 0 )
{
//No task to wake up yet
if( timeout > MAX_TIMEOUT )
{
NFC_DBG("No task to wake up");
return MAX_TIMEOUT;
}
else
{
NFC_DBG("No task to wake up, wait %lu ms", timeout);
return timeout;
}
}
//Dequeue task
if( pPrioTaskPrevious == NULL )
{
pScheduler->pNext = pPrioTask->pNext;
}
else
{
pPrioTaskPrevious->pNext = pPrioTask->pNext;
}
pPrioTask->pNext = NULL;
//Execute task
NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent);
pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData);
events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event
triggered = true;
}
return MAX_TIMEOUT;
} }
void nfc_scheduler_queue_task(nfc_scheduler_t* pScheduler, nfc_task_t* pTask) void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask)
{ {
pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer); pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer);
NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout); NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout);
//Find last task //Find last task
nfc_task_t* pPrevTask = pScheduler->pNext; nfc_task_t *pPrevTask = pScheduler->pNext;
pTask->pNext = NULL;
if( pPrevTask == NULL )
{
pScheduler->pNext = pTask;
return;
}
while( pPrevTask->pNext != NULL )
{
pPrevTask = pPrevTask->pNext;
}
pPrevTask->pNext = pTask;
}
void nfc_scheduler_dequeue_task(nfc_scheduler_t* pScheduler, bool abort, nfc_task_t* pTask)
{
NFC_DBG("Dequeuing task %p", pTask);
//Find task
nfc_task_t* pPrevTask = pScheduler->pNext;
if( pPrevTask == NULL )
{
pTask->pNext = NULL; pTask->pNext = NULL;
return; if (pPrevTask == NULL) {
} pScheduler->pNext = pTask;
if( pPrevTask == pTask ) return;
{
if(abort)
{
pTask->fn(EVENT_ABORTED, pTask->pUserData);
} }
pScheduler->pNext = pTask->pNext; while (pPrevTask->pNext != NULL) {
pTask->pNext = NULL; pPrevTask = pPrevTask->pNext;
return;
}
while( pPrevTask->pNext != NULL )
{
if(pPrevTask->pNext == pTask)
{
if(abort)
{
pTask->fn(EVENT_ABORTED, pTask->pUserData);
}
pPrevTask->pNext = pTask->pNext;
pTask->pNext = NULL;
return;
} }
pPrevTask = pPrevTask->pNext; pPrevTask->pNext = pTask;
}
pTask->pNext = NULL;
} }
void task_init(nfc_task_t* pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void* pUserData) void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask)
{ {
pTask->events = events; NFC_DBG("Dequeuing task %p", pTask);
pTask->timeoutInitial = timeout; //Find task
pTask->fn = fn; nfc_task_t *pPrevTask = pScheduler->pNext;
pTask->pUserData = pUserData; if (pPrevTask == NULL) {
pTask->pNext = NULL; pTask->pNext = NULL;
return;
}
if (pPrevTask == pTask) {
if (abort) {
pTask->fn(EVENT_ABORTED, pTask->pUserData);
}
pScheduler->pNext = pTask->pNext;
pTask->pNext = NULL;
return;
}
while (pPrevTask->pNext != NULL) {
if (pPrevTask->pNext == pTask) {
if (abort) {
pTask->fn(EVENT_ABORTED, pTask->pUserData);
}
pPrevTask->pNext = pTask->pNext;
pTask->pNext = NULL;
return;
}
pPrevTask = pPrevTask->pNext;
}
pTask->pNext = NULL;
}
void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData)
{
pTask->events = events;
pTask->timeoutInitial = timeout;
pTask->fn = fn;
pTask->pUserData = pUserData;
pTask->pNext = NULL;
} }

View File

@ -45,62 +45,60 @@ typedef struct __nfc_timer nfc_scheduler_timer_t;
struct __nfc_task; struct __nfc_task;
typedef struct __nfc_task nfc_task_t; typedef struct __nfc_task nfc_task_t;
typedef struct __scheduler typedef struct __scheduler {
{ nfc_task_t *pNext;
nfc_task_t* pNext; nfc_scheduler_timer_t *pTimer;
nfc_scheduler_timer_t* pTimer;
} nfc_scheduler_t; } nfc_scheduler_t;
typedef void (*nfc_task_fn)(uint32_t events, void* pUserData); typedef void (*nfc_task_fn)(uint32_t events, void *pUserData);
struct __nfc_task struct __nfc_task {
{ uint32_t events;
uint32_t events; int64_t timeout; //millisecs
int64_t timeout; //millisecs int64_t timeoutInitial;
int64_t timeoutInitial;
nfc_task_fn fn; nfc_task_fn fn;
void* pUserData; void *pUserData;
nfc_task_t* pNext; nfc_task_t *pNext;
}; };
void nfc_scheduler_timer_init(nfc_scheduler_timer_t* timer); void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer);
void nfc_scheduler_timer_start(nfc_scheduler_timer_t* timer); void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer);
uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t* timer); uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer);
void nfc_scheduler_timer_stop(nfc_scheduler_timer_t* timer); void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer);
void nfc_scheduler_timer_reset(nfc_scheduler_timer_t* timer); void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer);
/** Init scheduler /** Init scheduler
* \param pScheduler scheduler instance to init * \param pScheduler scheduler instance to init
* \param pTimer timer instance * \param pTimer timer instance
*/ */
void nfc_scheduler_init(nfc_scheduler_t* pScheduler, nfc_scheduler_timer_t* pTimer); void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer);
/** Iterate through all tasks /** Iterate through all tasks
* \param pScheduler scheduler instance * \param pScheduler scheduler instance
* \param events mask of events (except EVENT_TIMEOUT) that have been raised since this function last returned (0 on first call) * \param events mask of events (except EVENT_TIMEOUT) that have been raised since this function last returned (0 on first call)
* \return time after which this function must be called again if no other event arises * \return time after which this function must be called again if no other event arises
*/ */
uint32_t nfc_scheduler_iteration(nfc_scheduler_t* pScheduler, uint32_t events); uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events);
/** Queue a task to execute /** Queue a task to execute
* \param pScheduler scheduler instance * \param pScheduler scheduler instance
* \param pTask task to queue * \param pTask task to queue
* *
*/ */
void nfc_scheduler_queue_task(nfc_scheduler_t* pScheduler, nfc_task_t* pTask); void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask);
/** Remove a task to execute /** Remove a task to execute
* \param pScheduler scheduler instance * \param pScheduler scheduler instance
* \param pTask task to remove * \param pTask task to remove
* \param abort abort task if queued * \param abort abort task if queued
*/ */
void nfc_scheduler_dequeue_task(nfc_scheduler_t* pScheduler, bool abort, nfc_task_t* pTask); void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask);
/** Initialize task with the following parameters /** Initialize task with the following parameters
* \param pTask task to initialize * \param pTask task to initialize
@ -109,7 +107,7 @@ void nfc_scheduler_dequeue_task(nfc_scheduler_t* pScheduler, bool abort, nfc_tas
* \param fn function to be called * \param fn function to be called
* \param pUserData data that will be passed to function * \param pUserData data that will be passed to function
*/ */
void task_init(nfc_task_t* pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void* pUserData); void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -36,11 +36,11 @@
* \param read transport read function * \param read transport read function
* \param pUser parameter that will be passed to any of the above functions * \param pUser parameter that will be passed to any of the above functions
*/ */
void nfc_transport_init( nfc_transport_t* pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void* pUser ) void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser)
{ {
pTransport->write = write; pTransport->write = write;
pTransport->read = read; pTransport->read = read;
pTransport->pUser = pUser; pTransport->pUser = pUser;
} }

View File

@ -41,7 +41,7 @@ extern "C" {
* \param outLen buffer's length * \param outLen buffer's length
* \param pUser parameter passed to the nfc_transport_init function * \param pUser parameter passed to the nfc_transport_init function
*/ */
typedef void (*nfc_transport_write_fn_t)( uint8_t address, const uint8_t* outBuf, size_t outLen, void* pUser ); typedef void (*nfc_transport_write_fn_t)(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser);
/** Function called to read a register's value /** Function called to read a register's value
* \param address address to read packet from * \param address address to read packet from
@ -49,25 +49,24 @@ typedef void (*nfc_transport_write_fn_t)( uint8_t address, const uint8_t* outBuf
* \param outLen buffer's length * \param outLen buffer's length
* \param pUser parameter passed to the nfc_transport_init function * \param pUser parameter passed to the nfc_transport_init function
*/ */
typedef void (*nfc_transport_read_fn_t)( uint8_t address, uint8_t* inBuf, size_t inLen, void* pUser ); typedef void (*nfc_transport_read_fn_t)(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser);
typedef struct __transport typedef struct __transport {
{ nfc_transport_write_fn_t write;
nfc_transport_write_fn_t write; nfc_transport_read_fn_t read;
nfc_transport_read_fn_t read; void *pUser;
void* pUser;
} nfc_transport_t; } nfc_transport_t;
void nfc_transport_init( nfc_transport_t* pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void* pUser ); void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser);
static inline void nfc_transport_write( nfc_transport_t* pTransport, uint8_t address, const uint8_t* outBuf, size_t outLen ) static inline void nfc_transport_write(nfc_transport_t *pTransport, uint8_t address, const uint8_t *outBuf, size_t outLen)
{ {
pTransport->write( address, outBuf, outLen, pTransport->pUser ); pTransport->write(address, outBuf, outLen, pTransport->pUser);
} }
static inline void nfc_transport_read( nfc_transport_t* pTransport, uint8_t address, uint8_t* inBuf, size_t inLen ) static inline void nfc_transport_read(nfc_transport_t *pTransport, uint8_t address, uint8_t *inBuf, size_t inLen)
{ {
pTransport->read( address, inBuf, inLen, pTransport->pUser ); pTransport->read(address, inBuf, inLen, pTransport->pUser);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -32,181 +32,169 @@
#include "iso7816_defs.h" #include "iso7816_defs.h"
#include "tech/isodep/isodep_target.h" #include "tech/isodep/isodep_target.h"
static void iso7816_disconnected(nfc_tech_iso7816_t* pIso7816, bool deselected); static void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected);
static nfc_err_t iso7816_parse(nfc_tech_iso7816_t* pIso7816); static nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816);
static void iso7816_receive(nfc_tech_iso7816_t* pIso7816); static void iso7816_receive(nfc_tech_iso7816_t *pIso7816);
static nfc_err_t iso7816_transmit(nfc_tech_iso7816_t* pIso7816); static nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816);
static bool iso7816_mf_command(nfc_tech_iso7816_t* pIso7816); static bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816);
static void iso_dep_received_cb(nfc_tech_isodep_t* pIsodep, nfc_err_t ret, void* pUserData); static void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData);
static void iso_dep_transmitted_cb(nfc_tech_isodep_t* pIsodep, nfc_err_t ret, void* pUserData); static void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData);
static void iso_dep_disconnected_cb(nfc_tech_isodep_t* pIsodep, bool deselected, void* pUserData); static void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData);
static void iso_dep_stream_transmit_cb(buffer_t* ppDataIn, bool* pClose, size_t maxLength, void* pUserParam); static void iso_dep_stream_transmit_cb(buffer_t *ppDataIn, bool *pClose, size_t maxLength, void *pUserParam);
static void iso_dep_stream_receive_cb(buffer_t* pDataOut, bool closed, void* pUserParam); static void iso_dep_stream_receive_cb(buffer_t *pDataOut, bool closed, void *pUserParam);
void nfc_tech_iso7816_init(nfc_tech_iso7816_t* pIso7816, nfc_transceiver_t* pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void* pUserData) void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData)
{ {
buffer_init(&pIso7816->hist, NULL, 0); buffer_init(&pIso7816->hist, NULL, 0);
nfc_tech_isodep_target_init(&pIso7816->isoDepTarget, pTransceiver, &pIso7816->hist, iso_dep_disconnected_cb, pIso7816); nfc_tech_isodep_target_init(&pIso7816->isoDepTarget, pTransceiver, &pIso7816->hist, iso_dep_disconnected_cb, pIso7816);
pIso7816->pAppList = NULL; pIso7816->pAppList = NULL;
pIso7816->pSelectedApp = NULL;
pIso7816->disconnectedCb = disconnectedCb;
istream_init(&pIso7816->inputStream, iso_dep_stream_transmit_cb, pIso7816);
ostream_init(&pIso7816->outputStream, iso_dep_stream_receive_cb, pIso7816);
buffer_builder_init(&pIso7816->txBldr, pIso7816->txBuf, 2); //Just enough to fit sw
buffer_builder_init(&pIso7816->rxBldr, pIso7816->rxBuf, ISO7816_RX_BUFFER_SIZE);
pIso7816->pUserData = pUserData;
}
void nfc_tech_iso7816_connect(nfc_tech_iso7816_t* pIso7816)
{
pIso7816->disconnected = false;
pIso7816->responseReady = true;
iso7816_receive(pIso7816);
nfc_tech_isodep_target_connect(&pIso7816->isoDepTarget);
}
void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t* pIso7816)
{
nfc_tech_isodep_target_disconnect(&pIso7816->isoDepTarget);
}
void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t* pIso7816, nfc_tech_iso7816_app_t* pIso7816App)
{
nfc_tech_iso7816_app_t** ppPrevApp = &pIso7816->pAppList;
while( *ppPrevApp != NULL )
{
ppPrevApp = &((*ppPrevApp)->pNext);
}
*ppPrevApp = pIso7816App;
pIso7816App->pNext = NULL;
}
nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t* pIso7816)
{
nfc_err_t ret;
//Serialize APDU and send
buffer_builder_reset(&pIso7816->txBldr);
buffer_builder_write_nu16(&pIso7816->txBldr, pIso7816->rApdu.sw);
buffer_append(&pIso7816->rApdu.dataOut, buffer_builder_buffer(&pIso7816->txBldr));
NFC_DBG("R-ADPU: (LE):%02X SW:%04X", buffer_reader_readable(&pIso7816->rApdu.dataOut), pIso7816->rApdu.sw);
DBG_BLOCK( buffer_dump(&pIso7816->rApdu.dataOut); )
ret = iso7816_transmit(pIso7816);
if(ret)
{
return ret;
}
return NFC_OK;
}
void iso7816_disconnected(nfc_tech_iso7816_t* pIso7816, bool deselected)
{
pIso7816->disconnected = true;
if(pIso7816->pSelectedApp != NULL)
{
//Deselect previous app
pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
pIso7816->pSelectedApp = NULL; pIso7816->pSelectedApp = NULL;
} pIso7816->disconnectedCb = disconnectedCb;
pIso7816->disconnectedCb(pIso7816, deselected, pIso7816->pUserData);
istream_init(&pIso7816->inputStream, iso_dep_stream_transmit_cb, pIso7816);
ostream_init(&pIso7816->outputStream, iso_dep_stream_receive_cb, pIso7816);
buffer_builder_init(&pIso7816->txBldr, pIso7816->txBuf, 2); //Just enough to fit sw
buffer_builder_init(&pIso7816->rxBldr, pIso7816->rxBuf, ISO7816_RX_BUFFER_SIZE);
pIso7816->pUserData = pUserData;
} }
nfc_err_t iso7816_parse(nfc_tech_iso7816_t* pIso7816) void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816)
{ {
//Reset R-APDU pIso7816->disconnected = false;
buffer_init(&pIso7816->rApdu.dataOut, NULL, 0); pIso7816->responseReady = true;
pIso7816->rApdu.sw = ISO7816_SW_OK;
DBG_BLOCK( buffer_dump(buffer_builder_buffer(&pIso7816->rxBldr)); ) iso7816_receive(pIso7816);
nfc_tech_isodep_target_connect(&pIso7816->isoDepTarget);
}
if( buffer_reader_readable( buffer_builder_buffer(&pIso7816->rxBldr) ) < 4 ) void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816)
{ {
NFC_ERR("C-APDU is too small"); nfc_tech_isodep_target_disconnect(&pIso7816->isoDepTarget);
pIso7816->rApdu.sw = ISO7816_SW_INVALID_CLASS; }
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_PROTOCOL;
}
pIso7816->cApdu.cla = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr)); void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App)
pIso7816->cApdu.ins = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr)); {
pIso7816->cApdu.p1 = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr)); nfc_tech_iso7816_app_t **ppPrevApp = &pIso7816->pAppList;
pIso7816->cApdu.p2 = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr)); while (*ppPrevApp != NULL) {
buffer_init(&pIso7816->cApdu.dataIn, NULL, 0); ppPrevApp = &((*ppPrevApp)->pNext);
pIso7816->cApdu.maxRespLength = 0;
if( buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) > 1 )
{
size_t lc = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
if( buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) >= lc )
{
buffer_split(&pIso7816->cApdu.dataIn, buffer_builder_buffer(&pIso7816->rxBldr), buffer_builder_buffer(&pIso7816->rxBldr), lc);
} }
else *ppPrevApp = pIso7816App;
{ pIso7816App->pNext = NULL;
pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH; }
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_LENGTH; //Not a valid frame nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816)
{
nfc_err_t ret;
//Serialize APDU and send
buffer_builder_reset(&pIso7816->txBldr);
buffer_builder_write_nu16(&pIso7816->txBldr, pIso7816->rApdu.sw);
buffer_append(&pIso7816->rApdu.dataOut, buffer_builder_buffer(&pIso7816->txBldr));
NFC_DBG("R-ADPU: (LE):%02X SW:%04X", buffer_reader_readable(&pIso7816->rApdu.dataOut), pIso7816->rApdu.sw);
DBG_BLOCK(buffer_dump(&pIso7816->rApdu.dataOut);)
ret = iso7816_transmit(pIso7816);
if (ret) {
return ret;
} }
}
if( buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) >= 1 )
{
pIso7816->cApdu.maxRespLength = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
}
NFC_DBG("C-APDU: CLA:%02X INS:%02X P1:%02X P2:%02X LC:%02X LE:%02X", pIso7816->cApdu.cla, pIso7816->cApdu.ins, pIso7816->cApdu.p1, pIso7816->cApdu.p2,
buffer_reader_readable(&pIso7816->cApdu.dataIn), pIso7816->cApdu.maxRespLength);
if( buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) > 0 )
{
pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_LENGTH; //Not a valid frame
}
//See if can select an app
if( iso7816_mf_command(pIso7816) )
{
nfc_tech_iso7816_reply(pIso7816);
return NFC_OK; return NFC_OK;
}
//Pass command to selected app
if( pIso7816->pSelectedApp == NULL )
{
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_NOT_FOUND; //Not a valid frame
}
pIso7816->pSelectedApp->apdu(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
return NFC_OK;
} }
void iso7816_receive(nfc_tech_iso7816_t* pIso7816) void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected)
{ {
buffer_builder_reset(&pIso7816->rxBldr); pIso7816->disconnected = true;
nfc_tech_isodep_target_receive(&pIso7816->isoDepTarget, &pIso7816->outputStream, iso_dep_received_cb, pIso7816); if (pIso7816->pSelectedApp != NULL) {
//Deselect previous app
pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
pIso7816->pSelectedApp = NULL;
}
pIso7816->disconnectedCb(pIso7816, deselected, pIso7816->pUserData);
} }
nfc_err_t iso7816_transmit(nfc_tech_iso7816_t* pIso7816) nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816)
{ {
return nfc_tech_isodep_target_transmit(&pIso7816->isoDepTarget, &pIso7816->inputStream, iso_dep_transmitted_cb, pIso7816); //Reset R-APDU
buffer_init(&pIso7816->rApdu.dataOut, NULL, 0);
pIso7816->rApdu.sw = ISO7816_SW_OK;
DBG_BLOCK(buffer_dump(buffer_builder_buffer(&pIso7816->rxBldr));)
if (buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) < 4) {
NFC_ERR("C-APDU is too small");
pIso7816->rApdu.sw = ISO7816_SW_INVALID_CLASS;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_PROTOCOL;
}
pIso7816->cApdu.cla = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
pIso7816->cApdu.ins = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
pIso7816->cApdu.p1 = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
pIso7816->cApdu.p2 = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
buffer_init(&pIso7816->cApdu.dataIn, NULL, 0);
pIso7816->cApdu.maxRespLength = 0;
if (buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) > 1) {
size_t lc = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
if (buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) >= lc) {
buffer_split(&pIso7816->cApdu.dataIn, buffer_builder_buffer(&pIso7816->rxBldr), buffer_builder_buffer(&pIso7816->rxBldr), lc);
} else {
pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_LENGTH; //Not a valid frame
}
}
if (buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) >= 1) {
pIso7816->cApdu.maxRespLength = buffer_read_nu8(buffer_builder_buffer(&pIso7816->rxBldr));
}
NFC_DBG("C-APDU: CLA:%02X INS:%02X P1:%02X P2:%02X LC:%02X LE:%02X", pIso7816->cApdu.cla, pIso7816->cApdu.ins, pIso7816->cApdu.p1, pIso7816->cApdu.p2,
buffer_reader_readable(&pIso7816->cApdu.dataIn), pIso7816->cApdu.maxRespLength);
if (buffer_reader_readable(buffer_builder_buffer(&pIso7816->rxBldr)) > 0) {
pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_LENGTH; //Not a valid frame
}
//See if can select an app
if (iso7816_mf_command(pIso7816)) {
nfc_tech_iso7816_reply(pIso7816);
return NFC_OK;
}
//Pass command to selected app
if (pIso7816->pSelectedApp == NULL) {
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
nfc_tech_iso7816_reply(pIso7816);
return NFC_ERR_NOT_FOUND; //Not a valid frame
}
pIso7816->pSelectedApp->apdu(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
return NFC_OK;
}
void iso7816_receive(nfc_tech_iso7816_t *pIso7816)
{
buffer_builder_reset(&pIso7816->rxBldr);
nfc_tech_isodep_target_receive(&pIso7816->isoDepTarget, &pIso7816->outputStream, iso_dep_received_cb, pIso7816);
}
nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816)
{
return nfc_tech_isodep_target_transmit(&pIso7816->isoDepTarget, &pIso7816->inputStream, iso_dep_transmitted_cb, pIso7816);
} }
/** Handle ISO7816-4 command /** Handle ISO7816-4 command
@ -220,147 +208,128 @@ nfc_err_t iso7816_transmit(nfc_tech_iso7816_t* pIso7816)
* \param SW status word * \param SW status word
* \return true if command was handled, false if it should be passed to the selected application * \return true if command was handled, false if it should be passed to the selected application
*/ */
bool iso7816_mf_command(nfc_tech_iso7816_t* pIso7816) bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816)
{ {
nfc_tech_iso7816_app_t* pApp; nfc_tech_iso7816_app_t *pApp;
if(pIso7816->cApdu.cla != 0x00) if (pIso7816->cApdu.cla != 0x00) {
{
return false;
}
switch(pIso7816->cApdu.ins)
{
case ISO7816_INS_SELECT:
switch(pIso7816->cApdu.p1)
{
case 0x04: //Selection by DF name
pApp = pIso7816->pAppList;
while(pApp != NULL)
{
if( buffer_reader_readable(&pIso7816->cApdu.dataIn) <= pApp->aidSize )
{
if( buffer_reader_cmp_bytes(&pIso7816->cApdu.dataIn, pApp->aid, buffer_reader_readable(&pIso7816->cApdu.dataIn)) )
{
if(pIso7816->pSelectedApp != NULL)
{
//Deselect previous app
pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
}
pIso7816->pSelectedApp = pApp;
pIso7816->pSelectedApp->selected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
pIso7816->rApdu.sw = ISO7816_SW_OK;
return true;
}
}
pApp = pApp->pNext;
}
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
return true;
default:
if(pIso7816->pSelectedApp == NULL)
{
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
return true;
}
else
{
return false; return false;
}
} }
break; switch (pIso7816->cApdu.ins) {
default: case ISO7816_INS_SELECT:
if(pIso7816->pSelectedApp == NULL) switch (pIso7816->cApdu.p1) {
case 0x04: //Selection by DF name
pApp = pIso7816->pAppList;
while (pApp != NULL) {
if (buffer_reader_readable(&pIso7816->cApdu.dataIn) <= pApp->aidSize) {
if (buffer_reader_cmp_bytes(&pIso7816->cApdu.dataIn, pApp->aid, buffer_reader_readable(&pIso7816->cApdu.dataIn))) {
if (pIso7816->pSelectedApp != NULL) {
//Deselect previous app
pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
}
pIso7816->pSelectedApp = pApp;
pIso7816->pSelectedApp->selected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData);
pIso7816->rApdu.sw = ISO7816_SW_OK;
return true;
}
}
pApp = pApp->pNext;
}
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
return true;
default:
if (pIso7816->pSelectedApp == NULL) {
pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND;
return true;
} else {
return false;
}
}
break;
default:
if (pIso7816->pSelectedApp == NULL) {
pIso7816->rApdu.sw = ISO7816_SW_INVALID_INS;
return true;
} else {
return false;
}
break;
}
}
void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData)
{
nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData;
(void) pIsodep;
if (ret) {
NFC_WARN("Got error %d", ret);
return;
}
//Parse received APDU
ret = iso7816_parse(pIso7816);
if (ret) {
NFC_WARN("Got error %d", ret);
return;
}
}
void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData)
{
nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData;
(void) pIsodep;
if (ret) {
NFC_WARN("Got error %d", ret);
return;
}
//Advertise that we have space in our buffer?
//Switch to receive mode!
iso7816_receive(pIso7816);
}
void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData)
{
nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData;
(void) pIsodep;
NFC_DBG("ISO DEP disconnected");
iso7816_disconnected(pIso7816, deselected);
}
void iso_dep_stream_transmit_cb(buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam)
{
nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam;
//Only close if buffer fits in this frame
if (maxLength >= buffer_reader_readable(&pIso7816->rApdu.dataOut))
//if( buffer_total_length(&pLlcp->tx) <= maxLength )
{ {
pIso7816->rApdu.sw = ISO7816_SW_INVALID_INS; maxLength = buffer_reader_readable(&pIso7816->rApdu.dataOut);
return true; *pClose = true;
} else {
*pClose = false;
} }
else
{ buffer_split(pDataIn, &pIso7816->rApdu.dataOut, &pIso7816->rApdu.dataOut, maxLength);
return false; }
void iso_dep_stream_receive_cb(buffer_t *pDataOut, bool closed, void *pUserParam)
{
nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam;
(void) closed;
if (buffer_reader_readable(pDataOut) > buffer_builder_writeable(&pIso7816->rxBldr)) {
NFC_ERR("Frame will not fit (%d > %d)", buffer_reader_readable(pDataOut), buffer_builder_writeable(&pIso7816->rxBldr));
} }
break;
} //Feed rx buffer
} buffer_builder_copy_n_bytes(&pIso7816->rxBldr, pDataOut, buffer_reader_readable(pDataOut));
void iso_dep_received_cb(nfc_tech_isodep_t* pIsodep, nfc_err_t ret, void* pUserData)
{
nfc_tech_iso7816_t* pIso7816 = (nfc_tech_iso7816_t*) pUserData;
(void) pIsodep;
if( ret )
{
NFC_WARN("Got error %d", ret);
return;
}
//Parse received APDU
ret = iso7816_parse(pIso7816);
if( ret )
{
NFC_WARN("Got error %d", ret);
return;
}
}
void iso_dep_transmitted_cb(nfc_tech_isodep_t* pIsodep, nfc_err_t ret, void* pUserData)
{
nfc_tech_iso7816_t* pIso7816 = (nfc_tech_iso7816_t*) pUserData;
(void) pIsodep;
if( ret )
{
NFC_WARN("Got error %d", ret);
return;
}
//Advertise that we have space in our buffer?
//Switch to receive mode!
iso7816_receive(pIso7816);
}
void iso_dep_disconnected_cb(nfc_tech_isodep_t* pIsodep, bool deselected, void* pUserData)
{
nfc_tech_iso7816_t* pIso7816 = (nfc_tech_iso7816_t*) pUserData;
(void) pIsodep;
NFC_DBG("ISO DEP disconnected");
iso7816_disconnected(pIso7816, deselected);
}
void iso_dep_stream_transmit_cb(buffer_t* pDataIn, bool* pClose, size_t maxLength, void* pUserParam)
{
nfc_tech_iso7816_t* pIso7816 = (nfc_tech_iso7816_t*) pUserParam;
//Only close if buffer fits in this frame
if( maxLength >= buffer_reader_readable(&pIso7816->rApdu.dataOut) )
//if( buffer_total_length(&pLlcp->tx) <= maxLength )
{
maxLength = buffer_reader_readable(&pIso7816->rApdu.dataOut);
*pClose = true;
}
else
{
*pClose = false;
}
buffer_split(pDataIn, &pIso7816->rApdu.dataOut, &pIso7816->rApdu.dataOut, maxLength);
}
void iso_dep_stream_receive_cb(buffer_t* pDataOut, bool closed, void* pUserParam)
{
nfc_tech_iso7816_t* pIso7816 = (nfc_tech_iso7816_t*) pUserParam;
(void) closed;
if( buffer_reader_readable(pDataOut) > buffer_builder_writeable(&pIso7816->rxBldr) )
{
NFC_ERR("Frame will not fit (%d > %d)", buffer_reader_readable(pDataOut), buffer_builder_writeable(&pIso7816->rxBldr) );
}
//Feed rx buffer
buffer_builder_copy_n_bytes(&pIso7816->rxBldr, pDataOut, buffer_reader_readable(pDataOut));
} }

View File

@ -32,20 +32,18 @@ extern "C" {
#include "tech/isodep/isodep_target.h" #include "tech/isodep/isodep_target.h"
struct nfc_tech_iso7816_c_apdu struct nfc_tech_iso7816_c_apdu {
{ uint8_t cla;
uint8_t cla; uint8_t ins;
uint8_t ins; uint8_t p1;
uint8_t p1; uint8_t p2;
uint8_t p2; buffer_t dataIn;
buffer_t dataIn; size_t maxRespLength;
size_t maxRespLength;
}; };
struct nfc_tech_iso7816_r_apdu struct nfc_tech_iso7816_r_apdu {
{ buffer_t dataOut;
buffer_t dataOut; uint16_t sw;
uint16_t sw;
}; };
#define ISO7816_RX_BUFFER_SIZE 256 #define ISO7816_RX_BUFFER_SIZE 256
@ -55,56 +53,55 @@ typedef struct nfc_tech_iso7816_r_apdu nfc_tech_iso7816_r_apdu_t;
typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t; typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t;
typedef void (*nfc_tech_iso7816_disconnected_cb)(nfc_tech_iso7816_t* pIso7816, bool deselected, void* pUserData); typedef void (*nfc_tech_iso7816_disconnected_cb)(nfc_tech_iso7816_t *pIso7816, bool deselected, void *pUserData);
struct nfc_tech_iso7816_app; struct nfc_tech_iso7816_app;
typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t; typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t;
struct nfc_tech_iso7816 struct nfc_tech_iso7816 {
{ nfc_tech_isodep_target_t isoDepTarget;
nfc_tech_isodep_target_t isoDepTarget;
nfc_tech_iso7816_app_t* pAppList; nfc_tech_iso7816_app_t *pAppList;
nfc_tech_iso7816_app_t* pSelectedApp; nfc_tech_iso7816_app_t *pSelectedApp;
bool disconnected; bool disconnected;
nfc_tech_iso7816_c_apdu_t cApdu; nfc_tech_iso7816_c_apdu_t cApdu;
nfc_tech_iso7816_r_apdu_t rApdu; nfc_tech_iso7816_r_apdu_t rApdu;
bool responseReady; bool responseReady;
nfc_tech_iso7816_disconnected_cb disconnectedCb; nfc_tech_iso7816_disconnected_cb disconnectedCb;
void* pUserData; void *pUserData;
buffer_t hist; //Historical bytes buffer_t hist; //Historical bytes
istream_t inputStream; istream_t inputStream;
ostream_t outputStream; ostream_t outputStream;
//PDU buffer (tx) //PDU buffer (tx)
uint8_t txBuf[2]; uint8_t txBuf[2];
buffer_builder_t txBldr; buffer_builder_t txBldr;
//Receive buffer //Receive buffer
uint8_t rxBuf[ISO7816_RX_BUFFER_SIZE]; uint8_t rxBuf[ISO7816_RX_BUFFER_SIZE];
buffer_builder_t rxBldr; buffer_builder_t rxBldr;
}; };
void nfc_tech_iso7816_init(nfc_tech_iso7816_t* pIso7816, nfc_transceiver_t* pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void* pUserData); void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData);
void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t* pIso7816, nfc_tech_iso7816_app_t* pIso7816App); void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App);
void nfc_tech_iso7816_connect(nfc_tech_iso7816_t* pIso7816); void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816);
void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t* pIso7816); void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816);
nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t* pIso7816); nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816);
inline static nfc_tech_iso7816_c_apdu_t* nfc_tech_iso7816_c_apdu(nfc_tech_iso7816_t* pIso7816) inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_c_apdu(nfc_tech_iso7816_t *pIso7816)
{ {
return &pIso7816->cApdu; return &pIso7816->cApdu;
} }
inline static nfc_tech_iso7816_r_apdu_t* nfc_tech_iso7816_r_apdu(nfc_tech_iso7816_t* pIso7816) inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_r_apdu(nfc_tech_iso7816_t *pIso7816)
{ {
return &pIso7816->rApdu; return &pIso7816->rApdu;
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -22,21 +22,21 @@
#include "iso7816_app.h" #include "iso7816_app.h"
void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t* pIso7816App, void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App,
nfc_tech_iso7816_t* pIso7816, nfc_tech_iso7816_t *pIso7816,
const uint8_t* aid, size_t aidSize, const uint8_t *aid, size_t aidSize,
nfc_tech_iso7816_app_cb selected, nfc_tech_iso7816_app_cb selected,
nfc_tech_iso7816_app_cb deselected, nfc_tech_iso7816_app_cb deselected,
nfc_tech_iso7816_app_cb apdu, nfc_tech_iso7816_app_cb apdu,
void* pUserData void *pUserData
) )
{ {
pIso7816App->pIso7816 = pIso7816; pIso7816App->pIso7816 = pIso7816;
pIso7816App->aid = aid; pIso7816App->aid = aid;
pIso7816App->aidSize = aidSize; pIso7816App->aidSize = aidSize;
pIso7816App->selected = selected; pIso7816App->selected = selected;
pIso7816App->deselected = deselected; pIso7816App->deselected = deselected;
pIso7816App->apdu = apdu; pIso7816App->apdu = apdu;
pIso7816App->pUserData = pUserData; pIso7816App->pUserData = pUserData;
pIso7816App->pNext = NULL; pIso7816App->pNext = NULL;
} }

View File

@ -34,44 +34,43 @@ struct nfc_tech_iso7816_app;
typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t; typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t;
typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t; typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t;
typedef void (*nfc_tech_iso7816_app_cb)( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ); typedef void (*nfc_tech_iso7816_app_cb)(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData);
struct nfc_tech_iso7816_app struct nfc_tech_iso7816_app {
{ nfc_tech_iso7816_t *pIso7816;
nfc_tech_iso7816_t* pIso7816;
const uint8_t* aid; const uint8_t *aid;
size_t aidSize; size_t aidSize;
nfc_tech_iso7816_app_cb selected; nfc_tech_iso7816_app_cb selected;
nfc_tech_iso7816_app_cb deselected; nfc_tech_iso7816_app_cb deselected;
nfc_tech_iso7816_app_cb apdu; nfc_tech_iso7816_app_cb apdu;
void* pUserData; void *pUserData;
nfc_tech_iso7816_app_t* pNext; nfc_tech_iso7816_app_t *pNext;
}; };
void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t* pIso7816App, nfc_tech_iso7816_t* pIso7816, const uint8_t* aid, size_t aidSize, void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App, nfc_tech_iso7816_t *pIso7816, const uint8_t *aid, size_t aidSize,
nfc_tech_iso7816_app_cb selected, nfc_tech_iso7816_app_cb selected,
nfc_tech_iso7816_app_cb deselected, nfc_tech_iso7816_app_cb deselected,
nfc_tech_iso7816_app_cb apdu, nfc_tech_iso7816_app_cb apdu,
void* pUserData void *pUserData
); );
inline static nfc_err_t nfc_tech_iso7816_app_reply(nfc_tech_iso7816_app_t* pIso7816App) inline static nfc_err_t nfc_tech_iso7816_app_reply(nfc_tech_iso7816_app_t *pIso7816App)
{ {
return nfc_tech_iso7816_reply(pIso7816App->pIso7816); return nfc_tech_iso7816_reply(pIso7816App->pIso7816);
} }
inline static nfc_tech_iso7816_c_apdu_t* nfc_tech_iso7816_app_c_apdu(nfc_tech_iso7816_app_t* pIso7816App) inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_app_c_apdu(nfc_tech_iso7816_app_t *pIso7816App)
{ {
return nfc_tech_iso7816_c_apdu(pIso7816App->pIso7816); return nfc_tech_iso7816_c_apdu(pIso7816App->pIso7816);
} }
inline static nfc_tech_iso7816_r_apdu_t* nfc_tech_iso7816_app_r_apdu(nfc_tech_iso7816_app_t* pIso7816App) inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_app_r_apdu(nfc_tech_iso7816_app_t *pIso7816App)
{ {
return nfc_tech_iso7816_r_apdu(pIso7816App->pIso7816); return nfc_tech_iso7816_r_apdu(pIso7816App->pIso7816);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -32,12 +32,11 @@ extern "C" {
struct nfc_tech_isodep; struct nfc_tech_isodep;
typedef struct nfc_tech_isodep nfc_tech_isodep_t; typedef struct nfc_tech_isodep nfc_tech_isodep_t;
typedef void (*nfc_tech_isodep_cb_t)(nfc_tech_isodep_t* pIsodep, nfc_err_t ret, void* pUserData); typedef void (*nfc_tech_isodep_cb_t)(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData);
typedef void (*nfc_tech_isodep_disconnected_cb)(nfc_tech_isodep_t* pIsodep, bool deselected, void* pUserData); typedef void (*nfc_tech_isodep_disconnected_cb)(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData);
struct nfc_tech_isodep struct nfc_tech_isodep {
{
}; };

File diff suppressed because it is too large Load Diff

View File

@ -35,81 +35,76 @@ struct nfc_tech_isodep_target;
typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t; typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t;
typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t; typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t;
struct nfc_tech_isodep_target struct nfc_tech_isodep_target {
{ nfc_tech_isodep_t isodep;
nfc_tech_isodep_t isodep; nfc_transceiver_t *pTransceiver;
nfc_transceiver_t* pTransceiver;
struct struct {
{ ostream_t *pReqStream;
ostream_t* pReqStream; istream_t *pResStream;
istream_t* pResStream;
nfc_tech_isodep_cb_t reqCb; nfc_tech_isodep_cb_t reqCb;
void* pReqUserData; void *pReqUserData;
nfc_tech_isodep_cb_t resCb; nfc_tech_isodep_cb_t resCb;
void* pResUserData; void *pResUserData;
buffer_t res; buffer_t res;
bool chaining; bool chaining;
uint8_t blockNumber; uint8_t blockNumber;
enum enum {
{ ISO_DEP_TARGET_DEP_FRAME_IDLE,
ISO_DEP_TARGET_DEP_FRAME_IDLE, ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_WTX_SENT,
ISO_DEP_TARGET_DEP_FRAME_WTX_SENT, ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT,
ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT, ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_NACK_SENT,
ISO_DEP_TARGET_DEP_FRAME_NACK_SENT, ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_ACK_SENT,
ISO_DEP_TARGET_DEP_FRAME_ACK_SENT, ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED,
ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED, ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT,
ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT, } frameState;
} frameState; } dep;
} dep; struct {
struct enum {
{ ISO_DEP_TARGET_COMMANDS_DISCONNECTED,
enum
{
ISO_DEP_TARGET_COMMANDS_DISCONNECTED,
ISO_DEP_TARGET_COMMANDS_CONNECTING, ISO_DEP_TARGET_COMMANDS_CONNECTING,
ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD, ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD,
ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT, ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT,
ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD, ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD,
ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT, ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT,
} state; } state;
size_t inPayloadSize; size_t inPayloadSize;
buffer_builder_t respBldr; buffer_builder_t respBldr;
uint8_t respBuf[32]; uint8_t respBuf[32];
buffer_t* pReq; buffer_t *pReq;
} commands; } commands;
buffer_t* pHist; buffer_t *pHist;
nfc_tech_isodep_disconnected_cb disconnectedCb; nfc_tech_isodep_disconnected_cb disconnectedCb;
void* pUserData; void *pUserData;
}; };
//High-level Target functions //High-level Target functions
void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t* pIsodepTarget, nfc_transceiver_t* pTransceiver, void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver,
buffer_t* pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void* pUserData); buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData);
nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t* pIsodepTarget); nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget);
void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t* pIsodepTarget); void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget);
nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t* pIsodepTarget, istream_t* pStream, nfc_tech_isodep_cb_t cb, void* pUserData); nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData);
nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t* pIsodepTarget, ostream_t* pStream, nfc_tech_isodep_cb_t cb, void* pUserData); nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -41,272 +41,246 @@ static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
#define NDEF_FILE 0xA443 #define NDEF_FILE 0xA443
#define DEFAULT_FILE 0x0000 #define DEFAULT_FILE 0x0000
static void app_selected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ); static void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData);
static void app_deselected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ); static void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData);
static void app_apdu( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ); static void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData);
static nfc_err_t data_read(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off, size_t len); static nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, buffer_t *pBuf, uint16_t file, size_t off, size_t len);
static nfc_err_t data_write(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off); static nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, buffer_t *pBuf, uint16_t file, size_t off);
void nfc_tech_type4_target_init(nfc_tech_type4_target_t* pType4Target, nfc_tech_iso7816_t* pIso7816, ndef_msg_t* pNdef) void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef)
{ {
buffer_builder_init(&pType4Target->ccFileBldr, pType4Target->ccFileBuf, /*sizeof(pType4Target->ccFileBuf)*/15); buffer_builder_init(&pType4Target->ccFileBldr, pType4Target->ccFileBuf, /*sizeof(pType4Target->ccFileBuf)*/15);
buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2);
pType4Target->selFile = DEFAULT_FILE; pType4Target->selFile = DEFAULT_FILE;
pType4Target->pNdef = pNdef; pType4Target->pNdef = pNdef;
pType4Target->written = false; pType4Target->written = false;
nfc_tech_iso7816_app_init(&pType4Target->app, pIso7816, aid, sizeof(aid), app_selected, app_deselected, app_apdu, pType4Target); nfc_tech_iso7816_app_init(&pType4Target->app, pIso7816, aid, sizeof(aid), app_selected, app_deselected, app_apdu, pType4Target);
nfc_tech_iso7816_add_app(pIso7816, &pType4Target->app); nfc_tech_iso7816_add_app(pIso7816, &pType4Target->app);
} }
void app_selected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ) void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData)
{ {
nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData; nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData;
DBG("Selected"); DBG("Selected");
(void) pIso7816App; (void) pIso7816App;
buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef));
//Populate CC file //Populate CC file
buffer_builder_reset(&pType4Target->ccFileBldr); buffer_builder_reset(&pType4Target->ccFileBldr);
buffer_builder_write_nu16( &pType4Target->ccFileBldr, 15 ); //CC file is 15 bytes long buffer_builder_write_nu16(&pType4Target->ccFileBldr, 15); //CC file is 15 bytes long
#if TYPE4_NDEF_VERSION == 2 #if TYPE4_NDEF_VERSION == 2
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x20 ); //NFC Forum Tag Type 4 V2.0 compliant buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x20); //NFC Forum Tag Type 4 V2.0 compliant
#else #else
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x10 ); //NFC Forum Tag Type 4 V1.0 compliant buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x10); //NFC Forum Tag Type 4 V1.0 compliant
#endif #endif
buffer_builder_write_nu16( &pType4Target->ccFileBldr, 256 /* Max frame size */ - 2 /* SW */ - 3 /* ISO-DEP PFB + DID + NAD */ ); //Max data size that can be read from the tag buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 2 /* SW */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be read from the tag
buffer_builder_write_nu16( &pType4Target->ccFileBldr, 256 /* Max frame size */ - 6 /* CLA INS P1 P2 LC LE */ - 3 /* ISO-DEP PFB + DID + NAD */ ); //Max data size that can be written to the tag buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 6 /* CLA INS P1 P2 LC LE */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be written to the tag
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x04 ); //NDEF File Control TLV - Type buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x04); //NDEF File Control TLV - Type
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 6 ); //NDEF File Control TLV - Length buffer_builder_write_nu8(&pType4Target->ccFileBldr, 6); //NDEF File Control TLV - Length
buffer_builder_write_nu16( &pType4Target->ccFileBldr, NDEF_FILE ); //NDEF file id buffer_builder_write_nu16(&pType4Target->ccFileBldr, NDEF_FILE); //NDEF file id
buffer_builder_write_nu16( &pType4Target->ccFileBldr, 2 /* length header */ + buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) ) ); //Max size of NDEF data buffer_builder_write_nu16(&pType4Target->ccFileBldr, 2 /* length header */ + buffer_builder_writeable(ndef_msg_buffer_builder(pType4Target->pNdef))); //Max size of NDEF data
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x00 ); //Open read access buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open read access
buffer_builder_write_nu8( &pType4Target->ccFileBldr, 0x00 ); //Open write access buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open write access
//Encode NDEF file //Encode NDEF file
ndef_msg_encode(pType4Target->pNdef); ndef_msg_encode(pType4Target->pNdef);
//Populate NDEF file //Populate NDEF file
buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2);
buffer_builder_write_nu16( &pType4Target->ndefFileBldr, buffer_reader_readable( buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)) ) ); buffer_builder_write_nu16(&pType4Target->ndefFileBldr, buffer_reader_readable(buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef))));
//Pad NDEF file with 0s //Pad NDEF file with 0s
while( buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) ) > 0 ) while (buffer_builder_writeable(ndef_msg_buffer_builder(pType4Target->pNdef)) > 0) {
{ buffer_builder_write_nu8(ndef_msg_buffer_builder(pType4Target->pNdef), 0);
buffer_builder_write_nu8(ndef_msg_buffer_builder(pType4Target->pNdef), 0); }
}
//No file selected //No file selected
pType4Target->selFile = DEFAULT_FILE; pType4Target->selFile = DEFAULT_FILE;
pType4Target->written = false; pType4Target->written = false;
} }
void app_deselected( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ) void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData)
{ {
nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData; nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData;
(void) pIso7816App; (void) pIso7816App;
//Reset buffers //Reset buffers
buffer_builder_reset(&pType4Target->ccFileBldr); buffer_builder_reset(&pType4Target->ccFileBldr);
buffer_builder_set_full(&pType4Target->ndefFileBldr); //To read length buffer_builder_set_full(&pType4Target->ndefFileBldr); //To read length
buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef));
DBG("Deselected"); DBG("Deselected");
if(pType4Target->written) if (pType4Target->written) {
{ DBG("New content has been written");
DBG("New content has been written"); //Try to parse NDEF
//Try to parse NDEF //Set buffer length based on file header
//Set buffer length based on file header size_t length = buffer_read_nu16(buffer_builder_buffer(&pType4Target->ndefFileBldr));
size_t length = buffer_read_nu16(buffer_builder_buffer(&pType4Target->ndefFileBldr)); DBG("Length is %lu", length);
DBG("Length is %lu", length); if (length < buffer_builder_writeable(ndef_msg_buffer_builder(pType4Target->pNdef))) {
if( length < buffer_builder_writeable( ndef_msg_buffer_builder(pType4Target->pNdef) )) buffer_builder_set_write_offset(ndef_msg_buffer_builder(pType4Target->pNdef), length);
{ ndef_msg_decode(pType4Target->pNdef);
buffer_builder_set_write_offset( ndef_msg_buffer_builder(pType4Target->pNdef), length ); } else {
ndef_msg_decode(pType4Target->pNdef); ERR("Invalid length");
}
} }
else
{
ERR("Invalid length");
}
}
} }
void app_apdu( nfc_tech_iso7816_app_t* pIso7816App, void* pUserData ) void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData)
{ {
nfc_tech_type4_target_t* pType4Target = (nfc_tech_type4_target_t*) pUserData; nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData;
//Reset buffers //Reset buffers
buffer_builder_set_full(&pType4Target->ccFileBldr); buffer_builder_set_full(&pType4Target->ccFileBldr);
buffer_builder_set_full(&pType4Target->ndefFileBldr); buffer_builder_set_full(&pType4Target->ndefFileBldr);
buffer_builder_set_full( ndef_msg_buffer_builder(pType4Target->pNdef) ); //Set offset to 0, size to max buffer_builder_set_full(ndef_msg_buffer_builder(pType4Target->pNdef)); //Set offset to 0, size to max
buffer_set_next(buffer_builder_buffer(&pType4Target->ndefFileBldr), buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef))); buffer_set_next(buffer_builder_buffer(&pType4Target->ndefFileBldr), buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)));
//Recover PDU //Recover PDU
nfc_tech_iso7816_c_apdu_t* pCApdu = nfc_tech_iso7816_app_c_apdu(pIso7816App); nfc_tech_iso7816_c_apdu_t *pCApdu = nfc_tech_iso7816_app_c_apdu(pIso7816App);
nfc_tech_iso7816_r_apdu_t* pRApdu = nfc_tech_iso7816_app_r_apdu(pIso7816App); nfc_tech_iso7816_r_apdu_t *pRApdu = nfc_tech_iso7816_app_r_apdu(pIso7816App);
nfc_err_t ret; nfc_err_t ret;
switch(pCApdu->ins) switch (pCApdu->ins) {
{ case ISO7816_INS_SELECT:
case ISO7816_INS_SELECT: switch (pCApdu->p1) {
switch (pCApdu->p1) case 0x00: //Selection by ID
{ case 0x02: //Selection by child ID
case 0x00: //Selection by ID if (buffer_reader_readable(&pCApdu->dataIn) != 2) {
case 0x02: //Selection by child ID pRApdu->sw = ISO7816_SW_NOT_FOUND;
if ( buffer_reader_readable(&pCApdu->dataIn) != 2) break;
{ }
pRApdu->sw = ISO7816_SW_NOT_FOUND;
break;
}
uint16_t file = buffer_read_nu16(&pCApdu->dataIn); uint16_t file = buffer_read_nu16(&pCApdu->dataIn);
if ( file == NDEF_FILE ) if (file == NDEF_FILE) {
{ pType4Target->selFile = NDEF_FILE;
pType4Target->selFile = NDEF_FILE; DBG("NDEF File selected");
DBG("NDEF File selected"); pRApdu->sw = ISO7816_SW_OK;
pRApdu->sw = ISO7816_SW_OK; } else if (file == CC_FILE) {
} pType4Target->selFile = CC_FILE;
else if ( file == CC_FILE ) DBG("CC File selected");
{ pRApdu->sw = ISO7816_SW_OK;
pType4Target->selFile = CC_FILE; } else {
DBG("CC File selected"); //file = DEFAULT_FILE;
pRApdu->sw = ISO7816_SW_OK; DBG("Could not select file %04X", file);
} pRApdu->sw = ISO7816_SW_NOT_FOUND;
else }
{ break;
//file = DEFAULT_FILE; default:
DBG("Could not select file %04X", file); pRApdu->sw = ISO7816_SW_NOT_FOUND;
pRApdu->sw = ISO7816_SW_NOT_FOUND; break;
} }
break; break;
default: case 0xB0: //Read binary
pRApdu->sw = ISO7816_SW_NOT_FOUND; DBG("Trying to read %d bytes at offset %d from file %04x", pCApdu->maxRespLength, (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
break; ret = data_read(pType4Target, &pRApdu->dataOut, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2, pCApdu->maxRespLength);
if (ret == NFC_OK) {
DBG("Read %d bytes", buffer_reader_readable(&pRApdu->dataOut));
DBG_BLOCK(buffer_dump(&pRApdu->dataOut);)
pRApdu->sw = ISO7816_SW_OK;
} else {
DBG("Failed with ret code %d", ret);
pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
}
break;
case 0xD6: //Update binary
DBG("Trying to write %d bytes at offset %d to file %04x", buffer_reader_readable(&pCApdu->dataIn), (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
ret = data_write(pType4Target, &pCApdu->dataIn, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2);
if (ret == NFC_OK) {
DBG("OK");
pRApdu->sw = ISO7816_SW_OK;
pType4Target->written = true;
} else {
DBG("Failed with ret code %d", ret);
pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
}
break;
default:
pRApdu->sw = ISO7816_SW_INVALID_INS;
break;
} }
break;
case 0xB0: //Read binary
DBG("Trying to read %d bytes at offset %d from file %04x", pCApdu->maxRespLength, (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
ret = data_read(pType4Target, &pRApdu->dataOut, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2, pCApdu->maxRespLength);
if (ret == NFC_OK)
{
DBG("Read %d bytes", buffer_reader_readable(&pRApdu->dataOut));
DBG_BLOCK( buffer_dump(&pRApdu->dataOut); )
pRApdu->sw = ISO7816_SW_OK;
}
else
{
DBG("Failed with ret code %d", ret);
pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
}
break;
case 0xD6: //Update binary
DBG("Trying to write %d bytes at offset %d to file %04x", buffer_reader_readable(&pCApdu->dataIn), (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile);
ret = data_write(pType4Target, &pCApdu->dataIn, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2);
if (ret == NFC_OK)
{
DBG("OK");
pRApdu->sw = ISO7816_SW_OK;
pType4Target->written = true;
}
else
{
DBG("Failed with ret code %d", ret);
pRApdu->sw = ISO7816_SW_WRONG_LENGTH;
}
break;
default:
pRApdu->sw = ISO7816_SW_INVALID_INS;
break;
}
//Send reply //Send reply
nfc_tech_iso7816_app_reply(pIso7816App); nfc_tech_iso7816_app_reply(pIso7816App);
} }
nfc_err_t data_read(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off, size_t len) nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, buffer_t *pBuf, uint16_t file, size_t off, size_t len)
{ {
buffer_t* pFile; buffer_t *pFile;
switch(file) switch (file) {
{ case CC_FILE:
case CC_FILE: pFile = buffer_builder_buffer(&pType4Target->ccFileBldr);
pFile = buffer_builder_buffer(&pType4Target->ccFileBldr); break;
break; case NDEF_FILE:
case NDEF_FILE: pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr);
pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr); break;
break; default:
default: return NFC_ERR_NOT_FOUND;
return NFC_ERR_NOT_FOUND; }
}
if( off > buffer_reader_readable(pFile) ) if (off > buffer_reader_readable(pFile)) {
{ return NFC_ERR_LENGTH;
return NFC_ERR_LENGTH; }
}
buffer_read_n_skip(pFile, off); buffer_read_n_skip(pFile, off);
if( len > buffer_reader_readable(pFile)) if (len > buffer_reader_readable(pFile)) {
{ len = buffer_reader_readable(pFile);
len = buffer_reader_readable(pFile); }
}
buffer_split(pBuf, pFile, pFile, len); buffer_split(pBuf, pFile, pFile, len);
return NFC_OK; return NFC_OK;
} }
nfc_err_t data_write(nfc_tech_type4_target_t* pType4Target, buffer_t* pBuf, uint16_t file, size_t off) nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, buffer_t *pBuf, uint16_t file, size_t off)
{ {
buffer_t* pFile; buffer_t *pFile;
switch(file) switch (file) {
{ case NDEF_FILE:
case NDEF_FILE: pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr);
pFile = buffer_builder_buffer(&pType4Target->ndefFileBldr); break;
break; case CC_FILE: //Cannot write to CC file!
case CC_FILE: //Cannot write to CC file! default:
default: return NFC_ERR_NOT_FOUND;
return NFC_ERR_NOT_FOUND; }
}
size_t len = buffer_reader_readable(pBuf); size_t len = buffer_reader_readable(pBuf);
if( off > buffer_reader_readable(pFile) ) if (off > buffer_reader_readable(pFile)) {
{ return NFC_ERR_LENGTH;
return NFC_ERR_LENGTH; }
}
buffer_read_n_skip(pFile, off); buffer_read_n_skip(pFile, off);
if( len > buffer_reader_readable(pFile) ) if (len > buffer_reader_readable(pFile)) {
{ len = buffer_reader_readable(pFile);
len = buffer_reader_readable(pFile); }
}
while( len > 0 ) while (len > 0) {
{ size_t cpy;
size_t cpy; buffer_builder_t builder;
buffer_builder_t builder; buffer_dup(buffer_builder_buffer(&builder), pFile);
buffer_dup(buffer_builder_buffer(&builder), pFile); buffer_builder_from_buffer(&builder);
buffer_builder_from_buffer(&builder); cpy = buffer_builder_writeable(&builder);
cpy = buffer_builder_writeable(&builder); cpy = MIN(cpy, len);
cpy = MIN(cpy, len); buffer_builder_copy_n_bytes(&builder, pBuf, cpy);
buffer_builder_copy_n_bytes(&builder, pBuf, cpy); pFile = buffer_next(pFile);
pFile = buffer_next(pFile); len -= cpy;
len -= cpy; }
}
return NFC_OK; return NFC_OK;
} }

View File

@ -35,26 +35,25 @@ extern "C" {
typedef struct nfc_tech_type4_target nfc_tech_type4_target_t; typedef struct nfc_tech_type4_target nfc_tech_type4_target_t;
typedef void (*nfc_tech_type4_cb)(nfc_tech_type4_target_t* pType4Target, nfc_err_t ret, void* pUserData); typedef void (*nfc_tech_type4_cb)(nfc_tech_type4_target_t *pType4Target, nfc_err_t ret, void *pUserData);
struct nfc_tech_type4_target struct nfc_tech_type4_target {
{ nfc_tech_iso7816_app_t app;
nfc_tech_iso7816_app_t app;
ndef_msg_t* pNdef; ndef_msg_t *pNdef;
uint8_t ccFileBuf[15]; uint8_t ccFileBuf[15];
buffer_builder_t ccFileBldr; buffer_builder_t ccFileBldr;
uint8_t ndefFileBuf[2]; uint8_t ndefFileBuf[2];
buffer_builder_t ndefFileBldr; buffer_builder_t ndefFileBldr;
uint16_t selFile; uint16_t selFile;
bool written; bool written;
}; };
void nfc_tech_type4_target_init(nfc_tech_type4_target_t* pType4Target, nfc_tech_iso7816_t* pIso7816, ndef_msg_t* pNdef); void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -60,8 +60,7 @@
//PN 512 VTABLE //PN 512 VTABLE
static const transceiver_impl_t pn512_impl = static const transceiver_impl_t pn512_impl = {
{
.set_protocols = pn512_set_protocols, .set_protocols = pn512_set_protocols,
.poll = pn512_poll, .poll = pn512_poll,
.transceive = pn512_transceive, .transceive = pn512_transceive,
@ -76,7 +75,7 @@ static const transceiver_impl_t pn512_impl =
.get_last_byte_length = pn512_get_last_byte_length, .get_last_byte_length = pn512_get_last_byte_length,
.set_first_byte_align = pn512_set_first_byte_align, .set_first_byte_align = pn512_set_first_byte_align,
.close = pn512_close, .close = pn512_close,
.sleep = pn512_sleep .sleep = pn512_sleep
}; };
/** Initialize PN512 transceiver /** Initialize PN512 transceiver
@ -84,291 +83,271 @@ static const transceiver_impl_t pn512_impl =
* \param pTransport pointer to already initialized nfc_transport_t structure * \param pTransport pointer to already initialized nfc_transport_t structure
* \return NFC_OK (0) on success or NFC_ERR_* error on failure * \return NFC_OK (0) on success or NFC_ERR_* error on failure
*/ */
nfc_err_t pn512_init(pn512_t* pPN512, nfc_transport_t* pTransport, nfc_scheduler_timer_t* pTimer) nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer)
{ {
//// ////
//For Self-test //For Self-test
//// ////
#if NFC_PN512_SELFTEST #if NFC_PN512_SELFTEST
const uint8_t null_array[25] = {0}; const uint8_t null_array[25] = {0};
#endif #endif
//// ////
uint8_t r; uint8_t r;
//Init transceiver //Init transceiver
transceiver_init((nfc_transceiver_t*)pPN512, pTransport, pTimer); transceiver_init((nfc_transceiver_t *)pPN512, pTransport, pTimer);
//Init buffer //Init buffer
buffer_builder_init(&pPN512->readBufBldr, pPN512->payload, 256); buffer_builder_init(&pPN512->readBufBldr, pPN512->payload, 256);
pPN512->readFirstByteAlign = 0; pPN512->readFirstByteAlign = 0;
pPN512->readLastByteLength = 8; pPN512->readLastByteLength = 8;
pPN512->writeLastByteLength = 8; pPN512->writeLastByteLength = 8;
//Populate functions //Populate functions
pPN512->transceiver.fn = &pn512_impl; pPN512->transceiver.fn = &pn512_impl;
//Init variables //Init variables
memset(&pPN512->config.initiators, 0, sizeof(nfc_tech_t)); memset(&pPN512->config.initiators, 0, sizeof(nfc_tech_t));
memset(&pPN512->config.targets, 0, sizeof(nfc_tech_t)); memset(&pPN512->config.targets, 0, sizeof(nfc_tech_t));
pPN512->timeout = -1; pPN512->timeout = -1;
pPN512->nextFrameMode = pn512_transceive_mode_transceive; pPN512->nextFrameMode = pn512_transceive_mode_transceive;
pn512_hw_init(pPN512); pn512_hw_init(pPN512);
pn512_registers_init(pPN512); //Cannot switch page now pn512_registers_init(pPN512); //Cannot switch page now
pn512_cmd_init(pPN512); pn512_cmd_init(pPN512);
pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST);
pn512_cmd_wait_idle(pPN512, -1); pn512_cmd_wait_idle(pPN512, -1);
//pn512_registers_init(pPN512); //pn512_registers_init(pPN512);
//Put into known state //Put into known state
pn512_registers_reset(pPN512); pn512_registers_reset(pPN512);
pPN512->transceive.mode = pn512_transceive_mode_idle; pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_clear(pPN512, PN512_IRQ_ALL); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_fifo_clear(pPN512); pn512_fifo_clear(pPN512);
pn512_cmd_exec(pPN512, PN512_CMD_IDLE); pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_cmd_wait_idle(pPN512, -1); pn512_cmd_wait_idle(pPN512, -1);
pn512_rf_field_switch_off(pPN512); pn512_rf_field_switch_off(pPN512);
//Required for polling loop //Required for polling loop
srand(4242); srand(4242);
#if NFC_PN512_SELFTEST // Self test #if NFC_PN512_SELFTEST // Self test
pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST);
pn512_cmd_wait_idle(pPN512, -1); pn512_cmd_wait_idle(pPN512, -1);
const uint8_t null_array_buf[25]={0}; //FIXME const uint8_t null_array_buf[25] = {0}; //FIXME
buffer_t null_array; buffer_t null_array;
buffer_init(&null_array, null_array_buf, 25); buffer_init(&null_array, null_array_buf, 25);
//Perform self test //Perform self test
pn512_fifo_write(pPN512, &null_array); pn512_fifo_write(pPN512, &null_array);
pn512_cmd_exec(pPN512, PN512_CMD_CONFIG); pn512_cmd_exec(pPN512, PN512_CMD_CONFIG);
while(pn512_cmd_get(pPN512) != PN512_CMD_IDLE); while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE);
pn512_register_write(pPN512, PN512_REG_AUTOTEST, 0x09); pn512_register_write(pPN512, PN512_REG_AUTOTEST, 0x09);
buffer_init(&null_array, null_array_buf, 1); buffer_init(&null_array, null_array_buf, 1);
pn512_fifo_write(pPN512, &null_array); pn512_fifo_write(pPN512, &null_array);
pn512_cmd_exec(pPN512, PN512_CMD_CRC); pn512_cmd_exec(pPN512, PN512_CMD_CRC);
while(pn512_cmd_get(pPN512) != PN512_CMD_IDLE); while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE);
DBGX_ENTER(); DBGX_ENTER();
NFC_DBG("Test result:"); NFC_DBG("Test result:");
while(pn512_fifo_length(pPN512)) while (pn512_fifo_length(pPN512)) {
{ buffer_builder_t read_byte;
buffer_builder_t read_byte; buffer_builder_init(&read_byte, null_array_buf, 1);
buffer_builder_init(&read_byte, null_array_buf, 1);
pn512_fifo_read(pPN512, &read_byte); pn512_fifo_read(pPN512, &read_byte);
DBGX("%02x ", null_array_buf[0]); DBGX("%02x ", null_array_buf[0]);
} }
DBGX("\n"); DBGX("\n");
DBGX_LEAVE(); DBGX_LEAVE();
#endif #endif
r = pn512_register_read(pPN512, PN512_REG_VERSION); r = pn512_register_read(pPN512, PN512_REG_VERSION);
DBG_BLOCK( DBG_BLOCK(
NFC_DBG("PN512 version %02x", r); NFC_DBG("PN512 version %02x", r);
) )
if((r != 0x82) && (r != 0xB1) && (r != 0xB2)) if ((r != 0x82) && (r != 0xB1) && (r != 0xB2)) {
{ return NFC_ERR_UNSUPPORTED; //PN512 not found
return NFC_ERR_UNSUPPORTED; //PN512 not found }
}
return NFC_OK; return NFC_OK;
} }
/** Get pointer to nfc_transceiver_t structure /** Get pointer to nfc_transceiver_t structure
* \param pPN512 pointer to pn512_t instance * \param pPN512 pointer to pn512_t instance
* \return pointer to initialized nfc_transceiver_t instance * \return pointer to initialized nfc_transceiver_t instance
*/ */
nfc_transceiver_t* pn512_get_transceiver(pn512_t* pPN512) nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512)
{ {
return &pPN512->transceiver; return &pPN512->transceiver;
} }
void pn512_set_protocols(nfc_transceiver_t* pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; pn512_t *pPN512 = (pn512_t *) pTransceiver;
//If different, reconfigure //If different, reconfigure
if( memcmp(&initiators, &pPN512->config.initiators, sizeof(nfc_tech_t)) || memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t)) ) if (memcmp(&initiators, &pPN512->config.initiators, sizeof(nfc_tech_t)) || memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) {
{ pPN512->config.initiators = initiators;
pPN512->config.initiators = initiators; if (memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) {
if( memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t)) ) pPN512->config.targets = targets;
{ pn512_poll_setup(pPN512);
pPN512->config.targets = targets; }
pn512_poll_setup(pPN512); pTransceiver->initiator_ntarget = false;
memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t));
} }
pTransceiver->initiator_ntarget = false; pPN512->config.options = options;
memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t));
}
pPN512->config.options = options;
} }
void pn512_poll(nfc_transceiver_t* pTransceiver) void pn512_poll(nfc_transceiver_t *pTransceiver)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; pn512_t *pPN512 = (pn512_t *) pTransceiver;
pPN512->nextFrameMode = pn512_transceive_mode_transceive;
return pn512_poll_hw(pPN512, pn512_transceiver_callback);
}
void pn512_set_crc(nfc_transceiver_t* pTransceiver, bool crc_out, bool crc_in)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
pn512_framing_crc_set(pPN512, crc_out, crc_in);
}
void pn512_set_timeout(nfc_transceiver_t* pTransceiver, int timeout)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
pPN512->timeout = timeout;
}
void pn512_set_transceive_options(nfc_transceiver_t* pTransceiver, bool transmit, bool receive, bool repoll)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
if( transmit && receive )
{
pPN512->nextFrameMode = pn512_transceive_mode_transceive; pPN512->nextFrameMode = pn512_transceive_mode_transceive;
} return pn512_poll_hw(pPN512, pn512_transceiver_callback);
else if(transmit && repoll)
{
pPN512->nextFrameMode = pn512_transceive_mode_transmit_and_target_autocoll;
}
else if(transmit)
{
pPN512->nextFrameMode = pn512_transceive_mode_transmit;
}
else if(receive)
{
pPN512->nextFrameMode = pn512_transceive_mode_receive;
}
else
{
pPN512->nextFrameMode = pn512_transceive_mode_target_autocoll;
}
} }
void pn512_set_transceive_framing(nfc_transceiver_t* pTransceiver, nfc_framing_t framing) void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; pn512_t *pPN512 = (pn512_t *) pTransceiver;
pn512_framing_set(pPN512, framing); pn512_framing_crc_set(pPN512, crc_out, crc_in);
}
//Switch NFC tech if NFC DEP void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout)
if( pTransceiver->active_tech.nfc_nfc_dep_a {
|| pTransceiver->active_tech.nfc_nfc_dep_f_212 pn512_t *pPN512 = (pn512_t *) pTransceiver;
|| pTransceiver->active_tech.nfc_nfc_dep_f_424 ) pPN512->timeout = timeout;
{ }
//FIXME
pTransceiver->active_tech.nfc_nfc_dep_a = 0; void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll)
pTransceiver->active_tech.nfc_nfc_dep_f_212 = 0; {
pTransceiver->active_tech.nfc_nfc_dep_f_424 = 0; pn512_t *pPN512 = (pn512_t *) pTransceiver;
switch(framing) if (transmit && receive) {
{ pPN512->nextFrameMode = pn512_transceive_mode_transceive;
case nfc_framing_target_a_106: } else if (transmit && repoll) {
case nfc_framing_initiator_a_106: pPN512->nextFrameMode = pn512_transceive_mode_transmit_and_target_autocoll;
pTransceiver->active_tech.nfc_nfc_dep_a = 1; } else if (transmit) {
break; pPN512->nextFrameMode = pn512_transceive_mode_transmit;
case nfc_framing_target_f_212: } else if (receive) {
case nfc_framing_initiator_f_212: pPN512->nextFrameMode = pn512_transceive_mode_receive;
pTransceiver->active_tech.nfc_nfc_dep_f_212 = 1; } else {
break; pPN512->nextFrameMode = pn512_transceive_mode_target_autocoll;
case nfc_framing_target_f_424:
case nfc_framing_initiator_f_424:
pTransceiver->active_tech.nfc_nfc_dep_f_424 = 1;
break;
default:
break;
} }
}
} }
void pn512_set_write(nfc_transceiver_t* pTransceiver, buffer_t* pWriteBuf) void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; pn512_t *pPN512 = (pn512_t *) pTransceiver;
if( pWriteBuf == NULL ) pn512_framing_set(pPN512, framing);
{
buffer_init(&pPN512->writeBuf, NULL, 0); //Switch NFC tech if NFC DEP
if (pTransceiver->active_tech.nfc_nfc_dep_a
|| pTransceiver->active_tech.nfc_nfc_dep_f_212
|| pTransceiver->active_tech.nfc_nfc_dep_f_424) {
//FIXME
pTransceiver->active_tech.nfc_nfc_dep_a = 0;
pTransceiver->active_tech.nfc_nfc_dep_f_212 = 0;
pTransceiver->active_tech.nfc_nfc_dep_f_424 = 0;
switch (framing) {
case nfc_framing_target_a_106:
case nfc_framing_initiator_a_106:
pTransceiver->active_tech.nfc_nfc_dep_a = 1;
break;
case nfc_framing_target_f_212:
case nfc_framing_initiator_f_212:
pTransceiver->active_tech.nfc_nfc_dep_f_212 = 1;
break;
case nfc_framing_target_f_424:
case nfc_framing_initiator_f_424:
pTransceiver->active_tech.nfc_nfc_dep_f_424 = 1;
break;
default:
break;
}
}
}
void pn512_set_write(nfc_transceiver_t *pTransceiver, buffer_t *pWriteBuf)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
if (pWriteBuf == NULL) {
buffer_init(&pPN512->writeBuf, NULL, 0);
return;
}
buffer_dup(&pPN512->writeBuf, pWriteBuf);
}
buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
return buffer_builder_buffer(&pPN512->readBufBldr);
}
void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
if ((lastByteLength > 8) || (lastByteLength == 0)) {
lastByteLength = 8;
}
pPN512->writeLastByteLength = lastByteLength;
}
void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
firstByteAlign &= 0x7;
pPN512->readFirstByteAlign = firstByteAlign;
}
size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
return pPN512->readLastByteLength;
}
void pn512_transceive(nfc_transceiver_t *pTransceiver)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
pn512_transceive_hw(pPN512, pPN512->nextFrameMode, pn512_transceiver_callback);
pPN512->nextFrameMode = pn512_transceive_mode_transceive;
}
void pn512_abort(nfc_transceiver_t *pTransceiver)
{
pn512_t *pPN512 = (pn512_t *) pTransceiver;
scheduler_dequeue_task(&pTransceiver->scheduler, true, &pPN512->transceiver.task);
}
void pn512_close(nfc_transceiver_t *pTransceiver)
{
//pn512_t* pPN512 = (pn512_t*) pTransceiver;
(void) pTransceiver;
//TODO
return; return;
}
buffer_dup(&pPN512->writeBuf, pWriteBuf);
} }
buffer_t* pn512_get_read(nfc_transceiver_t* pTransceiver) void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; pn512_t *pPN512 = (pn512_t *) pTransceiver;
return buffer_builder_buffer(&pPN512->readBufBldr);
if (sleep) {
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down
} else {
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00);
while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10);
}
} }
void pn512_set_last_byte_length(nfc_transceiver_t* pTransceiver, size_t lastByteLength) void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret)
{ {
pn512_t* pPN512 = (pn512_t*) pTransceiver; transceiver_callback(&pPN512->transceiver, ret);
if( (lastByteLength > 8) || (lastByteLength == 0) )
{
lastByteLength = 8;
}
pPN512->writeLastByteLength = lastByteLength;
}
void pn512_set_first_byte_align(nfc_transceiver_t* pTransceiver, size_t firstByteAlign)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
firstByteAlign &= 0x7;
pPN512->readFirstByteAlign = firstByteAlign;
}
size_t pn512_get_last_byte_length(nfc_transceiver_t* pTransceiver)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
return pPN512->readLastByteLength;
}
void pn512_transceive(nfc_transceiver_t* pTransceiver)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
pn512_transceive_hw(pPN512, pPN512->nextFrameMode, pn512_transceiver_callback);
pPN512->nextFrameMode = pn512_transceive_mode_transceive;
}
void pn512_abort(nfc_transceiver_t* pTransceiver)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
scheduler_dequeue_task(&pTransceiver->scheduler, true, &pPN512->transceiver.task);
}
void pn512_close(nfc_transceiver_t* pTransceiver)
{
//pn512_t* pPN512 = (pn512_t*) pTransceiver;
(void) pTransceiver;
//TODO
return;
}
void pn512_sleep(nfc_transceiver_t* pTransceiver, bool sleep)
{
pn512_t* pPN512 = (pn512_t*) pTransceiver;
if(sleep)
{
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down
}
else
{
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00);
while( pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10 );
}
}
void pn512_transceiver_callback(pn512_t* pPN512, nfc_err_t ret)
{
transceiver_callback(&pPN512->transceiver, ret);
} }
/** /**

View File

@ -34,131 +34,118 @@ typedef struct __pn512 pn512_t;
#include "pn512_callback.h" #include "pn512_callback.h"
#include "pn512_types.h" #include "pn512_types.h"
typedef enum __pn512_state typedef enum __pn512_state {
{ pn512_state_ready,
pn512_state_ready, pn512_state_target_autocoll,
pn512_state_target_autocoll, pn512_state_initiator_transceive_first_frame,
pn512_state_initiator_transceive_first_frame, pn512_state_transceive,
pn512_state_transceive, pn512_state_transceive_last_frame,
pn512_state_transceive_last_frame,
} pn512_state_t; } pn512_state_t;
typedef enum __pn512_transceive_mode typedef enum __pn512_transceive_mode {
{ pn512_transceive_mode_idle,
pn512_transceive_mode_idle, pn512_transceive_mode_target_autocoll,
pn512_transceive_mode_target_autocoll, pn512_transceive_mode_transmit,
pn512_transceive_mode_transmit, pn512_transceive_mode_transmit_and_target_autocoll,
pn512_transceive_mode_transmit_and_target_autocoll, pn512_transceive_mode_transceive,
pn512_transceive_mode_transceive, pn512_transceive_mode_receive,
pn512_transceive_mode_receive,
} pn512_transceive_mode_t; } pn512_transceive_mode_t;
typedef struct __pn512 typedef struct __pn512 {
{ nfc_transceiver_t transceiver;
nfc_transceiver_t transceiver; //Impl specific
//Impl specific pn512_registers_t registers;
pn512_registers_t registers; bool rf_on;
bool rf_on; struct {
struct bool out;
{ bool in;
bool out; } crc;
bool in; int timeout;
} crc;
int timeout;
struct struct {
{ nfc_tech_t initiators;
nfc_tech_t initiators; nfc_tech_t targets;
nfc_tech_t targets; polling_options_t options;
polling_options_t options; } config;
} config;
//Transceive options //Transceive options
pn512_transceive_mode_t nextFrameMode; pn512_transceive_mode_t nextFrameMode;
nfc_framing_t framing; nfc_framing_t framing;
uint16_t irqsEn; uint16_t irqsEn;
uint8_t payload[256]; //Incoming buffer uint8_t payload[256]; //Incoming buffer
buffer_builder_t readBufBldr; buffer_builder_t readBufBldr;
buffer_t writeBuf; buffer_t writeBuf;
uint8_t readFirstByteAlign; uint8_t readFirstByteAlign;
uint8_t readLastByteLength; uint8_t readLastByteLength;
uint8_t writeLastByteLength; uint8_t writeLastByteLength;
//Task parameters //Task parameters
struct struct {
{ //Polling
//Polling struct {
struct enum {
{ pn512_polling_state_start_listening,
enum {
pn512_polling_state_start_listening,
pn512_polling_state_listen_wait_for_remote_field, pn512_polling_state_listen_wait_for_remote_field,
pn512_polling_state_listen_anticollision, pn512_polling_state_listen_anticollision,
pn512_polling_state_listen_no_target_found, pn512_polling_state_listen_no_target_found,
pn512_polling_state_start_polling, pn512_polling_state_start_polling,
pn512_polling_state_rf_collision_avoidance, // TID + n × TRFW, n is random, TID>4096/(13.56E6) ~ 302.06us, TRFW=51/(13.56E6) ~ 37.76us pn512_polling_state_rf_collision_avoidance, // TID + n × TRFW, n is random, TID>4096/(13.56E6) ~ 302.06us, TRFW=51/(13.56E6) ~ 37.76us
pn512_polling_state_polling_nfc_a_start, pn512_polling_state_polling_nfc_a_start,
pn512_polling_state_polling_nfc_a_gt, // guard time nfc a >= 5.0 ms pn512_polling_state_polling_nfc_a_gt, // guard time nfc a >= 5.0 ms
pn512_polling_state_polling_nfc_a_anticollision, // polling for nfc a pn512_polling_state_polling_nfc_a_anticollision, // polling for nfc a
pn512_polling_state_polling_nfc_b_start, pn512_polling_state_polling_nfc_b_start,
pn512_polling_state_polling_nfc_b_gt, // guard time nfc b >= 5.0 ms pn512_polling_state_polling_nfc_b_gt, // guard time nfc b >= 5.0 ms
pn512_polling_state_polling_nfc_b_anticollision, // polling for nfc b pn512_polling_state_polling_nfc_b_anticollision, // polling for nfc b
pn512_polling_state_polling_nfc_f_start, pn512_polling_state_polling_nfc_f_start,
pn512_polling_state_polling_nfc_f_gt, // guard time nfc f >= 20 ms pn512_polling_state_polling_nfc_f_gt, // guard time nfc f >= 20 ms
pn512_polling_state_polling_nfc_f_anticollision, // polling for nfc f pn512_polling_state_polling_nfc_f_anticollision, // polling for nfc f
pn512_polling_state_finish_polling, pn512_polling_state_finish_polling,
} state; } state;
pn512_cb_t cb; pn512_cb_t cb;
} poll; } poll;
struct struct {
{ pn512_cb_t cb;
pn512_cb_t cb; pn512_transceive_mode_t mode;
pn512_transceive_mode_t mode; } transceive;
} transceive; struct {
struct pn512_cb_t cb;
{ } rf;
pn512_cb_t cb; struct {
} rf; union {
struct // ISO A
{ struct {
union bool more_targets; // Collision detected
{ uint8_t cascade_level;
// ISO A uint8_t cln[5];
struct uint8_t valid_bits; // valid bits within cascade level
{ } iso_a;
bool more_targets; // Collision detected // ISO B
uint8_t cascade_level; struct {
uint8_t cln[5]; bool more_targets; // Collision detected
uint8_t valid_bits; // valid bits within cascade level uint8_t slots_num_exponent;
} iso_a; uint8_t slot_number;
// ISO B bool found_one;
struct } iso_b;
{ };
bool more_targets; // Collision detected pn512_cb_t cb;
uint8_t slots_num_exponent; } anticollision;
uint8_t slot_number; };
bool found_one;
} iso_b;
};
pn512_cb_t cb;
} anticollision;
};
} pn512_t; } pn512_t;
nfc_err_t pn512_init(pn512_t* pPN512, nfc_transport_t* pTransport, nfc_scheduler_timer_t* pTimer); nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer);
nfc_transceiver_t* pn512_get_transceiver(pn512_t* pPN512); nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -28,7 +28,7 @@ extern "C" {
#endif #endif
typedef struct __pn512 pn512_t; typedef struct __pn512 pn512_t;
typedef void (*pn512_cb_t)(pn512_t* pPN512, nfc_err_t ret); typedef void (*pn512_cb_t)(pn512_t *pPN512, nfc_err_t ret);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -47,9 +47,9 @@
/** \internal Initialize underlying pn512_cmd_t structure /** \internal Initialize underlying pn512_cmd_t structure
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
*/ */
void pn512_cmd_init(pn512_t* pPN512) void pn512_cmd_init(pn512_t *pPN512)
{ {
(void) pPN512; (void) pPN512;
} }
//Fifo read / write //Fifo read / write
@ -57,64 +57,64 @@ void pn512_cmd_init(pn512_t* pPN512)
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param pData buffer to write * \param pData buffer to write
*/ */
void pn512_fifo_write(pn512_t* pPN512, buffer_t* pData) void pn512_fifo_write(pn512_t *pPN512, buffer_t *pData)
{ {
uint8_t fifo_space = pn512_fifo_space(pPN512); //Do not call this fn twice uint8_t fifo_space = pn512_fifo_space(pPN512); //Do not call this fn twice
size_t len = buffer_reader_readable(pData); size_t len = buffer_reader_readable(pData);
len = MIN(fifo_space, len); len = MIN(fifo_space, len);
pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); pn512_register_switch_page(pPN512, PN512_REG_FIFODATA);
pn512_hw_write_buffer(pPN512, PN512_REG_FIFODATA, pData, len); pn512_hw_write_buffer(pPN512, PN512_REG_FIFODATA, pData, len);
} }
/** \internal Read bytes from FIFO /** \internal Read bytes from FIFO
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param pData buffer in which to read * \param pData buffer in which to read
*/ */
void pn512_fifo_read(pn512_t* pPN512, buffer_builder_t* pData) void pn512_fifo_read(pn512_t *pPN512, buffer_builder_t *pData)
{ {
uint8_t fifo_len = pn512_fifo_length(pPN512); //Do not call this fn twice uint8_t fifo_len = pn512_fifo_length(pPN512); //Do not call this fn twice
size_t len = buffer_builder_writeable(pData); size_t len = buffer_builder_writeable(pData);
len = MIN(fifo_len, len); len = MIN(fifo_len, len);
pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); pn512_register_switch_page(pPN512, PN512_REG_FIFODATA);
pn512_hw_read_buffer(pPN512, PN512_REG_FIFODATA, pData, len); pn512_hw_read_buffer(pPN512, PN512_REG_FIFODATA, pData, len);
} }
/** \internal Clear FIFO /** \internal Clear FIFO
* Removes any bytes left in FIFO * Removes any bytes left in FIFO
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
*/ */
void pn512_fifo_clear(pn512_t* pPN512) void pn512_fifo_clear(pn512_t *pPN512)
{ {
pn512_register_write(pPN512, PN512_REG_FIFOLEVEL, 0x80); //Flush FIFO pn512_register_write(pPN512, PN512_REG_FIFOLEVEL, 0x80); //Flush FIFO
} }
/** \internal Get space in FIFO /** \internal Get space in FIFO
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \return number of bytes that can be written to FIFO * \return number of bytes that can be written to FIFO
*/ */
size_t pn512_fifo_space(pn512_t* pPN512) size_t pn512_fifo_space(pn512_t *pPN512)
{ {
return PN512_FIFO_SIZE - pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); return PN512_FIFO_SIZE - pn512_register_read(pPN512, PN512_REG_FIFOLEVEL);
} }
/** \internal Get FIFO length /** \internal Get FIFO length
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \return number of bytes that can be read from FIFO * \return number of bytes that can be read from FIFO
*/ */
size_t pn512_fifo_length(pn512_t* pPN512) size_t pn512_fifo_length(pn512_t *pPN512)
{ {
return pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); return pn512_register_read(pPN512, PN512_REG_FIFOLEVEL);
} }
/** \internal Execute command /** \internal Execute command
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param cmd PN512 command to execute * \param cmd PN512 command to execute
*/ */
void pn512_cmd_exec(pn512_t* pPN512, uint8_t cmd) void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd)
{ {
pn512_register_write(pPN512, PN512_REG_COMMAND, cmd); pn512_register_write(pPN512, PN512_REG_COMMAND, cmd);
} }
/** \internal Wait for command completion /** \internal Wait for command completion
@ -122,14 +122,13 @@ void pn512_cmd_exec(pn512_t* pPN512, uint8_t cmd)
* \param timeout timeout in milliseconds or -1 for blocking mode * \param timeout timeout in milliseconds or -1 for blocking mode
* \return NFC_OK on success or NFC_ERR_TIMEOUT on timeout * \return NFC_OK on success or NFC_ERR_TIMEOUT on timeout
*/ */
nfc_err_t pn512_cmd_wait_idle(pn512_t* pPN512, int timeout) nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout)
{ {
(void) timeout; (void) timeout;
while( pn512_cmd_get(pPN512) != PN512_CMD_IDLE ) while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE) {
{
} }
return NFC_OK; return NFC_OK;
} }
@ -137,9 +136,9 @@ nfc_err_t pn512_cmd_wait_idle(pn512_t* pPN512, int timeout)
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \return PN512 command being executed * \return PN512 command being executed
*/ */
uint8_t pn512_cmd_get(pn512_t* pPN512) uint8_t pn512_cmd_get(pn512_t *pPN512)
{ {
return pn512_register_read(pPN512, PN512_REG_COMMAND) & PN512_CMD_REG_MASK; return pn512_register_read(pPN512, PN512_REG_COMMAND) & PN512_CMD_REG_MASK;
} }
/** /**

View File

@ -47,28 +47,28 @@ extern "C" {
#define PN512_CMD_REG_MASK 0x0F #define PN512_CMD_REG_MASK 0x0F
void pn512_cmd_init(pn512_t* pPN512); void pn512_cmd_init(pn512_t *pPN512);
//Fifo read / write //Fifo read / write
void pn512_fifo_write(pn512_t* pPN512, buffer_t* pData); void pn512_fifo_write(pn512_t *pPN512, buffer_t *pData);
void pn512_fifo_read(pn512_t* pPN512, buffer_builder_t* pData); void pn512_fifo_read(pn512_t *pPN512, buffer_builder_t *pData);
//Fifo clear //Fifo clear
void pn512_fifo_clear(pn512_t* pPN512); void pn512_fifo_clear(pn512_t *pPN512);
//Fifo bytes read //Fifo bytes read
size_t pn512_fifo_space(pn512_t* pPN512); size_t pn512_fifo_space(pn512_t *pPN512);
size_t pn512_fifo_length(pn512_t* pPN512); size_t pn512_fifo_length(pn512_t *pPN512);
//Execute command //Execute command
void pn512_cmd_exec(pn512_t* pPN512, uint8_t cmd); void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd);
//Wait for command completion //Wait for command completion
nfc_err_t pn512_cmd_wait_idle(pn512_t* pPN512, int timeout); nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout);
//Read executed command //Read executed command
uint8_t pn512_cmd_get(pn512_t* pPN512); uint8_t pn512_cmd_get(pn512_t *pPN512);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -40,10 +40,10 @@
/** \internal Initialize underlying pn512_hw_t structure /** \internal Initialize underlying pn512_hw_t structure
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
*/ */
void pn512_hw_init(pn512_t* pPN512) void pn512_hw_init(pn512_t *pPN512)
{ {
//Nothing to init in this implementation //Nothing to init in this implementation
(void) pPN512; (void) pPN512;
} }

View File

@ -35,7 +35,7 @@ extern "C" {
#define PN512_SPI_ADDR_R(x) ((1<<7) | ((x) << 1)) #define PN512_SPI_ADDR_R(x) ((1<<7) | ((x) << 1))
#define PN512_SPI_ADDR_W(x) ((0<<7) | ((x) << 1)) #define PN512_SPI_ADDR_W(x) ((0<<7) | ((x) << 1))
void pn512_hw_init(pn512_t* pPN512); void pn512_hw_init(pn512_t *pPN512);
/** \internal Write bytes at the specified address on the underlying transport link /** \internal Write bytes at the specified address on the underlying transport link
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
@ -43,9 +43,9 @@ void pn512_hw_init(pn512_t* pPN512);
* \param buf buffer to write * \param buf buffer to write
* \param len length of buffer * \param len length of buffer
*/ */
static inline void pn512_hw_write(pn512_t* pPN512, uint8_t addr, uint8_t* buf, size_t len) static inline void pn512_hw_write(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len)
{ {
nfc_transport_write(((nfc_transceiver_t*)pPN512)->pTransport, addr, buf, len); nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len);
} }
/** \internal Read bytes from the specified address on the underlying transport link /** \internal Read bytes from the specified address on the underlying transport link
@ -54,40 +54,36 @@ static inline void pn512_hw_write(pn512_t* pPN512, uint8_t addr, uint8_t* buf, s
* \param buf buffer to read * \param buf buffer to read
* \param len length of buffer * \param len length of buffer
*/ */
static inline void pn512_hw_read(pn512_t* pPN512, uint8_t addr, uint8_t* buf, size_t len) static inline void pn512_hw_read(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len)
{ {
nfc_transport_read(((nfc_transceiver_t*)pPN512)->pTransport, addr, buf, len); nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len);
} }
static inline void pn512_hw_write_buffer(pn512_t* pPN512, uint8_t addr, buffer_t* pData, size_t len) static inline void pn512_hw_write_buffer(pn512_t *pPN512, uint8_t addr, buffer_t *pData, size_t len)
{ {
while( len > 0 ) while (len > 0) {
{ if (buffer_reader_readable(pData) == 0) {
if( buffer_reader_readable(pData) == 0 ) return;
{ }
return; size_t cpyLen = MIN(len, buffer_reader_current_buffer_length(pData));
nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, buffer_reader_current_buffer_pointer(pData), cpyLen);
buffer_read_n_skip(pData, cpyLen);
len -= cpyLen;
} }
size_t cpyLen = MIN(len, buffer_reader_current_buffer_length(pData));
nfc_transport_write(((nfc_transceiver_t*)pPN512)->pTransport, addr, buffer_reader_current_buffer_pointer(pData), cpyLen);
buffer_read_n_skip(pData, cpyLen);
len -= cpyLen;
}
} }
static inline void pn512_hw_read_buffer(pn512_t* pPN512, uint8_t addr, buffer_builder_t* pData, size_t len) static inline void pn512_hw_read_buffer(pn512_t *pPN512, uint8_t addr, buffer_builder_t *pData, size_t len)
{ {
while( len > 0 ) while (len > 0) {
{ if (buffer_builder_writeable(pData) == 0) {
if( buffer_builder_writeable(pData) == 0 ) return;
{ }
return; //Read payload
size_t cpyLen = MIN(len, buffer_builder_space(pData));
nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, buffer_builder_write_position(pData), cpyLen);
buffer_builder_write_n_skip(pData, cpyLen);
len -= cpyLen;
} }
//Read payload
size_t cpyLen = MIN(len, buffer_builder_space(pData));
nfc_transport_read(((nfc_transceiver_t*)pPN512)->pTransport, addr, buffer_builder_write_position(pData), cpyLen);
buffer_builder_write_n_skip(pData, cpyLen);
len -= cpyLen;
}
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -35,42 +35,42 @@ extern "C" {
#include "pn512_callback.h" #include "pn512_callback.h"
//Public //Public
void pn512_set_protocols(nfc_transceiver_t* pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options);
void pn512_poll(nfc_transceiver_t* pTransceiver); void pn512_poll(nfc_transceiver_t *pTransceiver);
void pn512_set_crc(nfc_transceiver_t* pTransceiver, bool crc_out, bool crc_in); void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in);
void pn512_set_timeout(nfc_transceiver_t* pTransceiver, int timeout); void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout);
void pn512_set_transceive_options(nfc_transceiver_t* pTransceiver, bool transmit, bool receive, bool repoll); void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll);
void pn512_set_transceive_framing(nfc_transceiver_t* pTransceiver, nfc_framing_t framing); void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing);
void pn512_set_write(nfc_transceiver_t* pTransceiver, buffer_t* pWriteBuf); void pn512_set_write(nfc_transceiver_t *pTransceiver, buffer_t *pWriteBuf);
buffer_t* pn512_get_read(nfc_transceiver_t* pTransceiver); buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver);
size_t pn512_get_last_byte_length(nfc_transceiver_t* pTransceiver); size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver);
void pn512_set_last_byte_length(nfc_transceiver_t* pTransceiver, size_t lastByteLength); void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength);
void pn512_set_first_byte_align(nfc_transceiver_t* pTransceiver, size_t firstByteAlign); void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign);
void pn512_abort(nfc_transceiver_t* pTransceiver); void pn512_abort(nfc_transceiver_t *pTransceiver);
void pn512_transceive(nfc_transceiver_t* pTransceiver); void pn512_transceive(nfc_transceiver_t *pTransceiver);
void pn512_close(nfc_transceiver_t* pTransceiver); void pn512_close(nfc_transceiver_t *pTransceiver);
void pn512_sleep(nfc_transceiver_t* pTransceiver, bool sleep); void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep);
void pn512_transceiver_callback(pn512_t* pPN512, nfc_err_t ret); void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret);
static inline void pn512_rf_callback(pn512_t* pPN512, nfc_err_t ret) static inline void pn512_rf_callback(pn512_t *pPN512, nfc_err_t ret)
{ {
pPN512->rf.cb(pPN512, ret); pPN512->rf.cb(pPN512, ret);
} }
static inline void pn512_poll_callback(pn512_t* pPN512, nfc_err_t ret) static inline void pn512_poll_callback(pn512_t *pPN512, nfc_err_t ret)
{ {
pPN512->poll.cb(pPN512, ret); pPN512->poll.cb(pPN512, ret);
} }
static inline void pn512_anticollision_callback(pn512_t* pPN512, nfc_err_t ret) static inline void pn512_anticollision_callback(pn512_t *pPN512, nfc_err_t ret)
{ {
pPN512->anticollision.cb(pPN512, ret); pPN512->anticollision.cb(pPN512, ret);
} }
static inline void pn512_transceive_callback(pn512_t* pPN512, nfc_err_t ret) static inline void pn512_transceive_callback(pn512_t *pPN512, nfc_err_t ret)
{ {
pPN512->transceive.cb(pPN512, ret); pPN512->transceive.cb(pPN512, ret);
} }

View File

@ -65,20 +65,20 @@ extern "C" {
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param irqs MSB is DIVIEN value, LSB is COMIEN value * \param irqs MSB is DIVIEN value, LSB is COMIEN value
*/ */
static inline void pn512_irq_set(pn512_t* pPN512, uint16_t irqs) //ORed static inline void pn512_irq_set(pn512_t *pPN512, uint16_t irqs) //ORed
{ {
pn512_register_write(pPN512, PN512_REG_COMIEN, PN512_REG_COMIEN_VAL | (PN512_REG_COMIEN_MASK & (irqs & 0xFF))); pn512_register_write(pPN512, PN512_REG_COMIEN, PN512_REG_COMIEN_VAL | (PN512_REG_COMIEN_MASK & (irqs & 0xFF)));
pn512_register_write(pPN512, PN512_REG_DIVIEN, PN512_REG_DIVIEN_VAL | (PN512_REG_DIVIEN_MASK & (irqs >> 8))); pn512_register_write(pPN512, PN512_REG_DIVIEN, PN512_REG_DIVIEN_VAL | (PN512_REG_DIVIEN_MASK & (irqs >> 8)));
pPN512->irqsEn = irqs; pPN512->irqsEn = irqs;
} }
/** \internal Get IRQ enable registers /** \internal Get IRQ enable registers
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \return MSB is DIVIEN value, LSB is COMIEN value * \return MSB is DIVIEN value, LSB is COMIEN value
*/ */
static inline uint16_t pn512_irq_enabled(pn512_t* pPN512) //ORed static inline uint16_t pn512_irq_enabled(pn512_t *pPN512) //ORed
{ {
return pPN512->irqsEn /*(pn512_register_read(pPN512, PN512_REG_COMIEN_VAL) & PN512_REG_COMIEN_MASK) return pPN512->irqsEn /*(pn512_register_read(pPN512, PN512_REG_COMIEN_VAL) & PN512_REG_COMIEN_MASK)
| ((pn512_register_read(pPN512, PN512_REG_DIVIEN_VAL) & PN512_REG_DIVIEN_MASK) << 8)*/; | ((pn512_register_read(pPN512, PN512_REG_DIVIEN_VAL) & PN512_REG_DIVIEN_MASK) << 8)*/;
} }
@ -86,20 +86,20 @@ static inline uint16_t pn512_irq_enabled(pn512_t* pPN512) //ORed
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \return MSB is DIVIRQ value, LSB is COMIRQ value * \return MSB is DIVIRQ value, LSB is COMIRQ value
*/ */
static inline uint16_t pn512_irq_get(pn512_t* pPN512) //ORed static inline uint16_t pn512_irq_get(pn512_t *pPN512) //ORed
{ {
return ((pn512_register_read(pPN512, PN512_REG_COMIRQ) & PN512_REG_COMIEN_MASK) return ((pn512_register_read(pPN512, PN512_REG_COMIRQ) & PN512_REG_COMIEN_MASK)
| ((pn512_register_read(pPN512, PN512_REG_DIVIRQ) & PN512_REG_DIVIEN_MASK) << 8)) & pPN512->irqsEn; | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ) & PN512_REG_DIVIEN_MASK) << 8)) & pPN512->irqsEn;
} }
/** \internal Clear some interrupts /** \internal Clear some interrupts
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param irqs MSB is DIVIEN value, LSB is COMIEN value * \param irqs MSB is DIVIEN value, LSB is COMIEN value
*/ */
static inline void pn512_irq_clear(pn512_t* pPN512, uint16_t irqs) static inline void pn512_irq_clear(pn512_t *pPN512, uint16_t irqs)
{ {
pn512_register_write(pPN512, PN512_REG_COMIRQ, PN512_REG_COMIRQ_CLEAR | (PN512_REG_COMIRQ_MASK & (irqs & 0xFF))); pn512_register_write(pPN512, PN512_REG_COMIRQ, PN512_REG_COMIRQ_CLEAR | (PN512_REG_COMIRQ_MASK & (irqs & 0xFF)));
pn512_register_write(pPN512, PN512_REG_DIVIRQ, PN512_REG_DIVIRQ_CLEAR | (PN512_REG_DIVIRQ_MASK & (irqs >> 8))); pn512_register_write(pPN512, PN512_REG_DIVIRQ, PN512_REG_DIVIRQ_CLEAR | (PN512_REG_DIVIRQ_MASK & (irqs >> 8)));
} }
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,8 @@ extern "C" {
#include "inc/nfc.h" #include "inc/nfc.h"
void pn512_poll_setup(pn512_t* pPN512); void pn512_poll_setup(pn512_t *pPN512);
void pn512_poll_hw(pn512_t* pPN512, pn512_cb_t cb); void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -43,14 +43,14 @@
* @{ * @{
*/ */
static void pn512_register_switch_page_intl(pn512_t* pPN512, uint8_t page); static void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page);
/** \internal Initialize underlying pn512_registers_t structure /** \internal Initialize underlying pn512_registers_t structure
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
*/ */
void pn512_registers_init(pn512_t* pPN512) void pn512_registers_init(pn512_t *pPN512)
{ {
pPN512->registers.registers_page = 0; pPN512->registers.registers_page = 0;
} }
#define PN512_CFG_INIT_LEN 9 #define PN512_CFG_INIT_LEN 9
@ -80,13 +80,12 @@ static const uint8_t PN512_CFG_INIT_VALS[] = {
/** \internal Switch to known (0) registers page, reset registers state /** \internal Switch to known (0) registers page, reset registers state
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
*/ */
void pn512_registers_reset(pn512_t* pPN512) void pn512_registers_reset(pn512_t *pPN512)
{ {
pn512_register_switch_page_intl(pPN512, 0); pn512_register_switch_page_intl(pPN512, 0);
for(int i = 0; i < PN512_CFG_INIT_LEN; i++) for (int i = 0; i < PN512_CFG_INIT_LEN; i++) {
{ pn512_register_write(pPN512, PN512_CFG_INIT_REGS[i], PN512_CFG_INIT_VALS[i]);
pn512_register_write(pPN512, PN512_CFG_INIT_REGS[i], PN512_CFG_INIT_VALS[i]); }
}
} }
/** \internal Write register /** \internal Write register
@ -94,15 +93,14 @@ void pn512_registers_reset(pn512_t* pPN512)
* \param address register address * \param address register address
* \param data value to write in register * \param data value to write in register
*/ */
void pn512_register_write(pn512_t* pPN512, uint8_t address, uint8_t data) void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data)
{ {
NFC_DBG("Write [%02x] << %02x", address, data); NFC_DBG("Write [%02x] << %02x", address, data);
if(REGISTER_PAGE(address) != pPN512->registers.registers_page) if (REGISTER_PAGE(address) != pPN512->registers.registers_page) {
{ pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address));
pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); }
} address = REGISTER_ADDR(address);
address=REGISTER_ADDR(address); pn512_hw_write(pPN512, address, &data, 1);
pn512_hw_write(pPN512, address, &data, 1);
} }
/** \internal Read register /** \internal Read register
@ -110,43 +108,41 @@ void pn512_register_write(pn512_t* pPN512, uint8_t address, uint8_t data)
* \param address register address * \param address register address
* \return data value read from register * \return data value read from register
*/ */
uint8_t pn512_register_read(pn512_t* pPN512, uint8_t address) uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address)
{ {
uint8_t data; uint8_t data;
DBG_BLOCK( DBG_BLOCK(
uint8_t __dbg_addr; uint8_t __dbg_addr;
__dbg_addr = address; //FIXME __dbg_addr = address; //FIXME
) )
if(REGISTER_PAGE(address) != pPN512->registers.registers_page) if (REGISTER_PAGE(address) != pPN512->registers.registers_page) {
{ pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address));
pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); }
} address = REGISTER_ADDR(address);
address=REGISTER_ADDR(address); pn512_hw_read(pPN512, address, &data, 1);
pn512_hw_read(pPN512, address, &data, 1); NFC_DBG("Read [%02x] >> %02x", __dbg_addr, data);
NFC_DBG("Read [%02x] >> %02x", __dbg_addr, data); return data;
return data;
} }
void pn512_register_switch_page(pn512_t* pPN512, uint8_t address) void pn512_register_switch_page(pn512_t *pPN512, uint8_t address)
{ {
if(REGISTER_PAGE(address) != pPN512->registers.registers_page) if (REGISTER_PAGE(address) != pPN512->registers.registers_page) {
{ pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address));
pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); }
}
} }
/** \internal Switch registers page /** \internal Switch registers page
* \param pPN512 pointer to pn512_t structure * \param pPN512 pointer to pn512_t structure
* \param page registers page * \param page registers page
*/ */
void pn512_register_switch_page_intl(pn512_t* pPN512, uint8_t page) void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page)
{ {
uint8_t pageRegValue; uint8_t pageRegValue;
pageRegValue = (1 << 7) | page; pageRegValue = (1 << 7) | page;
pn512_hw_write(pPN512, PN512_REG_PAGE, &pageRegValue, 1); pn512_hw_write(pPN512, PN512_REG_PAGE, &pageRegValue, 1);
pPN512->registers.registers_page = page; pPN512->registers.registers_page = page;
} }

View File

@ -99,13 +99,13 @@ extern "C" {
#define PN512_REG_TESTADC 0x3B //Shows the actual value of ADC I and Q #define PN512_REG_TESTADC 0x3B //Shows the actual value of ADC I and Q
void pn512_registers_init(pn512_t* pPN512); void pn512_registers_init(pn512_t *pPN512);
void pn512_registers_reset(pn512_t* pPN512); void pn512_registers_reset(pn512_t *pPN512);
void pn512_register_write(pn512_t* pPN512, uint8_t address, uint8_t data); void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data);
uint8_t pn512_register_read(pn512_t* pPN512, uint8_t address); uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address);
void pn512_register_switch_page(pn512_t* pPN512, uint8_t address); void pn512_register_switch_page(pn512_t *pPN512, uint8_t address);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -46,296 +46,279 @@ static const uint8_t framing_registers_target_iso14443a_106k[] = { 0x3D, 0x80, 0
static const uint8_t framing_registers_felica_212k[] = { 0x3A, 0x92, 0x92, 0x12, 0x55, 0x15 }; static const uint8_t framing_registers_felica_212k[] = { 0x3A, 0x92, 0x92, 0x12, 0x55, 0x15 };
static const uint8_t framing_registers_felica_414k[] = { 0x3A, 0xA2, 0xA2, 0x12, 0x55, 0x0A }; static const uint8_t framing_registers_felica_414k[] = { 0x3A, 0xA2, 0xA2, 0x12, 0x55, 0x0A };
nfc_err_t pn512_framing_set(pn512_t* pPN512, nfc_framing_t framing) nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing)
{ {
if(framing == pPN512->framing) //No need to do anything if (framing == pPN512->framing) { //No need to do anything
{ return NFC_OK;
return NFC_OK; }
}
NFC_DBG("Switching to %u", framing); NFC_DBG("Switching to %u", framing);
const uint8_t* framing_registers_values; const uint8_t *framing_registers_values;
switch(framing) switch (framing) {
{ case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: framing_registers_values = framing_registers_mode_detector;
framing_registers_values = framing_registers_mode_detector; break;
break; case nfc_framing_target_a_106:
case nfc_framing_target_a_106: framing_registers_values = framing_registers_target_iso14443a_106k;
framing_registers_values = framing_registers_target_iso14443a_106k; break;
break; case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: framing_registers_values = framing_registers_initiator_iso14443a_106k;
framing_registers_values = framing_registers_initiator_iso14443a_106k; break;
break; case nfc_framing_initiator_b_106:
case nfc_framing_initiator_b_106: framing_registers_values = framing_registers_initiator_iso14443b_106k;
framing_registers_values = framing_registers_initiator_iso14443b_106k; break;
break; case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: framing_registers_values = framing_registers_felica_212k;
framing_registers_values = framing_registers_felica_212k; break;
break; case nfc_framing_target_f_424:
case nfc_framing_target_f_424: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: framing_registers_values = framing_registers_felica_414k;
framing_registers_values = framing_registers_felica_414k; break;
break; default:
default: return NFC_ERR_UNSUPPORTED;
return NFC_ERR_UNSUPPORTED; }
}
for(int i = 0; i < PN512_FRAMING_REGS; i++) for (int i = 0; i < PN512_FRAMING_REGS; i++) {
{ pn512_register_write(pPN512, framing_registers[i], framing_registers_values[i]);
pn512_register_write(pPN512, framing_registers[i], framing_registers_values[i]); }
}
pPN512->framing = framing; pPN512->framing = framing;
pPN512->crc.out = true; pPN512->crc.out = true;
pPN512->crc.in = true; pPN512->crc.in = true;
//TODO initiator: PN512_REG_MODGSP //TODO initiator: PN512_REG_MODGSP
switch(pPN512->framing) switch (pPN512->framing) {
{ case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: case nfc_framing_initiator_b_106:
case nfc_framing_initiator_b_106: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x10); //Act as initiator
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x10); //Act as initiator break;
break; case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: case nfc_framing_target_a_106:
case nfc_framing_target_a_106: case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_target_f_424:
case nfc_framing_target_f_424: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x00); //Act as target
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x00); //Act as target break;
break; default:
default: return NFC_ERR_UNSUPPORTED;
return NFC_ERR_UNSUPPORTED; }
}
#if 1 #if 1
if( (pPN512->framing == nfc_framing_initiator_a_106) /*|| (pPN512->framing == pn512_framing_target_iso14443a_106k)*/ ) if ((pPN512->framing == nfc_framing_initiator_a_106) /*|| (pPN512->framing == pn512_framing_target_iso14443a_106k)*/) {
{ //Enable 100% ASK Modulation
//Enable 100% ASK Modulation pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40);
pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40 ); } else {
} pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40));
else }
{
pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40) );
}
#endif #endif
return NFC_OK; return NFC_OK;
} }
nfc_err_t pn512_framing_crc_set(pn512_t* pPN512, bool out, bool in) nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in)
{ {
const uint8_t* framing_registers_values; const uint8_t *framing_registers_values;
switch(pPN512->framing) switch (pPN512->framing) {
{ case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: framing_registers_values = framing_registers_mode_detector;
framing_registers_values = framing_registers_mode_detector; break;
break; case nfc_framing_target_a_106:
case nfc_framing_target_a_106: framing_registers_values = framing_registers_target_iso14443a_106k;
framing_registers_values = framing_registers_target_iso14443a_106k; break;
break; case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: framing_registers_values = framing_registers_initiator_iso14443a_106k;
framing_registers_values = framing_registers_initiator_iso14443a_106k; break;
break; case nfc_framing_initiator_b_106:
case nfc_framing_initiator_b_106: framing_registers_values = framing_registers_initiator_iso14443b_106k;
framing_registers_values = framing_registers_initiator_iso14443b_106k; break;
break; case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: framing_registers_values = framing_registers_felica_212k;
framing_registers_values = framing_registers_felica_212k; break;
break; case nfc_framing_target_f_424:
case nfc_framing_target_f_424: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: framing_registers_values = framing_registers_felica_414k;
framing_registers_values = framing_registers_felica_414k; break;
break; default:
default: return NFC_ERR_UNSUPPORTED;
return NFC_ERR_UNSUPPORTED; }
}
if(pPN512->crc.out != out) if (pPN512->crc.out != out) {
{ pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out ? 0x80 : 0x00)); //TXMODE
pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out?0x80:0x00)); //TXMODE pPN512->crc.out = out;
pPN512->crc.out = out; }
} if (pPN512->crc.in != in) {
if(pPN512->crc.in != in) pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in ? 0x80 : 0x00)); //RXMODE
{ pPN512->crc.in = in;
pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in?0x80:0x00)); //RXMODE }
pPN512->crc.in = in;
}
return NFC_OK; return NFC_OK;
} }
nfc_err_t pn512_framing_rx_multiple_enable(pn512_t* pPN512) nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512)
{ {
const uint8_t* framing_registers_values; const uint8_t *framing_registers_values;
switch(pPN512->framing) switch (pPN512->framing) {
{ case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: framing_registers_values = framing_registers_mode_detector;
framing_registers_values = framing_registers_mode_detector; break;
break; case nfc_framing_target_a_106:
case nfc_framing_target_a_106: framing_registers_values = framing_registers_target_iso14443a_106k;
framing_registers_values = framing_registers_target_iso14443a_106k; break;
break; case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: framing_registers_values = framing_registers_initiator_iso14443a_106k;
framing_registers_values = framing_registers_initiator_iso14443a_106k; break;
break; case nfc_framing_initiator_b_106:
case nfc_framing_initiator_b_106: framing_registers_values = framing_registers_initiator_iso14443b_106k;
framing_registers_values = framing_registers_initiator_iso14443b_106k; break;
break; case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: framing_registers_values = framing_registers_felica_212k;
framing_registers_values = framing_registers_felica_212k; break;
break; case nfc_framing_target_f_424:
case nfc_framing_target_f_424: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: framing_registers_values = framing_registers_felica_414k;
framing_registers_values = framing_registers_felica_414k; break;
break; default:
default: return NFC_ERR_UNSUPPORTED;
return NFC_ERR_UNSUPPORTED; }
}
pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in?0x80:0x00) | 0x04); //RXMODE pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in ? 0x80 : 0x00) | 0x04); //RXMODE
return NFC_OK; return NFC_OK;
} }
void pn512_rf_field_switch_off(pn512_t* pPN512) void pn512_rf_field_switch_off(pn512_t *pPN512)
{ {
pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00);
pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80);
pPN512->rf_on = false;
}
void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void* pUserData)
{
pn512_t* pPN512 = (pn512_t*) pUserData;
uint16_t irq_res = pn512_irq_get(pPN512);
(void) events;
pn512_timer_stop(pPN512);
pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER);
if(irq_res & PN512_IRQ_RF_ON)
{
NFC_DBG("External field on");
//Clear TXAUTO register
pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00);
pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80);
pPN512->rf_on = false; //External field on pPN512->rf_on = false;
pn512_rf_callback(pPN512, NFC_OK);
return;
}
//Has our RF field been switched on?
if( pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40 ) //InitialRFOn bit is cleared automatically, if the RF field is switched on
{
NFC_ERR("InitialRFOn bit still set");
pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN);
return;
}
pPN512->rf_on = true; //Own field on and guard time ok
NFC_DBG("RF field enabled");
pn512_rf_callback(pPN512, NFC_OK);
} }
void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t* pPN512, pn512_cb_t cb) void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void *pUserData)
{ {
pPN512->rf.cb = cb; pn512_t *pPN512 = (pn512_t *) pUserData;
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER);
//If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475 uint16_t irq_res = pn512_irq_get(pPN512);
pn512_timer_config(pPN512, true, 3, 8475);
pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */ (void) events;
| PN512_IRQ_TIMER /* Timer reached 0 */ );
//Try to enable RF field in compliance with NFC-IP1
pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F);
//Is external RF Field already on?
if( pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4 )
{
NFC_DBG("External field already on");
pPN512->rf_on = false; //External field on
//Cancel
pn512_timer_stop(pPN512); pn512_timer_stop(pPN512);
pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER);
if (irq_res & PN512_IRQ_RF_ON) {
NFC_DBG("External field on");
//Clear TXAUTO register
pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00);
pPN512->rf_on = false; //External field on
pn512_rf_callback(pPN512, NFC_OK);
return;
}
//Has our RF field been switched on?
if (pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40) { //InitialRFOn bit is cleared automatically, if the RF field is switched on
NFC_ERR("InitialRFOn bit still set");
pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN);
return;
}
pPN512->rf_on = true; //Own field on and guard time ok
NFC_DBG("RF field enabled");
pn512_rf_callback(pPN512, NFC_OK); pn512_rf_callback(pPN512, NFC_OK);
return;
}
//Queue task to process IRQ
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
} }
void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void* pUserData) void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb)
{ {
pn512_t* pPN512 = (pn512_t*) pUserData; pPN512->rf.cb = cb;
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER);
NFC_DBG("%lu events", events); //If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475
pn512_timer_config(pPN512, true, 3, 8475);
//Wake up PN512 pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); | PN512_IRQ_TIMER /* Timer reached 0 */);
while( pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10 );
pn512_irq_set(pPN512, PN512_IRQ_NONE); //Try to enable RF field in compliance with NFC-IP1
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F);
if(events & EVENT_ABORTED) //Is external RF Field already on?
{ if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) {
pn512_rf_callback(pPN512, NFC_ERR_ABORTED); NFC_DBG("External field already on");
return; pPN512->rf_on = false; //External field on
}
if( events & EVENT_TIMEOUT ) //Cancel
{ pn512_timer_stop(pPN512);
NFC_DBG("Timeout"); pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart
pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT); pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER);
return; pn512_rf_callback(pPN512, NFC_OK);
} return;
}
NFC_DBG("On"); //Queue task to process IRQ
pn512_rf_callback(pPN512, NFC_OK); task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
} }
void pn512_rf_field_wait_for_external(pn512_t* pPN512, int timeout, pn512_cb_t cb) void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void *pUserData)
{ {
pPN512->rf.cb = cb; pn512_t *pPN512 = (pn512_t *) pUserData;
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); NFC_DBG("%lu events", events);
NFC_DBG("Wait for RF field to come up (timeout %d)", timeout); //Wake up PN512
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00);
while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10);
//Is external RF Field already on?
pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */);
if( pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4 )
{
NFC_DBG("RF field already on");
pn512_irq_set(pPN512, PN512_IRQ_NONE); pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); pn512_irq_clear(pPN512, PN512_IRQ_RF_ON);
if (events & EVENT_ABORTED) {
pn512_rf_callback(pPN512, NFC_ERR_ABORTED);
return;
}
if (events & EVENT_TIMEOUT) {
NFC_DBG("Timeout");
pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT);
return;
}
NFC_DBG("On");
pn512_rf_callback(pPN512, NFC_OK); pn512_rf_callback(pPN512, NFC_OK);
return; }
}
//Send PN512 to sleep mode void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb)
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down {
pPN512->rf.cb = cb;
//Queue task to process IRQ pn512_irq_clear(pPN512, PN512_IRQ_RF_ON);
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); NFC_DBG("Wait for RF field to come up (timeout %d)", timeout);
//Is external RF Field already on?
pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */);
if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) {
NFC_DBG("RF field already on");
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RF_ON);
pn512_rf_callback(pPN512, NFC_OK);
return;
}
//Send PN512 to sleep mode
pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down
//Queue task to process IRQ
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
} }

View File

@ -34,19 +34,19 @@ extern "C" {
typedef struct __pn512 pn512_t; typedef struct __pn512 pn512_t;
nfc_err_t pn512_framing_set(pn512_t* pPN512, nfc_framing_t framing); nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing);
nfc_err_t pn512_framing_crc_set(pn512_t* pPN512, bool out, bool in); nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in);
nfc_err_t pn512_framing_rx_multiple_enable(pn512_t* pPN512); nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512);
#define PN512_FRAMING_IS_TARGET( framing ) ((framing) <= nfc_framing_target_f_424) #define PN512_FRAMING_IS_TARGET( framing ) ((framing) <= nfc_framing_target_f_424)
void pn512_rf_field_switch_off(pn512_t* pPN512); void pn512_rf_field_switch_off(pn512_t *pPN512);
void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t* pPN512, pn512_cb_t cb); void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb);
void pn512_rf_field_wait_for_external(pn512_t* pPN512, int timeout, pn512_cb_t cb); void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -25,53 +25,51 @@
#include "pn512_timer.h" #include "pn512_timer.h"
#include "pn512_registers.h" #include "pn512_registers.h"
void pn512_timer_config(pn512_t* pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value) void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value)
{ {
pn512_timer_stop(pPN512); //just in case... pn512_timer_stop(pPN512); //just in case...
pn512_register_write(pPN512, PN512_REG_TRELOADLOW, countdown_value & 0xFF); pn512_register_write(pPN512, PN512_REG_TRELOADLOW, countdown_value & 0xFF);
pn512_register_write(pPN512, PN512_REG_TRELOADHIGH, (countdown_value >> 8) & 0xFF); pn512_register_write(pPN512, PN512_REG_TRELOADHIGH, (countdown_value >> 8) & 0xFF);
pn512_register_write(pPN512, PN512_REG_TPRESCALERLOW, prescaler & 0xFF); pn512_register_write(pPN512, PN512_REG_TPRESCALERLOW, prescaler & 0xFF);
pn512_register_write(pPN512, PN512_REG_TMODE_TPRESCALERHIGH, (autostart?0x80:0x00) | ((prescaler>>8) & 0x0F) ); pn512_register_write(pPN512, PN512_REG_TMODE_TPRESCALERHIGH, (autostart ? 0x80 : 0x00) | ((prescaler >> 8) & 0x0F));
} }
void pn512_timer_start(pn512_t* pPN512) void pn512_timer_start(pn512_t *pPN512)
{ {
//The control register also contains the initiator bit that we must set correctly //The control register also contains the initiator bit that we must set correctly
switch(pPN512->framing) switch (pPN512->framing) {
{ case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x50);
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x50); break;
break; case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: case nfc_framing_target_a_106:
case nfc_framing_target_a_106: case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_target_f_424:
case nfc_framing_target_f_424: default:
default: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x40);
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x40); break;
break; }
}
} }
void pn512_timer_stop(pn512_t* pPN512) void pn512_timer_stop(pn512_t *pPN512)
{ {
//The control register also contains the initiator bit that we must set correctly //The control register also contains the initiator bit that we must set correctly
switch(pPN512->framing) switch (pPN512->framing) {
{ case nfc_framing_initiator_a_106:
case nfc_framing_initiator_a_106: case nfc_framing_initiator_f_212:
case nfc_framing_initiator_f_212: case nfc_framing_initiator_f_424:
case nfc_framing_initiator_f_424: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x90);
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x90); break;
break; case nfc_framing_target_mode_detector:
case nfc_framing_target_mode_detector: case nfc_framing_target_a_106:
case nfc_framing_target_a_106: case nfc_framing_target_f_212:
case nfc_framing_target_f_212: case nfc_framing_target_f_424:
case nfc_framing_target_f_424: default:
default: pn512_register_write(pPN512, PN512_REG_CONTROL, 0x80);
pn512_register_write(pPN512, PN512_REG_CONTROL, 0x80); break;
break; }
}
} }

View File

@ -31,10 +31,10 @@ extern "C" {
typedef struct __pn512 pn512_t; typedef struct __pn512 pn512_t;
void pn512_timer_config(pn512_t* pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value); void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value);
void pn512_timer_start(pn512_t* pPN512); void pn512_timer_start(pn512_t *pPN512);
void pn512_timer_stop(pn512_t* pPN512); void pn512_timer_stop(pn512_t *pPN512);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -38,283 +38,212 @@
#define TIMEOUT 1000 #define TIMEOUT 1000
void pn512_transceive_hw_tx_iteration(pn512_t* pPN512, bool start) void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start)
{ {
uint16_t irqs_en = pn512_irq_enabled(pPN512); uint16_t irqs_en = pn512_irq_enabled(pPN512);
if( buffer_reader_readable(&pPN512->writeBuf) > 0 ) if (buffer_reader_readable(&pPN512->writeBuf) > 0) {
{ //Fill FIFO
//Fill FIFO pn512_fifo_write(pPN512, &pPN512->writeBuf);
pn512_fifo_write(pPN512, &pPN512->writeBuf);
if (buffer_reader_readable(&pPN512->writeBuf) > 0) //Did not fit in FIFO if (buffer_reader_readable(&pPN512->writeBuf) > 0) { //Did not fit in FIFO
{ pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT);
pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); //Has low FIFO alert IRQ already been enabled?
//Has low FIFO alert IRQ already been enabled? if (!(irqs_en & PN512_IRQ_LOW_ALERT)) {
if (!(irqs_en & PN512_IRQ_LOW_ALERT)) irqs_en |= PN512_IRQ_LOW_ALERT;
{ pn512_irq_set(pPN512, irqs_en);
irqs_en |= PN512_IRQ_LOW_ALERT; }
pn512_irq_set(pPN512, irqs_en); } else {
} if (irqs_en & PN512_IRQ_LOW_ALERT) {
} //Buffer has been fully sent
else irqs_en &= ~PN512_IRQ_LOW_ALERT;
{ pn512_irq_set(pPN512, irqs_en);
if (irqs_en & PN512_IRQ_LOW_ALERT) }
{ }
//Buffer has been fully sent
irqs_en &= ~PN512_IRQ_LOW_ALERT;
pn512_irq_set(pPN512, irqs_en);
}
}
}
if (start)
{
if ( (pPN512->transceive.mode == pn512_transceive_mode_transmit) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) )
{
//Update bitframing register
pn512_register_write(pPN512, PN512_REG_BITFRAMING,
0x00 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
//Use transmit command
pn512_cmd_exec(pPN512, PN512_CMD_TRANSMIT);
}
else
{
NFC_DBG("Bitframing %02X", 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
//Update bitframing register to start transmission
pn512_register_write(pPN512, PN512_REG_BITFRAMING,
0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
} }
//Reset last byte length, first byte align
pPN512->writeLastByteLength = 8;
pPN512->readFirstByteAlign = 0;
}
//Queue task to process IRQ if (start) {
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, TIMEOUT, pn512_transceive_hw_tx_task, pPN512); if ((pPN512->transceive.mode == pn512_transceive_mode_transmit) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) {
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); //Update bitframing register
pn512_register_write(pPN512, PN512_REG_BITFRAMING,
0x00 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
//Use transmit command
pn512_cmd_exec(pPN512, PN512_CMD_TRANSMIT);
} else {
NFC_DBG("Bitframing %02X", 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
//Update bitframing register to start transmission
pn512_register_write(pPN512, PN512_REG_BITFRAMING,
0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7));
}
//Reset last byte length, first byte align
pPN512->writeLastByteLength = 8;
pPN512->readFirstByteAlign = 0;
}
//Queue task to process IRQ
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, TIMEOUT, pn512_transceive_hw_tx_task, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
} }
void pn512_transceive_hw_tx_task(uint32_t events, void* pUserData) void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData)
{ {
pn512_t* pPN512 = (pn512_t*) pUserData; pn512_t *pPN512 = (pn512_t *) pUserData;
if(events & EVENT_ABORTED) if (events & EVENT_ABORTED) {
{ //Stop command
//Stop command pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_cmd_exec(pPN512, PN512_CMD_IDLE); pPN512->transceive.mode = pn512_transceive_mode_idle;
pPN512->transceive.mode = pn512_transceive_mode_idle;
NFC_ERR("Aborted TX"); NFC_ERR("Aborted TX");
pn512_irq_set(pPN512, PN512_IRQ_NONE); pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); pn512_transceive_callback(pPN512, NFC_ERR_ABORTED);
return; return;
}
NFC_DBG("TX task");
if(events & EVENT_TIMEOUT)
{
// Check status
NFC_DBG("Status = %02X %02X", pn512_register_read(pPN512, PN512_REG_STATUS1), pn512_register_read(pPN512, PN512_REG_STATUS2));
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
NFC_ERR("Timeout on TX");
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT);
return;
}
uint16_t irqs_en = pn512_irq_enabled(pPN512);
uint16_t irqs = pn512_irq_get(pPN512);
if( irqs & PN512_IRQ_RF_OFF )
{
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
NFC_WARN("RF Off");
pn512_transceive_callback(pPN512, NFC_ERR_FIELD);
return;
}
if( irqs & PN512_IRQ_TX )
{
if( irqs_en & PN512_IRQ_LOW_ALERT )
{
//If the transmission has been completed without us getting a chance to fill the buffer up it means that we had a buffer underflow
NFC_ERR("Buffer underflow");
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_transceive_callback(pPN512, NFC_ERR_UNDERFLOW);
return;
} }
//Transmission complete NFC_DBG("TX task");
pn512_irq_set(pPN512, PN512_IRQ_NONE); if (events & EVENT_TIMEOUT) {
pn512_irq_clear(pPN512, PN512_IRQ_TX | PN512_IRQ_LOW_ALERT); // Check status
NFC_DBG("Status = %02X %02X", pn512_register_read(pPN512, PN512_REG_STATUS1), pn512_register_read(pPN512, PN512_REG_STATUS2));
//Start receiving //Stop command
NFC_DBG("Transmission complete"); pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
if(pPN512->transceive.mode != pn512_transceive_mode_transmit) pPN512->transceive.mode = pn512_transceive_mode_idle;
{
if(pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) NFC_ERR("Timeout on TX");
{
//Make sure bitframing reg is clean pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT);
return;
}
uint16_t irqs_en = pn512_irq_enabled(pPN512);
uint16_t irqs = pn512_irq_get(pPN512);
if (irqs & PN512_IRQ_RF_OFF) {
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
NFC_WARN("RF Off");
pn512_transceive_callback(pPN512, NFC_ERR_FIELD);
return;
}
if (irqs & PN512_IRQ_TX) {
if (irqs_en & PN512_IRQ_LOW_ALERT) {
//If the transmission has been completed without us getting a chance to fill the buffer up it means that we had a buffer underflow
NFC_ERR("Buffer underflow");
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_transceive_callback(pPN512, NFC_ERR_UNDERFLOW);
return;
}
//Transmission complete
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_TX | PN512_IRQ_LOW_ALERT);
//Start receiving
NFC_DBG("Transmission complete");
if (pPN512->transceive.mode != pn512_transceive_mode_transmit) {
if (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) {
//Make sure bitframing reg is clean
pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00);
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_transceive_hw_rx_start(pPN512);
//Start autocoll
pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL);
} else {
pn512_transceive_hw_rx_start(pPN512);
}
return;
} else {
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT);
pn512_transceive_callback(pPN512, NFC_OK);
return;
}
}
if ((irqs & PN512_IRQ_LOW_ALERT) && (buffer_reader_readable(&pPN512->writeBuf) > 0)) {
//Continue to fill FIFO
pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT);
pn512_transceive_hw_tx_iteration(pPN512, false);
return;
}
if (irqs & PN512_IRQ_IDLE) {
pn512_irq_clear(pPN512, PN512_IRQ_ERR);
NFC_ERR("Modem went to idle");
pn512_cmd_exec(pPN512, PN512_CMD_IDLE); pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_transceive_hw_rx_start(pPN512); pPN512->transceive.mode = pn512_transceive_mode_idle;
//Start autocoll pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
} pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM);
else return;
{
pn512_transceive_hw_rx_start(pPN512);
}
return;
} }
else
{
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT);
pn512_transceive_callback(pPN512, NFC_OK);
return;
}
}
if( (irqs & PN512_IRQ_LOW_ALERT) && (buffer_reader_readable(&pPN512->writeBuf) > 0) )
{
//Continue to fill FIFO
pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT);
//Call back function
pn512_transceive_hw_tx_iteration(pPN512, false); pn512_transceive_hw_tx_iteration(pPN512, false);
return;
}
if( irqs & PN512_IRQ_IDLE )
{
pn512_irq_clear(pPN512, PN512_IRQ_ERR);
NFC_ERR("Modem went to idle");
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM);
return;
}
//Call back function
pn512_transceive_hw_tx_iteration(pPN512, false);
} }
void pn512_transceive_hw_rx_start(pn512_t* pPN512) void pn512_transceive_hw_rx_start(pn512_t *pPN512)
{ {
uint16_t irqs_en = PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_ERR; uint16_t irqs_en = PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_ERR;
if(PN512_FRAMING_IS_TARGET(pPN512->framing)) if (PN512_FRAMING_IS_TARGET(pPN512->framing)) {
{ irqs_en |= PN512_IRQ_RF_OFF;
irqs_en |= PN512_IRQ_RF_OFF; }
}
pn512_irq_set(pPN512, irqs_en); pn512_irq_set(pPN512, irqs_en);
//Reset buffer except if data should be appended to this -- TODO //Reset buffer except if data should be appended to this -- TODO
buffer_builder_reset(&pPN512->readBufBldr); buffer_builder_reset(&pPN512->readBufBldr);
//Queue task to process IRQ //Queue task to process IRQ
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT,
pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); pPN512->timeout, pn512_transceive_hw_rx_task, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler, scheduler_queue_task(&pPN512->transceiver.scheduler,
&pPN512->transceiver.task); &pPN512->transceiver.task);
} }
void pn512_transceive_hw_rx_task(uint32_t events, void* pUserData) void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData)
{ {
pn512_t* pPN512 = (pn512_t*) pUserData; pn512_t *pPN512 = (pn512_t *) pUserData;
NFC_DBG("RX task"); NFC_DBG("RX task");
if(events & EVENT_ABORTED) if (events & EVENT_ABORTED) {
{ //Stop command
//Stop command pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_cmd_exec(pPN512, PN512_CMD_IDLE); pPN512->transceive.mode = pn512_transceive_mode_idle;
pPN512->transceive.mode = pn512_transceive_mode_idle;
NFC_ERR("Aborted RX"); NFC_ERR("Aborted RX");
pn512_irq_set(pPN512, PN512_IRQ_NONE); pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); pn512_transceive_callback(pPN512, NFC_ERR_ABORTED);
return; return;
} }
if(events & EVENT_TIMEOUT)
{
NFC_WARN("Timeout");
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT);
return;
}
uint16_t irqs = pn512_irq_get(pPN512);
NFC_DBG("irqs %04x", irqs);
bool collision_detected = false;
if( irqs & PN512_IRQ_ERR )
{
pn512_irq_clear(pPN512, PN512_IRQ_ERR);
uint8_t err_reg = pn512_register_read(pPN512, PN512_REG_ERROR);
NFC_ERR("Got error - error reg is %02X", err_reg);
// if err_reg == 0, sticky error that must have been cleared automatically, continue
if( err_reg != 0 )
{
//If it's a collsision, flag it but still carry on with RX procedure
collision_detected = true;
if( (err_reg == 0x08) || (err_reg == 0x0A) ) // Collision (and maybe parity) (and no other error)
{
irqs &= ~PN512_IRQ_ERR;
irqs |= PN512_IRQ_RX;
}
else
{
DBG_BLOCK(
//Empty FIFO into buffer
pn512_fifo_read(pPN512, &pPN512->readBufBldr);
NFC_DBG("Received");
buffer_dump( buffer_builder_buffer(&pPN512->readBufBldr) );
NFC_DBG("Computed CRC = %02X %02X", pn512_register_read(pPN512, PN512_REG_CRCRESULT_MSB), pn512_register_read(pPN512, PN512_REG_CRCRESULT_LSB));
)
if (events & EVENT_TIMEOUT) {
NFC_WARN("Timeout");
//Stop command //Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE); pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle; pPN512->transceive.mode = pn512_transceive_mode_idle;
@ -323,172 +252,189 @@ void pn512_transceive_hw_rx_task(uint32_t events, void* pUserData)
pn512_irq_clear(pPN512, PN512_IRQ_ALL); pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback //Call callback
pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT);
return; return;
}
}
}
if( (irqs & PN512_IRQ_RX) || (irqs & PN512_IRQ_HIGH_ALERT) )
{
//Empty FIFO into buffer
pn512_fifo_read(pPN512, &pPN512->readBufBldr);
if( (buffer_builder_writeable(&pPN512->readBufBldr) == 0) && (pn512_fifo_length(pPN512) > 0) )
{
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
NFC_WARN("RX buffer overflow");
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_BUFFER_TOO_SMALL);
return; //overflow
} }
if( irqs & PN512_IRQ_HIGH_ALERT ) uint16_t irqs = pn512_irq_get(pPN512);
{ NFC_DBG("irqs %04x", irqs);
NFC_DBG("High alert"); bool collision_detected = false;
pn512_irq_clear(pPN512, PN512_IRQ_HIGH_ALERT); if (irqs & PN512_IRQ_ERR) {
} pn512_irq_clear(pPN512, PN512_IRQ_ERR);
if( irqs & PN512_IRQ_RX ) uint8_t err_reg = pn512_register_read(pPN512, PN512_REG_ERROR);
{ NFC_ERR("Got error - error reg is %02X", err_reg);
pn512_irq_clear(pPN512, PN512_IRQ_RX); // if err_reg == 0, sticky error that must have been cleared automatically, continue
if (err_reg != 0) {
//If it's a collsision, flag it but still carry on with RX procedure
collision_detected = true;
size_t last_byte_length = pn512_register_read(pPN512, PN512_REG_CONTROL) & 0x7; if ((err_reg == 0x08) || (err_reg == 0x0A)) { // Collision (and maybe parity) (and no other error)
if( last_byte_length == 0 ) irqs &= ~PN512_IRQ_ERR;
{ irqs |= PN512_IRQ_RX;
last_byte_length = 8; } else {
} DBG_BLOCK(
pPN512->readLastByteLength = last_byte_length; //Empty FIFO into buffer
pn512_fifo_read(pPN512, &pPN512->readBufBldr);
pn512_irq_set(pPN512, PN512_IRQ_NONE); NFC_DBG("Received");
pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); buffer_dump(buffer_builder_buffer(&pPN512->readBufBldr));
NFC_DBG("Received:"); NFC_DBG("Computed CRC = %02X %02X", pn512_register_read(pPN512, PN512_REG_CRCRESULT_MSB), pn512_register_read(pPN512, PN512_REG_CRCRESULT_LSB));
DBG_BLOCK( buffer_dump( buffer_builder_buffer(&pPN512->readBufBldr) ); )
if( (pPN512->transceive.mode == pn512_transceive_mode_target_autocoll) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) ) )
{
//Check if target was activated
if( !(pn512_register_read(pPN512, PN512_REG_STATUS2) & 0x10) )
{
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE); //Stop command
pn512_irq_clear(pPN512, PN512_IRQ_ALL); pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
//Call callback pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_transceive_callback(pPN512, NFC_ERR_PROTOCOL);
return; pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM);
return;
}
} }
//PN512 switches to transceive automatically
pPN512->transceive.mode = pn512_transceive_mode_transceive;
}
else if( pPN512->transceive.mode == pn512_transceive_mode_receive )
{
pPN512->transceive.mode = pn512_transceive_mode_transceive;
//pn512_cmd_exec(pPN512, PN512_CMD_IDLE); //Useful?
}
if(!collision_detected)
{
pn512_transceive_callback(pPN512, NFC_OK);
}
else
{
pn512_transceive_callback(pPN512, NFC_ERR_COLLISION);
}
return;
} }
} if ((irqs & PN512_IRQ_RX) || (irqs & PN512_IRQ_HIGH_ALERT)) {
if( irqs & PN512_IRQ_RF_OFF ) //Empty FIFO into buffer
{ pn512_fifo_read(pPN512, &pPN512->readBufBldr);
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE); if ((buffer_builder_writeable(&pPN512->readBufBldr) == 0) && (pn512_fifo_length(pPN512) > 0)) {
pn512_irq_clear(pPN512, PN512_IRQ_ALL); //Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
//Call callback NFC_WARN("RX buffer overflow");
pn512_transceive_callback(pPN512, NFC_ERR_FIELD);
return;
}
//Queue task to process IRQ pn512_irq_set(pPN512, PN512_IRQ_NONE);
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, pn512_irq_clear(pPN512, PN512_IRQ_ALL);
pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); //Call callback
scheduler_queue_task(&pPN512->transceiver.scheduler, pn512_transceive_callback(pPN512, NFC_ERR_BUFFER_TOO_SMALL);
&pPN512->transceiver.task); return; //overflow
}
if (irqs & PN512_IRQ_HIGH_ALERT) {
NFC_DBG("High alert");
pn512_irq_clear(pPN512, PN512_IRQ_HIGH_ALERT);
}
if (irqs & PN512_IRQ_RX) {
pn512_irq_clear(pPN512, PN512_IRQ_RX);
size_t last_byte_length = pn512_register_read(pPN512, PN512_REG_CONTROL) & 0x7;
if (last_byte_length == 0) {
last_byte_length = 8;
}
pPN512->readLastByteLength = last_byte_length;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT);
NFC_DBG("Received:");
DBG_BLOCK(buffer_dump(buffer_builder_buffer(&pPN512->readBufBldr));)
if ((pPN512->transceive.mode == pn512_transceive_mode_target_autocoll) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) {
//Check if target was activated
if (!(pn512_register_read(pPN512, PN512_REG_STATUS2) & 0x10)) {
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_PROTOCOL);
return;
}
//PN512 switches to transceive automatically
pPN512->transceive.mode = pn512_transceive_mode_transceive;
} else if (pPN512->transceive.mode == pn512_transceive_mode_receive) {
pPN512->transceive.mode = pn512_transceive_mode_transceive;
//pn512_cmd_exec(pPN512, PN512_CMD_IDLE); //Useful?
}
if (!collision_detected) {
pn512_transceive_callback(pPN512, NFC_OK);
} else {
pn512_transceive_callback(pPN512, NFC_ERR_COLLISION);
}
return;
}
}
if (irqs & PN512_IRQ_RF_OFF) {
//Stop command
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pPN512->transceive.mode = pn512_transceive_mode_idle;
pn512_irq_set(pPN512, PN512_IRQ_NONE);
pn512_irq_clear(pPN512, PN512_IRQ_ALL);
//Call callback
pn512_transceive_callback(pPN512, NFC_ERR_FIELD);
return;
}
//Queue task to process IRQ
task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT,
pPN512->timeout, pn512_transceive_hw_rx_task, pPN512);
scheduler_queue_task(&pPN512->transceiver.scheduler,
&pPN512->transceiver.task);
} }
void pn512_transceive_hw(pn512_t* pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb) void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb)
{ {
uint16_t irqs_en; uint16_t irqs_en;
//Store callback //Store callback
pPN512->transceive.cb = cb; pPN512->transceive.cb = cb;
//Clear FIFO //Clear FIFO
pn512_fifo_clear(pPN512); pn512_fifo_clear(pPN512);
//Clear previous IRQs if present //Clear previous IRQs if present
pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_TX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_LOW_ALERT | PN512_IRQ_ERR | PN512_IRQ_IDLE | PN512_IRQ_RF_OFF ); pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_TX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_LOW_ALERT | PN512_IRQ_ERR | PN512_IRQ_IDLE | PN512_IRQ_RF_OFF);
if( PN512_FRAMING_IS_TARGET(pPN512->framing) ) if (PN512_FRAMING_IS_TARGET(pPN512->framing)) {
{ //RF off?
//RF off? if (!(pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x04)) {
if(!(pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x04)) //Call callback
{ pn512_transceive_callback(pPN512, NFC_ERR_FIELD);
//Call callback return;
pn512_transceive_callback(pPN512, NFC_ERR_FIELD); }
return; } else if ((pPN512->transceive.mode != mode) && (mode == pn512_transceive_mode_transceive)) {
} pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE);
}
else if((pPN512->transceive.mode != mode) && (mode == pn512_transceive_mode_transceive))
{
pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE);
}
pPN512->transceive.mode = mode;
if( mode == pn512_transceive_mode_receive )
{
pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_transceive_hw_rx_start(pPN512);
pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE);
}
else if(mode == pn512_transceive_mode_target_autocoll)
{
//Make sure bitframing reg is clean
pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00);
pn512_transceive_hw_rx_start(pPN512);
//Start autocoll
pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL);
return;
}
else
{
NFC_DBG("Sending:");
DBG_BLOCK( buffer_dump(&pPN512->writeBuf); )
//Transmit a frame to remote target/initiator
irqs_en = PN512_IRQ_TX | PN512_IRQ_IDLE;
if( PN512_FRAMING_IS_TARGET(pPN512->framing) )
{
irqs_en |= PN512_IRQ_RF_OFF;
} }
pn512_irq_set(pPN512, irqs_en); pPN512->transceive.mode = mode;
pn512_transceive_hw_tx_iteration(pPN512, true); if (mode == pn512_transceive_mode_receive) {
} pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
pn512_transceive_hw_rx_start(pPN512);
pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE);
} else if (mode == pn512_transceive_mode_target_autocoll) {
//Make sure bitframing reg is clean
pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00);
pn512_transceive_hw_rx_start(pPN512);
//Start autocoll
pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL);
return;
} else {
NFC_DBG("Sending:");
DBG_BLOCK(buffer_dump(&pPN512->writeBuf);)
//Transmit a frame to remote target/initiator
irqs_en = PN512_IRQ_TX | PN512_IRQ_IDLE;
if (PN512_FRAMING_IS_TARGET(pPN512->framing)) {
irqs_en |= PN512_IRQ_RF_OFF;
}
pn512_irq_set(pPN512, irqs_en);
pn512_transceive_hw_tx_iteration(pPN512, true);
}
} }

View File

@ -29,13 +29,13 @@ extern "C" {
#include "pn512.h" #include "pn512.h"
void pn512_transceive_hw(pn512_t* pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb); void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb);
void pn512_transceive_hw_tx_task(uint32_t events, void* pUserData); void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData);
void pn512_transceive_hw_tx_iteration(pn512_t* pPN512, bool start); void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start);
void pn512_transceive_hw_rx_start(pn512_t* pPN512); void pn512_transceive_hw_rx_start(pn512_t *pPN512);
void pn512_transceive_hw_rx_task(uint32_t events, void* pUserData); void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -27,9 +27,8 @@
extern "C" { extern "C" {
#endif #endif
typedef struct __pn512_registers typedef struct __pn512_registers {
{ int8_t registers_page;
int8_t registers_page;
} pn512_registers_t; } pn512_registers_t;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -34,24 +34,23 @@
extern "C" { extern "C" {
#endif #endif
typedef enum __RF_PROTOCOL typedef enum __RF_PROTOCOL {
{ __RF_PROTOCOL_UNKNOWN = 0,
__RF_PROTOCOL_UNKNOWN = 0, //Reader
//Reader RF_PROTOCOL_ISO_14443_A_READER,
RF_PROTOCOL_ISO_14443_A_READER, RF_PROTOCOL_ISO_14443_B_READER,
RF_PROTOCOL_ISO_14443_B_READER, RF_PROTOCOL_INNOVATRON_READER,
RF_PROTOCOL_INNOVATRON_READER, RF_PROTOCOL_ISO_15693_READER,
RF_PROTOCOL_ISO_15693_READER, RF_PROTOCOL_FELICA_READER,
RF_PROTOCOL_FELICA_READER, //... add other protocols here
//... add other protocols here RF_PROTOCOL_ISO_14443_A_TARGET,
RF_PROTOCOL_ISO_14443_A_TARGET, RF_PROTOCOL_ISO_14443_B_TARGET,
RF_PROTOCOL_ISO_14443_B_TARGET, RF_PROTOCOL_INNOVATRON_TARGET,
RF_PROTOCOL_INNOVATRON_TARGET, RF_PROTOCOL_ISO_15693_TARGET,
RF_PROTOCOL_ISO_15693_TARGET, RF_PROTOCOL_FELICA_TARGET,
RF_PROTOCOL_FELICA_TARGET, RF_PROTOCOL_ISO_DEP_TARGET, //ISO 14443-4 transport protocol
RF_PROTOCOL_ISO_DEP_TARGET, //ISO 14443-4 transport protocol RF_PROTOCOL_NFC_DEP_TARGET, //NFC-IP 1 transport protocol
RF_PROTOCOL_NFC_DEP_TARGET, //NFC-IP 1 transport protocol //... add other protocols here
//... add other protocols here
} RF_PROTOCOL; } RF_PROTOCOL;
@ -67,12 +66,11 @@ typedef uint32_t RF_OPTION;
#define RF_OPTION_CHECK_PARITY 0x08 #define RF_OPTION_CHECK_PARITY 0x08
#define RF_OPTION_CLOSE 0x10 //Last frame #define RF_OPTION_CLOSE 0x10 //Last frame
typedef enum __RF_BITRATE typedef enum __RF_BITRATE {
{ RF_BITRATE_106K = 0x00,
RF_BITRATE_106K=0x00, RF_BITRATE_212K = 0x01,
RF_BITRATE_212K=0x01, RF_BITRATE_424K = 0x02,
RF_BITRATE_424K=0x02, RF_BITRATE_848K = 0x03,
RF_BITRATE_848K=0x03,
} RF_BITRATE; } RF_BITRATE;

View File

@ -34,10 +34,10 @@
* \param pTransport pointer to already initialized nfc_transport_t structure * \param pTransport pointer to already initialized nfc_transport_t structure
* \param pImpl pointer to the structure implementing the transceiver interface (eg pn512_t or pn532_t) * \param pImpl pointer to the structure implementing the transceiver interface (eg pn512_t or pn532_t)
*/ */
void transceiver_init(nfc_transceiver_t* pTransceiver, nfc_transport_t* pTransport, nfc_scheduler_timer_t* pTimer) void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer)
{ {
pTransceiver->pTransport = pTransport; pTransceiver->pTransport = pTransport;
scheduler_init(&pTransceiver->scheduler, pTimer); scheduler_init(&pTransceiver->scheduler, pTimer);
} }

View File

@ -37,239 +37,230 @@ typedef struct __transceiver_impl transceiver_impl_t;
typedef enum __nfc_framing nfc_framing_t; typedef enum __nfc_framing nfc_framing_t;
enum __nfc_framing { enum __nfc_framing {
nfc_framing_unknown, nfc_framing_unknown,
nfc_framing_target_mode_detector, //Framing is unknown and will be detected by the hardware nfc_framing_target_mode_detector, //Framing is unknown and will be detected by the hardware
nfc_framing_target_a_106, nfc_framing_target_a_106,
nfc_framing_target_b_106, nfc_framing_target_b_106,
nfc_framing_target_f_212, nfc_framing_target_f_212,
nfc_framing_target_f_424, nfc_framing_target_f_424,
nfc_framing_initiator_a_106, nfc_framing_initiator_a_106,
nfc_framing_initiator_b_106, nfc_framing_initiator_b_106,
nfc_framing_initiator_f_212, nfc_framing_initiator_f_212,
nfc_framing_initiator_f_424, nfc_framing_initiator_f_424,
}; };
typedef struct __nfc_tech typedef struct __nfc_tech {
{ unsigned int nfc_type1 : 1;
unsigned int nfc_type1 : 1; unsigned int nfc_type2 : 1;
unsigned int nfc_type2 : 1; unsigned int nfc_type3 : 1;
unsigned int nfc_type3 : 1; unsigned int nfc_iso_dep_a : 1;
unsigned int nfc_iso_dep_a : 1; unsigned int nfc_iso_dep_b : 1;
unsigned int nfc_iso_dep_b : 1; unsigned int nfc_nfc_dep_a : 1;
unsigned int nfc_nfc_dep_a : 1; unsigned int nfc_nfc_dep_f_212 : 1;
unsigned int nfc_nfc_dep_f_212 : 1; unsigned int nfc_nfc_dep_f_424 : 1;
unsigned int nfc_nfc_dep_f_424 : 1;
} nfc_tech_t; } nfc_tech_t;
typedef struct __polling_options polling_options_t; typedef struct __polling_options polling_options_t;
struct __polling_options struct __polling_options {
{ unsigned int bail_at_first_target : 1;
unsigned int bail_at_first_target : 1; unsigned int bail_at_first_tech : 1;
unsigned int bail_at_first_tech : 1; int32_t listen_for;
int32_t listen_for;
}; };
typedef void (*transceiver_cb_t)(nfc_transceiver_t* pTransceiver, nfc_err_t ret, void* pUserData); typedef void (*transceiver_cb_t)(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData);
typedef void (*set_protocols_fn_t)(nfc_transceiver_t* pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); typedef void (*set_protocols_fn_t)(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options);
typedef void (*poll_fn_t)(nfc_transceiver_t* pTransceiver); typedef void (*poll_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*set_crc_fn_t)(nfc_transceiver_t* pTransceiver, bool crcOut, bool crcIn); typedef void (*set_crc_fn_t)(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn);
typedef void (*set_timeout_fn_t)(nfc_transceiver_t* pTransceiver, int timeout); typedef void (*set_timeout_fn_t)(nfc_transceiver_t *pTransceiver, int timeout);
typedef void (*set_transceive_options_fn_t)(nfc_transceiver_t* pTransceiver, bool transmit, bool receive, bool repoll); typedef void (*set_transceive_options_fn_t)(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll);
typedef void (*set_transceive_framing_fn_t)(nfc_transceiver_t* pTransceiver, nfc_framing_t framing); typedef void (*set_transceive_framing_fn_t)(nfc_transceiver_t *pTransceiver, nfc_framing_t framing);
typedef void (*set_write_fn_t)(nfc_transceiver_t* pTransceiver, buffer_t* pWriteBuf); //Set write buffer typedef void (*set_write_fn_t)(nfc_transceiver_t *pTransceiver, buffer_t *pWriteBuf); //Set write buffer
typedef buffer_t* (*get_read_fn_t)(nfc_transceiver_t* pTransceiver); //Get read buffer typedef buffer_t *(*get_read_fn_t)(nfc_transceiver_t *pTransceiver); //Get read buffer
typedef size_t (*get_last_byte_length_fn_t)(nfc_transceiver_t* pTransceiver); typedef size_t (*get_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*set_last_byte_length_fn_t)(nfc_transceiver_t* pTransceiver, size_t lastByteLength); typedef void (*set_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver, size_t lastByteLength);
typedef size_t (*get_first_byte_align_fn_t)(nfc_transceiver_t* pTransceiver); typedef size_t (*get_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*set_first_byte_align_fn_t)(nfc_transceiver_t* pTransceiver, size_t firstByteAlign); typedef void (*set_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver, size_t firstByteAlign);
typedef void (*transceive_fn_t)(nfc_transceiver_t* pTransceiver); typedef void (*transceive_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*abort_fn_t)(nfc_transceiver_t* pTransceiver); typedef void (*abort_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*close_fn_t)(nfc_transceiver_t* pTransceiver); typedef void (*close_fn_t)(nfc_transceiver_t *pTransceiver);
typedef void (*sleep_fn_t)(nfc_transceiver_t* pTransceiver, bool sleep); typedef void (*sleep_fn_t)(nfc_transceiver_t *pTransceiver, bool sleep);
struct __transceiver_impl struct __transceiver_impl {
{ set_protocols_fn_t set_protocols;
set_protocols_fn_t set_protocols; poll_fn_t poll;
poll_fn_t poll; set_crc_fn_t set_crc;
set_crc_fn_t set_crc; set_timeout_fn_t set_timeout;
set_timeout_fn_t set_timeout; set_transceive_options_fn_t set_transceive_options;
set_transceive_options_fn_t set_transceive_options; set_transceive_framing_fn_t set_transceive_framing;
set_transceive_framing_fn_t set_transceive_framing; set_write_fn_t set_write;
set_write_fn_t set_write; get_read_fn_t get_read;
get_read_fn_t get_read; set_last_byte_length_fn_t set_last_byte_length;
set_last_byte_length_fn_t set_last_byte_length; get_last_byte_length_fn_t get_last_byte_length;
get_last_byte_length_fn_t get_last_byte_length; set_first_byte_align_fn_t set_first_byte_align;
set_first_byte_align_fn_t set_first_byte_align; transceive_fn_t transceive;
transceive_fn_t transceive; abort_fn_t abort;
abort_fn_t abort; close_fn_t close;
close_fn_t close; sleep_fn_t sleep;
sleep_fn_t sleep;
}; };
typedef struct __nfc_a_info nfc_a_info_t; typedef struct __nfc_a_info nfc_a_info_t;
struct __nfc_a_info struct __nfc_a_info {
{ uint8_t uid[10];
uint8_t uid[10]; size_t uidLength;
size_t uidLength; uint8_t sak;
uint8_t sak; uint8_t atqa[2];
uint8_t atqa[2];
}; };
typedef struct __nfc_b_info nfc_b_info_t; typedef struct __nfc_b_info nfc_b_info_t;
struct __nfc_b_info struct __nfc_b_info {
{ uint8_t pupi[4];
uint8_t pupi[4]; uint8_t application_data[4];
uint8_t application_data[4]; uint8_t protocol_info[3];
uint8_t protocol_info[3];
}; };
typedef struct __nfc_f_info nfc_f_info_t; typedef struct __nfc_f_info nfc_f_info_t;
struct __nfc_f_info struct __nfc_f_info {
{ uint8_t nfcid2[8];
uint8_t nfcid2[8];
}; };
typedef struct __nfc_info nfc_info_t; typedef struct __nfc_info nfc_info_t;
struct __nfc_info struct __nfc_info {
{ nfc_tech_t type;
nfc_tech_t type; union {
union { nfc_a_info_t nfcA;
nfc_a_info_t nfcA; nfc_b_info_t nfcB;
nfc_b_info_t nfcB; nfc_f_info_t nfcF;
nfc_f_info_t nfcF; };
};
}; };
#define MUNFC_MAX_REMOTE_TARGETS 4 #define MUNFC_MAX_REMOTE_TARGETS 4
struct __transceiver struct __transceiver {
{ const transceiver_impl_t *fn; //vtable
const transceiver_impl_t* fn; //vtable
bool initiator_ntarget; bool initiator_ntarget;
nfc_info_t remote_targets[MUNFC_MAX_REMOTE_TARGETS]; nfc_info_t remote_targets[MUNFC_MAX_REMOTE_TARGETS];
size_t remote_targets_count; size_t remote_targets_count;
nfc_tech_t active_tech; nfc_tech_t active_tech;
transceiver_cb_t cb; //Callback to upper layer transceiver_cb_t cb; //Callback to upper layer
void* pUserData; void *pUserData;
nfc_task_t task; //Task for deferred execution nfc_task_t task; //Task for deferred execution
nfc_transport_t* pTransport; nfc_transport_t *pTransport;
nfc_scheduler_t scheduler; nfc_scheduler_t scheduler;
}; };
void transceiver_init(nfc_transceiver_t* pTransceiver, nfc_transport_t* pTransport, nfc_scheduler_timer_t* pTimer); void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer);
static inline void transceiver_set_protocols(nfc_transceiver_t* pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) static inline void transceiver_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options)
{ {
pTransceiver->fn->set_protocols(pTransceiver, initiators, targets, options); pTransceiver->fn->set_protocols(pTransceiver, initiators, targets, options);
} }
static inline void transceiver_poll(nfc_transceiver_t* pTransceiver, transceiver_cb_t cb, void* pUserData) static inline void transceiver_poll(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData)
{ {
pTransceiver->cb = cb; pTransceiver->cb = cb;
pTransceiver->pUserData = pUserData; pTransceiver->pUserData = pUserData;
pTransceiver->fn->poll(pTransceiver); pTransceiver->fn->poll(pTransceiver);
} }
static inline void transceiver_set_crc(nfc_transceiver_t* pTransceiver, bool crcOut, bool crcIn) static inline void transceiver_set_crc(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn)
{ {
pTransceiver->fn->set_crc(pTransceiver, crcOut, crcIn); pTransceiver->fn->set_crc(pTransceiver, crcOut, crcIn);
} }
static inline void transceiver_set_timeout(nfc_transceiver_t* pTransceiver, int timeout) static inline void transceiver_set_timeout(nfc_transceiver_t *pTransceiver, int timeout)
{ {
pTransceiver->fn->set_timeout(pTransceiver, timeout); pTransceiver->fn->set_timeout(pTransceiver, timeout);
} }
static inline void transceiver_set_transceive_options(nfc_transceiver_t* pTransceiver, bool transmit, bool receive, bool repoll) static inline void transceiver_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll)
{ {
pTransceiver->fn->set_transceive_options(pTransceiver, transmit, receive, repoll); pTransceiver->fn->set_transceive_options(pTransceiver, transmit, receive, repoll);
} }
static inline void transceiver_set_transceive_framing(nfc_transceiver_t* pTransceiver, nfc_framing_t framing) static inline void transceiver_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing)
{ {
pTransceiver->fn->set_transceive_framing(pTransceiver, framing); pTransceiver->fn->set_transceive_framing(pTransceiver, framing);
} }
static inline void transceiver_set_write(nfc_transceiver_t* pTransceiver, buffer_t* pWriteBuf) static inline void transceiver_set_write(nfc_transceiver_t *pTransceiver, buffer_t *pWriteBuf)
{ {
pTransceiver->fn->set_write(pTransceiver, pWriteBuf); pTransceiver->fn->set_write(pTransceiver, pWriteBuf);
} }
static inline buffer_t* transceiver_get_read(nfc_transceiver_t* pTransceiver) static inline buffer_t *transceiver_get_read(nfc_transceiver_t *pTransceiver)
{ {
return pTransceiver->fn->get_read(pTransceiver); return pTransceiver->fn->get_read(pTransceiver);
} }
static inline size_t transceiver_get_last_byte_length(nfc_transceiver_t* pTransceiver) static inline size_t transceiver_get_last_byte_length(nfc_transceiver_t *pTransceiver)
{ {
return pTransceiver->fn->get_last_byte_length(pTransceiver); return pTransceiver->fn->get_last_byte_length(pTransceiver);
} }
static inline void transceiver_set_last_byte_length(nfc_transceiver_t* pTransceiver, size_t lastByteLength) static inline void transceiver_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength)
{ {
pTransceiver->fn->set_last_byte_length(pTransceiver, lastByteLength); pTransceiver->fn->set_last_byte_length(pTransceiver, lastByteLength);
} }
static inline void transceiver_set_first_byte_align(nfc_transceiver_t* pTransceiver, size_t firstByteAlign) static inline void transceiver_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign)
{ {
pTransceiver->fn->set_first_byte_align(pTransceiver, firstByteAlign); pTransceiver->fn->set_first_byte_align(pTransceiver, firstByteAlign);
} }
static inline void nfc_transceiver_transceive(nfc_transceiver_t* pTransceiver, transceiver_cb_t cb, void* pUserData) static inline void nfc_transceiver_transceive(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData)
{ {
pTransceiver->cb = cb; pTransceiver->cb = cb;
pTransceiver->pUserData = pUserData; pTransceiver->pUserData = pUserData;
pTransceiver->fn->transceive(pTransceiver); pTransceiver->fn->transceive(pTransceiver);
} }
static inline void transceiver_abort(nfc_transceiver_t* pTransceiver) static inline void transceiver_abort(nfc_transceiver_t *pTransceiver)
{ {
pTransceiver->fn->abort(pTransceiver); pTransceiver->fn->abort(pTransceiver);
} }
static inline void transceiver_close(nfc_transceiver_t* pTransceiver) static inline void transceiver_close(nfc_transceiver_t *pTransceiver)
{ {
pTransceiver->fn->close(pTransceiver); pTransceiver->fn->close(pTransceiver);
} }
static inline bool transceiver_is_initiator_mode(nfc_transceiver_t* pTransceiver) static inline bool transceiver_is_initiator_mode(nfc_transceiver_t *pTransceiver)
{ {
return pTransceiver->initiator_ntarget; return pTransceiver->initiator_ntarget;
} }
static inline nfc_tech_t transceiver_get_active_techs(nfc_transceiver_t* pTransceiver) static inline nfc_tech_t transceiver_get_active_techs(nfc_transceiver_t *pTransceiver)
{ {
return pTransceiver->active_tech; return pTransceiver->active_tech;
} }
static inline nfc_scheduler_t* transceiver_get_scheduler(nfc_transceiver_t* pTransceiver) static inline nfc_scheduler_t *transceiver_get_scheduler(nfc_transceiver_t *pTransceiver)
{ {
return &pTransceiver->scheduler; return &pTransceiver->scheduler;
} }
static inline const nfc_info_t* transceiver_get_remote_target_info(nfc_transceiver_t* pTransceiver, size_t number) static inline const nfc_info_t *transceiver_get_remote_target_info(nfc_transceiver_t *pTransceiver, size_t number)
{ {
if( number > pTransceiver->remote_targets_count ) if (number > pTransceiver->remote_targets_count) {
{ return NULL;
return NULL; }
} return &pTransceiver->remote_targets[number];
return &pTransceiver->remote_targets[number];
} }
static inline size_t transceiver_get_remote_targets_count(nfc_transceiver_t* pTransceiver) static inline size_t transceiver_get_remote_targets_count(nfc_transceiver_t *pTransceiver)
{ {
return pTransceiver->remote_targets_count; return pTransceiver->remote_targets_count;
} }
static inline void transceiver_sleep(nfc_transceiver_t* pTransceiver, bool sleep) static inline void transceiver_sleep(nfc_transceiver_t *pTransceiver, bool sleep)
{ {
pTransceiver->fn->sleep(pTransceiver, sleep); pTransceiver->fn->sleep(pTransceiver, sleep);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -29,9 +29,9 @@ extern "C" {
#include "transceiver.h" #include "transceiver.h"
static inline void transceiver_callback(nfc_transceiver_t* pTransceiver, nfc_err_t ret) static inline void transceiver_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret)
{ {
pTransceiver->cb(pTransceiver, ret, pTransceiver->pUserData); pTransceiver->cb(pTransceiver, ret, pTransceiver->pUserData);
} }
#ifdef __cplusplus #ifdef __cplusplus