diff options
Diffstat (limited to 'net/nfc/digital_technology.c')
-rw-r--r-- | net/nfc/digital_technology.c | 230 |
1 files changed, 228 insertions, 2 deletions
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 278c3fed27e0..c2c1c0189b7c 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 | static 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 | { |
@@ -877,6 +1091,18 @@ exit: | |||
877 | dev_kfree_skb(resp); | 1091 | dev_kfree_skb(resp); |
878 | } | 1092 | } |
879 | 1093 | ||
1094 | static void digital_tg_recv_atr_or_sensf_req(struct nfc_digital_dev *ddev, | ||
1095 | void *arg, struct sk_buff *resp) | ||
1096 | { | ||
1097 | if (!IS_ERR(resp) && (resp->len >= 2) && | ||
1098 | (resp->data[1] == DIGITAL_CMD_SENSF_REQ)) | ||
1099 | digital_tg_recv_sensf_req(ddev, arg, resp); | ||
1100 | else | ||
1101 | digital_tg_recv_atr_req(ddev, arg, resp); | ||
1102 | |||
1103 | return; | ||
1104 | } | ||
1105 | |||
880 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | 1106 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, |
881 | struct digital_sensf_req *sensf_req) | 1107 | struct digital_sensf_req *sensf_req) |
882 | { | 1108 | { |
@@ -887,7 +1113,7 @@ static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | |||
887 | 1113 | ||
888 | size = sizeof(struct digital_sensf_res); | 1114 | size = sizeof(struct digital_sensf_res); |
889 | 1115 | ||
890 | if (sensf_req->rc != DIGITAL_SENSF_REQ_RC_NONE) | 1116 | if (sensf_req->rc == DIGITAL_SENSF_REQ_RC_NONE) |
891 | size -= sizeof(sensf_res->rd); | 1117 | size -= sizeof(sensf_res->rd); |
892 | 1118 | ||
893 | skb = digital_skb_alloc(ddev, size); | 1119 | skb = digital_skb_alloc(ddev, size); |
@@ -922,7 +1148,7 @@ static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | |||
922 | digital_skb_add_crc_f(skb); | 1148 | digital_skb_add_crc_f(skb); |
923 | 1149 | ||
924 | rc = digital_tg_send_cmd(ddev, skb, 300, | 1150 | rc = digital_tg_send_cmd(ddev, skb, 300, |
925 | digital_tg_recv_atr_req, NULL); | 1151 | digital_tg_recv_atr_or_sensf_req, NULL); |
926 | if (rc) | 1152 | if (rc) |
927 | kfree_skb(skb); | 1153 | kfree_skb(skb); |
928 | 1154 | ||