diff options
Diffstat (limited to 'net/nfc/hci')
-rw-r--r-- | net/nfc/hci/command.c | 3 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 56 |
2 files changed, 59 insertions, 0 deletions
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 677d24b..91df487 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c @@ -345,6 +345,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, pr_debug("\n"); + if (hdev->gate2pipe[dest_gate] == NFC_HCI_DO_NOT_CREATE_PIPE) + return 0; + if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) return -EADDRINUSE; diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 1177082..ef50e77 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -167,6 +167,48 @@ exit: void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, struct sk_buff *skb) { + int r = 0; + u8 gate = nfc_hci_pipe2gate(hdev, pipe); + u8 local_gate, new_pipe; + u8 gate_opened = 0x00; + + pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); + + switch (cmd) { + case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: + if (skb->len != 5) { + r = -EPROTO; + break; + } + + local_gate = skb->data[3]; + new_pipe = skb->data[4]; + nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0); + + /* save the new created pipe and bind with local gate, + * the description for skb->data[3] is destination gate id + * but since we received this cmd from host controller, we + * are the destination and it is our local gate + */ + hdev->gate2pipe[local_gate] = new_pipe; + break; + case NFC_HCI_ANY_OPEN_PIPE: + /* if the pipe is already created, we allow remote host to + * open it + */ + if (gate != 0xff) + nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, + &gate_opened, 1); + break; + case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED: + nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0); + break; + default: + pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate); + r = -EINVAL; + break; + } + kfree_skb(skb); } @@ -717,6 +759,19 @@ static int hci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) return 0; } +static int hci_se_io(struct nfc_dev *nfc_dev, u32 se_idx, + u8 *apdu, size_t apdu_length, + se_io_cb_t cb, void *cb_context) +{ + struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); + + if (hdev->ops->se_io) + return hdev->ops->se_io(hdev, se_idx, apdu, + apdu_length, cb, cb_context); + + return 0; +} + static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) { mutex_lock(&hdev->msg_tx_mutex); @@ -830,6 +885,7 @@ static struct nfc_ops hci_nfc_ops = { .discover_se = hci_discover_se, .enable_se = hci_enable_se, .disable_se = hci_disable_se, + .se_io = hci_se_io, }; struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, |