NFC: nci: Add NCI_RESET return code check before setup
[deliverable/linux.git] / net / nfc / nci / core.c
CommitLineData
6a2968aa
IE
1/*
2 * The NFC Controller Interface is the communication protocol between an
3 * NFC Controller (NFCC) and a Device Host (DH).
4 *
5 * Copyright (C) 2011 Texas Instruments, Inc.
772dccf4 6 * Copyright (C) 2014 Marvell International Ltd.
6a2968aa
IE
7 *
8 * Written by Ilan Elias <ilane@ti.com>
9 *
10 * Acknowledgements:
11 * This file is based on hci_core.c, which was written
12 * by Maxim Krasnyansky.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
98b32dec 24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
6a2968aa
IE
25 *
26 */
27
52858b51 28#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
ed1e0ad8 29
8a70e7f8 30#include <linux/module.h>
b6355e97 31#include <linux/kernel.h>
6a2968aa
IE
32#include <linux/types.h>
33#include <linux/workqueue.h>
34#include <linux/completion.h>
bc3b2d7f 35#include <linux/export.h>
6a2968aa
IE
36#include <linux/sched.h>
37#include <linux/bitops.h>
38#include <linux/skbuff.h>
39
40#include "../nfc.h"
41#include <net/nfc/nci.h>
42#include <net/nfc/nci_core.h>
43#include <linux/nfc.h>
44
b16ae716
CR
45struct core_conn_create_data {
46 int length;
47 struct nci_core_conn_create_cmd *cmd;
48};
49
6a2968aa
IE
50static void nci_cmd_work(struct work_struct *work);
51static void nci_rx_work(struct work_struct *work);
52static void nci_tx_work(struct work_struct *work);
53
4aeee687
CR
54struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
55 int conn_id)
56{
57 struct nci_conn_info *conn_info;
58
59 list_for_each_entry(conn_info, &ndev->conn_info_list, list) {
60 if (conn_info->conn_id == conn_id)
61 return conn_info;
62 }
63
64 return NULL;
65}
66
6a2968aa
IE
67/* ---- NCI requests ---- */
68
69void nci_req_complete(struct nci_dev *ndev, int result)
70{
71 if (ndev->req_status == NCI_REQ_PEND) {
72 ndev->req_result = result;
73 ndev->req_status = NCI_REQ_DONE;
74 complete(&ndev->req_completion);
75 }
76}
77
78static void nci_req_cancel(struct nci_dev *ndev, int err)
79{
80 if (ndev->req_status == NCI_REQ_PEND) {
81 ndev->req_result = err;
82 ndev->req_status = NCI_REQ_CANCELED;
83 complete(&ndev->req_completion);
84 }
85}
86
87/* Execute request and wait for completion. */
88static int __nci_request(struct nci_dev *ndev,
eb9bc6e9
SO
89 void (*req)(struct nci_dev *ndev, unsigned long opt),
90 unsigned long opt, __u32 timeout)
6a2968aa
IE
91{
92 int rc = 0;
f8c141c3 93 long completion_rc;
6a2968aa
IE
94
95 ndev->req_status = NCI_REQ_PEND;
96
9bec44bf 97 reinit_completion(&ndev->req_completion);
6a2968aa 98 req(ndev, opt);
eb9bc6e9
SO
99 completion_rc =
100 wait_for_completion_interruptible_timeout(&ndev->req_completion,
101 timeout);
6a2968aa 102
20c239c1 103 pr_debug("wait_for_completion return %ld\n", completion_rc);
6a2968aa
IE
104
105 if (completion_rc > 0) {
106 switch (ndev->req_status) {
107 case NCI_REQ_DONE:
108 rc = nci_to_errno(ndev->req_result);
109 break;
110
111 case NCI_REQ_CANCELED:
112 rc = -ndev->req_result;
113 break;
114
115 default:
116 rc = -ETIMEDOUT;
117 break;
118 }
119 } else {
ed1e0ad8
JP
120 pr_err("wait_for_completion_interruptible_timeout failed %ld\n",
121 completion_rc);
6a2968aa
IE
122
123 rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc));
124 }
125
126 ndev->req_status = ndev->req_result = 0;
127
128 return rc;
129}
130
11f54f22
CR
131inline int nci_request(struct nci_dev *ndev,
132 void (*req)(struct nci_dev *ndev,
133 unsigned long opt),
134 unsigned long opt, __u32 timeout)
6a2968aa
IE
135{
136 int rc;
137
138 if (!test_bit(NCI_UP, &ndev->flags))
139 return -ENETDOWN;
140
141 /* Serialize all requests */
142 mutex_lock(&ndev->req_lock);
143 rc = __nci_request(ndev, req, opt, timeout);
144 mutex_unlock(&ndev->req_lock);
145
146 return rc;
147}
148
149static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
150{
e8c0dacd
IE
151 struct nci_core_reset_cmd cmd;
152
153 cmd.reset_type = NCI_RESET_TYPE_RESET_CONFIG;
154 nci_send_cmd(ndev, NCI_OP_CORE_RESET_CMD, 1, &cmd);
6a2968aa
IE
155}
156
157static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
158{
159 nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
160}
161
162static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
163{
2eb1dc10
IE
164 struct nci_rf_disc_map_cmd cmd;
165 struct disc_map_config *cfg = cmd.mapping_configs;
166 __u8 *num = &cmd.num_mapping_configs;
6a2968aa
IE
167 int i;
168
6a2968aa 169 /* set rf mapping configurations */
2eb1dc10 170 *num = 0;
6a2968aa
IE
171
172 /* by default mapping is set to NCI_RF_INTERFACE_FRAME */
173 for (i = 0; i < ndev->num_supported_rf_interfaces; i++) {
174 if (ndev->supported_rf_interfaces[i] ==
eb9bc6e9 175 NCI_RF_INTERFACE_ISO_DEP) {
2eb1dc10 176 cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
637d85a7
IE
177 cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
178 NCI_DISC_MAP_MODE_LISTEN;
179 cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP;
2eb1dc10 180 (*num)++;
6a2968aa 181 } else if (ndev->supported_rf_interfaces[i] ==
eb9bc6e9 182 NCI_RF_INTERFACE_NFC_DEP) {
2eb1dc10 183 cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
637d85a7
IE
184 cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
185 NCI_DISC_MAP_MODE_LISTEN;
186 cfg[*num].rf_interface = NCI_RF_INTERFACE_NFC_DEP;
2eb1dc10 187 (*num)++;
6a2968aa
IE
188 }
189
2eb1dc10 190 if (*num == NCI_MAX_NUM_MAPPING_CONFIGS)
6a2968aa
IE
191 break;
192 }
193
194 nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD,
eb9bc6e9 195 (1 + ((*num) * sizeof(struct disc_map_config))), &cmd);
6a2968aa
IE
196}
197
7e035230
IE
198struct nci_set_config_param {
199 __u8 id;
200 size_t len;
201 __u8 *val;
202};
203
204static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt)
205{
206 struct nci_set_config_param *param = (struct nci_set_config_param *)opt;
207 struct nci_core_set_config_cmd cmd;
208
209 BUG_ON(param->len > NCI_MAX_PARAM_LEN);
210
211 cmd.num_params = 1;
212 cmd.param.id = param->id;
213 cmd.param.len = param->len;
214 memcpy(cmd.param.val, param->val, param->len);
215
216 nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd);
217}
218
772dccf4
JL
219struct nci_rf_discover_param {
220 __u32 im_protocols;
221 __u32 tm_protocols;
222};
223
6a2968aa
IE
224static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
225{
772dccf4
JL
226 struct nci_rf_discover_param *param =
227 (struct nci_rf_discover_param *)opt;
6a2968aa 228 struct nci_rf_disc_cmd cmd;
6a2968aa
IE
229
230 cmd.num_disc_configs = 0;
231
232 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
772dccf4
JL
233 (param->im_protocols & NFC_PROTO_JEWEL_MASK ||
234 param->im_protocols & NFC_PROTO_MIFARE_MASK ||
235 param->im_protocols & NFC_PROTO_ISO14443_MASK ||
236 param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
637d85a7 237 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
eb9bc6e9 238 NCI_NFC_A_PASSIVE_POLL_MODE;
6a2968aa
IE
239 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
240 cmd.num_disc_configs++;
241 }
242
243 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
772dccf4 244 (param->im_protocols & NFC_PROTO_ISO14443_B_MASK)) {
637d85a7 245 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
eb9bc6e9 246 NCI_NFC_B_PASSIVE_POLL_MODE;
6a2968aa
IE
247 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
248 cmd.num_disc_configs++;
249 }
250
251 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
772dccf4
JL
252 (param->im_protocols & NFC_PROTO_FELICA_MASK ||
253 param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
637d85a7 254 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
eb9bc6e9 255 NCI_NFC_F_PASSIVE_POLL_MODE;
6a2968aa
IE
256 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
257 cmd.num_disc_configs++;
258 }
259
cfdbeeaf 260 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
772dccf4 261 (param->im_protocols & NFC_PROTO_ISO15693_MASK)) {
cfdbeeaf
VC
262 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
263 NCI_NFC_V_PASSIVE_POLL_MODE;
264 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
265 cmd.num_disc_configs++;
266 }
267
772dccf4
JL
268 if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS - 1) &&
269 (param->tm_protocols & NFC_PROTO_NFC_DEP_MASK)) {
270 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
271 NCI_NFC_A_PASSIVE_LISTEN_MODE;
272 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
273 cmd.num_disc_configs++;
274 cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
275 NCI_NFC_F_PASSIVE_LISTEN_MODE;
276 cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
277 cmd.num_disc_configs++;
278 }
279
6a2968aa 280 nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
eb9bc6e9
SO
281 (1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
282 &cmd);
6a2968aa
IE
283}
284
019c4fba
IE
285struct nci_rf_discover_select_param {
286 __u8 rf_discovery_id;
287 __u8 rf_protocol;
288};
289
290static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt)
291{
292 struct nci_rf_discover_select_param *param =
eb9bc6e9 293 (struct nci_rf_discover_select_param *)opt;
019c4fba
IE
294 struct nci_rf_discover_select_cmd cmd;
295
296 cmd.rf_discovery_id = param->rf_discovery_id;
297 cmd.rf_protocol = param->rf_protocol;
298
299 switch (cmd.rf_protocol) {
300 case NCI_RF_PROTOCOL_ISO_DEP:
301 cmd.rf_interface = NCI_RF_INTERFACE_ISO_DEP;
302 break;
303
304 case NCI_RF_PROTOCOL_NFC_DEP:
305 cmd.rf_interface = NCI_RF_INTERFACE_NFC_DEP;
306 break;
307
308 default:
309 cmd.rf_interface = NCI_RF_INTERFACE_FRAME;
310 break;
311 }
312
313 nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD,
eb9bc6e9 314 sizeof(struct nci_rf_discover_select_cmd), &cmd);
019c4fba
IE
315}
316
6a2968aa
IE
317static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
318{
319 struct nci_rf_deactivate_cmd cmd;
320
9295b5b5 321 cmd.type = opt;
6a2968aa
IE
322
323 nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
eb9bc6e9 324 sizeof(struct nci_rf_deactivate_cmd), &cmd);
6a2968aa
IE
325}
326
327static int nci_open_device(struct nci_dev *ndev)
328{
329 int rc = 0;
330
331 mutex_lock(&ndev->req_lock);
332
333 if (test_bit(NCI_UP, &ndev->flags)) {
334 rc = -EALREADY;
335 goto done;
336 }
337
338 if (ndev->ops->open(ndev)) {
339 rc = -EIO;
340 goto done;
341 }
342
343 atomic_set(&ndev->cmd_cnt, 1);
344
345 set_bit(NCI_INIT, &ndev->flags);
346
347 rc = __nci_request(ndev, nci_reset_req, 0,
eb9bc6e9 348 msecs_to_jiffies(NCI_RESET_TIMEOUT));
6a2968aa 349
81859ab8
CR
350 if (!rc && ndev->ops->setup) {
351 rc = ndev->ops->setup(ndev);
352 }
86e8586e 353
6a2968aa
IE
354 if (!rc) {
355 rc = __nci_request(ndev, nci_init_req, 0,
eb9bc6e9 356 msecs_to_jiffies(NCI_INIT_TIMEOUT));
6a2968aa
IE
357 }
358
359 if (!rc) {
360 rc = __nci_request(ndev, nci_init_complete_req, 0,
eb9bc6e9 361 msecs_to_jiffies(NCI_INIT_TIMEOUT));
6a2968aa
IE
362 }
363
364 clear_bit(NCI_INIT, &ndev->flags);
365
366 if (!rc) {
367 set_bit(NCI_UP, &ndev->flags);
019c4fba 368 nci_clear_target_list(ndev);
8939e47f 369 atomic_set(&ndev->state, NCI_IDLE);
6a2968aa
IE
370 } else {
371 /* Init failed, cleanup */
372 skb_queue_purge(&ndev->cmd_q);
373 skb_queue_purge(&ndev->rx_q);
374 skb_queue_purge(&ndev->tx_q);
375
376 ndev->ops->close(ndev);
377 ndev->flags = 0;
378 }
379
380done:
381 mutex_unlock(&ndev->req_lock);
382 return rc;
383}
384
385static int nci_close_device(struct nci_dev *ndev)
386{
387 nci_req_cancel(ndev, ENODEV);
388 mutex_lock(&ndev->req_lock);
389
390 if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
391 del_timer_sync(&ndev->cmd_timer);
c4bf98b2 392 del_timer_sync(&ndev->data_timer);
6a2968aa
IE
393 mutex_unlock(&ndev->req_lock);
394 return 0;
395 }
396
397 /* Drop RX and TX queues */
398 skb_queue_purge(&ndev->rx_q);
399 skb_queue_purge(&ndev->tx_q);
400
401 /* Flush RX and TX wq */
402 flush_workqueue(ndev->rx_wq);
403 flush_workqueue(ndev->tx_wq);
404
405 /* Reset device */
406 skb_queue_purge(&ndev->cmd_q);
407 atomic_set(&ndev->cmd_cnt, 1);
408
409 set_bit(NCI_INIT, &ndev->flags);
410 __nci_request(ndev, nci_reset_req, 0,
eb9bc6e9 411 msecs_to_jiffies(NCI_RESET_TIMEOUT));
6a2968aa
IE
412 clear_bit(NCI_INIT, &ndev->flags);
413
fa9be5f0
AK
414 del_timer_sync(&ndev->cmd_timer);
415
6a2968aa
IE
416 /* Flush cmd wq */
417 flush_workqueue(ndev->cmd_wq);
418
419 /* After this point our queues are empty
420 * and no works are scheduled. */
421 ndev->ops->close(ndev);
422
423 /* Clear flags */
424 ndev->flags = 0;
425
426 mutex_unlock(&ndev->req_lock);
427
428 return 0;
429}
430
431/* NCI command timer function */
432static void nci_cmd_timer(unsigned long arg)
433{
434 struct nci_dev *ndev = (void *) arg;
435
6a2968aa
IE
436 atomic_set(&ndev->cmd_cnt, 1);
437 queue_work(ndev->cmd_wq, &ndev->cmd_work);
438}
439
c4bf98b2
IE
440/* NCI data exchange timer function */
441static void nci_data_timer(unsigned long arg)
442{
443 struct nci_dev *ndev = (void *) arg;
444
445 set_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
446 queue_work(ndev->rx_wq, &ndev->rx_work);
447}
448
6a2968aa
IE
449static int nci_dev_up(struct nfc_dev *nfc_dev)
450{
451 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
452
6a2968aa
IE
453 return nci_open_device(ndev);
454}
455
456static int nci_dev_down(struct nfc_dev *nfc_dev)
457{
458 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
459
6a2968aa
IE
460 return nci_close_device(ndev);
461}
462
22c15bf3
AK
463int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val)
464{
465 struct nci_set_config_param param;
466
467 if (!val || !len)
468 return 0;
469
470 param.id = id;
471 param.len = len;
472 param.val = val;
473
474 return __nci_request(ndev, nci_set_config_req, (unsigned long)&param,
475 msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
476}
477EXPORT_SYMBOL(nci_set_config);
478
af9c8aa6
CR
479static void nci_nfcee_discover_req(struct nci_dev *ndev, unsigned long opt)
480{
481 struct nci_nfcee_discover_cmd cmd;
482 __u8 action = opt;
483
484 cmd.discovery_action = action;
485
486 nci_send_cmd(ndev, NCI_OP_NFCEE_DISCOVER_CMD, 1, &cmd);
487}
488
489int nci_nfcee_discover(struct nci_dev *ndev, u8 action)
490{
491 return nci_request(ndev, nci_nfcee_discover_req, action,
492 msecs_to_jiffies(NCI_CMD_TIMEOUT));
493}
494EXPORT_SYMBOL(nci_nfcee_discover);
495
f7f793f3
CR
496static void nci_nfcee_mode_set_req(struct nci_dev *ndev, unsigned long opt)
497{
498 struct nci_nfcee_mode_set_cmd *cmd =
499 (struct nci_nfcee_mode_set_cmd *)opt;
500
501 nci_send_cmd(ndev, NCI_OP_NFCEE_MODE_SET_CMD,
502 sizeof(struct nci_nfcee_mode_set_cmd), cmd);
503}
504
505int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode)
506{
507 struct nci_nfcee_mode_set_cmd cmd;
508
509 cmd.nfcee_id = nfcee_id;
510 cmd.nfcee_mode = nfcee_mode;
511
512 return nci_request(ndev, nci_nfcee_mode_set_req, (unsigned long)&cmd,
513 msecs_to_jiffies(NCI_CMD_TIMEOUT));
514}
515EXPORT_SYMBOL(nci_nfcee_mode_set);
516
736bb957
CR
517static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt)
518{
b16ae716
CR
519 struct core_conn_create_data *data =
520 (struct core_conn_create_data *)opt;
521
522 nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, data->length, data->cmd);
736bb957
CR
523}
524
b16ae716
CR
525int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
526 u8 number_destination_params,
527 size_t params_len,
736bb957
CR
528 struct core_conn_create_dest_spec_params *params)
529{
b16ae716
CR
530 int r;
531 struct nci_core_conn_create_cmd *cmd;
532 struct core_conn_create_data data;
533
534 data.length = params_len + sizeof(struct nci_core_conn_create_cmd);
535 cmd = kzalloc(data.length, GFP_KERNEL);
536 if (!cmd)
537 return -ENOMEM;
538
539 cmd->destination_type = destination_type;
540 cmd->number_destination_params = number_destination_params;
541 memcpy(cmd->params, params, params_len);
542
543 data.cmd = cmd;
544 ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX];
545
546 r = __nci_request(ndev, nci_core_conn_create_req,
547 (unsigned long)&data,
548 msecs_to_jiffies(NCI_CMD_TIMEOUT));
549 kfree(cmd);
550 return r;
736bb957
CR
551}
552EXPORT_SYMBOL(nci_core_conn_create);
553
554static void nci_core_conn_close_req(struct nci_dev *ndev, unsigned long opt)
555{
556 __u8 conn_id = opt;
557
558 nci_send_cmd(ndev, NCI_OP_CORE_CONN_CLOSE_CMD, 1, &conn_id);
559}
560
561int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id)
562{
563 return nci_request(ndev, nci_core_conn_close_req, conn_id,
564 msecs_to_jiffies(NCI_CMD_TIMEOUT));
565}
566EXPORT_SYMBOL(nci_core_conn_close);
567
7e035230
IE
568static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
569{
570 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
571 struct nci_set_config_param param;
529ee066 572 int rc;
7e035230
IE
573
574 param.val = nfc_get_local_general_bytes(nfc_dev, &param.len);
575 if ((param.val == NULL) || (param.len == 0))
f9fc36f4 576 return 0;
7e035230 577
460d8f97 578 if (param.len > NFC_MAX_GT_LEN)
7e035230
IE
579 return -EINVAL;
580
7e035230 581 param.id = NCI_PN_ATR_REQ_GEN_BYTES;
7e035230 582
529ee066
JL
583 rc = nci_request(ndev, nci_set_config_req, (unsigned long)&param,
584 msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
585 if (rc)
586 return rc;
587
588 param.id = NCI_LN_ATR_RES_GEN_BYTES;
589
f9fc36f4
SJ
590 return nci_request(ndev, nci_set_config_req, (unsigned long)&param,
591 msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
7e035230
IE
592}
593
90d78c13
JL
594static int nci_set_listen_parameters(struct nfc_dev *nfc_dev)
595{
596 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
597 int rc;
598 __u8 val;
599
600 val = NCI_LA_SEL_INFO_NFC_DEP_MASK;
601
602 rc = nci_set_config(ndev, NCI_LA_SEL_INFO, 1, &val);
603 if (rc)
604 return rc;
605
606 val = NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK;
607
608 rc = nci_set_config(ndev, NCI_LF_PROTOCOL_TYPE, 1, &val);
609 if (rc)
610 return rc;
611
612 val = NCI_LF_CON_BITR_F_212 | NCI_LF_CON_BITR_F_424;
613
614 return nci_set_config(ndev, NCI_LF_CON_BITR_F, 1, &val);
615}
616
fe7c5800
SO
617static int nci_start_poll(struct nfc_dev *nfc_dev,
618 __u32 im_protocols, __u32 tm_protocols)
6a2968aa
IE
619{
620 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
772dccf4 621 struct nci_rf_discover_param param;
6a2968aa
IE
622 int rc;
623
019c4fba 624 if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
eb9bc6e9 625 (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) {
ed1e0ad8 626 pr_err("unable to start poll, since poll is already active\n");
6a2968aa
IE
627 return -EBUSY;
628 }
629
de054799 630 if (ndev->target_active_prot) {
ed1e0ad8 631 pr_err("there is an active target\n");
de054799
IE
632 return -EBUSY;
633 }
634
019c4fba 635 if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) ||
eb9bc6e9 636 (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
019c4fba 637 pr_debug("target active or w4 select, implicitly deactivate\n");
6a2968aa 638
9295b5b5
CR
639 rc = nci_request(ndev, nci_rf_deactivate_req,
640 NCI_DEACTIVATE_TYPE_IDLE_MODE,
eb9bc6e9 641 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
6a2968aa
IE
642 if (rc)
643 return -EBUSY;
644 }
645
529ee066 646 if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
7e035230
IE
647 rc = nci_set_local_general_bytes(nfc_dev);
648 if (rc) {
649 pr_err("failed to set local general bytes\n");
650 return rc;
651 }
652 }
653
90d78c13
JL
654 if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
655 rc = nci_set_listen_parameters(nfc_dev);
656 if (rc)
657 pr_err("failed to set listen parameters\n");
658 }
659
772dccf4
JL
660 param.im_protocols = im_protocols;
661 param.tm_protocols = tm_protocols;
662 rc = nci_request(ndev, nci_rf_discover_req, (unsigned long)&param,
eb9bc6e9 663 msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
6a2968aa
IE
664
665 if (!rc)
fe7c5800 666 ndev->poll_prots = im_protocols;
6a2968aa
IE
667
668 return rc;
669}
670
671static void nci_stop_poll(struct nfc_dev *nfc_dev)
672{
673 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
674
019c4fba 675 if ((atomic_read(&ndev->state) != NCI_DISCOVERY) &&
eb9bc6e9 676 (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) {
ed1e0ad8 677 pr_err("unable to stop poll, since poll is not active\n");
6a2968aa
IE
678 return;
679 }
680
9295b5b5 681 nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE,
eb9bc6e9 682 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
6a2968aa
IE
683}
684
90099433
EL
685static int nci_activate_target(struct nfc_dev *nfc_dev,
686 struct nfc_target *target, __u32 protocol)
6a2968aa
IE
687{
688 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
019c4fba 689 struct nci_rf_discover_select_param param;
90099433 690 struct nfc_target *nci_target = NULL;
019c4fba
IE
691 int i;
692 int rc = 0;
6a2968aa 693
90099433 694 pr_debug("target_idx %d, protocol 0x%x\n", target->idx, protocol);
6a2968aa 695
019c4fba 696 if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) &&
eb9bc6e9 697 (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
ed1e0ad8 698 pr_err("there is no available target to activate\n");
6a2968aa
IE
699 return -EINVAL;
700 }
701
702 if (ndev->target_active_prot) {
ed1e0ad8 703 pr_err("there is already an active target\n");
6a2968aa
IE
704 return -EBUSY;
705 }
706
019c4fba 707 for (i = 0; i < ndev->n_targets; i++) {
90099433
EL
708 if (ndev->targets[i].idx == target->idx) {
709 nci_target = &ndev->targets[i];
019c4fba
IE
710 break;
711 }
712 }
713
90099433 714 if (!nci_target) {
019c4fba
IE
715 pr_err("unable to find the selected target\n");
716 return -EINVAL;
717 }
718
90099433 719 if (!(nci_target->supported_protocols & (1 << protocol))) {
ed1e0ad8
JP
720 pr_err("target does not support the requested protocol 0x%x\n",
721 protocol);
6a2968aa
IE
722 return -EINVAL;
723 }
724
019c4fba 725 if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) {
90099433 726 param.rf_discovery_id = nci_target->logical_idx;
019c4fba
IE
727
728 if (protocol == NFC_PROTO_JEWEL)
729 param.rf_protocol = NCI_RF_PROTOCOL_T1T;
730 else if (protocol == NFC_PROTO_MIFARE)
731 param.rf_protocol = NCI_RF_PROTOCOL_T2T;
732 else if (protocol == NFC_PROTO_FELICA)
733 param.rf_protocol = NCI_RF_PROTOCOL_T3T;
01d719a2
SO
734 else if (protocol == NFC_PROTO_ISO14443 ||
735 protocol == NFC_PROTO_ISO14443_B)
019c4fba
IE
736 param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
737 else
738 param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
739
740 rc = nci_request(ndev, nci_rf_discover_select_req,
eb9bc6e9
SO
741 (unsigned long)&param,
742 msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
019c4fba 743 }
6a2968aa 744
019c4fba
IE
745 if (!rc)
746 ndev->target_active_prot = protocol;
747
748 return rc;
6a2968aa
IE
749}
750
90099433
EL
751static void nci_deactivate_target(struct nfc_dev *nfc_dev,
752 struct nfc_target *target)
6a2968aa
IE
753{
754 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
755
767f19ae 756 pr_debug("entry\n");
6a2968aa
IE
757
758 if (!ndev->target_active_prot) {
ed1e0ad8 759 pr_err("unable to deactivate target, no active target\n");
6a2968aa
IE
760 return;
761 }
762
763 ndev->target_active_prot = 0;
764
8939e47f 765 if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
9295b5b5
CR
766 nci_request(ndev, nci_rf_deactivate_req,
767 NCI_DEACTIVATE_TYPE_SLEEP_MODE,
eb9bc6e9 768 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
6a2968aa
IE
769 }
770}
771
767f19ae
IE
772static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
773 __u8 comm_mode, __u8 *gb, size_t gb_len)
774{
775 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
776 int rc;
777
778 pr_debug("target_idx %d, comm_mode %d\n", target->idx, comm_mode);
779
780 rc = nci_activate_target(nfc_dev, target, NFC_PROTO_NFC_DEP);
781 if (rc)
782 return rc;
783
784 rc = nfc_set_remote_general_bytes(nfc_dev, ndev->remote_gb,
785 ndev->remote_gb_len);
786 if (!rc)
787 rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_PASSIVE,
788 NFC_RF_INITIATOR);
789
790 return rc;
791}
792
793static int nci_dep_link_down(struct nfc_dev *nfc_dev)
794{
d7979e13
JL
795 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
796 int rc;
797
767f19ae
IE
798 pr_debug("entry\n");
799
d7979e13
JL
800 if (nfc_dev->rf_mode == NFC_RF_INITIATOR) {
801 nci_deactivate_target(nfc_dev, NULL);
802 } else {
803 if (atomic_read(&ndev->state) == NCI_LISTEN_ACTIVE ||
804 atomic_read(&ndev->state) == NCI_DISCOVERY) {
805 nci_request(ndev, nci_rf_deactivate_req, 0,
806 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
807 }
808
809 rc = nfc_tm_deactivated(nfc_dev);
810 if (rc)
811 pr_err("error when signaling tm deactivation\n");
812 }
767f19ae
IE
813
814 return 0;
815}
816
817
be9ae4ce
SO
818static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
819 struct sk_buff *skb,
820 data_exchange_cb_t cb, void *cb_context)
6a2968aa
IE
821{
822 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
38f04c6b 823 int rc;
4aeee687
CR
824 struct nci_conn_info *conn_info;
825
12bdf27d 826 conn_info = ndev->rf_conn_info;
4aeee687
CR
827 if (!conn_info)
828 return -EPROTO;
6a2968aa 829
90099433 830 pr_debug("target_idx %d, len %d\n", target->idx, skb->len);
6a2968aa
IE
831
832 if (!ndev->target_active_prot) {
ed1e0ad8 833 pr_err("unable to exchange data, no active target\n");
6a2968aa
IE
834 return -EINVAL;
835 }
836
38f04c6b
IE
837 if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags))
838 return -EBUSY;
839
6a2968aa 840 /* store cb and context to be used on receiving data */
4aeee687
CR
841 conn_info->data_exchange_cb = cb;
842 conn_info->data_exchange_cb_context = cb_context;
6a2968aa 843
e8c0dacd 844 rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
38f04c6b
IE
845 if (rc)
846 clear_bit(NCI_DATA_EXCHANGE, &ndev->flags);
847
848 return rc;
6a2968aa
IE
849}
850
485f442f
JL
851static int nci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
852{
853 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
854 int rc;
855
856 rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
857 if (rc)
858 pr_err("unable to send data\n");
859
860 return rc;
861}
862
0a946301
SO
863static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx)
864{
93bca2bf
CR
865 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
866
867 if (ndev->ops->enable_se)
868 return ndev->ops->enable_se(ndev, se_idx);
869
0a946301
SO
870 return 0;
871}
872
873static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx)
874{
e9ef9431
CR
875 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
876
877 if (ndev->ops->disable_se)
878 return ndev->ops->disable_se(ndev, se_idx);
879
0a946301
SO
880 return 0;
881}
882
883static int nci_discover_se(struct nfc_dev *nfc_dev)
884{
fa00e8fe 885 int r;
ba4db551
CR
886 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
887
fa00e8fe
CR
888 if (ndev->ops->discover_se) {
889 r = nci_nfcee_discover(ndev, NCI_NFCEE_DISCOVERY_ACTION_ENABLE);
890 if (r != NCI_STATUS_OK)
891 return -EPROTO;
892
ba4db551 893 return ndev->ops->discover_se(ndev);
fa00e8fe 894 }
ba4db551 895
0a946301
SO
896 return 0;
897}
898
a688bf55
CR
899static int nci_se_io(struct nfc_dev *nfc_dev, u32 se_idx,
900 u8 *apdu, size_t apdu_length,
901 se_io_cb_t cb, void *cb_context)
902{
903 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
904
905 if (ndev->ops->se_io)
906 return ndev->ops->se_io(ndev, se_idx, apdu,
907 apdu_length, cb, cb_context);
908
909 return 0;
910}
911
25af01ed
CP
912static int nci_fw_download(struct nfc_dev *nfc_dev, const char *firmware_name)
913{
914 struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
915
916 if (!ndev->ops->fw_download)
917 return -ENOTSUPP;
918
919 return ndev->ops->fw_download(ndev, firmware_name);
920}
921
6a2968aa
IE
922static struct nfc_ops nci_nfc_ops = {
923 .dev_up = nci_dev_up,
924 .dev_down = nci_dev_down,
925 .start_poll = nci_start_poll,
926 .stop_poll = nci_stop_poll,
767f19ae
IE
927 .dep_link_up = nci_dep_link_up,
928 .dep_link_down = nci_dep_link_down,
6a2968aa
IE
929 .activate_target = nci_activate_target,
930 .deactivate_target = nci_deactivate_target,
be9ae4ce 931 .im_transceive = nci_transceive,
485f442f 932 .tm_send = nci_tm_send,
0a946301
SO
933 .enable_se = nci_enable_se,
934 .disable_se = nci_disable_se,
935 .discover_se = nci_discover_se,
a688bf55 936 .se_io = nci_se_io,
25af01ed 937 .fw_download = nci_fw_download,
6a2968aa
IE
938};
939
940/* ---- Interface to NCI drivers ---- */
6a2968aa
IE
941/**
942 * nci_allocate_device - allocate a new nci device
943 *
944 * @ops: device operations
945 * @supported_protocols: NFC protocols supported by the device
946 */
947struct nci_dev *nci_allocate_device(struct nci_ops *ops,
eb9bc6e9
SO
948 __u32 supported_protocols,
949 int tx_headroom, int tx_tailroom)
6a2968aa 950{
8ebafde0 951 struct nci_dev *ndev;
6a2968aa 952
24bf3304 953 pr_debug("supported_protocols 0x%x\n", supported_protocols);
6a2968aa
IE
954
955 if (!ops->open || !ops->close || !ops->send)
8ebafde0 956 return NULL;
6a2968aa
IE
957
958 if (!supported_protocols)
8ebafde0 959 return NULL;
6a2968aa
IE
960
961 ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL);
962 if (!ndev)
8ebafde0 963 return NULL;
6a2968aa
IE
964
965 ndev->ops = ops;
b6355e97
SO
966
967 if (ops->n_prop_ops > NCI_MAX_PROPRIETARY_CMD) {
968 pr_err("Too many proprietary commands: %zd\n",
969 ops->n_prop_ops);
970 ops->prop_ops = NULL;
971 ops->n_prop_ops = 0;
972 }
973
6a2968aa
IE
974 ndev->tx_headroom = tx_headroom;
975 ndev->tx_tailroom = tx_tailroom;
9bec44bf 976 init_completion(&ndev->req_completion);
6a2968aa
IE
977
978 ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
eb9bc6e9
SO
979 supported_protocols,
980 tx_headroom + NCI_DATA_HDR_SIZE,
981 tx_tailroom);
6a2968aa 982 if (!ndev->nfc_dev)
11f54f22
CR
983 goto free_nci;
984
985 ndev->hci_dev = nci_hci_allocate(ndev);
986 if (!ndev->hci_dev)
987 goto free_nfc;
6a2968aa
IE
988
989 nfc_set_drvdata(ndev->nfc_dev, ndev);
990
8ebafde0 991 return ndev;
6a2968aa 992
11f54f22
CR
993free_nfc:
994 kfree(ndev->nfc_dev);
995
996free_nci:
6a2968aa 997 kfree(ndev);
8ebafde0 998 return NULL;
6a2968aa
IE
999}
1000EXPORT_SYMBOL(nci_allocate_device);
1001
1002/**
1003 * nci_free_device - deallocate nci device
1004 *
1005 * @ndev: The nci device to deallocate
1006 */
1007void nci_free_device(struct nci_dev *ndev)
1008{
6a2968aa
IE
1009 nfc_free_device(ndev->nfc_dev);
1010 kfree(ndev);
1011}
1012EXPORT_SYMBOL(nci_free_device);
1013
1014/**
1015 * nci_register_device - register a nci device in the nfc subsystem
1016 *
1017 * @dev: The nci device to register
1018 */
1019int nci_register_device(struct nci_dev *ndev)
1020{
1021 int rc;
1022 struct device *dev = &ndev->nfc_dev->dev;
1023 char name[32];
1024
6a2968aa
IE
1025 ndev->flags = 0;
1026
1027 INIT_WORK(&ndev->cmd_work, nci_cmd_work);
1028 snprintf(name, sizeof(name), "%s_nci_cmd_wq", dev_name(dev));
1029 ndev->cmd_wq = create_singlethread_workqueue(name);
1030 if (!ndev->cmd_wq) {
1031 rc = -ENOMEM;
3c1c0f5d 1032 goto exit;
6a2968aa
IE
1033 }
1034
1035 INIT_WORK(&ndev->rx_work, nci_rx_work);
1036 snprintf(name, sizeof(name), "%s_nci_rx_wq", dev_name(dev));
1037 ndev->rx_wq = create_singlethread_workqueue(name);
1038 if (!ndev->rx_wq) {
1039 rc = -ENOMEM;
1040 goto destroy_cmd_wq_exit;
1041 }
1042
1043 INIT_WORK(&ndev->tx_work, nci_tx_work);
1044 snprintf(name, sizeof(name), "%s_nci_tx_wq", dev_name(dev));
1045 ndev->tx_wq = create_singlethread_workqueue(name);
1046 if (!ndev->tx_wq) {
1047 rc = -ENOMEM;
1048 goto destroy_rx_wq_exit;
1049 }
1050
1051 skb_queue_head_init(&ndev->cmd_q);
1052 skb_queue_head_init(&ndev->rx_q);
1053 skb_queue_head_init(&ndev->tx_q);
1054
1055 setup_timer(&ndev->cmd_timer, nci_cmd_timer,
eb9bc6e9 1056 (unsigned long) ndev);
c4bf98b2 1057 setup_timer(&ndev->data_timer, nci_data_timer,
eb9bc6e9 1058 (unsigned long) ndev);
6a2968aa
IE
1059
1060 mutex_init(&ndev->req_lock);
4aeee687 1061 INIT_LIST_HEAD(&ndev->conn_info_list);
6a2968aa 1062
3c1c0f5d
VC
1063 rc = nfc_register_device(ndev->nfc_dev);
1064 if (rc)
1065 goto destroy_rx_wq_exit;
1066
6a2968aa
IE
1067 goto exit;
1068
1069destroy_rx_wq_exit:
1070 destroy_workqueue(ndev->rx_wq);
1071
1072destroy_cmd_wq_exit:
1073 destroy_workqueue(ndev->cmd_wq);
1074
6a2968aa
IE
1075exit:
1076 return rc;
1077}
1078EXPORT_SYMBOL(nci_register_device);
1079
1080/**
1081 * nci_unregister_device - unregister a nci device in the nfc subsystem
1082 *
1083 * @dev: The nci device to unregister
1084 */
1085void nci_unregister_device(struct nci_dev *ndev)
1086{
4aeee687
CR
1087 struct nci_conn_info *conn_info, *n;
1088
6a2968aa
IE
1089 nci_close_device(ndev);
1090
1091 destroy_workqueue(ndev->cmd_wq);
1092 destroy_workqueue(ndev->rx_wq);
1093 destroy_workqueue(ndev->tx_wq);
1094
4aeee687
CR
1095 list_for_each_entry_safe(conn_info, n, &ndev->conn_info_list, list) {
1096 list_del(&conn_info->list);
1097 /* conn_info is allocated with devm_kzalloc */
1098 }
1099
6a2968aa
IE
1100 nfc_unregister_device(ndev->nfc_dev);
1101}
1102EXPORT_SYMBOL(nci_unregister_device);
1103
1104/**
1105 * nci_recv_frame - receive frame from NCI drivers
1106 *
1095e69f 1107 * @ndev: The nci device
6a2968aa
IE
1108 * @skb: The sk_buff to receive
1109 */
1095e69f 1110int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb)
6a2968aa 1111{
24bf3304 1112 pr_debug("len %d\n", skb->len);
6a2968aa 1113
874934f4
SJ
1114 if (!ndev || (!test_bit(NCI_UP, &ndev->flags) &&
1115 !test_bit(NCI_INIT, &ndev->flags))) {
6a2968aa
IE
1116 kfree_skb(skb);
1117 return -ENXIO;
1118 }
1119
1120 /* Queue frame for rx worker thread */
1121 skb_queue_tail(&ndev->rx_q, skb);
1122 queue_work(ndev->rx_wq, &ndev->rx_work);
1123
1124 return 0;
1125}
1126EXPORT_SYMBOL(nci_recv_frame);
1127
1095e69f 1128static int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb)
6a2968aa 1129{
24bf3304 1130 pr_debug("len %d\n", skb->len);
6a2968aa
IE
1131
1132 if (!ndev) {
1133 kfree_skb(skb);
1134 return -ENODEV;
1135 }
1136
1137 /* Get rid of skb owner, prior to sending to the driver. */
1138 skb_orphan(skb);
1139
05158296
HT
1140 /* Send copy to sniffer */
1141 nfc_send_to_raw_sock(ndev->nfc_dev, skb,
1142 RAW_PAYLOAD_NCI, NFC_DIRECTION_TX);
1143
1095e69f 1144 return ndev->ops->send(ndev, skb);
6a2968aa
IE
1145}
1146
1147/* Send NCI command */
1148int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload)
1149{
1150 struct nci_ctrl_hdr *hdr;
1151 struct sk_buff *skb;
1152
24bf3304 1153 pr_debug("opcode 0x%x, plen %d\n", opcode, plen);
6a2968aa
IE
1154
1155 skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL);
1156 if (!skb) {
ed1e0ad8 1157 pr_err("no memory for command\n");
6a2968aa
IE
1158 return -ENOMEM;
1159 }
1160
1161 hdr = (struct nci_ctrl_hdr *) skb_put(skb, NCI_CTRL_HDR_SIZE);
1162 hdr->gid = nci_opcode_gid(opcode);
1163 hdr->oid = nci_opcode_oid(opcode);
1164 hdr->plen = plen;
1165
1166 nci_mt_set((__u8 *)hdr, NCI_MT_CMD_PKT);
1167 nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST);
1168
1169 if (plen)
1170 memcpy(skb_put(skb, plen), payload, plen);
1171
6a2968aa
IE
1172 skb_queue_tail(&ndev->cmd_q, skb);
1173 queue_work(ndev->cmd_wq, &ndev->cmd_work);
1174
1175 return 0;
1176}
1177
b6355e97
SO
1178/* Proprietary commands API */
1179static struct nci_prop_ops *prop_cmd_lookup(struct nci_dev *ndev,
1180 __u16 opcode)
1181{
1182 size_t i;
1183 struct nci_prop_ops *prop_op;
1184
1185 if (!ndev->ops->prop_ops || !ndev->ops->n_prop_ops)
1186 return NULL;
1187
1188 for (i = 0; i < ndev->ops->n_prop_ops; i++) {
1189 prop_op = &ndev->ops->prop_ops[i];
1190 if (prop_op->opcode == opcode)
1191 return prop_op;
1192 }
1193
1194 return NULL;
1195}
1196
1197int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode,
1198 struct sk_buff *skb)
1199{
1200 struct nci_prop_ops *prop_op;
1201
1202 prop_op = prop_cmd_lookup(ndev, rsp_opcode);
1203 if (!prop_op || !prop_op->rsp)
1204 return -ENOTSUPP;
1205
1206 return prop_op->rsp(ndev, skb);
1207}
1208
1209int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode,
1210 struct sk_buff *skb)
1211{
1212 struct nci_prop_ops *prop_op;
1213
1214 prop_op = prop_cmd_lookup(ndev, ntf_opcode);
1215 if (!prop_op || !prop_op->ntf)
1216 return -ENOTSUPP;
1217
1218 return prop_op->ntf(ndev, skb);
1219}
1220
6a2968aa
IE
1221/* ---- NCI TX Data worker thread ---- */
1222
1223static void nci_tx_work(struct work_struct *work)
1224{
1225 struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work);
4aeee687 1226 struct nci_conn_info *conn_info;
6a2968aa
IE
1227 struct sk_buff *skb;
1228
4aeee687
CR
1229 conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_conn_id);
1230 if (!conn_info)
1231 return;
1232
1233 pr_debug("credits_cnt %d\n", atomic_read(&conn_info->credits_cnt));
6a2968aa
IE
1234
1235 /* Send queued tx data */
4aeee687 1236 while (atomic_read(&conn_info->credits_cnt)) {
6a2968aa
IE
1237 skb = skb_dequeue(&ndev->tx_q);
1238 if (!skb)
1239 return;
1240
db98c829 1241 /* Check if data flow control is used */
4aeee687 1242 if (atomic_read(&conn_info->credits_cnt) !=
eb9bc6e9 1243 NCI_DATA_FLOW_CONTROL_NOT_USED)
4aeee687 1244 atomic_dec(&conn_info->credits_cnt);
6a2968aa 1245
20c239c1
JP
1246 pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
1247 nci_pbf(skb->data),
1248 nci_conn_id(skb->data),
1249 nci_plen(skb->data));
6a2968aa 1250
1095e69f 1251 nci_send_frame(ndev, skb);
c4bf98b2
IE
1252
1253 mod_timer(&ndev->data_timer,
eb9bc6e9 1254 jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
6a2968aa
IE
1255 }
1256}
1257
1258/* ----- NCI RX worker thread (data & control) ----- */
1259
1260static void nci_rx_work(struct work_struct *work)
1261{
1262 struct nci_dev *ndev = container_of(work, struct nci_dev, rx_work);
1263 struct sk_buff *skb;
1264
1265 while ((skb = skb_dequeue(&ndev->rx_q))) {
05158296
HT
1266
1267 /* Send copy to sniffer */
1268 nfc_send_to_raw_sock(ndev->nfc_dev, skb,
1269 RAW_PAYLOAD_NCI, NFC_DIRECTION_RX);
1270
6a2968aa
IE
1271 /* Process frame */
1272 switch (nci_mt(skb->data)) {
1273 case NCI_MT_RSP_PKT:
1274 nci_rsp_packet(ndev, skb);
1275 break;
1276
1277 case NCI_MT_NTF_PKT:
1278 nci_ntf_packet(ndev, skb);
1279 break;
1280
1281 case NCI_MT_DATA_PKT:
1282 nci_rx_data_packet(ndev, skb);
1283 break;
1284
1285 default:
ed1e0ad8 1286 pr_err("unknown MT 0x%x\n", nci_mt(skb->data));
6a2968aa
IE
1287 kfree_skb(skb);
1288 break;
1289 }
1290 }
c4bf98b2
IE
1291
1292 /* check if a data exchange timout has occurred */
1293 if (test_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags)) {
1294 /* complete the data exchange transaction, if exists */
1295 if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
4aeee687
CR
1296 nci_data_exchange_complete(ndev, NULL,
1297 ndev->cur_conn_id,
1298 -ETIMEDOUT);
c4bf98b2
IE
1299
1300 clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
1301 }
6a2968aa
IE
1302}
1303
1304/* ----- NCI TX CMD worker thread ----- */
1305
1306static void nci_cmd_work(struct work_struct *work)
1307{
1308 struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work);
1309 struct sk_buff *skb;
1310
24bf3304 1311 pr_debug("cmd_cnt %d\n", atomic_read(&ndev->cmd_cnt));
6a2968aa
IE
1312
1313 /* Send queued command */
1314 if (atomic_read(&ndev->cmd_cnt)) {
1315 skb = skb_dequeue(&ndev->cmd_q);
1316 if (!skb)
1317 return;
1318
1319 atomic_dec(&ndev->cmd_cnt);
1320
20c239c1
JP
1321 pr_debug("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
1322 nci_pbf(skb->data),
1323 nci_opcode_gid(nci_opcode(skb->data)),
1324 nci_opcode_oid(nci_opcode(skb->data)),
1325 nci_plen(skb->data));
6a2968aa 1326
1095e69f 1327 nci_send_frame(ndev, skb);
6a2968aa
IE
1328
1329 mod_timer(&ndev->cmd_timer,
eb9bc6e9 1330 jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
6a2968aa
IE
1331 }
1332}
8a70e7f8
DJ
1333
1334MODULE_LICENSE("GPL");
This page took 0.242733 seconds and 5 git commands to generate.