* [PATCH 04/30] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-10-20 21:47 ` Christophe Ricard
2015-10-20 21:47 ` [PATCH 05/30] nfc: nci: add nci_hci_clear_all_pipes functions Christophe Ricard
` (13 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:47 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA, stable-u79uwXL29TY76Z2rM5mHXA
When receiving data in nci_hci_msg_rx_work, extract pipe value using
NCI_HCP_MSG_GET_PIPE macro.
Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
net/nfc/nci/hci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 73afb47..abe0200 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -400,7 +400,7 @@ static void nci_hci_msg_rx_work(struct work_struct *work)
u8 pipe, type, instruction;
while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
- pipe = skb->data[0];
+ pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
message = (struct nci_hcp_message *)skb->data;
type = NCI_HCP_MSG_GET_TYPE(message->header);
@@ -437,7 +437,7 @@ void nci_hci_data_received_cb(void *context,
/* it's the last fragment. Does it need re-aggregation? */
if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
- pipe = packet->header & NCI_HCI_FRAGMENT;
+ pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
msg_len = 0;
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 05/30] nfc: nci: add nci_hci_clear_all_pipes functions
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-20 21:47 ` [PATCH 04/30] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE Christophe Ricard
@ 2015-10-20 21:47 ` Christophe Ricard
2015-10-20 21:47 ` [PATCH 06/30] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation Christophe Ricard
` (12 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:47 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
nci_hci_clear_all_pipes might be use full in some cases for example after
a firmware update.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
include/net/nfc/nci_core.h | 1 +
net/nfc/nci/hci.c | 15 +++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index d0d0f1e..b2f2e04 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -305,6 +305,7 @@ int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
const u8 *param, size_t param_len);
int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
struct sk_buff **skb);
+int nci_hci_clear_all_pipes(struct nci_dev *ndev);
int nci_hci_dev_session_init(struct nci_dev *ndev);
static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index abe0200..e7148cf 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -70,6 +70,7 @@ struct nci_hcp_packet {
#define NCI_HCI_ANY_SET_PARAMETER 0x01
#define NCI_HCI_ANY_GET_PARAMETER 0x02
#define NCI_HCI_ANY_CLOSE_PIPE 0x04
+#define NCI_HCI_ADM_CLEAR_ALL_PIPE 0x14
#define NCI_HFP_NO_CHAINING 0x80
@@ -265,6 +266,20 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
}
EXPORT_SYMBOL(nci_hci_send_cmd);
+int nci_hci_clear_all_pipes(struct nci_dev *ndev)
+{
+ int r;
+
+ r = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
+ NCI_HCI_ADM_CLEAR_ALL_PIPE, NULL, 0, NULL);
+ if (r < 0)
+ return r;
+
+ nci_hci_reset_pipes(ndev->hci_dev);
+ return r;
+}
+EXPORT_SYMBOL(nci_hci_clear_all_pipes);
+
static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
u8 event, struct sk_buff *skb)
{
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 06/30] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation.
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-20 21:47 ` [PATCH 04/30] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE Christophe Ricard
2015-10-20 21:47 ` [PATCH 05/30] nfc: nci: add nci_hci_clear_all_pipes functions Christophe Ricard
@ 2015-10-20 21:47 ` Christophe Ricard
2015-10-20 21:47 ` [PATCH 07/30] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate Christophe Ricard
` (11 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:47 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
When session_id is filled to ff, the pipe configuration is probably
incorrect.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
net/nfc/nci/hci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index e7148cf..1b83219 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -701,6 +701,10 @@ int nci_hci_dev_session_init(struct nci_dev *ndev)
/* Restore gate<->pipe table from some proprietary location. */
r = ndev->ops->hci_load_session(ndev);
} else {
+ r = nci_hci_clear_all_pipes(ndev);
+ if (r < 0)
+ goto exit;
+
r = nci_hci_dev_connect_gates(ndev,
ndev->hci_dev->init_data.gate_count,
ndev->hci_dev->init_data.gates);
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 07/30] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (2 preceding siblings ...)
2015-10-20 21:47 ` [PATCH 06/30] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation Christophe Ricard
@ 2015-10-20 21:47 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 09/30] nfc: st21nfca: Remove hdev->init_data.gates initialization in load_session Christophe Ricard
` (10 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:47 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
Some gates might be interesting to have their pipes created.
Add in nci_hci_connect_gate a call to nci_hci_create_pipe for every gate
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-qxv4g6HH51o@public.gmane.org>
---
net/nfc/nci/hci.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 1b83219..5212ef2 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -79,6 +79,8 @@ struct nci_hcp_packet {
#define NCI_EVT_HOT_PLUG 0x03
#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01
+#define NCI_HCI_ADM_CREATE_PIPE 0x10
+#define NCI_HCI_ADM_DELETE_PIPE 0x11
/* HCP headers */
#define NCI_HCI_HCP_PACKET_HEADER_LEN 1
@@ -520,6 +522,42 @@ int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
}
EXPORT_SYMBOL(nci_hci_open_pipe);
+static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host,
+ u8 dest_gate, int *result)
+{
+ u8 pipe;
+ struct sk_buff *skb;
+ struct nci_hci_create_pipe_params params;
+ struct nci_hci_create_pipe_resp *resp;
+
+ pr_debug("gate=%d\n", dest_gate);
+
+ params.src_gate = NCI_HCI_ADMIN_GATE;
+ params.dest_host = dest_host;
+ params.dest_gate = dest_gate;
+
+ *result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE, NCI_HCI_ADM_CREATE_PIPE,
+ (u8 *)¶ms, sizeof(params), &skb);
+ if (*result < 0)
+ return NCI_HCI_INVALID_PIPE;
+
+ resp = (struct nci_hci_create_pipe_resp *)skb->data;
+ pipe = resp->pipe;
+ kfree_skb(skb);
+
+ pr_debug("pipe created=%d\n", pipe);
+
+ return pipe;
+}
+
+static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe)
+{
+ pr_debug("\n");
+
+ return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
+ NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
+}
+
int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
const u8 *param, size_t param_len)
{
@@ -611,6 +649,7 @@ EXPORT_SYMBOL(nci_hci_get_param);
int nci_hci_connect_gate(struct nci_dev *ndev,
u8 dest_host, u8 dest_gate, u8 pipe)
{
+ bool pipe_created = false;
int r;
if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
@@ -629,12 +668,26 @@ int nci_hci_connect_gate(struct nci_dev *ndev,
case NCI_HCI_ADMIN_GATE:
pipe = NCI_HCI_ADMIN_PIPE;
break;
+ default:
+ pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
+ if (pipe < 0)
+ return r;
+ pipe_created = true;
+ break;
}
open_pipe:
r = nci_hci_open_pipe(ndev, pipe);
- if (r < 0)
+ if (r < 0) {
+ if (pipe_created) {
+ if (nci_hci_delete_pipe(ndev, pipe) < 0) {
+ /* TODO: Cannot clean by deleting pipe...
+ * -> inconsistent state
+ */
+ }
+ }
return r;
+ }
ndev->hci_dev->pipes[pipe].gate = dest_gate;
ndev->hci_dev->pipes[pipe].host = dest_host;
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 09/30] nfc: st21nfca: Remove hdev->init_data.gates initialization in load_session
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (3 preceding siblings ...)
2015-10-20 21:47 ` [PATCH 07/30] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 10/30] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE Christophe Ricard
` (9 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA, stable-u79uwXL29TY76Z2rM5mHXA
hdev->init_data.gates is already initialized in st21nfca_hci_probe.
Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st21nfca/st21nfca.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index 0512865..33e1e8f 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -220,7 +220,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
}
}
- memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
free_list:
kfree_skb(skb_pipe_list);
return r;
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 10/30] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (4 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 09/30] nfc: st21nfca: Remove hdev->init_data.gates initialization in load_session Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 15/30] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE Christophe Ricard
` (8 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
NCI_HCI_LINK_MGMT_PIPE was never open in st_nci_hci_load_session.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/st-nci_se.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index 15fb0bb..3ea5384 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -245,6 +245,14 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
kfree_skb(skb_pipe_info);
}
+ /*
+ * 3 gates have a well known pipe ID. Only NCI_HCI_LINK_MGMT_GATE
+ * is not yet open at this stage.
+ */
+ r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
+ NCI_HCI_LINK_MGMT_GATE,
+ NCI_HCI_LINK_MGMT_PIPE);
+
kfree_skb(skb_pipe_list);
return r;
}
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 15/30] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (5 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 10/30] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 18/30] nfc: st-nci: Add support for proprietary commands for factory tests Christophe Ricard
` (7 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
NCI_HCI_IDENTITY_MGMT_GATE might be useful to get information for example
about hardware or firmware version.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/st-nci_se.c | 3 +++
include/net/nfc/nci_core.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index f5409ab..7b94387 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -113,6 +113,9 @@ static struct nci_hci_gate st_nci_gates[] = {
{ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
+ {NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
+
/* Secure element pipes are created by secure element host */
{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index b2f2e04..377f3de 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -125,6 +125,7 @@ struct nci_conn_info {
/* Gates */
#define NCI_HCI_ADMIN_GATE 0x00
+#define NCI_HCI_IDENTITY_MGMT_GATE 0x05
#define NCI_HCI_LINK_MGMT_GATE 0x06
/* Pipes */
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 18/30] nfc: st-nci: Add support for proprietary commands for factory tests
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (6 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 15/30] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
[not found] ` <1445377701-8353-19-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-20 21:48 ` [PATCH 20/30] nfc: st-nci: Add ese-present/uicc-present dts properties Christophe Ricard
` (6 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
Add support for proprietary commands useful mainly for factory testings.
Here is a list:
- FACTORY_MODE: Allow to set the driver into a mode where no secure element
are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
RF trimmings or low level drivers configurations (I2C, SPI, SWP).
- HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
table following RF technology, CLF mode or protocol.
- HCI_DM_GET_INFO: Allow to retrieve CLF information.
- HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
level drivers configurations or RF trimmings.
- HCI_DM_DIRECT_LOAD: Allow to load a firmware into the CLF. A complete
packet can be more than 8KB.
- HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
configuration changes without CLF power off.
- HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
white list).
- HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
technology. When using this command to anti-collision is done.
- HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
connectivity.
- HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
- HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
specific CLF command as there is no GPIO for this.
- HCI_DM_FWUPD_END: Allow to complete firmware update.
- HCI_DM_VDC_VALUE_COMPARISON: Allow to compare the field applied on the
CLF antenna to a reference value.
- MANUFACTURER_SPECIFIC: Allow to retrieve manufacturer specific data
received during a NCI_CORE_INIT_CMD.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/Makefile | 2 +-
drivers/nfc/st-nci/core.c | 14 +-
drivers/nfc/st-nci/st-nci.h | 4 +
drivers/nfc/st-nci/st-nci_se.c | 30 +-
drivers/nfc/st-nci/st-nci_vendor_cmds.c | 516 ++++++++++++++++++++++++++++++++
drivers/nfc/st-nci/st-nci_vendor_cmds.h | 88 ++++++
include/net/nfc/nci_core.h | 1 +
7 files changed, 645 insertions(+), 10 deletions(-)
create mode 100644 drivers/nfc/st-nci/st-nci_vendor_cmds.c
create mode 100644 drivers/nfc/st-nci/st-nci_vendor_cmds.h
diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
index 348ce76..60e569b 100644
--- a/drivers/nfc/st-nci/Makefile
+++ b/drivers/nfc/st-nci/Makefile
@@ -2,7 +2,7 @@
# Makefile for ST21NFCB NCI based NFC driver
#
-st-nci-objs = ndlc.o core.o st-nci_se.o
+st-nci-objs = ndlc.o core.o st-nci_se.o st-nci_vendor_cmds.o
obj-$(CONFIG_NFC_ST_NCI) += st-nci.o
st-nci_i2c-objs = i2c.o
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index c419d39..fd2a5ca 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -25,6 +25,7 @@
#include "st-nci.h"
#include "st-nci_se.h"
+#include "st-nci_vendor_cmds.h"
#define DRIVER_DESC "NCI NFC driver for ST_NCI"
@@ -153,14 +154,23 @@ int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
nci_set_drvdata(ndlc->ndev, info);
+ r = st_nci_vendor_cmds_init(ndlc->ndev);
+ if (r) {
+ pr_err("Cannot register proprietary vendor cmds\n");
+ goto err_reg_dev;
+ }
+
r = nci_register_device(ndlc->ndev);
if (r) {
pr_err("Cannot register nfc device to nci core\n");
- nci_free_device(ndlc->ndev);
- return r;
+ goto err_reg_dev;
}
return st_nci_se_init(ndlc->ndev);
+
+err_reg_dev:
+ nci_free_device(ndlc->ndev);
+ return r;
}
EXPORT_SYMBOL_GPL(st_nci_probe);
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 850a239..858e8e6 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -20,6 +20,7 @@
#define __LOCAL_ST_NCI_H_
#include "st-nci_se.h"
+#include "st-nci_vendor_cmds.h"
#include "ndlc.h"
/* Define private flags: */
@@ -28,6 +29,8 @@
#define ST_NCI_CORE_PROP 0x01
#define ST_NCI_SET_NFC_MODE 0x02
+#define ST_NCI_DEVICE_MGNT_GATE 0x01
+
struct nci_mode_set_cmd {
u8 cmd_type;
u8 mode;
@@ -41,6 +44,7 @@ struct st_nci_info {
struct llt_ndlc *ndlc;
unsigned long flags;
struct st_nci_se_info se_info;
+ struct st_nci_vendor_info vendor_info;
};
void st_nci_remove(struct nci_dev *ndev);
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index a8ae04e..45eda3e 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -24,6 +24,7 @@
#include "st-nci.h"
#include "st-nci_se.h"
+#include "st-nci_vendor_cmds.h"
struct st_nci_pipe_info {
u8 pipe_state;
@@ -40,7 +41,6 @@ struct st_nci_pipe_info {
#define ST_NCI_ESE_HOST_ID 0xc0
/* Gates */
-#define ST_NCI_DEVICE_MGNT_GATE 0x01
#define ST_NCI_APDU_READER_GATE 0xf0
#define ST_NCI_CONNECTIVITY_GATE 0x41
@@ -115,6 +115,8 @@ static struct nci_hci_gate st_nci_gates[] = {
{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
+ {NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
/* Secure element pipes are created by secure element host */
{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
@@ -377,8 +379,10 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
st_nci_hci_apdu_reader_event_received(ndev, event, skb);
break;
case ST_NCI_CONNECTIVITY_GATE:
- st_nci_hci_connectivity_event_received(ndev, host, event,
- skb);
+ st_nci_hci_connectivity_event_received(ndev, host, event, skb);
+ break;
+ case NCI_HCI_LOOPBACK_GATE:
+ st_nci_hci_loopback_event_received(ndev, event, skb);
break;
}
}
@@ -510,6 +514,7 @@ EXPORT_SYMBOL_GPL(st_nci_enable_se);
static int st_nci_hci_network_init(struct nci_dev *ndev)
{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
struct core_conn_create_dest_spec_params *dest_params;
struct dest_spec_params spec_params;
struct nci_conn_info *conn_info;
@@ -562,10 +567,17 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
if (r != NCI_HCI_ANY_OK)
goto free_dest_params;
- r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
- NCI_NFCEE_ENABLE);
- if (r != NCI_STATUS_OK)
- goto free_dest_params;
+ /*
+ * In factory mode, we prevent secure elements activation
+ * by disabling nfcee on the current HCI connection id.
+ * HCI will be used here only for proprietary commands.
+ */
+ if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+ r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+ NCI_NFCEE_DISABLE);
+ else
+ r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+ NCI_NFCEE_ENABLE);
free_dest_params:
kfree(dest_params);
@@ -579,6 +591,7 @@ int st_nci_discover_se(struct nci_dev *ndev)
u8 param[2];
int r;
int se_count = 0;
+ struct st_nci_info *info = nci_get_drvdata(ndev);
pr_debug("st_nci_discover_se\n");
@@ -586,6 +599,9 @@ int st_nci_discover_se(struct nci_dev *ndev)
if (r != 0)
return r;
+ if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+ return 0;
+
param[0] = ST_NCI_UICC_HOST_ID;
param[1] = ST_NCI_HCI_HOST_ID_ESE;
r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
diff --git a/drivers/nfc/st-nci/st-nci_vendor_cmds.c b/drivers/nfc/st-nci/st-nci_vendor_cmds.c
new file mode 100644
index 0000000..4e4247b
--- /dev/null
+++ b/drivers/nfc/st-nci/st-nci_vendor_cmds.c
@@ -0,0 +1,516 @@
+/*
+ * Proprietary commands extension for STMicroelectronics NFC NCI Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/delay.h>
+#include <net/nfc/nci_core.h>
+
+#include "st-nci.h"
+#include "st-nci_vendor_cmds.h"
+
+#define ST_NCI_HCI_DM_GETDATA 0x10
+#define ST_NCI_HCI_DM_PUTDATA 0x11
+#define ST_NCI_HCI_DM_LOAD 0x12
+#define ST_NCI_HCI_DM_GETINFO 0x13
+#define ST_NCI_HCI_DM_FWUPD_START 0x14
+#define ST_NCI_HCI_DM_FWUPD_STOP 0x15
+#define ST_NCI_HCI_DM_UPDATE_AID 0x20
+#define ST_NCI_HCI_DM_RESET 0x3e
+
+#define ST_NCI_HCI_DM_FIELD_GENERATOR 0x32
+#define ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE 0x33
+#define ST_NCI_HCI_DM_VDC_VALUE_COMPARISON 0x34
+
+#define ST_NCI_FACTORY_MODE_ON 1
+#define ST_NCI_FACTORY_MODE_OFF 0
+
+#define ST_NCI_EVT_POST_DATA 0x02
+
+struct get_param_data {
+ u8 gate;
+ u8 data;
+} __packed;
+
+static int st_nci_factory_mode(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ if (data_len != 1)
+ return -EINVAL;
+
+ pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+ switch (((u8 *)data)[0]) {
+ case ST_NCI_FACTORY_MODE_ON:
+ test_and_set_bit(ST_NCI_FACTORY_MODE, &info->flags);
+ break;
+ case ST_NCI_FACTORY_MODE_OFF:
+ clear_bit(ST_NCI_FACTORY_MODE, &info->flags);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int st_nci_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_clear_all_pipes(ndev);
+}
+
+static int st_nci_hci_dm_put_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_PUTDATA, data,
+ data_len, NULL);
+}
+
+static int st_nci_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_get_info(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETINFO,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_GET_INFO, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_get_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETDATA,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_GET_DATA, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_fwupd_start(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ dev->fw_download_in_progress = true;
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FWUPD_START, data, data_len, NULL);
+ if (r)
+ dev->fw_download_in_progress = false;
+
+ return r;
+}
+
+static int st_nci_hci_dm_fwupd_end(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FWUPD_STOP, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_direct_load(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (dev->fw_download_in_progress) {
+ dev->fw_download_in_progress = false;
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_LOAD, data, data_len, NULL);
+ }
+ return -EPROTO;
+}
+
+static int st_nci_hci_dm_reset(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_RESET, data, data_len, NULL);
+ msleep(200);
+
+ return 0;
+}
+
+static int st_nci_hci_get_param(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct get_param_data *param = (struct get_param_data *)data;
+
+ if (data_len < sizeof(struct get_param_data))
+ return -EPROTO;
+
+ r = nci_hci_get_param(ndev, param->gate, param->data, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_GET_PARAM, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_vdc_measurement_value(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (data_len != 4)
+ return -EPROTO;
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_VDC_MEASUREMENT_VALUE, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ if (data_len != 2)
+ return -EPROTO;
+
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_HCI_DM_VDC_VALUE_COMPARISON,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ HCI_DM_VDC_VALUE_COMPARISON, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+ struct sk_buff *skb)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ switch (event) {
+ case ST_NCI_EVT_POST_DATA:
+ info->vendor_info.rx_skb = skb;
+
+ complete(&info->vendor_info.req_completion);
+ break;
+ }
+}
+EXPORT_SYMBOL(st_nci_hci_loopback_event_received);
+
+static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ if (data_len <= 0)
+ return -EPROTO;
+
+ reinit_completion(&info->vendor_info.req_completion);
+ info->vendor_info.rx_skb = NULL;
+
+ r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
+ ST_NCI_EVT_POST_DATA, data, data_len);
+ if (r != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ wait_for_completion_interruptible(&info->vendor_info.req_completion);
+
+ if (!info->vendor_info.rx_skb ||
+ info->vendor_info.rx_skb->len != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
+ ST_NCI_VENDOR_OUI,
+ HCI_LOOPBACK,
+ info->vendor_info.rx_skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+ info->vendor_info.rx_skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+free_skb:
+ kfree_skb(info->vendor_info.rx_skb);
+exit:
+ return r;
+}
+
+static int st_nci_manufacturer_specific(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct sk_buff *msg;
+ struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+ MANUFACTURER_SPECIFIC,
+ sizeof(ndev->manufact_specific_info));
+ if (!msg)
+ return -ENOMEM;
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, sizeof(ndev->manufact_specific_info),
+ &ndev->manufact_specific_info)) {
+ kfree_skb(msg);
+ return -ENOBUFS;
+ }
+
+ return nfc_vendor_cmd_reply(msg);
+}
+
+static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = FACTORY_MODE,
+ .doit = st_nci_factory_mode,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_CLEAR_ALL_PIPES,
+ .doit = st_nci_hci_clear_all_pipes,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_PUT_DATA,
+ .doit = st_nci_hci_dm_put_data,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_UPDATE_AID,
+ .doit = st_nci_hci_dm_update_aid,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_INFO,
+ .doit = st_nci_hci_dm_get_info,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_DATA,
+ .doit = st_nci_hci_dm_get_data,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_DIRECT_LOAD,
+ .doit = st_nci_hci_dm_direct_load,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_RESET,
+ .doit = st_nci_hci_dm_reset,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_GET_PARAM,
+ .doit = st_nci_hci_get_param,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FIELD_GENERATOR,
+ .doit = st_nci_hci_dm_field_generator,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FWUPD_START,
+ .doit = st_nci_hci_dm_fwupd_start,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_FWUPD_END,
+ .doit = st_nci_hci_dm_fwupd_end,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_LOOPBACK,
+ .doit = st_nci_hci_loopback,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_VDC_MEASUREMENT_VALUE,
+ .doit = st_nci_hci_dm_vdc_measurement_value,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = HCI_DM_VDC_VALUE_COMPARISON,
+ .doit = st_nci_hci_dm_vdc_value_comparison,
+ },
+ {
+ .vendor_id = ST_NCI_VENDOR_OUI,
+ .subcmd = MANUFACTURER_SPECIFIC,
+ .doit = st_nci_manufacturer_specific,
+ },
+};
+
+int st_nci_vendor_cmds_init(struct nci_dev *ndev)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ init_completion(&info->vendor_info.req_completion);
+ return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
+ sizeof(st_nci_vendor_cmds));
+}
+EXPORT_SYMBOL(st_nci_vendor_cmds_init);
diff --git a/drivers/nfc/st-nci/st-nci_vendor_cmds.h b/drivers/nfc/st-nci/st-nci_vendor_cmds.h
new file mode 100644
index 0000000..89542da
--- /dev/null
+++ b/drivers/nfc/st-nci/st-nci_vendor_cmds.h
@@ -0,0 +1,88 @@
+/*
+ * Vendor commands extension for STMicroelectronics NFC NCI Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LOCAL_ST_NCI_VENDOR_CMDS_H__
+#define __LOCAL_ST_NCI_VENDOR_CMDS_H__
+
+#define ST_NCI_VENDOR_OUI 0x0080E1 /* STMicroelectronics */
+
+#define ST_NCI_FACTORY_MODE 2
+
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ * are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ * It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ * RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ * table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ * level drivers configurations or RF trimmings.
+ * @HCI_DM_DIRECT_LOAD: Allow to load a firmware into the CLF. A complete
+ * packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ * configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ * white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ * technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ * connectivity.
+ * @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
+ * CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
+ * @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
+ * specific CLF command as there is no GPIO for this.
+ * @HCI_DM_FWUPD_END: Allow to complete firmware update.
+ * @HCI_DM_VDC_VALUE_COMPARISON: Allow to compare the field applied on the
+ * CLF antenna to a reference value.
+ * @MANUFACTURER_SPECIFIC: Allow to retrieve manufacturer specific data
+ * received during a NCI_CORE_INIT_CMD.
+ */
+enum nfc_vendor_cmds {
+ FACTORY_MODE,
+ HCI_CLEAR_ALL_PIPES,
+ HCI_DM_PUT_DATA,
+ HCI_DM_UPDATE_AID,
+ HCI_DM_GET_INFO,
+ HCI_DM_GET_DATA,
+ HCI_DM_DIRECT_LOAD,
+ HCI_DM_RESET,
+ HCI_GET_PARAM,
+ HCI_DM_FIELD_GENERATOR,
+ HCI_LOOPBACK,
+ HCI_DM_FWUPD_START,
+ HCI_DM_FWUPD_END,
+ HCI_DM_VDC_MEASUREMENT_VALUE,
+ HCI_DM_VDC_VALUE_COMPARISON,
+ MANUFACTURER_SPECIFIC,
+};
+
+struct st_nci_vendor_info {
+ struct completion req_completion;
+ struct sk_buff *rx_skb;
+};
+
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+ struct sk_buff *skb);
+int st_nci_vendor_cmds_init(struct nci_dev *ndev);
+
+#endif
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 377f3de..591338f 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -125,6 +125,7 @@ struct nci_conn_info {
/* Gates */
#define NCI_HCI_ADMIN_GATE 0x00
+#define NCI_HCI_LOOPBACK_GATE 0x04
#define NCI_HCI_IDENTITY_MGMT_GATE 0x05
#define NCI_HCI_LINK_MGMT_GATE 0x06
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 20/30] nfc: st-nci: Add ese-present/uicc-present dts properties
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (7 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 18/30] nfc: st-nci: Add support for proprietary commands for factory tests Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
[not found] ` <1445377701-8353-21-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-20 21:48 ` [PATCH 21/30] nfc: st-nci: Increase waiting time between 2 secure element activation Christophe Ricard
` (5 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
In order to align with st21nfca, dts configuration properties ese_present
and uicc_present are made available in st-nci driver.
So far, in early development firmware, because nci_nfcee_mode_set(DISABLE)
was not supported pushed us to try to enable during the secure element
discovery phase.
After several trials on commercial and qualified firmware it appears that
nci_nfcee_mode_set(ENABLE) and nci_nfcee_mode_set(DISABLE) are properly
supported.
Such feature also help us to eventually save some time (~5ms) if only
one secure element is connected.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
.../devicetree/bindings/net/nfc/st-nci-i2c.txt | 7 ++
.../devicetree/bindings/net/nfc/st-nci-spi.txt | 9 +-
drivers/nfc/st-nci/core.c | 4 +-
drivers/nfc/st-nci/i2c.c | 12 ++-
drivers/nfc/st-nci/ndlc.c | 7 +-
drivers/nfc/st-nci/ndlc.h | 5 +-
drivers/nfc/st-nci/spi.c | 12 ++-
drivers/nfc/st-nci/st-nci.h | 3 +-
drivers/nfc/st-nci/st-nci_se.c | 98 ++++++++++++++--------
drivers/nfc/st-nci/st-nci_se.h | 10 ++-
include/linux/platform_data/st-nci.h | 2 +
11 files changed, 123 insertions(+), 46 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt b/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
index d707588..263732e 100644
--- a/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
@@ -11,6 +11,10 @@ Required properties:
Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.
+- ese-present: Specifies that an ese is physically connected to the nfc
+controller.
+- uicc-present: Specifies that the uicc swp signal can be physically
+connected to the nfc controller.
Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
@@ -29,5 +33,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+
+ ese-present;
+ uicc-present;
};
};
diff --git a/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt b/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
index 525681b..711ca85 100644
--- a/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
@@ -2,7 +2,7 @@
Required properties:
- compatible: Should be "st,st21nfcb-spi"
-- spi-max-frequency: Maximum SPI frequency (<= 10000000).
+- spi-max-frequency: Maximum SPI frequency (<= 4000000).
- interrupt-parent: phandle for the interrupt gpio controller
- interrupts: GPIO interrupt to which the chip is connected
- reset-gpios: Output GPIO pin used to reset the ST21NFCB
@@ -10,6 +10,10 @@ Required properties:
Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.
+- ese-present: Specifies that an ese is physically connected to the nfc
+controller.
+- uicc-present: Specifies that the uicc swp signal can be physically
+connected to the nfc controller.
Example (for ARM-based BeagleBoard xM with ST21NFCB on SPI4):
@@ -27,5 +31,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on SPI4):
interrupts = <2 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+
+ ese-present;
+ uicc-present;
};
};
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index fd2a5ca..e88c882 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -125,7 +125,7 @@ static struct nci_ops st_nci_ops = {
};
int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
- int phy_tailroom)
+ int phy_tailroom, struct st_nci_se_status *se_status)
{
struct st_nci_info *info;
int r;
@@ -166,7 +166,7 @@ int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
goto err_reg_dev;
}
- return st_nci_se_init(ndlc->ndev);
+ return st_nci_se_init(ndlc->ndev, se_status);
err_reg_dev:
nci_free_device(ndlc->ndev);
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 707ed2e..a2700a6 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -52,6 +52,8 @@ struct st_nci_i2c_phy {
unsigned int gpio_reset;
unsigned int irq_polarity;
+
+ struct st_nci_se_status se_status;
};
#define I2C_DUMP_SKB(info, skb) \
@@ -245,6 +247,11 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
phy->irq_polarity = irq_get_trigger_type(client->irq);
+ phy->se_status.is_ese_present =
+ of_property_read_bool(pp, "ese-present");
+ phy->se_status.is_uicc_present =
+ of_property_read_bool(pp, "uicc-present");
+
return 0;
}
#else
@@ -277,6 +284,9 @@ static int st_nci_i2c_request_resources(struct i2c_client *client)
return r;
}
+ phy->se_status.is_ese_present = pdata->is_ese_present;
+ phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
return 0;
}
@@ -326,7 +336,7 @@ static int st_nci_i2c_probe(struct i2c_client *client,
r = ndlc_probe(phy, &i2c_phy_ops, &client->dev,
ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
- &phy->ndlc);
+ &phy->ndlc, &phy->se_status);
if (r < 0) {
nfc_err(&client->dev, "Unable to register ndlc layer\n");
return r;
diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c
index d2cf84e..0884b11 100644
--- a/drivers/nfc/st-nci/ndlc.c
+++ b/drivers/nfc/st-nci/ndlc.c
@@ -19,8 +19,8 @@
#include <linux/sched.h>
#include <net/nfc/nci_core.h>
-#include "ndlc.h"
#include "st-nci.h"
+#include "ndlc.h"
#define NDLC_TIMER_T1 100
#define NDLC_TIMER_T1_WAIT 400
@@ -266,7 +266,8 @@ static void ndlc_t2_timeout(unsigned long data)
}
int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
- int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id)
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+ struct st_nci_se_status *se_status)
{
struct llt_ndlc *ndlc;
@@ -296,7 +297,7 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
- return st_nci_probe(ndlc, phy_headroom, phy_tailroom);
+ return st_nci_probe(ndlc, phy_headroom, phy_tailroom, se_status);
}
EXPORT_SYMBOL(ndlc_probe);
diff --git a/drivers/nfc/st-nci/ndlc.h b/drivers/nfc/st-nci/ndlc.h
index 6361005..d3b6db7 100644
--- a/drivers/nfc/st-nci/ndlc.h
+++ b/drivers/nfc/st-nci/ndlc.h
@@ -22,6 +22,8 @@
#include <linux/skbuff.h>
#include <net/nfc/nfc.h>
+#include "st-nci_se.h"
+
/* Low Level Transport description */
struct llt_ndlc {
struct nci_dev *ndev;
@@ -55,6 +57,7 @@ void ndlc_close(struct llt_ndlc *ndlc);
int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb);
void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb);
int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
- int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id);
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+ struct st_nci_se_status *se_status);
void ndlc_remove(struct llt_ndlc *ndlc);
#endif /* __LOCAL_NDLC_H__ */
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index 887d308..c37ecd4 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -53,6 +53,8 @@ struct st_nci_spi_phy {
unsigned int gpio_reset;
unsigned int irq_polarity;
+
+ struct st_nci_se_status se_status;
};
#define SPI_DUMP_SKB(info, skb) \
@@ -260,6 +262,11 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
phy->irq_polarity = irq_get_trigger_type(dev->irq);
+ phy->se_status.is_ese_present =
+ of_property_read_bool(pp, "ese-present");
+ phy->se_status.is_uicc_present =
+ of_property_read_bool(pp, "uicc-present");
+
return 0;
}
#else
@@ -292,6 +299,9 @@ static int st_nci_spi_request_resources(struct spi_device *dev)
return r;
}
+ phy->se_status.is_ese_present = pdata->is_ese_present;
+ phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
return 0;
}
@@ -342,7 +352,7 @@ static int st_nci_spi_probe(struct spi_device *dev)
r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
- &phy->ndlc);
+ &phy->ndlc, &phy->se_status);
if (r < 0) {
nfc_err(&dev->dev, "Unable to register ndlc layer\n");
return r;
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 858e8e6..b0174a9 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -43,12 +43,13 @@ struct nci_mode_set_rsp {
struct st_nci_info {
struct llt_ndlc *ndlc;
unsigned long flags;
+
struct st_nci_se_info se_info;
struct st_nci_vendor_info vendor_info;
};
void st_nci_remove(struct nci_dev *ndev);
int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
- int phy_tailroom);
+ int phy_tailroom, struct st_nci_se_status *se_status);
#endif /* __LOCAL_ST_NCI_H_ */
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index 45eda3e..28f3c41 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -415,12 +415,8 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
}
EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received);
-/*
- * Remarks: On some early st_nci firmware, nci_nfcee_mode_set(0)
- * is rejected
- */
static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
- u8 state)
+ u8 state)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
int r;
@@ -445,7 +441,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
* retrieve a relevant host list.
*/
reinit_completion(&info->se_info.req_completion);
- r = nci_nfcee_mode_set(ndev, se_idx, NCI_NFCEE_ENABLE);
+ r = nci_nfcee_mode_set(ndev, se_idx, state);
if (r != NCI_STATUS_OK)
return r;
@@ -461,7 +457,9 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
* There is no possible synchronization to prevent this.
* Adding a small delay is the only way to solve the issue.
*/
- usleep_range(3000, 5000);
+ if (info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present)
+ usleep_range(3000, 5000);
r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
@@ -484,11 +482,20 @@ int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
pr_debug("st_nci_disable_se\n");
- if (se_idx == NFC_SE_EMBEDDED) {
- r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
- ST_NCI_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
- if (r < 0)
- return r;
+ /*
+ * According to upper layer, se_idx == NFC_SE_UICC when
+ * info->se_info.se_status->is_uicc_enable is true should never happen
+ * Same for eSE.
+ */
+ r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_OFF);
+ if (r < 0) {
+ /* Do best effort to release SWP */
+ if (se_idx == NFC_SE_EMBEDDED) {
+ r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_SE_END_OF_APDU_TRANSFER,
+ NULL, 0);
+ }
+ return r;
}
return 0;
@@ -501,11 +508,25 @@ int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
pr_debug("st_nci_enable_se\n");
- if (se_idx == ST_NCI_HCI_HOST_ID_ESE) {
+ /*
+ * According to upper layer, se_idx == NFC_SE_UICC when
+ * info->se_info.se_status->is_uicc_enable is true should never happen.
+ * Same for eSE.
+ */
+ r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON);
+ if (r == ST_NCI_HCI_HOST_ID_ESE) {
+ st_nci_se_get_atr(ndev);
r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
- if (r < 0)
- return r;
+ }
+
+ if (r < 0) {
+ /*
+ * The activation procedure failed, the secure element
+ * is not connected. Remove from the list.
+ */
+ nfc_remove_se(ndev->nfc_dev, se_idx);
+ return r;
}
return 0;
@@ -588,8 +609,8 @@ exit:
int st_nci_discover_se(struct nci_dev *ndev)
{
- u8 param[2];
- int r;
+ u8 white_list[2];
+ int r, wl_size = 0;
int se_count = 0;
struct st_nci_info *info = nci_get_drvdata(ndev);
@@ -602,29 +623,34 @@ int st_nci_discover_se(struct nci_dev *ndev)
if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
return 0;
- param[0] = ST_NCI_UICC_HOST_ID;
- param[1] = ST_NCI_HCI_HOST_ID_ESE;
- r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
- NCI_HCI_ADMIN_PARAM_WHITELIST,
- param, sizeof(param));
- if (r != NCI_HCI_ANY_OK)
- return r;
+ if (info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+ white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+ } else if (!info->se_info.se_status->is_ese_present &&
+ info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+ } else if (info->se_info.se_status->is_ese_present &&
+ !info->se_info.se_status->is_uicc_present) {
+ white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+ }
+
+ if (wl_size) {
+ r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
+ NCI_HCI_ADMIN_PARAM_WHITELIST,
+ white_list, wl_size);
+ if (r != NCI_HCI_ANY_OK)
+ return r;
+ }
- r = st_nci_control_se(ndev, ST_NCI_UICC_HOST_ID,
- ST_NCI_SE_MODE_ON);
- if (r == ST_NCI_UICC_HOST_ID) {
+ if (info->se_info.se_status->is_uicc_present) {
nfc_add_se(ndev->nfc_dev, ST_NCI_UICC_HOST_ID, NFC_SE_UICC);
se_count++;
}
- /* Try to enable eSE in order to check availability */
- r = st_nci_control_se(ndev, ST_NCI_HCI_HOST_ID_ESE,
- ST_NCI_SE_MODE_ON);
- if (r == ST_NCI_HCI_HOST_ID_ESE) {
- nfc_add_se(ndev->nfc_dev, ST_NCI_HCI_HOST_ID_ESE,
- NFC_SE_EMBEDDED);
+ if (info->se_info.se_status->is_ese_present) {
+ nfc_add_se(ndev->nfc_dev, ST_NCI_ESE_HOST_ID, NFC_SE_EMBEDDED);
se_count++;
- st_nci_se_get_atr(ndev);
}
return !se_count;
@@ -697,7 +723,7 @@ static void st_nci_se_activation_timeout(unsigned long data)
complete(&info->se_info.req_completion);
}
-int st_nci_se_init(struct nci_dev *ndev)
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
@@ -719,6 +745,8 @@ int st_nci_se_init(struct nci_dev *ndev)
info->se_info.wt_timeout =
ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI);
+ info->se_info.se_status = se_status;
+
return 0;
}
EXPORT_SYMBOL(st_nci_se_init);
diff --git a/drivers/nfc/st-nci/st-nci_se.h b/drivers/nfc/st-nci/st-nci_se.h
index ea66e87..e3f8e7e 100644
--- a/drivers/nfc/st-nci/st-nci_se.h
+++ b/drivers/nfc/st-nci/st-nci_se.h
@@ -18,6 +18,8 @@
#ifndef __LOCAL_ST_NCI_SE_H_
#define __LOCAL_ST_NCI_SE_H_
+#include <net/nfc/nci_core.h>
+
/*
* ref ISO7816-3 chap 8.1. the initial character TS is followed by a
* sequence of at most 32 characters.
@@ -25,7 +27,13 @@
#define ST_NCI_ESE_MAX_LENGTH 33
#define ST_NCI_HCI_HOST_ID_ESE 0xc0
+struct st_nci_se_status {
+ bool is_ese_present;
+ bool is_uicc_present;
+};
+
struct st_nci_se_info {
+ struct st_nci_se_status *se_status;
u8 atr[ST_NCI_ESE_MAX_LENGTH];
struct completion req_completion;
@@ -42,7 +50,7 @@ struct st_nci_se_info {
void *cb_context;
};
-int st_nci_se_init(struct nci_dev *ndev);
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status);
void st_nci_se_deinit(struct nci_dev *ndev);
int st_nci_discover_se(struct nci_dev *ndev);
diff --git a/include/linux/platform_data/st-nci.h b/include/linux/platform_data/st-nci.h
index d9d400a..f6494b3 100644
--- a/include/linux/platform_data/st-nci.h
+++ b/include/linux/platform_data/st-nci.h
@@ -24,6 +24,8 @@
struct st_nci_nfc_platform_data {
unsigned int gpio_reset;
unsigned int irq_polarity;
+ bool is_ese_present;
+ bool is_uicc_present;
};
#endif /* _ST_NCI_H_ */
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 21/30] nfc: st-nci: Increase waiting time between 2 secure element activation
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (8 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 20/30] nfc: st-nci: Add ese-present/uicc-present dts properties Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 24/30] nfc: netlink: Add suspend_target handler and nfc_reactivate_target Christophe Ricard
` (4 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
After internal discussion, it appears this timing should be increase to
20 ms for interoperability reason.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/st-nci_se.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index 28f3c41..ee53fc0 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -459,7 +459,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
*/
if (info->se_info.se_status->is_ese_present &&
info->se_info.se_status->is_uicc_present)
- usleep_range(3000, 5000);
+ usleep_range(15000, 20000);
r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 24/30] nfc: netlink: Add suspend_target handler and nfc_reactivate_target
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (9 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 21/30] nfc: st-nci: Increase waiting time between 2 secure element activation Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
[not found] ` <1445377701-8353-25-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-20 21:48 ` [PATCH 25/30] nfc: st-nci: Add few code style fixes Christophe Ricard
` (3 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
In order to manage in a better way the nci poll mode state machine, add
a suspend_target handler. In this way the netlink nfc_genl_activate_target
rely on a new function nfc_reactivate_target calling suspend_target handler
if available (only in nci core).
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
include/net/nfc/nfc.h | 2 ++
net/nfc/core.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
net/nfc/nci/core.c | 23 +++++++++++++++++++----
net/nfc/netlink.c | 3 +--
net/nfc/nfc.h | 2 ++
5 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 30afc9a..380ab8b 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -67,6 +67,8 @@ struct nfc_ops {
int (*dep_link_down)(struct nfc_dev *dev);
int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target,
u32 protocol);
+ void (*suspend_target)(struct nfc_dev *dev,
+ struct nfc_target *target);
void (*deactivate_target)(struct nfc_dev *dev,
struct nfc_target *target);
int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target,
diff --git a/net/nfc/core.c b/net/nfc/core.c
index cff3f16..70276b6 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -485,6 +485,52 @@ error:
}
/**
+ * nfc_reactivate_target - reactivate the target for data exchange
+ *
+ * @dev: The nfc device that found the target
+ * @target_idx: index of the target that must be activated
+ * @protocol: nfc protocol that will be used for data exchange
+ */
+int nfc_reactivate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
+{
+ int rc = 0;
+
+ pr_debug("dev_name=%s target_idx=%u\n",
+ dev_name(&dev->dev), target_idx);
+
+ device_lock(&dev->dev);
+
+ if (!device_is_registered(&dev->dev)) {
+ rc = -ENODEV;
+ goto error;
+ }
+
+ if (!dev->active_target) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
+ if (dev->active_target->idx != target_idx) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
+ if (dev->ops->check_presence)
+ del_timer_sync(&dev->check_pres_timer);
+
+ if (dev->ops->suspend_target)
+ dev->ops->suspend_target(dev, dev->active_target);
+
+ dev->active_target = NULL;
+ device_unlock(&dev->dev);
+
+ return nfc_activate_target(dev, target_idx, protocol);
+error:
+ device_unlock(&dev->dev);
+ return rc;
+}
+
+/**
* nfc_data_exchange - transceive data
*
* @dev: The nfc device that found the target
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 943889b..b45d6e3 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -800,8 +800,9 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
return rc;
}
-static void nci_deactivate_target(struct nfc_dev *nfc_dev,
- struct nfc_target *target)
+static void nci_deactivate_target_mode(struct nfc_dev *nfc_dev,
+ struct nfc_target *target,
+ __u8 mode)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
@@ -815,12 +816,25 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
ndev->target_active_prot = 0;
if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
- nci_request(ndev, nci_rf_deactivate_req,
- NCI_DEACTIVATE_TYPE_IDLE_MODE,
+ nci_request(ndev, nci_rf_deactivate_req, mode,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}
}
+static void nci_deactivate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
+{
+ nci_deactivate_target_mode(nfc_dev, target,
+ NCI_DEACTIVATE_TYPE_IDLE_MODE);
+}
+
+static void nci_suspend_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
+{
+ nci_deactivate_target_mode(nfc_dev, target,
+ NCI_DEACTIVATE_TYPE_SLEEP_MODE);
+}
+
static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
__u8 comm_mode, __u8 *gb, size_t gb_len)
{
@@ -979,6 +993,7 @@ static struct nfc_ops nci_nfc_ops = {
.dep_link_up = nci_dep_link_up,
.dep_link_down = nci_dep_link_down,
.activate_target = nci_activate_target,
+ .suspend_target = nci_suspend_target,
.deactivate_target = nci_deactivate_target,
.im_transceive = nci_transceive,
.tm_send = nci_tm_send,
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 853172c..bb0e098 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -885,8 +885,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
- nfc_deactivate_target(dev, target_idx);
- rc = nfc_activate_target(dev, target_idx, protocol);
+ rc = nfc_reactivate_target(dev, target_idx, protocol);
nfc_put_device(dev);
return 0;
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 5c93e84..6250c6e 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -147,6 +147,8 @@ int nfc_dep_link_down(struct nfc_dev *dev);
int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
+int nfc_reactivate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
+
int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 25/30] nfc: st-nci: Add few code style fixes
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (10 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 24/30] nfc: netlink: Add suspend_target handler and nfc_reactivate_target Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 27/30] nfc: st21nfca: Add support for proprietary commands for factory tests Christophe Ricard
` (2 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA, stable-u79uwXL29TY76Z2rM5mHXA
Add some few code style fixes.
Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/i2c.c | 2 +-
drivers/nfc/st-nci/st-nci_se.c | 2 +-
net/nfc/nci/hci.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index a2700a6..8b53cdf 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -32,7 +32,7 @@
#define DRIVER_DESC "NCI NFC driver for ST_NCI"
/* ndlc header */
-#define ST_NCI_FRAME_HEADROOM 1
+#define ST_NCI_FRAME_HEADROOM 1
#define ST_NCI_FRAME_TAILROOM 0
#define ST_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
diff --git a/drivers/nfc/st-nci/st-nci_se.c b/drivers/nfc/st-nci/st-nci_se.c
index 8886072..3d874a0 100644
--- a/drivers/nfc/st-nci/st-nci_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -64,7 +64,7 @@ struct st_nci_pipe_info {
#define ST_NCI_EVT_SE_HARD_RESET 0x20
#define ST_NCI_EVT_TRANSMIT_DATA 0x10
-#define ST_NCI_EVT_WTX_REQUEST 0x11
+#define ST_NCI_EVT_WTX_REQUEST 0x11
#define ST_NCI_EVT_SE_SOFT_RESET 0x11
#define ST_NCI_EVT_SE_END_OF_APDU_TRANSFER 0x21
#define ST_NCI_EVT_HOT_PLUG 0x03
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 5212ef2..d82fdef 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -405,7 +405,7 @@ static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
break;
}
- nci_req_complete(ndev, 0);
+ nci_req_complete(ndev, NCI_STATUS_OK);
}
static void nci_hci_msg_rx_work(struct work_struct *work)
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 27/30] nfc: st21nfca: Add support for proprietary commands for factory tests
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (11 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 25/30] nfc: st-nci: Add few code style fixes Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 28/30] nfc: st-nci: Make sure irq is not already active when powering the device Christophe Ricard
2015-10-20 21:48 ` [PATCH 30/30] nfc: st-nci: Replace st21nfcb by st_nci in makefile Christophe Ricard
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
Add support for proprietary commands useful mainly for factory testings.
Here is a list:
- FACTORY_MODE: Allow to set the driver into a mode where no secure element
are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
RF trimmings or low level drivers configurations (I2C, SPI, SWP).
- HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
table following RF technology, CLF mode or protocol.
- HCI_DM_GET_INFO: Allow to retrieve CLF information.
- HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
level drivers configurations or RF trimmings.
- HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete
packet can be more than 8KB.
- HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
configuration changes without CLF power off.
- HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
white list).
- HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
technology. When using this command to anti-collision is done.
- HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
connectivity.
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st21nfca/Makefile | 2 +-
drivers/nfc/st21nfca/st21nfca.c | 4 +
drivers/nfc/st21nfca/st21nfca.h | 4 +-
drivers/nfc/st21nfca/st21nfca_se.c | 4 +-
drivers/nfc/st21nfca/st21nfca_vendor_cmds.c | 369 ++++++++++++++++++++++++++++
drivers/nfc/st21nfca/st21nfca_vendor_cmds.h | 74 ++++++
6 files changed, 454 insertions(+), 3 deletions(-)
create mode 100644 drivers/nfc/st21nfca/st21nfca_vendor_cmds.c
create mode 100644 drivers/nfc/st21nfca/st21nfca_vendor_cmds.h
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 97edab4..e817c72 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -2,7 +2,7 @@
# Makefile for ST21NFCA HCI based NFC driver
#
-st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o
+st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o st21nfca_vendor_cmds.o
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o
st21nfca_i2c-objs = i2c.o
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index 76ef9cf..bf82459 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -24,6 +24,7 @@
#include "st21nfca.h"
#include "st21nfca_dep.h"
#include "st21nfca_se.h"
+#include "st21nfca_vendor_cmds.h"
#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
@@ -923,6 +924,8 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
event, skb);
case ST21NFCA_APDU_READER_GATE:
return st21nfca_apdu_reader_event_received(hdev, event, skb);
+ case NFC_HCI_LOOPBACK_GATE:
+ return st21nfca_hci_loopback_event_received(hdev, event, skb);
default:
return 1;
}
@@ -1024,6 +1027,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
*hdev = info->hdev;
st21nfca_dep_init(info->hdev);
st21nfca_se_init(info->hdev);
+ st21nfca_vendor_cmds_init(info->hdev);
return 0;
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 15a78d3..070136b 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -21,6 +21,7 @@
#include "st21nfca_dep.h"
#include "st21nfca_se.h"
+#include "st21nfca_vendor_cmds.h"
#define HCI_MODE 0
@@ -60,7 +61,7 @@ struct st21nfca_se_status {
int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
char *llc_name, int phy_headroom, int phy_tailroom,
int phy_payload, struct nfc_hci_dev **hdev,
- struct st21nfca_se_status *se_status);
+ struct st21nfca_se_status *se_status);
void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
enum st21nfca_state {
@@ -85,6 +86,7 @@ struct st21nfca_hci_info {
struct st21nfca_dep_info dep_info;
struct st21nfca_se_info se_info;
+ struct st21nfca_vendor_info vendor_info;
};
/* Reader RF commands */
diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/st21nfca_se.c
index 0eb42ef..646c340 100644
--- a/drivers/nfc/st21nfca/st21nfca_se.c
+++ b/drivers/nfc/st21nfca/st21nfca_se.c
@@ -168,6 +168,9 @@ int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
int se_count = 0;
+ if (test_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks))
+ return 0;
+
if (info->se_status->is_uicc_present) {
nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
se_count++;
@@ -192,7 +195,6 @@ int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
* Same for eSE.
*/
r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
-
if (r == ST21NFCA_ESE_HOST_ID) {
st21nfca_se_get_atr(hdev);
r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
diff --git a/drivers/nfc/st21nfca/st21nfca_vendor_cmds.c b/drivers/nfc/st21nfca/st21nfca_vendor_cmds.c
new file mode 100644
index 0000000..e7b1842
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_vendor_cmds.c
@@ -0,0 +1,369 @@
+/*
+ * Proprietary commands extension for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "st21nfca.h"
+#include "st21nfca_vendor_cmds.h"
+
+#define ST21NFCA_HCI_DM_GETDATA 0x10
+#define ST21NFCA_HCI_DM_PUTDATA 0x11
+#define ST21NFCA_HCI_DM_LOAD 0x12
+#define ST21NFCA_HCI_DM_GETINFO 0x13
+#define ST21NFCA_HCI_DM_UPDATE_AID 0x20
+#define ST21NFCA_HCI_DM_RESET 0x3e
+
+#define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32
+
+#define ST21NFCA_FACTORY_MODE_ON 1
+#define ST21NFCA_FACTORY_MODE_OFF 0
+
+#define ST21NFCA_EVT_POST_DATA 0x02
+
+struct get_param_data {
+ u8 gate;
+ u8 data;
+} __packed;
+
+static int st21nfca_factory_mode(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ if (data_len != 1)
+ return -EINVAL;
+
+ pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+ switch (((u8 *)data)[0]) {
+ case ST21NFCA_FACTORY_MODE_ON:
+ test_and_set_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+ break;
+ case ST21NFCA_FACTORY_MODE_OFF:
+ clear_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int st21nfca_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_disconnect_all_gates(hdev);
+}
+
+static int st21nfca_hci_dm_put_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_PUTDATA, data,
+ data_len, NULL);
+}
+
+static int st21nfca_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_get_info(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_HCI_DM_GETINFO,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_DM_GET_INFO, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_get_data(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_HCI_DM_GETDATA,
+ data, data_len, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_DM_GET_DATA, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_load(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_LOAD, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_reset(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ r = nfc_hci_send_cmd_async(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_RESET, data, data_len, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ r = nfc_llc_stop(hdev->llc);
+ if (r < 0)
+ return r;
+
+ return nfc_llc_start(hdev->llc);
+}
+
+static int st21nfca_hci_get_param(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg, *skb;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+ struct get_param_data *param = (struct get_param_data *)data;
+
+ if (data_len < sizeof(struct get_param_data))
+ return -EPROTO;
+
+ r = nfc_hci_get_param(hdev, param->gate, param->data, &skb);
+ if (r)
+ goto exit;
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+ HCI_GET_PARAM, skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+ kfree_skb(skb);
+exit:
+ return r;
+}
+
+static int st21nfca_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
+}
+
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *hdev, u8 event,
+ struct sk_buff *skb)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ switch (event) {
+ case ST21NFCA_EVT_POST_DATA:
+ info->vendor_info.rx_skb = skb;
+
+ complete(&info->vendor_info.req_completion);
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_loopback_event_received);
+
+static int st21nfca_hci_loopback(struct nfc_dev *dev, void *data,
+ size_t data_len)
+{
+ int r;
+ struct sk_buff *msg;
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ if (data_len <= 0)
+ return -EPROTO;
+
+ reinit_completion(&info->vendor_info.req_completion);
+ info->vendor_info.rx_skb = NULL;
+
+ r = nfc_hci_send_event(hdev, NFC_HCI_LOOPBACK_GATE,
+ ST21NFCA_EVT_POST_DATA, data, data_len);
+ if (r < 0) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ wait_for_completion_interruptible(&info->vendor_info.req_completion);
+ if (!info->vendor_info.rx_skb ||
+ info->vendor_info.rx_skb->len != data_len) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ msg = nfc_vendor_cmd_alloc_reply_skb(hdev->ndev,
+ ST21NFCA_VENDOR_OUI,
+ HCI_LOOPBACK,
+ info->vendor_info.rx_skb->len);
+ if (!msg) {
+ r = -ENOMEM;
+ goto free_skb;
+ }
+
+ if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+ info->vendor_info.rx_skb->data)) {
+ kfree_skb(msg);
+ r = -ENOBUFS;
+ goto free_skb;
+ }
+
+ r = nfc_vendor_cmd_reply(msg);
+free_skb:
+ kfree_skb(info->vendor_info.rx_skb);
+exit:
+ return r;
+}
+
+static struct nfc_vendor_cmd st21nfca_vendor_cmds[] = {
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = FACTORY_MODE,
+ .doit = st21nfca_factory_mode,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_CLEAR_ALL_PIPES,
+ .doit = st21nfca_hci_clear_all_pipes,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_PUT_DATA,
+ .doit = st21nfca_hci_dm_put_data,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_UPDATE_AID,
+ .doit = st21nfca_hci_dm_update_aid,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_INFO,
+ .doit = st21nfca_hci_dm_get_info,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_GET_DATA,
+ .doit = st21nfca_hci_dm_get_data,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_LOAD,
+ .doit = st21nfca_hci_dm_load,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_RESET,
+ .doit = st21nfca_hci_dm_reset,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_GET_PARAM,
+ .doit = st21nfca_hci_get_param,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_DM_FIELD_GENERATOR,
+ .doit = st21nfca_hci_dm_field_generator,
+ },
+ {
+ .vendor_id = ST21NFCA_VENDOR_OUI,
+ .subcmd = HCI_LOOPBACK,
+ .doit = st21nfca_hci_loopback,
+ },
+};
+
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *hdev)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ init_completion(&info->vendor_info.req_completion);
+ return nfc_set_vendor_cmds(hdev->ndev, st21nfca_vendor_cmds,
+ sizeof(st21nfca_vendor_cmds));
+}
+EXPORT_SYMBOL(st21nfca_vendor_cmds_init);
diff --git a/drivers/nfc/st21nfca/st21nfca_vendor_cmds.h b/drivers/nfc/st21nfca/st21nfca_vendor_cmds.h
new file mode 100644
index 0000000..da06a79
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_vendor_cmds.h
@@ -0,0 +1,74 @@
+/*
+ * Vendor commands extension for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LOCAL_ST21NFCA_VENDOR_CMDS_H__
+#define __LOCAL_ST21NFCA_VENDOR_CMDS_H__
+
+#define ST21NFCA_VENDOR_OUI 0x0080E1 /* STMicroelectronics */
+
+#define ST21NFCA_FACTORY_MODE 2
+
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ * are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ * It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ * RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ * table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ * level drivers configurations or RF trimmings.
+ * @HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete
+ * packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ * configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ * white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ * technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ * connectivity.
+ */
+enum nfc_vendor_cmds {
+ FACTORY_MODE,
+ HCI_CLEAR_ALL_PIPES,
+ HCI_DM_PUT_DATA,
+ HCI_DM_UPDATE_AID,
+ HCI_DM_GET_INFO,
+ HCI_DM_GET_DATA,
+ HCI_DM_LOAD,
+ HCI_DM_RESET,
+ HCI_GET_PARAM,
+ HCI_DM_FIELD_GENERATOR,
+ HCI_LOOPBACK,
+};
+
+struct st21nfca_vendor_info {
+ struct completion req_completion;
+ struct sk_buff *rx_skb;
+};
+
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *ndev, u8 event,
+ struct sk_buff *skb);
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *ndev);
+
+#endif
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 28/30] nfc: st-nci: Make sure irq is not already active when powering the device
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (12 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 27/30] nfc: st21nfca: Add support for proprietary commands for factory tests Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
2015-10-20 21:48 ` [PATCH 30/30] nfc: st-nci: Replace st21nfcb by st_nci in makefile Christophe Ricard
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
Upon some conditions (timing, CLF errors, platform errors...), the irq might
be already active when powering the device.
Add irq_active variable as a guard to avoid kernel warning message
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/i2c.c | 8 +++++++-
drivers/nfc/st-nci/spi.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 8b53cdf..13f5054 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -50,6 +50,8 @@ struct st_nci_i2c_phy {
struct i2c_client *i2c_dev;
struct llt_ndlc *ndlc;
+ bool irq_active;
+
unsigned int gpio_reset;
unsigned int irq_polarity;
@@ -72,8 +74,10 @@ static int st_nci_i2c_enable(void *phy_id)
gpio_set_value(phy->gpio_reset, 1);
usleep_range(80000, 85000);
- if (phy->ndlc->powered == 0)
+ if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
enable_irq(phy->i2c_dev->irq);
+ phy->irq_active = true;
+ }
return 0;
}
@@ -83,6 +87,7 @@ static void st_nci_i2c_disable(void *phy_id)
struct st_nci_i2c_phy *phy = phy_id;
disable_irq_nosync(phy->i2c_dev->irq);
+ phy->irq_active = false;
}
/*
@@ -342,6 +347,7 @@ static int st_nci_i2c_probe(struct i2c_client *client,
return r;
}
+ phy->irq_active = true;
r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
st_nci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index c37ecd4..10404c9 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -51,6 +51,8 @@ struct st_nci_spi_phy {
struct spi_device *spi_dev;
struct llt_ndlc *ndlc;
+ bool irq_active;
+
unsigned int gpio_reset;
unsigned int irq_polarity;
@@ -73,8 +75,10 @@ static int st_nci_spi_enable(void *phy_id)
gpio_set_value(phy->gpio_reset, 1);
usleep_range(80000, 85000);
- if (phy->ndlc->powered == 0)
+ if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
enable_irq(phy->spi_dev->irq);
+ phy->irq_active = true;
+ }
return 0;
}
@@ -84,6 +88,7 @@ static void st_nci_spi_disable(void *phy_id)
struct st_nci_spi_phy *phy = phy_id;
disable_irq_nosync(phy->spi_dev->irq);
+ phy->irq_active = false;
}
/*
@@ -358,6 +363,7 @@ static int st_nci_spi_probe(struct spi_device *dev)
return r;
}
+ phy->irq_active = true;
r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
st_nci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread* [PATCH 30/30] nfc: st-nci: Replace st21nfcb by st_nci in makefile
[not found] ` <1445377701-8353-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
` (13 preceding siblings ...)
2015-10-20 21:48 ` [PATCH 28/30] nfc: st-nci: Make sure irq is not already active when powering the device Christophe Ricard
@ 2015-10-20 21:48 ` Christophe Ricard
14 siblings, 0 replies; 42+ messages in thread
From: Christophe Ricard @ 2015-10-20 21:48 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw, christophe-h.ricard-qxv4g6HH51o,
christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA
Replace 1 missing st21nfcb by st_nci
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
drivers/nfc/st-nci/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
index 60e569b..bd74c60 100644
--- a/drivers/nfc/st-nci/Makefile
+++ b/drivers/nfc/st-nci/Makefile
@@ -1,5 +1,5 @@
#
-# Makefile for ST21NFCB NCI based NFC driver
+# Makefile for ST_NCI NCI based NFC driver
#
st-nci-objs = ndlc.o core.o st-nci_se.o st-nci_vendor_cmds.o
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 42+ messages in thread