Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/nfc/nci/rsp.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* The NFC Controller Interface is the communication protocol between an
4
* NFC Controller (NFCC) and a Device Host (DH).
5
*
6
* Copyright (C) 2011 Texas Instruments, Inc.
7
*
8
* Written by Ilan Elias <[email protected]>
9
*
10
* Acknowledgements:
11
* This file is based on hci_event.c, which was written
12
* by Maxim Krasnyansky.
13
*/
14
15
#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
16
17
#include <linux/types.h>
18
#include <linux/interrupt.h>
19
#include <linux/bitops.h>
20
#include <linux/skbuff.h>
21
22
#include "../nfc.h"
23
#include <net/nfc/nci.h>
24
#include <net/nfc/nci_core.h>
25
26
/* Handle NCI Response packets */
27
28
static void nci_core_reset_rsp_packet(struct nci_dev *ndev,
29
const struct sk_buff *skb)
30
{
31
const struct nci_core_reset_rsp *rsp = (void *)skb->data;
32
33
pr_debug("status 0x%x\n", rsp->status);
34
35
/* Handle NCI 1.x ver */
36
if (skb->len != 1) {
37
if (rsp->status == NCI_STATUS_OK) {
38
ndev->nci_ver = rsp->nci_ver;
39
pr_debug("nci_ver 0x%x, config_status 0x%x\n",
40
rsp->nci_ver, rsp->config_status);
41
}
42
43
nci_req_complete(ndev, rsp->status);
44
}
45
}
46
47
static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
48
const struct sk_buff *skb)
49
{
50
const struct nci_core_init_rsp_1 *rsp_1 = (void *)skb->data;
51
const struct nci_core_init_rsp_2 *rsp_2;
52
53
pr_debug("status 0x%x\n", rsp_1->status);
54
55
if (rsp_1->status != NCI_STATUS_OK)
56
return rsp_1->status;
57
58
ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
59
ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
60
61
ndev->num_supported_rf_interfaces =
62
min((int)ndev->num_supported_rf_interfaces,
63
NCI_MAX_SUPPORTED_RF_INTERFACES);
64
65
memcpy(ndev->supported_rf_interfaces,
66
rsp_1->supported_rf_interfaces,
67
ndev->num_supported_rf_interfaces);
68
69
rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces);
70
71
ndev->max_logical_connections = rsp_2->max_logical_connections;
72
ndev->max_routing_table_size =
73
__le16_to_cpu(rsp_2->max_routing_table_size);
74
ndev->max_ctrl_pkt_payload_len =
75
rsp_2->max_ctrl_pkt_payload_len;
76
ndev->max_size_for_large_params =
77
__le16_to_cpu(rsp_2->max_size_for_large_params);
78
ndev->manufact_id =
79
rsp_2->manufact_id;
80
ndev->manufact_specific_info =
81
__le32_to_cpu(rsp_2->manufact_specific_info);
82
83
return NCI_STATUS_OK;
84
}
85
86
static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
87
const struct sk_buff *skb)
88
{
89
const struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
90
const u8 *supported_rf_interface = rsp->supported_rf_interfaces;
91
u8 rf_interface_idx = 0;
92
u8 rf_extension_cnt = 0;
93
94
pr_debug("status %x\n", rsp->status);
95
96
if (rsp->status != NCI_STATUS_OK)
97
return rsp->status;
98
99
ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
100
ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
101
102
ndev->num_supported_rf_interfaces =
103
min((int)ndev->num_supported_rf_interfaces,
104
NCI_MAX_SUPPORTED_RF_INTERFACES);
105
106
while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
107
ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
108
109
/* skip rf extension parameters */
110
rf_extension_cnt = *supported_rf_interface++;
111
supported_rf_interface += rf_extension_cnt;
112
}
113
114
ndev->max_logical_connections = rsp->max_logical_connections;
115
ndev->max_routing_table_size =
116
__le16_to_cpu(rsp->max_routing_table_size);
117
ndev->max_ctrl_pkt_payload_len =
118
rsp->max_ctrl_pkt_payload_len;
119
ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
120
121
return NCI_STATUS_OK;
122
}
123
124
static void nci_core_init_rsp_packet(struct nci_dev *ndev, const struct sk_buff *skb)
125
{
126
u8 status = 0;
127
128
if (!(ndev->nci_ver & NCI_VER_2_MASK))
129
status = nci_core_init_rsp_packet_v1(ndev, skb);
130
else
131
status = nci_core_init_rsp_packet_v2(ndev, skb);
132
133
if (status != NCI_STATUS_OK)
134
goto exit;
135
136
pr_debug("nfcc_features 0x%x\n",
137
ndev->nfcc_features);
138
pr_debug("num_supported_rf_interfaces %d\n",
139
ndev->num_supported_rf_interfaces);
140
pr_debug("supported_rf_interfaces[0] 0x%x\n",
141
ndev->supported_rf_interfaces[0]);
142
pr_debug("supported_rf_interfaces[1] 0x%x\n",
143
ndev->supported_rf_interfaces[1]);
144
pr_debug("supported_rf_interfaces[2] 0x%x\n",
145
ndev->supported_rf_interfaces[2]);
146
pr_debug("supported_rf_interfaces[3] 0x%x\n",
147
ndev->supported_rf_interfaces[3]);
148
pr_debug("max_logical_connections %d\n",
149
ndev->max_logical_connections);
150
pr_debug("max_routing_table_size %d\n",
151
ndev->max_routing_table_size);
152
pr_debug("max_ctrl_pkt_payload_len %d\n",
153
ndev->max_ctrl_pkt_payload_len);
154
pr_debug("max_size_for_large_params %d\n",
155
ndev->max_size_for_large_params);
156
pr_debug("manufact_id 0x%x\n",
157
ndev->manufact_id);
158
pr_debug("manufact_specific_info 0x%x\n",
159
ndev->manufact_specific_info);
160
161
exit:
162
nci_req_complete(ndev, status);
163
}
164
165
static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
166
const struct sk_buff *skb)
167
{
168
const struct nci_core_set_config_rsp *rsp = (void *)skb->data;
169
170
pr_debug("status 0x%x\n", rsp->status);
171
172
nci_req_complete(ndev, rsp->status);
173
}
174
175
static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
176
const struct sk_buff *skb)
177
{
178
__u8 status = skb->data[0];
179
180
pr_debug("status 0x%x\n", status);
181
182
nci_req_complete(ndev, status);
183
}
184
185
static void nci_rf_disc_rsp_packet(struct nci_dev *ndev,
186
const struct sk_buff *skb)
187
{
188
struct nci_conn_info *conn_info;
189
__u8 status = skb->data[0];
190
191
pr_debug("status 0x%x\n", status);
192
193
if (status == NCI_STATUS_OK) {
194
atomic_set(&ndev->state, NCI_DISCOVERY);
195
196
conn_info = ndev->rf_conn_info;
197
if (!conn_info) {
198
conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
199
sizeof(struct nci_conn_info),
200
GFP_KERNEL);
201
if (!conn_info) {
202
status = NCI_STATUS_REJECTED;
203
goto exit;
204
}
205
conn_info->conn_id = NCI_STATIC_RF_CONN_ID;
206
INIT_LIST_HEAD(&conn_info->list);
207
list_add(&conn_info->list, &ndev->conn_info_list);
208
ndev->rf_conn_info = conn_info;
209
}
210
}
211
212
exit:
213
nci_req_complete(ndev, status);
214
}
215
216
static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
217
const struct sk_buff *skb)
218
{
219
__u8 status = skb->data[0];
220
221
pr_debug("status 0x%x\n", status);
222
223
/* Complete the request on intf_activated_ntf or generic_error_ntf */
224
if (status != NCI_STATUS_OK)
225
nci_req_complete(ndev, status);
226
}
227
228
static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
229
const struct sk_buff *skb)
230
{
231
__u8 status = skb->data[0];
232
233
pr_debug("status 0x%x\n", status);
234
235
/* If target was active, complete the request only in deactivate_ntf */
236
if ((status != NCI_STATUS_OK) ||
237
(atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
238
nci_clear_target_list(ndev);
239
atomic_set(&ndev->state, NCI_IDLE);
240
nci_req_complete(ndev, status);
241
}
242
}
243
244
static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
245
const struct sk_buff *skb)
246
{
247
const struct nci_nfcee_discover_rsp *discover_rsp;
248
249
if (skb->len != 2) {
250
nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR);
251
return;
252
}
253
254
discover_rsp = (struct nci_nfcee_discover_rsp *)skb->data;
255
256
if (discover_rsp->status != NCI_STATUS_OK ||
257
discover_rsp->num_nfcee == 0)
258
nci_req_complete(ndev, discover_rsp->status);
259
}
260
261
static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
262
const struct sk_buff *skb)
263
{
264
__u8 status = skb->data[0];
265
266
pr_debug("status 0x%x\n", status);
267
nci_req_complete(ndev, status);
268
}
269
270
static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
271
const struct sk_buff *skb)
272
{
273
__u8 status = skb->data[0];
274
struct nci_conn_info *conn_info = NULL;
275
const struct nci_core_conn_create_rsp *rsp;
276
277
pr_debug("status 0x%x\n", status);
278
279
if (status == NCI_STATUS_OK) {
280
rsp = (struct nci_core_conn_create_rsp *)skb->data;
281
282
conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
283
sizeof(*conn_info), GFP_KERNEL);
284
if (!conn_info) {
285
status = NCI_STATUS_REJECTED;
286
goto exit;
287
}
288
289
conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev,
290
sizeof(struct dest_spec_params),
291
GFP_KERNEL);
292
if (!conn_info->dest_params) {
293
status = NCI_STATUS_REJECTED;
294
goto free_conn_info;
295
}
296
297
conn_info->dest_type = ndev->cur_dest_type;
298
conn_info->dest_params->id = ndev->cur_params.id;
299
conn_info->dest_params->protocol = ndev->cur_params.protocol;
300
conn_info->conn_id = rsp->conn_id;
301
302
/* Note: data_exchange_cb and data_exchange_cb_context need to
303
* be specify out of nci_core_conn_create_rsp_packet
304
*/
305
306
INIT_LIST_HEAD(&conn_info->list);
307
list_add(&conn_info->list, &ndev->conn_info_list);
308
309
if (ndev->cur_params.id == ndev->hci_dev->nfcee_id)
310
ndev->hci_dev->conn_info = conn_info;
311
312
conn_info->conn_id = rsp->conn_id;
313
conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len;
314
atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
315
}
316
317
free_conn_info:
318
if (status == NCI_STATUS_REJECTED)
319
devm_kfree(&ndev->nfc_dev->dev, conn_info);
320
exit:
321
322
nci_req_complete(ndev, status);
323
}
324
325
static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
326
const struct sk_buff *skb)
327
{
328
struct nci_conn_info *conn_info;
329
__u8 status = skb->data[0];
330
331
pr_debug("status 0x%x\n", status);
332
if (status == NCI_STATUS_OK) {
333
conn_info = nci_get_conn_info_by_conn_id(ndev,
334
ndev->cur_conn_id);
335
if (conn_info) {
336
list_del(&conn_info->list);
337
if (conn_info == ndev->rf_conn_info)
338
ndev->rf_conn_info = NULL;
339
devm_kfree(&ndev->nfc_dev->dev, conn_info);
340
}
341
}
342
nci_req_complete(ndev, status);
343
}
344
345
void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
346
{
347
__u16 rsp_opcode = nci_opcode(skb->data);
348
349
/* we got a rsp, stop the cmd timer */
350
timer_delete(&ndev->cmd_timer);
351
352
pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
353
nci_pbf(skb->data),
354
nci_opcode_gid(rsp_opcode),
355
nci_opcode_oid(rsp_opcode),
356
nci_plen(skb->data));
357
358
/* strip the nci control header */
359
skb_pull(skb, NCI_CTRL_HDR_SIZE);
360
361
if (nci_opcode_gid(rsp_opcode) == NCI_GID_PROPRIETARY) {
362
if (nci_prop_rsp_packet(ndev, rsp_opcode, skb) == -ENOTSUPP) {
363
pr_err("unsupported rsp opcode 0x%x\n",
364
rsp_opcode);
365
}
366
367
goto end;
368
}
369
370
switch (rsp_opcode) {
371
case NCI_OP_CORE_RESET_RSP:
372
nci_core_reset_rsp_packet(ndev, skb);
373
break;
374
375
case NCI_OP_CORE_INIT_RSP:
376
nci_core_init_rsp_packet(ndev, skb);
377
break;
378
379
case NCI_OP_CORE_SET_CONFIG_RSP:
380
nci_core_set_config_rsp_packet(ndev, skb);
381
break;
382
383
case NCI_OP_CORE_CONN_CREATE_RSP:
384
nci_core_conn_create_rsp_packet(ndev, skb);
385
break;
386
387
case NCI_OP_CORE_CONN_CLOSE_RSP:
388
nci_core_conn_close_rsp_packet(ndev, skb);
389
break;
390
391
case NCI_OP_RF_DISCOVER_MAP_RSP:
392
nci_rf_disc_map_rsp_packet(ndev, skb);
393
break;
394
395
case NCI_OP_RF_DISCOVER_RSP:
396
nci_rf_disc_rsp_packet(ndev, skb);
397
break;
398
399
case NCI_OP_RF_DISCOVER_SELECT_RSP:
400
nci_rf_disc_select_rsp_packet(ndev, skb);
401
break;
402
403
case NCI_OP_RF_DEACTIVATE_RSP:
404
nci_rf_deactivate_rsp_packet(ndev, skb);
405
break;
406
407
case NCI_OP_NFCEE_DISCOVER_RSP:
408
nci_nfcee_discover_rsp_packet(ndev, skb);
409
break;
410
411
case NCI_OP_NFCEE_MODE_SET_RSP:
412
nci_nfcee_mode_set_rsp_packet(ndev, skb);
413
break;
414
415
default:
416
pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
417
break;
418
}
419
420
nci_core_rsp_packet(ndev, rsp_opcode, skb);
421
end:
422
kfree_skb(skb);
423
424
/* trigger the next cmd */
425
atomic_set(&ndev->cmd_cnt, 1);
426
if (!skb_queue_empty(&ndev->cmd_q))
427
queue_work(ndev->cmd_wq, &ndev->cmd_work);
428
}
429
430