diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-10-25 17:54:25 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-10-26 01:53:13 -0400 |
commit | a1b0b9415817c14d207921582f269d03f848b69f (patch) | |
tree | 207337705492431a3750a1ec014d26259ea6c2e5 /net/nfc | |
parent | 8a49943f5bc5ff4f835d50451ecf2380eab44d2e (diff) |
NFC: nci: Create pipe on specific gate in nci_hci_connect_gate
Some gates might need to have their pipes explicitly created.
Add a call to nci_hci_create_pipe in nci_hci_connect_gate for
every gate that is different than NCI_HCI_LINK_MGMT_GATE or
NCI_HCI_ADMIN_GATE.
In case of an error when opening a pipe, like in hci layer,
delete the pipe if it was created.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/nci/hci.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c index af401fff72d9..c96830421097 100644 --- a/net/nfc/nci/hci.c +++ b/net/nfc/nci/hci.c | |||
@@ -79,6 +79,8 @@ struct nci_hcp_packet { | |||
79 | #define NCI_EVT_HOT_PLUG 0x03 | 79 | #define NCI_EVT_HOT_PLUG 0x03 |
80 | 80 | ||
81 | #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01 | 81 | #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01 |
82 | #define NCI_HCI_ADM_CREATE_PIPE 0x10 | ||
83 | #define NCI_HCI_ADM_DELETE_PIPE 0x11 | ||
82 | 84 | ||
83 | /* HCP headers */ | 85 | /* HCP headers */ |
84 | #define NCI_HCI_HCP_PACKET_HEADER_LEN 1 | 86 | #define NCI_HCI_HCP_PACKET_HEADER_LEN 1 |
@@ -523,6 +525,43 @@ int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe) | |||
523 | } | 525 | } |
524 | EXPORT_SYMBOL(nci_hci_open_pipe); | 526 | EXPORT_SYMBOL(nci_hci_open_pipe); |
525 | 527 | ||
528 | static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host, | ||
529 | u8 dest_gate, int *result) | ||
530 | { | ||
531 | u8 pipe; | ||
532 | struct sk_buff *skb; | ||
533 | struct nci_hci_create_pipe_params params; | ||
534 | struct nci_hci_create_pipe_resp *resp; | ||
535 | |||
536 | pr_debug("gate=%d\n", dest_gate); | ||
537 | |||
538 | params.src_gate = NCI_HCI_ADMIN_GATE; | ||
539 | params.dest_host = dest_host; | ||
540 | params.dest_gate = dest_gate; | ||
541 | |||
542 | *result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE, | ||
543 | NCI_HCI_ADM_CREATE_PIPE, | ||
544 | (u8 *)¶ms, sizeof(params), &skb); | ||
545 | if (*result < 0) | ||
546 | return NCI_HCI_INVALID_PIPE; | ||
547 | |||
548 | resp = (struct nci_hci_create_pipe_resp *)skb->data; | ||
549 | pipe = resp->pipe; | ||
550 | kfree_skb(skb); | ||
551 | |||
552 | pr_debug("pipe created=%d\n", pipe); | ||
553 | |||
554 | return pipe; | ||
555 | } | ||
556 | |||
557 | static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe) | ||
558 | { | ||
559 | pr_debug("\n"); | ||
560 | |||
561 | return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE, | ||
562 | NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL); | ||
563 | } | ||
564 | |||
526 | int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx, | 565 | int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx, |
527 | const u8 *param, size_t param_len) | 566 | const u8 *param, size_t param_len) |
528 | { | 567 | { |
@@ -616,6 +655,7 @@ EXPORT_SYMBOL(nci_hci_get_param); | |||
616 | int nci_hci_connect_gate(struct nci_dev *ndev, | 655 | int nci_hci_connect_gate(struct nci_dev *ndev, |
617 | u8 dest_host, u8 dest_gate, u8 pipe) | 656 | u8 dest_host, u8 dest_gate, u8 pipe) |
618 | { | 657 | { |
658 | bool pipe_created = false; | ||
619 | int r; | 659 | int r; |
620 | 660 | ||
621 | if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE) | 661 | if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE) |
@@ -634,12 +674,26 @@ int nci_hci_connect_gate(struct nci_dev *ndev, | |||
634 | case NCI_HCI_ADMIN_GATE: | 674 | case NCI_HCI_ADMIN_GATE: |
635 | pipe = NCI_HCI_ADMIN_PIPE; | 675 | pipe = NCI_HCI_ADMIN_PIPE; |
636 | break; | 676 | break; |
677 | default: | ||
678 | pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r); | ||
679 | if (pipe < 0) | ||
680 | return r; | ||
681 | pipe_created = true; | ||
682 | break; | ||
637 | } | 683 | } |
638 | 684 | ||
639 | open_pipe: | 685 | open_pipe: |
640 | r = nci_hci_open_pipe(ndev, pipe); | 686 | r = nci_hci_open_pipe(ndev, pipe); |
641 | if (r < 0) | 687 | if (r < 0) { |
688 | if (pipe_created) { | ||
689 | if (nci_hci_delete_pipe(ndev, pipe) < 0) { | ||
690 | /* TODO: Cannot clean by deleting pipe... | ||
691 | * -> inconsistent state | ||
692 | */ | ||
693 | } | ||
694 | } | ||
642 | return r; | 695 | return r; |
696 | } | ||
643 | 697 | ||
644 | ndev->hci_dev->pipes[pipe].gate = dest_gate; | 698 | ndev->hci_dev->pipes[pipe].gate = dest_gate; |
645 | ndev->hci_dev->pipes[pipe].host = dest_host; | 699 | ndev->hci_dev->pipes[pipe].host = dest_host; |