aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/digital_technology.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/digital_technology.c')
-rw-r--r--net/nfc/digital_technology.c247
1 files changed, 245 insertions, 2 deletions
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index 251c8c753ebe..278c3fed27e0 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -30,6 +30,7 @@
30 30
31#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) 31#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
32#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) 32#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
33#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
33#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) 34#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
34 35
35#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) 36#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
@@ -51,6 +52,34 @@
51#define DIGITAL_SENSF_REQ_RC_SC 1 52#define DIGITAL_SENSF_REQ_RC_SC 1
52#define DIGITAL_SENSF_REQ_RC_AP 2 53#define DIGITAL_SENSF_REQ_RC_AP 2
53 54
55#define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01
56
57#define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1)
58#define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2)
59#define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5)
60#define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0)
61#define DIGITAL_ISO15693_RES_IS_VALID(flags) \
62 (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
63
64#define DIGITAL_ISO_DEP_I_PCB 0x02
65#define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01)
66
67#define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0)
68
69#define DIGITAL_ISO_DEP_I_BLOCK 0x00
70
71#define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08)
72
73static const u8 digital_ats_fsc[] = {
74 16, 24, 32, 40, 48, 64, 96, 128,
75};
76
77#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
78#define DIGITAL_ATS_MAX_FSC 256
79
80#define DIGITAL_RATS_BYTE1 0xE0
81#define DIGITAL_RATS_PARAM 0x80
82
54struct digital_sdd_res { 83struct digital_sdd_res {
55 u8 nfcid1[4]; 84 u8 nfcid1[4];
56 u8 bcc; 85 u8 bcc;
@@ -82,9 +111,127 @@ struct digital_sensf_res {
82 u8 rd[2]; 111 u8 rd[2];
83} __packed; 112} __packed;
84 113
114struct digital_iso15693_inv_req {
115 u8 flags;
116 u8 cmd;
117 u8 mask_len;
118 u64 mask;
119} __packed;
120
121struct digital_iso15693_inv_res {
122 u8 flags;
123 u8 dsfid;
124 u64 uid;
125} __packed;
126
85static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, 127static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
86 struct nfc_target *target); 128 struct nfc_target *target);
87 129
130int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
131 struct sk_buff *skb)
132{
133 u8 pcb;
134 u8 block_type;
135
136 if (skb->len < 1)
137 return -EIO;
138
139 pcb = *skb->data;
140 block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb);
141
142 /* No support fo R-block nor S-block */
143 if (block_type != DIGITAL_ISO_DEP_I_BLOCK) {
144 pr_err("ISO_DEP R-block and S-block not supported\n");
145 return -EIO;
146 }
147
148 if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) {
149 pr_err("DID field in ISO_DEP PCB not supported\n");
150 return -EIO;
151 }
152
153 skb_pull(skb, 1);
154
155 return 0;
156}
157
158int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
159 struct sk_buff *skb)
160{
161 /*
162 * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must
163 * not be greater than remote FSC
164 */
165 if (skb->len + 3 > ddev->target_fsc)
166 return -EIO;
167
168 skb_push(skb, 1);
169
170 *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni;
171
172 ddev->curr_nfc_dep_pni =
173 DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1);
174
175 return 0;
176}
177
178static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
179 struct sk_buff *resp)
180{
181 struct nfc_target *target = arg;
182 u8 fsdi;
183 int rc;
184
185 if (IS_ERR(resp)) {
186 rc = PTR_ERR(resp);
187 resp = NULL;
188 goto exit;
189 }
190
191 if (resp->len < 2) {
192 rc = -EIO;
193 goto exit;
194 }
195
196 fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
197 if (fsdi >= 8)
198 ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
199 else
200 ddev->target_fsc = digital_ats_fsc[fsdi];
201
202 ddev->curr_nfc_dep_pni = 0;
203
204 rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
205
206exit:
207 dev_kfree_skb(resp);
208 kfree(target);
209
210 if (rc)
211 digital_poll_next_tech(ddev);
212}
213
214static int digital_in_send_rats(struct nfc_digital_dev *ddev,
215 struct nfc_target *target)
216{
217 int rc;
218 struct sk_buff *skb;
219
220 skb = digital_skb_alloc(ddev, 2);
221 if (!skb)
222 return -ENOMEM;
223
224 *skb_put(skb, 1) = DIGITAL_RATS_BYTE1;
225 *skb_put(skb, 1) = DIGITAL_RATS_PARAM;
226
227 rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
228 target);
229 if (rc)
230 kfree_skb(skb);
231
232 return rc;
233}
234
88static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, 235static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
89 struct sk_buff *resp) 236 struct sk_buff *resp)
90{ 237{
@@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
122 goto exit_free_skb; 269 goto exit_free_skb;
123 } 270 }
124 271
272 target->sel_res = sel_res;
273
125 if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { 274 if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
126 nfc_proto = NFC_PROTO_MIFARE; 275 nfc_proto = NFC_PROTO_MIFARE;
276 } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
277 rc = digital_in_send_rats(ddev, target);
278 if (rc)
279 goto exit;
280 /*
281 * Skip target_found and don't free it for now. This will be
282 * done when receiving the ATS
283 */
284 goto exit_free_skb;
127 } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { 285 } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
128 nfc_proto = NFC_PROTO_NFC_DEP; 286 nfc_proto = NFC_PROTO_NFC_DEP;
129 } else { 287 } else {
@@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
131 goto exit; 289 goto exit;
132 } 290 }
133 291
134 target->sel_res = sel_res;
135
136 rc = digital_target_found(ddev, target, nfc_proto); 292 rc = digital_target_found(ddev, target, nfc_proto);
137 293
138exit: 294exit:
@@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech)
473 return rc; 629 return rc;
474} 630}
475 631
632static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev,
633 void *arg, struct sk_buff *resp)
634{
635 struct digital_iso15693_inv_res *res;
636 struct nfc_target *target = NULL;
637 int rc;
638
639 if (IS_ERR(resp)) {
640 rc = PTR_ERR(resp);
641 resp = NULL;
642 goto out_free_skb;
643 }
644
645 if (resp->len != sizeof(*res)) {
646 rc = -EIO;
647 goto out_free_skb;
648 }
649
650 res = (struct digital_iso15693_inv_res *)resp->data;
651
652 if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) {
653 PROTOCOL_ERR("ISO15693 - 10.3.1");
654 rc = -EINVAL;
655 goto out_free_skb;
656 }
657
658 target = kzalloc(sizeof(*target), GFP_KERNEL);
659 if (!target) {
660 rc = -ENOMEM;
661 goto out_free_skb;
662 }
663
664 target->is_iso15693 = 1;
665 target->iso15693_dsfid = res->dsfid;
666 memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid));
667
668 rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693);
669
670 kfree(target);
671
672out_free_skb:
673 dev_kfree_skb(resp);
674
675 if (rc)
676 digital_poll_next_tech(ddev);
677}
678
679int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech)
680{
681 struct digital_iso15693_inv_req *req;
682 struct sk_buff *skb;
683 int rc;
684
685 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
686 NFC_DIGITAL_RF_TECH_ISO15693);
687 if (rc)
688 return rc;
689
690 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
691 NFC_DIGITAL_FRAMING_ISO15693_INVENTORY);
692 if (rc)
693 return rc;
694
695 skb = digital_skb_alloc(ddev, sizeof(*req));
696 if (!skb)
697 return -ENOMEM;
698
699 skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */
700 req = (struct digital_iso15693_inv_req *)skb->data;
701
702 /* Single sub-carrier, high data rate, no AFI, single slot
703 * Inventory command
704 */
705 req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE |
706 DIGITAL_ISO15693_REQ_FLAG_INVENTORY |
707 DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS;
708 req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ;
709 req->mask_len = 0;
710
711 rc = digital_in_send_cmd(ddev, skb, 30,
712 digital_in_recv_iso15693_inv_res, NULL);
713 if (rc)
714 kfree_skb(skb);
715
716 return rc;
717}
718
476static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) 719static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev)
477{ 720{
478 struct sk_buff *skb; 721 struct sk_buff *skb;