aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/digital_dep.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/digital_dep.c')
-rw-r--r--net/nfc/digital_dep.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index e1638dab076d..b60aa35c074f 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -33,6 +33,8 @@
33#define DIGITAL_ATR_REQ_MAX_SIZE 64 33#define DIGITAL_ATR_REQ_MAX_SIZE 64
34 34
35#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30 35#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
36#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
37 (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
36#define DIGITAL_GB_BIT 0x02 38#define DIGITAL_GB_BIT 0x02
37 39
38#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) 40#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
@@ -127,6 +129,98 @@ static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
127 return 0; 129 return 0;
128} 130}
129 131
132static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
133 struct sk_buff *resp)
134{
135 struct nfc_target *target = arg;
136 struct digital_psl_res *psl_res;
137 int rc;
138
139 if (IS_ERR(resp)) {
140 rc = PTR_ERR(resp);
141 resp = NULL;
142 goto exit;
143 }
144
145 rc = ddev->skb_check_crc(resp);
146 if (rc) {
147 PROTOCOL_ERR("14.4.1.6");
148 goto exit;
149 }
150
151 rc = digital_skb_pull_dep_sod(ddev, resp);
152 if (rc) {
153 PROTOCOL_ERR("14.4.1.2");
154 goto exit;
155 }
156
157 psl_res = (struct digital_psl_res *)resp->data;
158
159 if ((resp->len != sizeof(*psl_res)) ||
160 (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
161 (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
162 rc = -EIO;
163 goto exit;
164 }
165
166 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
167 NFC_DIGITAL_RF_TECH_424F);
168 if (rc)
169 goto exit;
170
171 rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
172 NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
173 if (rc)
174 goto exit;
175
176 if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
177 (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
178 ddev->skb_add_crc = digital_skb_add_crc_f;
179 ddev->skb_check_crc = digital_skb_check_crc_f;
180 }
181
182 ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
183
184 nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
185 NFC_RF_INITIATOR);
186
187 ddev->curr_nfc_dep_pni = 0;
188
189exit:
190 dev_kfree_skb(resp);
191
192 if (rc)
193 ddev->curr_protocol = 0;
194}
195
196static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
197 struct nfc_target *target)
198{
199 struct sk_buff *skb;
200 struct digital_psl_req *psl_req;
201
202 skb = digital_skb_alloc(ddev, sizeof(*psl_req));
203 if (!skb)
204 return -ENOMEM;
205
206 skb_put(skb, sizeof(*psl_req));
207
208 psl_req = (struct digital_psl_req *)skb->data;
209
210 psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
211 psl_req->cmd = DIGITAL_CMD_PSL_REQ;
212 psl_req->did = 0;
213 psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
214 psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
215
216 digital_skb_push_dep_sod(ddev, skb);
217
218 ddev->skb_add_crc(skb);
219
220 return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
221 target);
222}
223
130static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, 224static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
131 struct sk_buff *resp) 225 struct sk_buff *resp)
132{ 226{
@@ -166,6 +260,13 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
166 if (rc) 260 if (rc)
167 goto exit; 261 goto exit;
168 262
263 if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
264 (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
265 rc = digital_in_send_psl_req(ddev, target);
266 if (!rc)
267 goto exit;
268 }
269
169 rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE, 270 rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
170 NFC_RF_INITIATOR); 271 NFC_RF_INITIATOR);
171 272