summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-01-28 22:49:55 -0800
committerDavid S. Miller <davem@davemloft.net>2015-01-28 22:49:55 -0800
commitb8f8be3f043d6dba7d6c3426e4597d2ebf5a3547 (patch)
tree8f2b80088b24b7c5fb0aba4c6b3b45b5ca4a2bb2 /net
parentff660f75be36e6db75d45dc742a4a468c5a9c20d (diff)
parent0a5942c8e1480db4b8ee7a8d643e4945ef2f8fed (diff)
Merge tag 'nfc-next-3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next
NFC: 3.20 first pull request This is the first NFC pull request for 3.20. With this one we have: - Secure element support for the ST Micro st21nfca driver. This depends on a few HCI internal changes in order for example to support more than one secure element per controller. - ACPI support for NXP's pn544 HCI driver. This controller is found on many x86 SoCs and is typically enumerated on the ACPI bus there. - A few st21nfca and st21nfcb fixes. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/core.c2
-rw-r--r--net/nfc/hci/command.c23
-rw-r--r--net/nfc/hci/core.c97
-rw-r--r--net/nfc/hci/hci.h10
-rw-r--r--net/nfc/hci/hcp.c11
5 files changed, 84 insertions, 59 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 819b87702b70..7f1b6351755c 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -555,7 +555,6 @@ EXPORT_SYMBOL(nfc_find_se);
int nfc_enable_se(struct nfc_dev *dev, u32 se_idx)
{
-
struct nfc_se *se;
int rc;
@@ -605,7 +604,6 @@ error:
int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
{
-
struct nfc_se *se;
int rc;
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 91df487aa0a9..844673cb7c18 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -116,23 +116,6 @@ int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
}
EXPORT_SYMBOL(nfc_hci_send_event);
-int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
- const u8 *param, size_t param_len)
-{
- u8 pipe;
-
- pr_debug("\n");
-
- pipe = hdev->gate2pipe[gate];
- if (pipe == NFC_HCI_INVALID_PIPE)
- return -EADDRNOTAVAIL;
-
- return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE,
- response, param, param_len, NULL, NULL,
- 0);
-}
-EXPORT_SYMBOL(nfc_hci_send_response);
-
/*
* Execute an hci command sent to gate.
* skb will contain response data if success. skb can be NULL if you are not
@@ -331,7 +314,7 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev)
if (r < 0)
return r;
- memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
+ nfc_hci_reset_pipes(hdev);
return 0;
}
@@ -345,7 +328,7 @@ 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)
+ if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE)
return 0;
if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
@@ -380,6 +363,8 @@ open_pipe:
return r;
}
+ hdev->pipes[pipe].gate = dest_gate;
+ hdev->pipes[pipe].dest_host = dest_host;
hdev->gate2pipe[dest_gate] = pipe;
return 0;
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;
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h
index c3d2e2c1394c..ab4c8e80b1ad 100644
--- a/net/nfc/hci/hci.h
+++ b/net/nfc/hci/hci.h
@@ -65,6 +65,14 @@ struct hci_create_pipe_resp {
u8 pipe;
} __packed;
+struct hci_delete_pipe_noti {
+ u8 pipe;
+} __packed;
+
+struct hci_all_pipe_cleared_noti {
+ u8 host;
+} __packed;
+
#define NFC_HCI_FRAGMENT 0x7f
#define HCP_HEADER(type, instr) ((((type) & 0x03) << 6) | ((instr) & 0x3f))
@@ -77,8 +85,6 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe,
data_exchange_cb_t cb, void *cb_context,
unsigned long completion_delay);
-u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe);
-
void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type,
u8 instruction, struct sk_buff *skb);
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c
index e9de1514656e..1fe725d66085 100644
--- a/net/nfc/hci/hcp.c
+++ b/net/nfc/hci/hcp.c
@@ -124,17 +124,6 @@ out_skb_err:
return err;
}
-u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe)
-{
- int gate;
-
- for (gate = 0; gate < NFC_HCI_MAX_GATES; gate++)
- if (hdev->gate2pipe[gate] == pipe)
- return gate;
-
- return 0xff;
-}
-
/*
* Receive hcp message for pipe, with type and cmd.
* skb contains optional message data only.