diff options
author | Julien Lefrique <lefrique@marvell.com> | 2014-10-21 10:52:46 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-11-28 08:07:51 -0500 |
commit | a99903ec4566eeeaaaf611499cae00abbe844938 (patch) | |
tree | 67fa8332a70691e99011ca0289e25ec227ce3fb7 /net/nfc/nci | |
parent | 90d78c13965859d87622b37a221ebf29522585a8 (diff) |
NFC: NCI: Handle Target mode activation
Changes:
* Extract the Listen mode activation parameters from RF_INTF_ACTIVATED_NTF.
* Store the General Bytes of ATR_REQ.
* Signal that Target mode is activated in case of an activation in NFC-DEP.
* Update the NCI state accordingly.
* Use the various constants defined in nfc.h.
* Fix the ATR_REQ and ATR_RES maximum size. As per NCI 1.0 and NCI 1.1, the
Activation Parameters for both Poll and Listen mode contain all the bytes of
ATR_REQ/ATR_RES starting and including Byte 3 as defined in [DIGITAL].
In [DIGITAL], the maximum size of ATR_REQ/ATR_RES is 64 bytes and they are
numbered starting from Byte 1.
Signed-off-by: Julien Lefrique <lefrique@marvell.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/nci')
-rw-r--r-- | net/nfc/nci/ntf.c | 133 |
1 files changed, 109 insertions, 24 deletions
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 205b35f666db..46b2a90ac55a 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -167,6 +167,18 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev, | |||
167 | return data; | 167 | return data; |
168 | } | 168 | } |
169 | 169 | ||
170 | static __u8 *nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev, | ||
171 | struct rf_tech_specific_params_nfcf_listen *nfcf_listen, | ||
172 | __u8 *data) | ||
173 | { | ||
174 | nfcf_listen->local_nfcid2_len = min_t(__u8, *data++, | ||
175 | NFC_NFCID2_MAXSIZE); | ||
176 | memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len); | ||
177 | data += nfcf_listen->local_nfcid2_len; | ||
178 | |||
179 | return data; | ||
180 | } | ||
181 | |||
170 | __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol) | 182 | __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol) |
171 | { | 183 | { |
172 | if (ndev->ops->get_rfprotocol) | 184 | if (ndev->ops->get_rfprotocol) |
@@ -401,17 +413,29 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev, | |||
401 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) | 413 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) |
402 | { | 414 | { |
403 | struct activation_params_poll_nfc_dep *poll; | 415 | struct activation_params_poll_nfc_dep *poll; |
416 | struct activation_params_listen_nfc_dep *listen; | ||
404 | 417 | ||
405 | switch (ntf->activation_rf_tech_and_mode) { | 418 | switch (ntf->activation_rf_tech_and_mode) { |
406 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 419 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
407 | case NCI_NFC_F_PASSIVE_POLL_MODE: | 420 | case NCI_NFC_F_PASSIVE_POLL_MODE: |
408 | poll = &ntf->activation_params.poll_nfc_dep; | 421 | poll = &ntf->activation_params.poll_nfc_dep; |
409 | poll->atr_res_len = min_t(__u8, *data++, 63); | 422 | poll->atr_res_len = min_t(__u8, *data++, |
423 | NFC_ATR_RES_MAXSIZE - 2); | ||
410 | pr_debug("atr_res_len %d\n", poll->atr_res_len); | 424 | pr_debug("atr_res_len %d\n", poll->atr_res_len); |
411 | if (poll->atr_res_len > 0) | 425 | if (poll->atr_res_len > 0) |
412 | memcpy(poll->atr_res, data, poll->atr_res_len); | 426 | memcpy(poll->atr_res, data, poll->atr_res_len); |
413 | break; | 427 | break; |
414 | 428 | ||
429 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: | ||
430 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: | ||
431 | listen = &ntf->activation_params.listen_nfc_dep; | ||
432 | listen->atr_req_len = min_t(__u8, *data++, | ||
433 | NFC_ATR_REQ_MAXSIZE - 2); | ||
434 | pr_debug("atr_req_len %d\n", listen->atr_req_len); | ||
435 | if (listen->atr_req_len > 0) | ||
436 | memcpy(listen->atr_req, data, listen->atr_req_len); | ||
437 | break; | ||
438 | |||
415 | default: | 439 | default: |
416 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | 440 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", |
417 | ntf->activation_rf_tech_and_mode); | 441 | ntf->activation_rf_tech_and_mode); |
@@ -444,6 +468,50 @@ static void nci_target_auto_activated(struct nci_dev *ndev, | |||
444 | nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets); | 468 | nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets); |
445 | } | 469 | } |
446 | 470 | ||
471 | static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev, | ||
472 | struct nci_rf_intf_activated_ntf *ntf) | ||
473 | { | ||
474 | ndev->remote_gb_len = 0; | ||
475 | |||
476 | if (ntf->activation_params_len <= 0) | ||
477 | return NCI_STATUS_OK; | ||
478 | |||
479 | switch (ntf->activation_rf_tech_and_mode) { | ||
480 | case NCI_NFC_A_PASSIVE_POLL_MODE: | ||
481 | case NCI_NFC_F_PASSIVE_POLL_MODE: | ||
482 | /* ATR_RES general bytes at offset 15 */ | ||
483 | ndev->remote_gb_len = min_t(__u8, | ||
484 | (ntf->activation_params.poll_nfc_dep.atr_res_len | ||
485 | - NFC_ATR_RES_GT_OFFSET), | ||
486 | NFC_MAX_GT_LEN); | ||
487 | memcpy(ndev->remote_gb, | ||
488 | (ntf->activation_params.poll_nfc_dep .atr_res | ||
489 | + NFC_ATR_RES_GT_OFFSET), | ||
490 | ndev->remote_gb_len); | ||
491 | break; | ||
492 | |||
493 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: | ||
494 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: | ||
495 | /* ATR_REQ general bytes at offset 14 */ | ||
496 | ndev->remote_gb_len = min_t(__u8, | ||
497 | (ntf->activation_params.listen_nfc_dep.atr_req_len | ||
498 | - NFC_ATR_REQ_GT_OFFSET), | ||
499 | NFC_MAX_GT_LEN); | ||
500 | memcpy(ndev->remote_gb, | ||
501 | (ntf->activation_params.listen_nfc_dep.atr_req | ||
502 | + NFC_ATR_REQ_GT_OFFSET), | ||
503 | ndev->remote_gb_len); | ||
504 | break; | ||
505 | |||
506 | default: | ||
507 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | ||
508 | ntf->activation_rf_tech_and_mode); | ||
509 | return NCI_STATUS_RF_PROTOCOL_ERROR; | ||
510 | } | ||
511 | |||
512 | return NCI_STATUS_OK; | ||
513 | } | ||
514 | |||
447 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | 515 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
448 | struct sk_buff *skb) | 516 | struct sk_buff *skb) |
449 | { | 517 | { |
@@ -493,6 +561,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
493 | &(ntf.rf_tech_specific_params.nfcv_poll), data); | 561 | &(ntf.rf_tech_specific_params.nfcv_poll), data); |
494 | break; | 562 | break; |
495 | 563 | ||
564 | case NCI_NFC_A_PASSIVE_LISTEN_MODE: | ||
565 | /* no RF technology specific parameters */ | ||
566 | break; | ||
567 | |||
568 | case NCI_NFC_F_PASSIVE_LISTEN_MODE: | ||
569 | data = nci_extract_rf_params_nfcf_passive_listen(ndev, | ||
570 | &(ntf.rf_tech_specific_params.nfcf_listen), | ||
571 | data); | ||
572 | break; | ||
573 | |||
496 | default: | 574 | default: |
497 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | 575 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", |
498 | ntf.activation_rf_tech_and_mode); | 576 | ntf.activation_rf_tech_and_mode); |
@@ -546,32 +624,39 @@ exit: | |||
546 | 624 | ||
547 | /* store general bytes to be reported later in dep_link_up */ | 625 | /* store general bytes to be reported later in dep_link_up */ |
548 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { | 626 | if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { |
549 | ndev->remote_gb_len = 0; | 627 | err = nci_store_general_bytes_nfc_dep(ndev, &ntf); |
550 | 628 | if (err != NCI_STATUS_OK) | |
551 | if (ntf.activation_params_len > 0) { | 629 | pr_err("unable to store general bytes\n"); |
552 | /* ATR_RES general bytes at offset 15 */ | ||
553 | ndev->remote_gb_len = min_t(__u8, | ||
554 | (ntf.activation_params | ||
555 | .poll_nfc_dep.atr_res_len | ||
556 | - NFC_ATR_RES_GT_OFFSET), | ||
557 | NFC_MAX_GT_LEN); | ||
558 | memcpy(ndev->remote_gb, | ||
559 | (ntf.activation_params.poll_nfc_dep | ||
560 | .atr_res + NFC_ATR_RES_GT_OFFSET), | ||
561 | ndev->remote_gb_len); | ||
562 | } | ||
563 | } | 630 | } |
564 | } | 631 | } |
565 | 632 | ||
566 | if (atomic_read(&ndev->state) == NCI_DISCOVERY) { | 633 | if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) { |
567 | /* A single target was found and activated automatically */ | 634 | /* Poll mode */ |
568 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); | 635 | if (atomic_read(&ndev->state) == NCI_DISCOVERY) { |
569 | if (err == NCI_STATUS_OK) | 636 | /* A single target was found and activated |
570 | nci_target_auto_activated(ndev, &ntf); | 637 | * automatically */ |
571 | } else { /* ndev->state == NCI_W4_HOST_SELECT */ | 638 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); |
572 | /* A selected target was activated, so complete the request */ | 639 | if (err == NCI_STATUS_OK) |
573 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); | 640 | nci_target_auto_activated(ndev, &ntf); |
574 | nci_req_complete(ndev, err); | 641 | } else { /* ndev->state == NCI_W4_HOST_SELECT */ |
642 | /* A selected target was activated, so complete the | ||
643 | * request */ | ||
644 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); | ||
645 | nci_req_complete(ndev, err); | ||
646 | } | ||
647 | } else { | ||
648 | /* Listen mode */ | ||
649 | atomic_set(&ndev->state, NCI_LISTEN_ACTIVE); | ||
650 | if (err == NCI_STATUS_OK && | ||
651 | ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) { | ||
652 | err = nfc_tm_activated(ndev->nfc_dev, | ||
653 | NFC_PROTO_NFC_DEP_MASK, | ||
654 | NFC_COMM_PASSIVE, | ||
655 | ndev->remote_gb, | ||
656 | ndev->remote_gb_len); | ||
657 | if (err != NCI_STATUS_OK) | ||
658 | pr_err("error when signaling tm activation\n"); | ||
659 | } | ||
575 | } | 660 | } |
576 | } | 661 | } |
577 | 662 | ||