diff options
Diffstat (limited to 'net/nfc/digital_dep.c')
-rw-r--r-- | net/nfc/digital_dep.c | 101 |
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 | ||
132 | static 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 | |||
189 | exit: | ||
190 | dev_kfree_skb(resp); | ||
191 | |||
192 | if (rc) | ||
193 | ddev->curr_protocol = 0; | ||
194 | } | ||
195 | |||
196 | static 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 | |||
130 | static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, | 224 | static 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 | ||