diff options
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/digital.h | 1 | ||||
-rw-r--r-- | net/nfc/digital_core.c | 20 | ||||
-rw-r--r-- | net/nfc/digital_technology.c | 214 |
3 files changed, 233 insertions, 2 deletions
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 3759add68b1b..71ad7eefddd4 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
@@ -71,6 +71,7 @@ static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev, | |||
71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); | 71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); |
72 | 72 | ||
73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
74 | int digital_in_send_sensb_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 75 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
75 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 76 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
76 | 77 | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index e01e15dbf1ab..b105cfb00e76 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ | 22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ |
23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) | 23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) |
24 | 24 | ||
25 | #define DIGITAL_PROTO_NFCB_RF_TECH NFC_PROTO_ISO14443_B_MASK | ||
26 | |||
25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | 27 | #define DIGITAL_PROTO_NFCF_RF_TECH \ |
26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | 28 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) |
27 | 29 | ||
@@ -345,6 +347,12 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
345 | add_crc = digital_skb_add_crc_a; | 347 | add_crc = digital_skb_add_crc_a; |
346 | break; | 348 | break; |
347 | 349 | ||
350 | case NFC_PROTO_ISO14443_B: | ||
351 | framing = NFC_DIGITAL_FRAMING_NFCB_T4T; | ||
352 | check_crc = digital_skb_check_crc_b; | ||
353 | add_crc = digital_skb_add_crc_b; | ||
354 | break; | ||
355 | |||
348 | default: | 356 | default: |
349 | pr_err("Invalid protocol %d\n", protocol); | 357 | pr_err("Invalid protocol %d\n", protocol); |
350 | return -EINVAL; | 358 | return -EINVAL; |
@@ -475,6 +483,10 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
475 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 483 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
476 | digital_in_send_sens_req); | 484 | digital_in_send_sens_req); |
477 | 485 | ||
486 | if (matching_im_protocols & DIGITAL_PROTO_NFCB_RF_TECH) | ||
487 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106B, | ||
488 | digital_in_send_sensb_req); | ||
489 | |||
478 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | 490 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { |
479 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | 491 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, |
480 | digital_in_send_sensf_req); | 492 | digital_in_send_sensf_req); |
@@ -635,7 +647,8 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | |||
635 | goto done; | 647 | goto done; |
636 | } | 648 | } |
637 | 649 | ||
638 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | 650 | if ((ddev->curr_protocol == NFC_PROTO_ISO14443) || |
651 | (ddev->curr_protocol == NFC_PROTO_ISO14443_B)) { | ||
639 | rc = digital_in_iso_dep_pull_sod(ddev, resp); | 652 | rc = digital_in_iso_dep_pull_sod(ddev, resp); |
640 | if (rc) | 653 | if (rc) |
641 | goto done; | 654 | goto done; |
@@ -676,7 +689,8 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
676 | goto exit; | 689 | goto exit; |
677 | } | 690 | } |
678 | 691 | ||
679 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | 692 | if ((ddev->curr_protocol == NFC_PROTO_ISO14443) || |
693 | (ddev->curr_protocol == NFC_PROTO_ISO14443_B)) { | ||
680 | rc = digital_in_iso_dep_push_sod(ddev, skb); | 694 | rc = digital_in_iso_dep_push_sod(ddev, skb); |
681 | if (rc) | 695 | if (rc) |
682 | goto exit; | 696 | goto exit; |
@@ -747,6 +761,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
747 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; | 761 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; |
748 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) | 762 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) |
749 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; | 763 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; |
764 | if (supported_protocols & NFC_PROTO_ISO14443_B_MASK) | ||
765 | ddev->protocols |= NFC_PROTO_ISO14443_B_MASK; | ||
750 | 766 | ||
751 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | 767 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; |
752 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | 768 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 278c3fed27e0..88e946adb7bf 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
@@ -41,6 +41,24 @@ | |||
41 | #define DIGITAL_MIFARE_READ_RES_LEN 16 | 41 | #define DIGITAL_MIFARE_READ_RES_LEN 16 |
42 | #define DIGITAL_MIFARE_ACK_RES 0x0A | 42 | #define DIGITAL_MIFARE_ACK_RES 0x0A |
43 | 43 | ||
44 | #define DIGITAL_CMD_SENSB_REQ 0x05 | ||
45 | #define DIGITAL_SENSB_ADVANCED BIT(5) | ||
46 | #define DIGITAL_SENSB_EXTENDED BIT(4) | ||
47 | #define DIGITAL_SENSB_ALLB_REQ BIT(3) | ||
48 | #define DIGITAL_SENSB_N(n) ((n) & 0x7) | ||
49 | |||
50 | #define DIGITAL_CMD_SENSB_RES 0x50 | ||
51 | |||
52 | #define DIGITAL_CMD_ATTRIB_REQ 0x1D | ||
53 | #define DIGITAL_ATTRIB_P1_TR0_DEFAULT (0x0 << 6) | ||
54 | #define DIGITAL_ATTRIB_P1_TR1_DEFAULT (0x0 << 4) | ||
55 | #define DIGITAL_ATTRIB_P1_SUPRESS_EOS BIT(3) | ||
56 | #define DIGITAL_ATTRIB_P1_SUPRESS_SOS BIT(2) | ||
57 | #define DIGITAL_ATTRIB_P2_LISTEN_POLL_1 (0x0 << 6) | ||
58 | #define DIGITAL_ATTRIB_P2_POLL_LISTEN_1 (0x0 << 4) | ||
59 | #define DIGITAL_ATTRIB_P2_MAX_FRAME_256 0x8 | ||
60 | #define DIGITAL_ATTRIB_P4_DID(n) ((n) & 0xf) | ||
61 | |||
44 | #define DIGITAL_CMD_SENSF_REQ 0x00 | 62 | #define DIGITAL_CMD_SENSF_REQ 0x00 |
45 | #define DIGITAL_CMD_SENSF_RES 0x01 | 63 | #define DIGITAL_CMD_SENSF_RES 0x01 |
46 | 64 | ||
@@ -75,6 +93,7 @@ static const u8 digital_ats_fsc[] = { | |||
75 | }; | 93 | }; |
76 | 94 | ||
77 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) | 95 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) |
96 | #define DIGITAL_SENSB_FSCI(pi2) (((pi2) & 0xF0) >> 4) | ||
78 | #define DIGITAL_ATS_MAX_FSC 256 | 97 | #define DIGITAL_ATS_MAX_FSC 256 |
79 | 98 | ||
80 | #define DIGITAL_RATS_BYTE1 0xE0 | 99 | #define DIGITAL_RATS_BYTE1 0xE0 |
@@ -92,6 +111,32 @@ struct digital_sel_req { | |||
92 | u8 bcc; | 111 | u8 bcc; |
93 | } __packed; | 112 | } __packed; |
94 | 113 | ||
114 | struct digital_sensb_req { | ||
115 | u8 cmd; | ||
116 | u8 afi; | ||
117 | u8 param; | ||
118 | } __packed; | ||
119 | |||
120 | struct digital_sensb_res { | ||
121 | u8 cmd; | ||
122 | u8 nfcid0[4]; | ||
123 | u8 app_data[4]; | ||
124 | u8 proto_info[3]; | ||
125 | } __packed; | ||
126 | |||
127 | struct digital_attrib_req { | ||
128 | u8 cmd; | ||
129 | u8 nfcid0[4]; | ||
130 | u8 param1; | ||
131 | u8 param2; | ||
132 | u8 param3; | ||
133 | u8 param4; | ||
134 | } __packed; | ||
135 | |||
136 | struct digital_attrib_res { | ||
137 | u8 mbli_did; | ||
138 | } __packed; | ||
139 | |||
95 | struct digital_sensf_req { | 140 | struct digital_sensf_req { |
96 | u8 cmd; | 141 | u8 cmd; |
97 | u8 sc1; | 142 | u8 sc1; |
@@ -531,6 +576,175 @@ int digital_in_recv_mifare_res(struct sk_buff *resp) | |||
531 | return -EIO; | 576 | return -EIO; |
532 | } | 577 | } |
533 | 578 | ||
579 | static void digital_in_recv_attrib_res(struct nfc_digital_dev *ddev, void *arg, | ||
580 | struct sk_buff *resp) | ||
581 | { | ||
582 | struct nfc_target *target = arg; | ||
583 | struct digital_attrib_res *attrib_res; | ||
584 | int rc; | ||
585 | |||
586 | if (IS_ERR(resp)) { | ||
587 | rc = PTR_ERR(resp); | ||
588 | resp = NULL; | ||
589 | goto exit; | ||
590 | } | ||
591 | |||
592 | if (resp->len < sizeof(*attrib_res)) { | ||
593 | PROTOCOL_ERR("12.6.2"); | ||
594 | rc = -EIO; | ||
595 | goto exit; | ||
596 | } | ||
597 | |||
598 | attrib_res = (struct digital_attrib_res *)resp->data; | ||
599 | |||
600 | if (attrib_res->mbli_did & 0x0f) { | ||
601 | PROTOCOL_ERR("12.6.2.1"); | ||
602 | rc = -EIO; | ||
603 | goto exit; | ||
604 | } | ||
605 | |||
606 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443_B); | ||
607 | |||
608 | exit: | ||
609 | dev_kfree_skb(resp); | ||
610 | kfree(target); | ||
611 | |||
612 | if (rc) | ||
613 | digital_poll_next_tech(ddev); | ||
614 | } | ||
615 | |||
616 | int digital_in_send_attrib_req(struct nfc_digital_dev *ddev, | ||
617 | struct nfc_target *target, | ||
618 | struct digital_sensb_res *sensb_res) | ||
619 | { | ||
620 | struct digital_attrib_req *attrib_req; | ||
621 | struct sk_buff *skb; | ||
622 | int rc; | ||
623 | |||
624 | skb = digital_skb_alloc(ddev, sizeof(*attrib_req)); | ||
625 | if (!skb) | ||
626 | return -ENOMEM; | ||
627 | |||
628 | attrib_req = (struct digital_attrib_req *)skb_put(skb, | ||
629 | sizeof(*attrib_req)); | ||
630 | |||
631 | attrib_req->cmd = DIGITAL_CMD_ATTRIB_REQ; | ||
632 | memcpy(attrib_req->nfcid0, sensb_res->nfcid0, | ||
633 | sizeof(attrib_req->nfcid0)); | ||
634 | attrib_req->param1 = DIGITAL_ATTRIB_P1_TR0_DEFAULT | | ||
635 | DIGITAL_ATTRIB_P1_TR1_DEFAULT; | ||
636 | attrib_req->param2 = DIGITAL_ATTRIB_P2_LISTEN_POLL_1 | | ||
637 | DIGITAL_ATTRIB_P2_POLL_LISTEN_1 | | ||
638 | DIGITAL_ATTRIB_P2_MAX_FRAME_256; | ||
639 | attrib_req->param3 = sensb_res->proto_info[1] & 0x07; | ||
640 | attrib_req->param4 = DIGITAL_ATTRIB_P4_DID(0); | ||
641 | |||
642 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_attrib_res, | ||
643 | target); | ||
644 | if (rc) | ||
645 | kfree_skb(skb); | ||
646 | |||
647 | return rc; | ||
648 | } | ||
649 | |||
650 | static void digital_in_recv_sensb_res(struct nfc_digital_dev *ddev, void *arg, | ||
651 | struct sk_buff *resp) | ||
652 | { | ||
653 | struct nfc_target *target = NULL; | ||
654 | struct digital_sensb_res *sensb_res; | ||
655 | u8 fsci; | ||
656 | int rc; | ||
657 | |||
658 | if (IS_ERR(resp)) { | ||
659 | rc = PTR_ERR(resp); | ||
660 | resp = NULL; | ||
661 | goto exit; | ||
662 | } | ||
663 | |||
664 | if (resp->len != sizeof(*sensb_res)) { | ||
665 | PROTOCOL_ERR("5.6.2.1"); | ||
666 | rc = -EIO; | ||
667 | goto exit; | ||
668 | } | ||
669 | |||
670 | sensb_res = (struct digital_sensb_res *)resp->data; | ||
671 | |||
672 | if (sensb_res->cmd != DIGITAL_CMD_SENSB_RES) { | ||
673 | PROTOCOL_ERR("5.6.2"); | ||
674 | rc = -EIO; | ||
675 | goto exit; | ||
676 | } | ||
677 | |||
678 | if (!(sensb_res->proto_info[1] & BIT(0))) { | ||
679 | PROTOCOL_ERR("5.6.2.12"); | ||
680 | rc = -EIO; | ||
681 | goto exit; | ||
682 | } | ||
683 | |||
684 | if (sensb_res->proto_info[1] & BIT(3)) { | ||
685 | PROTOCOL_ERR("5.6.2.16"); | ||
686 | rc = -EIO; | ||
687 | goto exit; | ||
688 | } | ||
689 | |||
690 | fsci = DIGITAL_SENSB_FSCI(sensb_res->proto_info[1]); | ||
691 | if (fsci >= 8) | ||
692 | ddev->target_fsc = DIGITAL_ATS_MAX_FSC; | ||
693 | else | ||
694 | ddev->target_fsc = digital_ats_fsc[fsci]; | ||
695 | |||
696 | target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | ||
697 | if (!target) { | ||
698 | rc = -ENOMEM; | ||
699 | goto exit; | ||
700 | } | ||
701 | |||
702 | rc = digital_in_send_attrib_req(ddev, target, sensb_res); | ||
703 | |||
704 | exit: | ||
705 | dev_kfree_skb(resp); | ||
706 | |||
707 | if (rc) { | ||
708 | kfree(target); | ||
709 | digital_poll_next_tech(ddev); | ||
710 | } | ||
711 | } | ||
712 | |||
713 | int digital_in_send_sensb_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
714 | { | ||
715 | struct digital_sensb_req *sensb_req; | ||
716 | struct sk_buff *skb; | ||
717 | int rc; | ||
718 | |||
719 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
720 | NFC_DIGITAL_RF_TECH_106B); | ||
721 | if (rc) | ||
722 | return rc; | ||
723 | |||
724 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
725 | NFC_DIGITAL_FRAMING_NFCB); | ||
726 | if (rc) | ||
727 | return rc; | ||
728 | |||
729 | skb = digital_skb_alloc(ddev, sizeof(*sensb_req)); | ||
730 | if (!skb) | ||
731 | return -ENOMEM; | ||
732 | |||
733 | sensb_req = (struct digital_sensb_req *)skb_put(skb, | ||
734 | sizeof(*sensb_req)); | ||
735 | |||
736 | sensb_req->cmd = DIGITAL_CMD_SENSB_REQ; | ||
737 | sensb_req->afi = 0x00; /* All families and sub-families */ | ||
738 | sensb_req->param = DIGITAL_SENSB_N(0); | ||
739 | |||
740 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensb_res, | ||
741 | NULL); | ||
742 | if (rc) | ||
743 | kfree_skb(skb); | ||
744 | |||
745 | return rc; | ||
746 | } | ||
747 | |||
534 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, | 748 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, |
535 | struct sk_buff *resp) | 749 | struct sk_buff *resp) |
536 | { | 750 | { |