Skip to content

Commit

Permalink
NFC: pn533: Add extended information frame decoding support
Browse files Browse the repository at this point in the history
Extended Information frames are slightly different from standard frames
as they can (theorically) handle datas up tu 64kB. PN533 firmware only
supports packet data up to 265 (incl. TFI byte)
This kind of frame are used when the pn533 wants to exchange more than
255 bytes, and this patch handles the reception of such frames.

Signed-off-by: Olivier Guiter <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
  • Loading branch information
Olivier Guiter authored and Samuel Ortiz committed Aug 13, 2013
1 parent 3a8eab3 commit 1575b9d
Showing 1 changed file with 72 additions and 13 deletions.
85 changes: 72 additions & 13 deletions drivers/nfc/pn533.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2

/* Standard pn533 frame definitions */
/* Standard pn533 frame definitions (standard and extended)*/
#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
+ 2) /* data[0] TFI, data[1] CC */
#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/

#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \
+ 2) /* data[0] TFI, data[1] CC */

#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
#define PN533_CMD_DATAFRAME_MAXLEN 240 /* max data length (send) */

/*
* Max extended frame payload len, excluding TFI and CC
* which are already in PN533_FRAME_HEADER_LEN.
Expand All @@ -99,6 +105,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
Postamble (1) */
#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
/* Half start code (3), LEN (4) should be 0xffff for extended frame */
#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \
&& (hdr)->datalen_checksum == 0xFF)
#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)])

/* start of frame */
#define PN533_STD_FRAME_SOF 0x00FF
Expand All @@ -124,7 +134,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83

/* PN533 Commands */
#define PN533_STD_FRAME_CMD(f) (f->data[1])
#define PN533_FRAME_CMD(f) (f->data[1])

#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_RF_CONFIGURATION 0x32
Expand Down Expand Up @@ -406,6 +416,15 @@ struct pn533_std_frame {
u8 data[];
} __packed;

struct pn533_ext_frame { /* Extended Information frame */
u8 preamble;
__be16 start_frame;
__be16 eif_flag; /* fixed to 0xFFFF */
__be16 datalen;
u8 datalen_checksum;
u8 data[];
} __packed;

struct pn533_frame_ops {
void (*tx_frame_init)(void *frame, u8 cmd_code);
void (*tx_frame_finish)(void *frame);
Expand Down Expand Up @@ -513,7 +532,7 @@ static u8 pn533_acr122_get_cmd_code(void *frame)
{
struct pn533_acr122_rx_frame *f = frame;

return PN533_STD_FRAME_CMD(f);
return PN533_FRAME_CMD(f);
}

static struct pn533_frame_ops pn533_acr122_frame_ops = {
Expand All @@ -532,6 +551,12 @@ static struct pn533_frame_ops pn533_acr122_frame_ops = {
.get_cmd_code = pn533_acr122_get_cmd_code,
};

/* The rule: value(high byte) + value(low byte) + checksum = 0 */
static inline u8 pn533_ext_checksum(u16 value)
{
return ~(u8)(((value & 0xFF00) >> 8) + (u8)(value & 0xFF)) + 1;
}

/* The rule: value + checksum = 0 */
static inline u8 pn533_std_checksum(u8 value)
{
Expand All @@ -557,7 +582,7 @@ static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
frame->preamble = 0;
frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
PN533_STD_FRAME_CMD(frame) = cmd_code;
PN533_FRAME_CMD(frame) = cmd_code;
frame->datalen = 2;
}

Expand All @@ -583,18 +608,35 @@ static void pn533_std_tx_update_payload_len(void *_frame, int len)
static bool pn533_std_rx_frame_is_valid(void *_frame)
{
u8 checksum;
struct pn533_std_frame *frame = _frame;
struct pn533_std_frame *stdf = _frame;

if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
if (stdf->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
return false;

checksum = pn533_std_checksum(frame->datalen);
if (checksum != frame->datalen_checksum)
return false;
if (likely(!PN533_STD_IS_EXTENDED(stdf))) {
/* Standard frame code */

checksum = pn533_std_data_checksum(frame->data, frame->datalen);
if (checksum != PN533_STD_FRAME_CHECKSUM(frame))
return false;
checksum = pn533_std_checksum(stdf->datalen);
if (checksum != stdf->datalen_checksum)
return false;

checksum = pn533_std_data_checksum(stdf->data, stdf->datalen);
if (checksum != PN533_STD_FRAME_CHECKSUM(stdf))
return false;
} else {
/* Extended */
struct pn533_ext_frame *eif = _frame;

checksum = pn533_ext_checksum(be16_to_cpu(eif->datalen));
if (checksum != eif->datalen_checksum)
return false;

/* check data checksum */
checksum = pn533_std_data_checksum(eif->data,
be16_to_cpu(eif->datalen));
if (checksum != PN533_EXT_FRAME_CHECKSUM(eif))
return false;
}

return true;
}
Expand All @@ -614,15 +656,27 @@ static inline int pn533_std_rx_frame_size(void *frame)
{
struct pn533_std_frame *f = frame;

/* check for Extended Information frame */
if (PN533_STD_IS_EXTENDED(f)) {
struct pn533_ext_frame *eif = frame;

return sizeof(struct pn533_ext_frame)
+ be16_to_cpu(eif->datalen) + PN533_STD_FRAME_TAIL_LEN;
}

return sizeof(struct pn533_std_frame) + f->datalen +
PN533_STD_FRAME_TAIL_LEN;
}

static u8 pn533_std_get_cmd_code(void *frame)
{
struct pn533_std_frame *f = frame;
struct pn533_ext_frame *eif = frame;

return PN533_STD_FRAME_CMD(f);
if (PN533_STD_IS_EXTENDED(f))
return PN533_FRAME_CMD(eif);
else
return PN533_FRAME_CMD(f);
}

static struct pn533_frame_ops pn533_std_frame_ops = {
Expand Down Expand Up @@ -690,6 +744,11 @@ static void pn533_recv_response(struct urb *urb)
goto sched_wq;
}

if (PN533_STD_IS_EXTENDED((struct pn533_std_frame *)in_frame))
dev->ops->rx_header_len = PN533_EXT_FRAME_HEADER_LEN;
else
dev->ops->rx_header_len = PN533_STD_FRAME_HEADER_LEN;

sched_wq:
queue_work(dev->wq, &dev->cmd_complete_work);
}
Expand Down

0 comments on commit 1575b9d

Please sign in to comment.