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 | |
| 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')
| -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 | ||
