summaryrefslogtreecommitdiff
path: root/net/nfc/hci/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/hci/core.c')
-rw-r--r--net/nfc/hci/core.c97
1 files changed, 72 insertions, 25 deletions
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ef50e7716c4a..6e061da2258a 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -46,6 +46,32 @@ int nfc_hci_result_to_errno(u8 result)
}
EXPORT_SYMBOL(nfc_hci_result_to_errno);
+void nfc_hci_reset_pipes(struct nfc_hci_dev *hdev)
+{
+ int i = 0;
+
+ for (i = 0; i < NFC_HCI_MAX_PIPES; i++) {
+ hdev->pipes[i].gate = NFC_HCI_INVALID_GATE;
+ hdev->pipes[i].dest_host = NFC_HCI_INVALID_HOST;
+ }
+ memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
+}
+EXPORT_SYMBOL(nfc_hci_reset_pipes);
+
+void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host)
+{
+ int i = 0;
+
+ for (i = 0; i < NFC_HCI_MAX_PIPES; i++) {
+ if (hdev->pipes[i].dest_host != host)
+ continue;
+
+ hdev->pipes[i].gate = NFC_HCI_INVALID_GATE;
+ hdev->pipes[i].dest_host = NFC_HCI_INVALID_HOST;
+ }
+}
+EXPORT_SYMBOL(nfc_hci_reset_pipes_per_host);
+
static void nfc_hci_msg_tx_work(struct work_struct *work)
{
struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev,
@@ -167,48 +193,69 @@ 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;
+ u8 gate = hdev->pipes[pipe].gate;
+ u8 status = NFC_HCI_ANY_OK;
+ struct hci_create_pipe_resp *create_info;
+ struct hci_delete_pipe_noti *delete_info;
+ struct hci_all_pipe_cleared_noti *cleared_info;
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;
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
}
+ create_info = (struct hci_create_pipe_resp *)skb->data;
- 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,
+ /* 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;
+ hdev->gate2pipe[create_info->dest_gate] = create_info->pipe;
+ hdev->pipes[create_info->pipe].gate = create_info->dest_gate;
+ hdev->pipes[create_info->pipe].dest_host =
+ create_info->src_host;
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);
+ if (gate == NFC_HCI_INVALID_GATE) {
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
+ }
+ break;
+ case NFC_HCI_ADM_NOTIFY_PIPE_DELETED:
+ if (skb->len != 1) {
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
+ }
+ delete_info = (struct hci_delete_pipe_noti *)skb->data;
+
+ hdev->pipes[delete_info->pipe].gate = NFC_HCI_INVALID_GATE;
+ hdev->pipes[delete_info->pipe].dest_host = NFC_HCI_INVALID_HOST;
break;
case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
- nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
+ if (skb->len != 1) {
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
+ }
+ cleared_info = (struct hci_all_pipe_cleared_noti *)skb->data;
+
+ nfc_hci_reset_pipes_per_host(hdev, cleared_info->host);
break;
default:
pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate);
- r = -EINVAL;
break;
}
+ if (hdev->ops->cmd_received)
+ hdev->ops->cmd_received(hdev, pipe, cmd, skb);
+
+exit:
+ nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE,
+ status, NULL, 0, NULL, NULL, 0);
+
kfree_skb(skb);
}
@@ -330,15 +377,15 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
struct sk_buff *skb)
{
int r = 0;
- u8 gate = nfc_hci_pipe2gate(hdev, pipe);
+ u8 gate = hdev->pipes[pipe].gate;
- if (gate == 0xff) {
+ if (gate == NFC_HCI_INVALID_GATE) {
pr_err("Discarded event %x to unopened pipe %x\n", event, pipe);
goto exit;
}
if (hdev->ops->event_received) {
- r = hdev->ops->event_received(hdev, gate, event, skb);
+ r = hdev->ops->event_received(hdev, pipe, event, skb);
if (r <= 0)
goto exit_noskb;
}
@@ -573,7 +620,7 @@ static int hci_dev_down(struct nfc_dev *nfc_dev)
if (hdev->ops->close)
hdev->ops->close(hdev);
- memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
+ nfc_hci_reset_pipes(hdev);
return 0;
}
@@ -932,7 +979,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
nfc_set_drvdata(hdev->ndev, hdev);
- memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
+ nfc_hci_reset_pipes(hdev);
hdev->quirks = quirks;