aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc/pn533.c
diff options
context:
space:
mode:
authorOlivier Guiter <olivier.guiter@linux.intel.com>2013-06-13 09:43:27 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-08-13 18:35:18 -0400
commit1575b9d8668f4ecf2648a08751313c826fb6a6e9 (patch)
tree52a8982277e0ecae1d0fba45a55079680d2e2dca /drivers/nfc/pn533.c
parent3a8eab39ac53f2d35d663634e16b486e8a5a65a9 (diff)
NFC: pn533: Add extended information frame decoding support
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 <olivier.guiter@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc/pn533.c')
-rw-r--r--drivers/nfc/pn533.c85
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 125d995c11a9..ae0fa9ee169d 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -84,11 +84,17 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
84/* How much time we spend listening for initiators */ 84/* How much time we spend listening for initiators */
85#define PN533_LISTEN_TIME 2 85#define PN533_LISTEN_TIME 2
86 86
87/* Standard pn533 frame definitions */ 87/* Standard pn533 frame definitions (standard and extended)*/
88#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \ 88#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
89 + 2) /* data[0] TFI, data[1] CC */ 89 + 2) /* data[0] TFI, data[1] CC */
90#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ 90#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
91 91
92#define PN533_EXT_FRAME_HEADER_LEN (sizeof(struct pn533_ext_frame) \
93 + 2) /* data[0] TFI, data[1] CC */
94
95#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
96#define PN533_CMD_DATAFRAME_MAXLEN 240 /* max data length (send) */
97
92/* 98/*
93 * Max extended frame payload len, excluding TFI and CC 99 * Max extended frame payload len, excluding TFI and CC
94 * which are already in PN533_FRAME_HEADER_LEN. 100 * which are already in PN533_FRAME_HEADER_LEN.
@@ -99,6 +105,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
99 Postamble (1) */ 105 Postamble (1) */
100#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen]) 106#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
101#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) 107#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
108/* Half start code (3), LEN (4) should be 0xffff for extended frame */
109#define PN533_STD_IS_EXTENDED(hdr) ((hdr)->datalen == 0xFF \
110 && (hdr)->datalen_checksum == 0xFF)
111#define PN533_EXT_FRAME_CHECKSUM(f) (f->data[be16_to_cpu(f->datalen)])
102 112
103/* start of frame */ 113/* start of frame */
104#define PN533_STD_FRAME_SOF 0x00FF 114#define PN533_STD_FRAME_SOF 0x00FF
@@ -124,7 +134,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
124#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83 134#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
125 135
126/* PN533 Commands */ 136/* PN533 Commands */
127#define PN533_STD_FRAME_CMD(f) (f->data[1]) 137#define PN533_FRAME_CMD(f) (f->data[1])
128 138
129#define PN533_CMD_GET_FIRMWARE_VERSION 0x02 139#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
130#define PN533_CMD_RF_CONFIGURATION 0x32 140#define PN533_CMD_RF_CONFIGURATION 0x32
@@ -406,6 +416,15 @@ struct pn533_std_frame {
406 u8 data[]; 416 u8 data[];
407} __packed; 417} __packed;
408 418
419struct pn533_ext_frame { /* Extended Information frame */
420 u8 preamble;
421 __be16 start_frame;
422 __be16 eif_flag; /* fixed to 0xFFFF */
423 __be16 datalen;
424 u8 datalen_checksum;
425 u8 data[];
426} __packed;
427
409struct pn533_frame_ops { 428struct pn533_frame_ops {
410 void (*tx_frame_init)(void *frame, u8 cmd_code); 429 void (*tx_frame_init)(void *frame, u8 cmd_code);
411 void (*tx_frame_finish)(void *frame); 430 void (*tx_frame_finish)(void *frame);
@@ -513,7 +532,7 @@ static u8 pn533_acr122_get_cmd_code(void *frame)
513{ 532{
514 struct pn533_acr122_rx_frame *f = frame; 533 struct pn533_acr122_rx_frame *f = frame;
515 534
516 return PN533_STD_FRAME_CMD(f); 535 return PN533_FRAME_CMD(f);
517} 536}
518 537
519static struct pn533_frame_ops pn533_acr122_frame_ops = { 538static struct pn533_frame_ops pn533_acr122_frame_ops = {
@@ -532,6 +551,12 @@ static struct pn533_frame_ops pn533_acr122_frame_ops = {
532 .get_cmd_code = pn533_acr122_get_cmd_code, 551 .get_cmd_code = pn533_acr122_get_cmd_code,
533}; 552};
534 553
554/* The rule: value(high byte) + value(low byte) + checksum = 0 */
555static inline u8 pn533_ext_checksum(u16 value)
556{
557 return ~(u8)(((value & 0xFF00) >> 8) + (u8)(value & 0xFF)) + 1;
558}
559
535/* The rule: value + checksum = 0 */ 560/* The rule: value + checksum = 0 */
536static inline u8 pn533_std_checksum(u8 value) 561static inline u8 pn533_std_checksum(u8 value)
537{ 562{
@@ -557,7 +582,7 @@ static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
557 frame->preamble = 0; 582 frame->preamble = 0;
558 frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF); 583 frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
559 PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT; 584 PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
560 PN533_STD_FRAME_CMD(frame) = cmd_code; 585 PN533_FRAME_CMD(frame) = cmd_code;
561 frame->datalen = 2; 586 frame->datalen = 2;
562} 587}
563 588
@@ -583,18 +608,35 @@ static void pn533_std_tx_update_payload_len(void *_frame, int len)
583static bool pn533_std_rx_frame_is_valid(void *_frame) 608static bool pn533_std_rx_frame_is_valid(void *_frame)
584{ 609{
585 u8 checksum; 610 u8 checksum;
586 struct pn533_std_frame *frame = _frame; 611 struct pn533_std_frame *stdf = _frame;
587 612
588 if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF)) 613 if (stdf->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
589 return false; 614 return false;
590 615
591 checksum = pn533_std_checksum(frame->datalen); 616 if (likely(!PN533_STD_IS_EXTENDED(stdf))) {
592 if (checksum != frame->datalen_checksum) 617 /* Standard frame code */
593 return false;
594 618
595 checksum = pn533_std_data_checksum(frame->data, frame->datalen); 619 checksum = pn533_std_checksum(stdf->datalen);
596 if (checksum != PN533_STD_FRAME_CHECKSUM(frame)) 620 if (checksum != stdf->datalen_checksum)
597 return false; 621 return false;
622
623 checksum = pn533_std_data_checksum(stdf->data, stdf->datalen);
624 if (checksum != PN533_STD_FRAME_CHECKSUM(stdf))
625 return false;
626 } else {
627 /* Extended */
628 struct pn533_ext_frame *eif = _frame;
629
630 checksum = pn533_ext_checksum(be16_to_cpu(eif->datalen));
631 if (checksum != eif->datalen_checksum)
632 return false;
633
634 /* check data checksum */
635 checksum = pn533_std_data_checksum(eif->data,
636 be16_to_cpu(eif->datalen));
637 if (checksum != PN533_EXT_FRAME_CHECKSUM(eif))
638 return false;
639 }
598 640
599 return true; 641 return true;
600} 642}
@@ -614,6 +656,14 @@ static inline int pn533_std_rx_frame_size(void *frame)
614{ 656{
615 struct pn533_std_frame *f = frame; 657 struct pn533_std_frame *f = frame;
616 658
659 /* check for Extended Information frame */
660 if (PN533_STD_IS_EXTENDED(f)) {
661 struct pn533_ext_frame *eif = frame;
662
663 return sizeof(struct pn533_ext_frame)
664 + be16_to_cpu(eif->datalen) + PN533_STD_FRAME_TAIL_LEN;
665 }
666
617 return sizeof(struct pn533_std_frame) + f->datalen + 667 return sizeof(struct pn533_std_frame) + f->datalen +
618 PN533_STD_FRAME_TAIL_LEN; 668 PN533_STD_FRAME_TAIL_LEN;
619} 669}
@@ -621,8 +671,12 @@ static inline int pn533_std_rx_frame_size(void *frame)
621static u8 pn533_std_get_cmd_code(void *frame) 671static u8 pn533_std_get_cmd_code(void *frame)
622{ 672{
623 struct pn533_std_frame *f = frame; 673 struct pn533_std_frame *f = frame;
674 struct pn533_ext_frame *eif = frame;
624 675
625 return PN533_STD_FRAME_CMD(f); 676 if (PN533_STD_IS_EXTENDED(f))
677 return PN533_FRAME_CMD(eif);
678 else
679 return PN533_FRAME_CMD(f);
626} 680}
627 681
628static struct pn533_frame_ops pn533_std_frame_ops = { 682static struct pn533_frame_ops pn533_std_frame_ops = {
@@ -690,6 +744,11 @@ static void pn533_recv_response(struct urb *urb)
690 goto sched_wq; 744 goto sched_wq;
691 } 745 }
692 746
747 if (PN533_STD_IS_EXTENDED((struct pn533_std_frame *)in_frame))
748 dev->ops->rx_header_len = PN533_EXT_FRAME_HEADER_LEN;
749 else
750 dev->ops->rx_header_len = PN533_STD_FRAME_HEADER_LEN;
751
693sched_wq: 752sched_wq:
694 queue_work(dev->wq, &dev->cmd_complete_work); 753 queue_work(dev->wq, &dev->cmd_complete_work);
695} 754}