All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/34] Minor clean & Secure Element support for ST21NFCA/ST21NFCB
@ 2014-12-08 21:08 Christophe Ricard
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  0 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Samuel,

I think it is time to drop the ongoing work for Secure Element support for
a first review.

I guess patches #1, #2, #3, #4, #13, #14, #16, #17, #18 and #34 are sanity patches.
May be they could target a second pull request for 3.19 (?)
Most likely:
- #1 and #2 are a resend from the previous patchset trying to not break an
ABI. If you believe they are not necessary, i will understand.
- #3 and #4 are taking into account feedbacks from Dan Carpenter & Julia Lawall.
- #13, #14, #16 and #18 are just sanity patches
- #17 and #34 remove a memory leaks

Secure Element support for HCI based NFC controller:
--------------------------------------------
I am changing a little bit the way pipes and gates are referenced because 1 gate
on the Terminal Host may connect severals differents Host (e.g: UICC, eSE...). 
I chose to reference a pipe with a tuple {gate, host}.
I chose also to keep the gate --> pipe reference with a little drawback:
- se_io will only be able to send data to an eSE (over SWP)... To my knowledge
the aren't any UICC with APDU Reader gate available in the field.

Overall patches:
- #5 to #12 are introducing this pipe referencing changes.
- #15 and #19 are introducing Secure Element complete support for ST21NFCA.

Secure Element support for NCI based NFC controller:
----------------------------------------------------
I have to introduce dynnamic conn_id management has described in the NCI
specification. Only RF static conn_id was supported so far. I have tried to 
do a minimun changeset in order to bring all the necessary NCI functions in
order to operate with a secure element with ST21NFCB NFC controller. Besides the
standard NCI commands, the HCI commands are sent following a proprietary
implementation.

Overall patches:
- #20 to #26 are introducing NCI core changes in order to be able to support
secure element communication.
- #27 is bringing support for HCI protocol allowing to send HCI data over NCI.
- #28 is introducing Secure Element support for ST21NFCB.


Miscellaneous
-------------
I am also routing the HCI event TRANSACTION up to user space. It may help to understand
the necessity to reference every pipe with a tuple {gate, host}. This for example allows 
to keep the host information generating this particular event.

Open Questions:
---------------
Both integration may have little gap in their card emulation behavior.
For example:
- ST21NFCA will have card emulation active as soon as we activate a secure element.
- ST21NFCB will have card emulation active according to the selected polling mode.
When do you expect to have card emulation to be active ?

When an application is running, it might be necessary to signals to the under layers
that it has finished to operate with a particular secure element. The goal here is to release
a secure element without deactivating it. For example to allow automatic sleep mode.
With my current implementation, 
- With ST21NFCB, enable_se/disable_se may fit this request as both secure element are kept activated.
- With ST21NFCA, enable_se/disable_se does not fit this requirement as i am completely deactivating 
the secure element.
I am not sure if the SE activation should not be done in the discovery_se without any deactivation 
until the device remove function(?).

Any feedback are welcome.

Best Regards
Christophe

Christophe Ricard (34):
  NFC: dts: st21nfca: Fix compatible string spelling to follow other
    drivers
  NFC: dts: st21nfcb: Fix compatible string spelling to follow other
    drivers
  NFC: st21nfcb: Fix "WARNING: invalid free of devm_ allocated data"
  NFC: st21nfca: Remove unreachable code
  NFC: hci: Change event_received handler gate parameter to pipe
  NFC: hci: Add pipes table to reference them with a tuple {gate, host}
  NFC: hci: Change nfc_hci_send_response gate parameter to pipe
  NFC: hci: Reference every pipe information according to notification
  NFC: hci: Add cmd_received handler
  NFC: pn544: Change event_received gate parameter to pipe
  NFC: microread: Change event_received gate parameter to pipe
  NFC: hci: Remove nfc_hci_pipe2gate function
  NFC: nfc_enable_se Remove useless blank line at beginning of function
  NFC: nfc_disable_se Remove useless blank line at beginning of function
  NFC: st21nfca: Adding support for secure element
  NFC: st21nfca: Remove useless ST21NFCA_SE_HOST_EVT_HOT_PLUG macro
  NFC: st21nfca: Remove skb_pipe_list and skb_pipe_info useless
    allocation
  NFC: st21nfca: Remove checkpatch.pl warning Possible unnecessary 'out
    of memory' message
  NFC: dts: st21nfca: Document ese-present & uicc-present DTS property
  NFC: nci: Add dynamic conn_id NCI concept.
  NFC: nci: Make nci_request available for nfc driver
  NFC: nci: Add NCI NFCEE constant
  NFC: nci: Add nci_nfcee_discover handler command/response/notification
  NFC: nci: Add nci_nfcee_mode_set handler command/response
  NFC: nci: Add nci_core_conn_create handler command/response
  NFC: nci: Add nci_core_conn_close handler command/response
  NFC: st21nfcb: Add HCI protocol over NCI protocol support
  NFC: st21nfcb: Adding support for secure element
  NFC: Forward NFC_EVT_TRANSACTION up to user space
  NFC: nci: Add support RF_NFCEE_ACTION_NTF
  NFC: nci: Change NCI state machine to LISTEN_ACTIVE and ignore
    parameters in rf_intf_activated_ntf
  NFC: st21nfcb: Add support for HCI event transaction
  NFC: st21nfca: Add support for HCI event transaction
  NFC: st21nfca: Fix some skb memory leaks

 .../devicetree/bindings/net/nfc/st21nfca.txt       |  11 +-
 .../devicetree/bindings/net/nfc/st21nfcb.txt       |   4 +-
 drivers/nfc/microread/microread.c                  |   3 +-
 drivers/nfc/pn544/pn544.c                          |   3 +-
 drivers/nfc/st21nfca/Makefile                      |   2 +-
 drivers/nfc/st21nfca/i2c.c                         |  23 +-
 drivers/nfc/st21nfca/st21nfca.c                    | 186 +++--
 drivers/nfc/st21nfca/st21nfca.h                    |  21 +-
 drivers/nfc/st21nfca/st21nfca_se.c                 | 411 +++++++++++
 drivers/nfc/st21nfca/st21nfca_se.h                 |  63 ++
 drivers/nfc/st21nfcb/Makefile                      |   2 +-
 drivers/nfc/st21nfcb/i2c.c                         |   1 +
 drivers/nfc/st21nfcb/ndlc.c                        |   1 -
 drivers/nfc/st21nfcb/st21nfcb.c                    |   8 +-
 drivers/nfc/st21nfcb/st21nfcb.h                    |   2 +
 drivers/nfc/st21nfcb/st21nfcb_hci_core.c           | 783 +++++++++++++++++++++
 drivers/nfc/st21nfcb/st21nfcb_hci_core.h           | 134 ++++
 drivers/nfc/st21nfcb/st21nfcb_se.c                 | 631 +++++++++++++++++
 drivers/nfc/st21nfcb/st21nfcb_se.h                 |  59 ++
 include/linux/platform_data/st21nfca.h             |   2 +
 include/net/nfc/hci.h                              |  27 +-
 include/net/nfc/nci.h                              |  95 +++
 include/net/nfc/nci_core.h                         |  40 +-
 include/net/nfc/nfc.h                              |  27 +
 include/uapi/linux/nfc.h                           |   1 +
 net/nfc/core.c                                     |  23 +-
 net/nfc/hci/command.c                              |  13 +-
 net/nfc/hci/core.c                                 |  96 ++-
 net/nfc/hci/hci.h                                  |  10 +-
 net/nfc/hci/hcp.c                                  |  11 -
 net/nfc/nci/core.c                                 | 112 ++-
 net/nfc/nci/data.c                                 |  57 +-
 net/nfc/nci/ntf.c                                  |  82 ++-
 net/nfc/nci/rsp.c                                  |  94 ++-
 net/nfc/netlink.c                                  |  47 ++
 net/nfc/nfc.h                                      |   2 +
 36 files changed, 2926 insertions(+), 161 deletions(-)
 create mode 100644 drivers/nfc/st21nfca/st21nfca_se.c
 create mode 100644 drivers/nfc/st21nfca/st21nfca_se.h
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.c
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.h
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_se.c
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_se.h

-- 
2.1.0

--
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	[flat|nested] 45+ messages in thread

* [PATCH v1 01/34] NFC: dts: st21nfca: Fix compatible string spelling to follow other drivers
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 02/34] NFC: dts: st21nfcb: " Christophe Ricard
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Other drivers are following the following compatible string format for dts:
s/_/-/

Because some devices may still use the previous string, the new corrected
string is added to the of_device_id table.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 Documentation/devicetree/bindings/net/nfc/st21nfca.txt | 4 ++--
 drivers/nfc/st21nfca/i2c.c                             | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt
index e4faa2e..db677fe 100644
--- a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt
@@ -1,7 +1,7 @@
 * STMicroelectronics SAS. ST21NFCA NFC Controller
 
 Required properties:
-- compatible: Should be "st,st21nfca_i2c".
+- compatible: Should be "st,st21nfca-i2c".
 - clock-frequency: I²C work frequency.
 - reg: address on the bus
 - interrupt-parent: phandle for the interrupt gpio controller
@@ -20,7 +20,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2):
 
 	st21nfca: st21nfca@1 {
 
-		compatible = "st,st21nfca_i2c";
+		compatible = "st,st21nfca-i2c";
 
 		reg = <0x01>;
 		clock-frequency = <400000>;
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 0572208..b2e0792 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -661,6 +661,7 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client)
 
 #ifdef CONFIG_OF
 static const struct of_device_id of_st21nfca_i2c_match[] = {
+	{ .compatible = "st,st21nfca-i2c", },
 	{ .compatible = "st,st21nfca_i2c", },
 	{}
 };
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 02/34] NFC: dts: st21nfcb: Fix compatible string spelling to follow other drivers
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 01/34] NFC: dts: st21nfca: Fix compatible string spelling to follow other drivers Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 03/34] NFC: st21nfcb: Fix "WARNING: invalid free of devm_ allocated data" Christophe Ricard
                     ` (31 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Other drivers are following the following compatible string format for dts:
s/_/-/

Because some devices may still use the previous string, the new corrected
string is added to the of_device_id table.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 Documentation/devicetree/bindings/net/nfc/st21nfcb.txt | 4 ++--
 drivers/nfc/st21nfcb/i2c.c                             | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
index 9005608..bb23707 100644
--- a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
@@ -1,7 +1,7 @@
 * STMicroelectronics SAS. ST21NFCB NFC Controller
 
 Required properties:
-- compatible: Should be "st,st21nfcb_i2c".
+- compatible: Should be "st,st21nfcb-i2c".
 - clock-frequency: I²C work frequency.
 - reg: address on the bus
 - interrupt-parent: phandle for the interrupt gpio controller
@@ -20,7 +20,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
 
 	st21nfcb: st21nfcb@8 {
 
-		compatible = "st,st21nfcb_i2c";
+		compatible = "st,st21nfcb-i2c";
 
 		reg = <0x08>;
 		clock-frequency = <400000>;
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c
index 01ba865..b65847c 100644
--- a/drivers/nfc/st21nfcb/i2c.c
+++ b/drivers/nfc/st21nfcb/i2c.c
@@ -373,6 +373,7 @@ static int st21nfcb_nci_i2c_remove(struct i2c_client *client)
 
 #ifdef CONFIG_OF
 static const struct of_device_id of_st21nfcb_i2c_match[] = {
+	{ .compatible = "st,st21nfcb-i2c", },
 	{ .compatible = "st,st21nfcb_i2c", },
 	{}
 };
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 03/34] NFC: st21nfcb: Fix "WARNING: invalid free of devm_ allocated data"
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 01/34] NFC: dts: st21nfca: Fix compatible string spelling to follow other drivers Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 02/34] NFC: dts: st21nfcb: " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code Christophe Ricard
                     ` (30 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

ndlc pointer got allocated with devm_kzalloc in ndlc_probe function.

This gives this error message:
drivers/nfc/st21nfcb/ndlc.c:296:1-6: WARNING: invalid free of devm_ allocated data.

Reported-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
Reported-by: Julia Lawall <julia.lawall-L2FTfq7BK8M@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfcb/ndlc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c
index bac50e8..ef0f997 100644
--- a/drivers/nfc/st21nfcb/ndlc.c
+++ b/drivers/nfc/st21nfcb/ndlc.c
@@ -297,6 +297,5 @@ void ndlc_remove(struct llt_ndlc *ndlc)
 	skb_queue_purge(&ndlc->send_q);
 
 	st21nfcb_nci_remove(ndlc->ndev);
-	kfree(ndlc);
 }
 EXPORT_SYMBOL(ndlc_remove);
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (2 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 03/34] NFC: st21nfcb: Fix "WARNING: invalid free of devm_ allocated data" Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 05/34] NFC: hci: Change event_received handler gate parameter to pipe Christophe Ricard
                     ` (29 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

kfree_skb(skb) in st21nfca_hci_event_received is never reach.

Reported-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/st21nfca.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index f2596c8..880193b 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -845,8 +845,6 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
 	default:
 		return 1;
 	}
-	kfree_skb(skb);
-	return 0;
 }
 
 static struct nfc_hci_ops st21nfca_hci_ops = {
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 05/34] NFC: hci: Change event_received handler gate parameter to pipe
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (3 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 06/34] NFC: hci: Add pipes table to reference them with a tuple {gate, host} Christophe Ricard
                     ` (28 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

We are usually receiving an event from a known pipe.

Keep this information as is as we can easily determine gate and host
triggering this event.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/hci.h | 2 +-
 net/nfc/hci/core.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 14bd0e1..031c0be 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -51,7 +51,7 @@ struct nfc_hci_ops {
 	int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
 	int (*check_presence)(struct nfc_hci_dev *hdev,
 			      struct nfc_target *target);
-	int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+	int (*event_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
 			      struct sk_buff *skb);
 	int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name);
 	int (*discover_se)(struct nfc_hci_dev *dev);
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ef50e77..12a9a4b 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -338,7 +338,7 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
 	}
 
 	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;
 	}
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 06/34] NFC: hci: Add pipes table to reference them with a tuple {gate, host}
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (4 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 05/34] NFC: hci: Change event_received handler gate parameter to pipe Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-7-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 07/34] NFC: hci: Change nfc_hci_send_response gate parameter to pipe Christophe Ricard
                     ` (27 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

In order to keep host source information on specific hci event (such as
evt_connectivity or evt_transaction) and because 2 pipes can be connected
to the same gate, it is necessary to add a table referencing every pipe
with a {gate, host} tuple.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/hci.h | 15 +++++++++++++--
 net/nfc/hci/command.c |  6 ++++--
 net/nfc/hci/core.c    | 35 ++++++++++++++++++++++++++++++-----
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 031c0be..c1c644b 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -63,17 +63,25 @@ struct nfc_hci_ops {
 };
 
 /* Pipes */
-#define NFC_HCI_INVALID_PIPE	0x80
 #define NFC_HCI_DO_NOT_CREATE_PIPE	0x81
+#define NFC_HCI_INVALID_PIPE	0x80
+#define NFC_HCI_INVALID_GATE	0xFF
+#define NFC_HCI_INVALID_HOST	0x80
 #define NFC_HCI_LINK_MGMT_PIPE	0x00
 #define NFC_HCI_ADMIN_PIPE	0x01
 
 struct nfc_hci_gate {
 	u8 gate;
 	u8 pipe;
-};
+} __packed;
+
+struct nfc_hci_pipe {
+	u8 gate;
+	u8 dest_host;
+} __packed;
 
 #define NFC_HCI_MAX_CUSTOM_GATES	50
+#define NFC_HCI_MAX_PIPES		127
 struct nfc_hci_init_data {
 	u8 gate_count;
 	struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
@@ -125,6 +133,7 @@ struct nfc_hci_dev {
 	void *clientdata;
 
 	u8 gate2pipe[NFC_HCI_MAX_GATES];
+	struct nfc_hci_pipe pipes[NFC_HCI_MAX_PIPES];
 
 	u8 sw_romlib;
 	u8 sw_patch;
@@ -167,6 +176,8 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
 void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
 
 int nfc_hci_result_to_errno(u8 result);
+void nfc_hci_reset_pipes(struct nfc_hci_dev *dev);
+void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host);
 
 /* Host IDs */
 #define NFC_HCI_HOST_CONTROLLER_ID	0x00
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 91df487..9acf586 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -331,7 +331,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 +345,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 +380,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 12a9a4b..88af43a 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -46,6 +46,31 @@ 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) {
+			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,
@@ -168,7 +193,7 @@ 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 gate = hdev->pipes[pipe].gate;
 	u8 local_gate, new_pipe;
 	u8 gate_opened = 0x00;
 
@@ -330,9 +355,9 @@ 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;
 	}
@@ -573,7 +598,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 +957,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;
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 07/34] NFC: hci: Change nfc_hci_send_response gate parameter to pipe
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (5 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 06/34] NFC: hci: Add pipes table to reference them with a tuple {gate, host} Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-8-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 08/34] NFC: hci: Reference every pipe information according to notification Christophe Ricard
                     ` (26 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

We are usually sending a response to a command received from a known pipe.
Keep this information as is.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/hci.h | 2 +-
 net/nfc/hci/command.c | 7 +------
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index c1c644b..6f11ca2 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -260,7 +260,7 @@ int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
 int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
 			   const u8 *param, size_t param_len,
 			   data_exchange_cb_t cb, void *cb_context);
-int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
+int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 pipe, u8 response,
 			  const u8 *param, size_t param_len);
 int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
 		       const u8 *param, size_t param_len);
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 9acf586..e061dc6 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -116,16 +116,11 @@ 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,
+int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 pipe, 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,
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 08/34] NFC: hci: Reference every pipe information according to notification
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (6 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 07/34] NFC: hci: Change nfc_hci_send_response gate parameter to pipe Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 09/34] NFC: hci: Add cmd_received handler Christophe Ricard
                     ` (25 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Save a relevant pipe status according to received command in pipes table
with tuple {gate, host}.

Also:
- If an error is detected it was so far not reported to the CLF.
- Any HCI command can be received, we need to respond something back to the
CLF.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/hci/core.c | 56 ++++++++++++++++++++++++++++++++++++------------------
 net/nfc/hci/hci.h  |  8 ++++++++
 2 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 88af43a..67e7049 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -192,48 +192,66 @@ exit:
 void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
 			  struct sk_buff *skb)
 {
-	int r = 0;
 	u8 gate = hdev->pipes[pipe].gate;
-	u8 local_gate, new_pipe;
-	u8 gate_opened = 0x00;
+	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 the pipe is not created report an error */
+		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;
 	}
 
+exit:
+	nfc_hci_send_response(hdev, pipe, status, NULL, 0);
+
 	kfree_skb(skb);
 }
 
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h
index c3d2e2c..c1278bd 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))
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 09/34] NFC: hci: Add cmd_received handler
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (7 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 08/34] NFC: hci: Reference every pipe information according to notification Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 10/34] NFC: pn544: Change event_received gate parameter to pipe Christophe Ricard
                     ` (24 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

When a command is received, it is sometime needed to let the CLF driver do
some additional operations. (ex: count remaining pipe notification...)

Make also generic HCI commands available to other NFC drivers

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/hci.h | 8 ++++++++
 net/nfc/hci/core.c    | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 6f11ca2..4c998a9 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -53,6 +53,8 @@ struct nfc_hci_ops {
 			      struct nfc_target *target);
 	int (*event_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
 			      struct sk_buff *skb);
+	void (*cmd_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
+			    struct sk_buff *skb);
 	int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name);
 	int (*discover_se)(struct nfc_hci_dev *dev);
 	int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
@@ -230,6 +232,12 @@ void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host);
 #define NFC_HCI_EVT_POST_DATA			0x02
 #define NFC_HCI_EVT_HOT_PLUG			0x03
 
+/* Generic commands */
+#define NFC_HCI_ANY_SET_PARAMETER	0x01
+#define NFC_HCI_ANY_GET_PARAMETER	0x02
+#define NFC_HCI_ANY_OPEN_PIPE		0x03
+#define NFC_HCI_ANY_CLOSE_PIPE		0x04
+
 /* Reader RF gates events */
 #define NFC_HCI_EVT_READER_REQUESTED	0x10
 #define NFC_HCI_EVT_END_OPERATION	0x11
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 67e7049..bae1b3f 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -249,6 +249,9 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
 		break;
 	}
 
+	if (hdev->ops->cmd_received)
+		hdev->ops->cmd_received(hdev, pipe, cmd, skb);
+
 exit:
 	nfc_hci_send_response(hdev, pipe, status, NULL, 0);
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 10/34] NFC: pn544: Change event_received gate parameter to pipe
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (8 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 09/34] NFC: hci: Add cmd_received handler Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 11/34] NFC: microread: " Christophe Ricard
                     ` (23 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The below event_received hci handler has change the gate parameter to pipe.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/pn544/pn544.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c
index 9c8051d..12e819d 100644
--- a/drivers/nfc/pn544/pn544.c
+++ b/drivers/nfc/pn544/pn544.c
@@ -724,10 +724,11 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
  * <= 0: driver handled the event, skb consumed
  *    1: driver does not handle the event, please do standard processing
  */
-static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
 				    struct sk_buff *skb)
 {
 	struct sk_buff *rgb_skb = NULL;
+	u8 gate = hdev->pipes[pipe].gate;
 	int r;
 
 	pr_debug("hci event %d\n", event);
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 11/34] NFC: microread: Change event_received gate parameter to pipe
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (9 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 10/34] NFC: pn544: Change event_received gate parameter to pipe Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 12/34] NFC: hci: Remove nfc_hci_pipe2gate function Christophe Ricard
                     ` (22 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The below event_received hci handler has change the gate parameter to pipe.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/microread/microread.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c
index 963a4a5..f454dc6 100644
--- a/drivers/nfc/microread/microread.c
+++ b/drivers/nfc/microread/microread.c
@@ -557,10 +557,11 @@ exit:
 		pr_err("Failed to handle discovered target err=%d\n", r);
 }
 
-static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate,
+static int microread_event_received(struct nfc_hci_dev *hdev, u8 pipe,
 				     u8 event, struct sk_buff *skb)
 {
 	int r;
+	u8 gate = hdev->pipes[pipe].gate;
 	u8 mode;
 
 	pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate);
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 12/34] NFC: hci: Remove nfc_hci_pipe2gate function
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (10 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 11/34] NFC: microread: " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 13/34] NFC: nfc_enable_se Remove useless blank line at beginning of function Christophe Ricard
                     ` (21 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

nfc_hci_pipe2gate is now doing double usage with the pipes table field in
the struct nfc_hci_dev. Also it is not used any more.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/hci/hci.h |  2 --
 net/nfc/hci/hcp.c | 11 -----------
 2 files changed, 13 deletions(-)

diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h
index c1278bd..ab4c8e8 100644
--- a/net/nfc/hci/hci.h
+++ b/net/nfc/hci/hci.h
@@ -85,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 e9de151..1fe725d 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.
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 13/34] NFC: nfc_enable_se Remove useless blank line at beginning of function
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (11 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 12/34] NFC: hci: Remove nfc_hci_pipe2gate function Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 14/34] NFC: nfc_disable_se " Christophe Ricard
                     ` (20 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Remove one useless blank line at beginning of nfc_enable_se function.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/nfc/core.c b/net/nfc/core.c
index 819b877..81fabed 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;
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 14/34] NFC: nfc_disable_se Remove useless blank line at beginning of function
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (12 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 13/34] NFC: nfc_enable_se Remove useless blank line at beginning of function Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 15/34] NFC: st21nfca: Adding support for secure element Christophe Ricard
                     ` (19 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Remove one useless blank line at beginning of nfc_disable_se function.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/nfc/core.c b/net/nfc/core.c
index 81fabed..7f1b635 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -604,7 +604,6 @@ error:
 
 int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
 {
-
 	struct nfc_se *se;
 	int rc;
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 15/34] NFC: st21nfca: Adding support for secure element
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (13 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 14/34] NFC: nfc_disable_se " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 16/34] NFC: st21nfca: Remove useless ST21NFCA_SE_HOST_EVT_HOT_PLUG macro Christophe Ricard
                     ` (18 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

st21nfca has 1 physical SWP line and can support up to 2 secure elements
(UICC & eSE) thanks to an external switch managed with a gpio.

The platform integrator needs to specify thanks to 2 initialization
properties, uicc-present and ese-present, if it is suppose to have uicc
and/or ese. Of course if the platform does not have an external switch,
only one kind of secure element can be supported. Those parameters are
under platform integrator responsibilities.

During initialization, the white_list will be set according to those
parameters.

The discovery_se function will assume a secure element is physically
present according to uicc-present and ese-present values and will add it
to the secure element list. On ese activation, the atr is retrieved to
calculate a command exchange timeout based on the first atr(TB) value.

The se_io will allow to transfer data over SWP. 2 kind of events may appear
after a data is sent over:
- ST21NFCA_EVT_TRANSMIT_DATA when receiving an apdu answer
- ST21NFCA_EVT_WTX_REQUEST when the secure element needs more time than
expected to compute a command. If this timeout expired, a first recovery
tentative consist to send a simple software reset proprietary command.
If this tentative still fail, a second recovery tentative consist to send
a hardware reset proprietary command.
This function is only relevant for eSE like secure element.

This patch also change the way a pipe is referenced. There can be
different pipe connected to the same gate with different host destination
(ex: CONNECTIVITY). In order to keep host information every pipe are
reference with a tuple (gate, host). In order to reduce changes, we are
keeping unchanged the way a gate is addressed on the Terminal Host.
However, this is working because we consider the apdu reader gate is only
present on the eSE slot also the connectivity gate cannot give a reliable
value; it will give the latest stored pipe value.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/Makefile          |   2 +-
 drivers/nfc/st21nfca/i2c.c             |  17 +-
 drivers/nfc/st21nfca/st21nfca.c        | 135 ++++++++++--
 drivers/nfc/st21nfca/st21nfca.h        |  21 +-
 drivers/nfc/st21nfca/st21nfca_se.c     | 390 +++++++++++++++++++++++++++++++++
 drivers/nfc/st21nfca/st21nfca_se.h     |  63 ++++++
 include/linux/platform_data/st21nfca.h |   2 +
 7 files changed, 609 insertions(+), 21 deletions(-)
 create mode 100644 drivers/nfc/st21nfca/st21nfca_se.c
 create mode 100644 drivers/nfc/st21nfca/st21nfca_se.h

diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 7d688f9..97edab4 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_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o
 obj-$(CONFIG_NFC_ST21NFCA)     += st21nfca_hci.o
 
 st21nfca_i2c-objs  = i2c.o
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index b2e0792..ea3db65 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -74,6 +74,8 @@ struct st21nfca_i2c_phy {
 	unsigned int gpio_ena;
 	unsigned int irq_polarity;
 
+	struct st21nfca_se_status se_status;
+
 	struct sk_buff *pending_skb;
 	int current_read_len;
 	/*
@@ -537,6 +539,11 @@ static int st21nfca_hci_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
@@ -571,6 +578,9 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
 		}
 	}
 
+	phy->se_status.is_ese_present = pdata->is_ese_present;
+	phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
 	return 0;
 }
 
@@ -641,8 +651,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
 	}
 
 	return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
-			       ST21NFCA_FRAME_HEADROOM, ST21NFCA_FRAME_TAILROOM,
-			       ST21NFCA_HCI_LLC_MAX_PAYLOAD, &phy->hdev);
+					ST21NFCA_FRAME_HEADROOM,
+					ST21NFCA_FRAME_TAILROOM,
+					ST21NFCA_HCI_LLC_MAX_PAYLOAD,
+					&phy->hdev,
+					&phy->se_status);
 }
 
 static int st21nfca_hci_i2c_remove(struct i2c_client *client)
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index 880193b..d57e342 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -23,6 +23,7 @@
 
 #include "st21nfca.h"
 #include "st21nfca_dep.h"
+#include "st21nfca_se.h"
 
 #define DRIVER_DESC "HCI NFC driver for ST21NFCA"
 
@@ -62,7 +63,6 @@
 #define ST21NFCA_RF_CARD_F_DATARATE		0x08
 #define ST21NFCA_RF_CARD_F_DATARATE_212_424	0x01
 
-#define ST21NFCA_DEVICE_MGNT_GATE		0x01
 #define ST21NFCA_DEVICE_MGNT_PIPE		0x02
 
 #define ST21NFCA_DM_GETINFO			0x13
@@ -78,6 +78,12 @@
 
 #define ST21NFCA_NFC_MODE			0x03	/* NFC_MODE parameter*/
 
+#define ST21NFCA_EVT_HOT_PLUG			0x03
+#define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
+#define ST21NFCA_SE_HOST_EVT_HOT_PLUG	0x01
+
+#define ST21NFCA_SE_TO_PIPES			2000
+
 static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
 
 static struct nfc_hci_gate st21nfca_gates[] = {
@@ -92,6 +98,10 @@ static struct nfc_hci_gate st21nfca_gates[] = {
 	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
+
+	/* Secure element pipes are created by secure element host */
+	{ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
+	{ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
 };
 
 struct st21nfca_pipe_info {
@@ -148,7 +158,8 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 	 * Pipe can be closed and need to be open.
 	 */
 	r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
-		ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE);
+				ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_DEVICE_MGNT_PIPE);
 	if (r < 0)
 		goto free_info;
 
@@ -179,17 +190,28 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 		 * - destination gid (1byte)
 		 */
 		info = (struct st21nfca_pipe_info *) skb_pipe_info->data;
+		if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE &&
+			info->src_host_id != ST21NFCA_ESE_HOST_ID) {
+			pr_err("Unexpected apdu_reader pipe on host %x\n",
+				info->src_host_id);
+			continue;
+		}
+
 		for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
-			(st21nfca_gates[j].gate != info->dst_gate_id);
-			j++)
+			(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
 			;
 
 		if (j < ARRAY_SIZE(st21nfca_gates) &&
 			st21nfca_gates[j].gate == info->dst_gate_id &&
 			ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
 			st21nfca_gates[j].pipe = pipe_info[2];
+
 			hdev->gate2pipe[st21nfca_gates[j].gate] =
-				st21nfca_gates[j].pipe;
+							st21nfca_gates[j].pipe;
+			hdev->pipes[st21nfca_gates[j].pipe].gate =
+							st21nfca_gates[j].gate;
+			hdev->pipes[st21nfca_gates[j].pipe].dest_host =
+							info->src_host_id;
 		}
 	}
 
@@ -199,7 +221,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 	 */
 	if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
 		for (i = skb_pipe_list->len + 3;
-				i < ARRAY_SIZE(st21nfca_gates); i++) {
+				i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
 			r = nfc_hci_connect_gate(hdev,
 					NFC_HCI_HOST_CONTROLLER_ID,
 					st21nfca_gates[i].gate,
@@ -257,16 +279,33 @@ out:
 
 static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)
 {
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 	struct sk_buff *skb;
 
 	u8 param;
+	u8 white_list[2];
+	int wl_size = 0;
 	int r;
 
-	param = NFC_HCI_UICC_HOST_ID;
-	r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
-			      NFC_HCI_ADMIN_WHITELIST, &param, 1);
-	if (r < 0)
-		return r;
+	if (info->se_status->is_ese_present &&
+		info->se_status->is_uicc_present) {
+		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
+		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
+	} else if (!info->se_status->is_ese_present &&
+			 info->se_status->is_uicc_present) {
+		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
+	} else if (info->se_status->is_ese_present &&
+			!info->se_status->is_uicc_present) {
+		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
+	}
+
+	if (wl_size) {
+		r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
+					NFC_HCI_ADMIN_WHITELIST,
+					(u8 *) &white_list, wl_size);
+		if (r < 0)
+			return r;
+	}
 
 	/* Set NFC_MODE in device management gate to enable */
 	r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
@@ -829,19 +868,79 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
 	}
 }
 
+static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
+				struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	u8 gate = hdev->pipes[pipe].gate;
+
+	pr_debug("cmd: %x\n", cmd);
+
+	switch (cmd) {
+	case NFC_HCI_ANY_OPEN_PIPE:
+		if (gate != ST21NFCA_APDU_READER_GATE &&
+			hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID)
+			info->se_info.count_pipes++;
+
+		if (info->se_info.count_pipes == info->se_info.expected_pipes) {
+			del_timer_sync(&info->se_info.se_active_timer);
+			info->se_info.se_active = false;
+			info->se_info.count_pipes = 0;
+			complete(&info->se_info.req_completion);
+		}
+	break;
+	}
+}
+
+static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
+					struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("admin event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_HOT_PLUG:
+		if (info->se_info.se_active) {
+			if (!ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
+				del_timer_sync(&info->se_info.se_active_timer);
+				info->se_info.se_active = false;
+				complete(&info->se_info.req_completion);
+			} else {
+				mod_timer(&info->se_info.se_active_timer,
+					jiffies +
+					msecs_to_jiffies(ST21NFCA_SE_TO_PIPES));
+			}
+		}
+	break;
+	}
+	kfree_skb(skb);
+	return 0;
+}
+
 /*
  * Returns:
  * <= 0: driver handled the event, skb consumed
  *    1: driver does not handle the event, please do standard processing
  */
-static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
+static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
 				       u8 event, struct sk_buff *skb)
 {
+	u8 gate = hdev->pipes[pipe].gate;
+	u8 host = hdev->pipes[pipe].dest_host;
+
 	pr_debug("hci event: %d gate: %x\n", event, gate);
 
 	switch (gate) {
+	case NFC_HCI_ADMIN_GATE:
+		return st21nfca_admin_event_received(hdev, event, skb);
 	case ST21NFCA_RF_CARD_F_GATE:
 		return st21nfca_dep_event_received(hdev, event, skb);
+	case ST21NFCA_CONNECTIVITY_GATE:
+		return st21nfca_connectivity_event_received(hdev, host,
+							event, skb);
+	case ST21NFCA_APDU_READER_GATE:
+		return st21nfca_apdu_reader_event_received(hdev, event, skb);
 	default:
 		return 1;
 	}
@@ -863,11 +962,17 @@ static struct nfc_hci_ops st21nfca_hci_ops = {
 	.tm_send = st21nfca_hci_tm_send,
 	.check_presence = st21nfca_hci_check_presence,
 	.event_received = st21nfca_hci_event_received,
+	.cmd_received = st21nfca_hci_cmd_received,
+	.discover_se = st21nfca_hci_discover_se,
+	.enable_se = st21nfca_hci_enable_se,
+	.disable_se = st21nfca_hci_disable_se,
+	.se_io = st21nfca_hci_se_io,
 };
 
 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)
+		       int phy_payload, struct nfc_hci_dev **hdev,
+			   struct st21nfca_se_status *se_status)
 {
 	struct st21nfca_hci_info *info;
 	int r = 0;
@@ -927,6 +1032,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
 		goto err_alloc_hdev;
 	}
 
+	info->se_status = se_status;
+
 	nfc_hci_set_clientdata(info->hdev, info);
 
 	r = nfc_hci_register_device(info->hdev);
@@ -935,6 +1042,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);
 
 	return 0;
 
@@ -953,6 +1061,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev)
 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 
 	st21nfca_dep_deinit(hdev);
+	st21nfca_se_deinit(hdev);
 	nfc_hci_unregister_device(hdev);
 	nfc_hci_free_device(hdev);
 	kfree(info);
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 7c2a852..15a78d3 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -20,6 +20,7 @@
 #include <net/nfc/hci.h>
 
 #include "st21nfca_dep.h"
+#include "st21nfca_se.h"
 
 #define HCI_MODE 0
 
@@ -51,9 +52,15 @@
 
 #define ST21NFCA_NUM_DEVICES 256
 
+struct st21nfca_se_status {
+	bool is_ese_present;
+	bool is_uicc_present;
+};
+
 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);
+		       int phy_payload, struct nfc_hci_dev **hdev,
+			   struct st21nfca_se_status *se_status);
 void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
 
 enum st21nfca_state {
@@ -66,6 +73,7 @@ struct st21nfca_hci_info {
 	void *phy_id;
 
 	struct nfc_hci_dev *hdev;
+	struct st21nfca_se_status *se_status;
 
 	enum st21nfca_state state;
 
@@ -76,13 +84,16 @@ struct st21nfca_hci_info {
 	void *async_cb_context;
 
 	struct st21nfca_dep_info dep_info;
+	struct st21nfca_se_info se_info;
 };
 
 /* Reader RF commands */
-#define ST21NFCA_WR_XCHG_DATA            0x10
-
-#define ST21NFCA_RF_READER_F_GATE               0x14
+#define ST21NFCA_WR_XCHG_DATA           0x10
 
-#define ST21NFCA_RF_CARD_F_GATE 0x24
+#define ST21NFCA_DEVICE_MGNT_GATE       0x01
+#define ST21NFCA_RF_READER_F_GATE       0x14
+#define ST21NFCA_RF_CARD_F_GATE			0x24
+#define ST21NFCA_APDU_READER_GATE		0xf0
+#define ST21NFCA_CONNECTIVITY_GATE		0x41
 
 #endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/st21nfca_se.c
new file mode 100644
index 0000000..9b93d39
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_se.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2014  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/nfc/hci.h>
+
+#include "st21nfca.h"
+#include "st21nfca_se.h"
+
+#define ST21NFCA_EVT_UICC_ACTIVATE		0x10
+#define ST21NFCA_EVT_UICC_DEACTIVATE	0x13
+#define ST21NFCA_EVT_SE_HARD_RESET		0x20
+#define ST21NFCA_EVT_SE_SOFT_RESET		0x11
+#define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER	0x21
+#define ST21NFCA_EVT_SE_ACTIVATE		0x22
+#define ST21NFCA_EVT_SE_DEACTIVATE		0x23
+
+#define ST21NFCA_EVT_TRANSMIT_DATA		0x10
+#define ST21NFCA_EVT_WTX_REQUEST		0x11
+
+#define ST21NFCA_EVT_CONNECTIVITY		0x10
+#define ST21NFCA_EVT_TRANSACTION		0x12
+
+#define ST21NFCA_ESE_HOST_ID			0xc0
+
+#define ST21NFCA_SE_TO_HOT_PLUG			1000
+/* Connectivity pipe only */
+#define ST21NFCA_SE_COUNT_PIPE_UICC		0x01
+/* Connectivity + APDU Reader pipe */
+#define ST21NFCA_SE_COUNT_PIPE_EMBEDDED	0x02
+
+#define ST21NFCA_SE_MODE_OFF			0x00
+#define ST21NFCA_SE_MODE_ON				0x01
+
+#define ST21NFCA_PARAM_ATR				0x01
+#define ST21NFCA_ATR_DEFAULT_BWI		0x04
+
+/*
+ * WT = 2^BWI/10[s], convert into msecs and add a secure
+ * room by increasing by 2 this timeout
+ */
+#define ST21NFCA_BWI_TO_TIMEOUT(x)		((1 << x) * 200)
+#define ST21NFCA_ATR_GET_Y_FROM_TD(x)	(x >> 4)
+
+/* If TA is present bit 0 is set */
+#define ST21NFCA_ATR_TA_PRESENT(x) (x & 0x01)
+/* If TB is present bit 1 is set */
+#define ST21NFCA_ATR_TB_PRESENT(x) (x & 0x02)
+
+static u8 st21nfca_se_get_bwi(struct nfc_hci_dev *hdev)
+{
+	int i;
+	u8 td;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	/* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
+	for (i = 1; i < ST21NFCA_ESE_MAX_LENGTH; i++) {
+		td = ST21NFCA_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
+		if (ST21NFCA_ATR_TA_PRESENT(td))
+			i++;
+		if (ST21NFCA_ATR_TB_PRESENT(td)) {
+			i++;
+			return info->se_info.atr[i] >> 4;
+		}
+	}
+	return ST21NFCA_ATR_DEFAULT_BWI;
+}
+
+static void st21nfca_se_get_atr(struct nfc_hci_dev *hdev)
+{
+	int r;
+	struct sk_buff *skb;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_APDU_READER_GATE,
+			ST21NFCA_PARAM_ATR, &skb);
+	if (r < 0)
+		return;
+
+	if (skb->len <= ST21NFCA_ESE_MAX_LENGTH) {
+		memcpy(info->se_info.atr, skb->data, skb->len);
+		info->se_info.wt_timeout =
+			ST21NFCA_BWI_TO_TIMEOUT(st21nfca_se_get_bwi(hdev));
+	}
+	kfree_skb(skb);
+}
+
+static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
+				u8 state)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	int r;
+	struct sk_buff *sk_host_list;
+	u8 se_event, host_id;
+
+	switch (se_idx) {
+	case NFC_HCI_UICC_HOST_ID:
+		se_event = (state == ST21NFCA_SE_MODE_ON ?
+					ST21NFCA_EVT_UICC_ACTIVATE :
+					ST21NFCA_EVT_UICC_DEACTIVATE);
+
+		info->se_info.count_pipes = 0;
+		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_UICC;
+		break;
+	case ST21NFCA_ESE_HOST_ID:
+		se_event = (state == ST21NFCA_SE_MODE_ON ?
+					ST21NFCA_EVT_SE_ACTIVATE :
+					ST21NFCA_EVT_SE_DEACTIVATE);
+
+		info->se_info.count_pipes = 0;
+		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_EMBEDDED;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Wait for an EVT_HOT_PLUG in order to
+	 * retrieve a relevant host list.
+	 */
+	reinit_completion(&info->se_info.req_completion);
+	r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, se_event,
+			       NULL, 0);
+	if (r < 0)
+		return r;
+
+	mod_timer(&info->se_info.se_active_timer, jiffies +
+		msecs_to_jiffies(ST21NFCA_SE_TO_HOT_PLUG));
+	info->se_info.se_active = true;
+
+	/* Ignore return value and check in any case the host_list */
+	wait_for_completion_interruptible(&info->se_info.req_completion);
+
+	r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE,
+			NFC_HCI_ADMIN_HOST_LIST,
+			&sk_host_list);
+	if (r < 0)
+		return r;
+
+	host_id = sk_host_list->data[sk_host_list->len - 1];
+	kfree_skb(sk_host_list);
+
+	if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
+		return se_idx;
+	else if (state == ST21NFCA_SE_MODE_OFF && host_id != se_idx)
+		return se_idx;
+
+	return -1;
+}
+
+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 (info->se_status->is_uicc_present) {
+		nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
+		se_count++;
+	}
+
+	if (info->se_status->is_ese_present) {
+		nfc_add_se(hdev->ndev, ST21NFCA_ESE_HOST_ID, NFC_SE_EMBEDDED);
+		se_count++;
+	}
+
+	return !se_count;
+}
+EXPORT_SYMBOL(st21nfca_hci_discover_se);
+
+int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
+{
+	int r;
+
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_status->is_uicc_enable is true should never happen.
+	 * 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,
+				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
+		if (r < 0)
+			return r;
+	} else if (r < 0) {
+		/*
+		 * The activation tentative failed, the secure element
+		 * is not connected. Remove from the list.
+		 */
+		nfc_remove_se(hdev->ndev, se_idx);
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_enable_se);
+
+int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx)
+{
+	int r;
+
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_status->is_uicc_enable is true should never happen
+	 * Same for eSE.
+	 */
+	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_OFF);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_disable_se);
+
+int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+			u8 *apdu, size_t apdu_length,
+			se_io_cb_t cb, void *cb_context)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("se_io %x\n", se_idx);
+
+	switch (se_idx) {
+	case ST21NFCA_ESE_HOST_ID:
+		info->se_info.cb = cb;
+		info->se_info.cb_context = cb_context;
+		mod_timer(&info->se_info.bwi_timer, jiffies +
+			  msecs_to_jiffies(info->se_info.wt_timeout));
+		info->se_info.bwi_active = true;
+		return nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
+					ST21NFCA_EVT_TRANSMIT_DATA,
+					apdu, apdu_length);
+	default:
+		return -ENODEV;
+	}
+}
+EXPORT_SYMBOL(st21nfca_hci_se_io);
+
+static void st21nfca_se_wt_timeout(unsigned long data)
+{
+	/*
+	 * No answer from the secure element
+	 * within the defined timeout.
+	 * Let's send a reset request as recovery procedure.
+	 * According to the situation, we first try to send a software reset
+	 * to the secure element. If the next command is still not
+	 * answering in time, we send to the CLF a secure element hardware
+	 * reset request.
+	 */
+	/* hardware reset managed through VCC_UICC_OUT power supply */
+	u8 param = 0x01;
+	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
+
+	pr_debug("\n");
+
+	info->se_info.bwi_active = false;
+
+	if (!info->se_info.xch_error) {
+		info->se_info.xch_error = true;
+		nfc_hci_send_event(info->hdev, ST21NFCA_APDU_READER_GATE,
+				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
+	} else {
+		info->se_info.xch_error = false;
+		nfc_hci_send_event(info->hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
+	}
+	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
+}
+
+static void st21nfca_se_activation_timeout(unsigned long data)
+{
+	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
+
+	pr_debug("\n");
+
+	info->se_info.se_active = false;
+
+	complete(&info->se_info.req_completion);
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+				u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+
+	pr_debug("connectivity gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CONNECTIVITY:
+		break;
+	case ST21NFCA_EVT_TRANSACTION:
+		break;
+	default:
+		return 1;
+	}
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_connectivity_event_received);
+
+int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+					u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("apdu reader gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_TRANSMIT_DATA:
+		del_timer_sync(&info->se_info.bwi_timer);
+		info->se_info.bwi_active = false;
+		r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
+		if (r < 0)
+			goto exit;
+
+		info->se_info.cb(info->se_info.cb_context,
+			skb->data, skb->len, 0);
+		break;
+	case ST21NFCA_EVT_WTX_REQUEST:
+		mod_timer(&info->se_info.bwi_timer, jiffies +
+				msecs_to_jiffies(info->se_info.wt_timeout));
+		break;
+	}
+
+exit:
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_apdu_reader_event_received);
+
+void st21nfca_se_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	init_completion(&info->se_info.req_completion);
+	/* initialize timers */
+	init_timer(&info->se_info.bwi_timer);
+	info->se_info.bwi_timer.data = (unsigned long)info;
+	info->se_info.bwi_timer.function = st21nfca_se_wt_timeout;
+	info->se_info.bwi_active = false;
+
+	init_timer(&info->se_info.se_active_timer);
+	info->se_info.se_active_timer.data = (unsigned long)info;
+	info->se_info.se_active_timer.function = st21nfca_se_activation_timeout;
+	info->se_info.se_active = false;
+
+	info->se_info.count_pipes = 0;
+	info->se_info.expected_pipes = 0;
+
+	info->se_info.xch_error = false;
+
+	info->se_info.wt_timeout =
+			ST21NFCA_BWI_TO_TIMEOUT(ST21NFCA_ATR_DEFAULT_BWI);
+}
+EXPORT_SYMBOL(st21nfca_se_init);
+
+void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	if (info->se_info.bwi_active)
+		del_timer_sync(&info->se_info.bwi_timer);
+	if (info->se_info.se_active)
+		del_timer_sync(&info->se_info.se_active_timer);
+
+	info->se_info.bwi_active = false;
+	info->se_info.se_active = false;
+}
+EXPORT_SYMBOL(st21nfca_se_deinit);
diff --git a/drivers/nfc/st21nfca/st21nfca_se.h b/drivers/nfc/st21nfca/st21nfca_se.h
new file mode 100644
index 0000000..b172cfc
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_se.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014  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 __ST21NFCA_SE_H
+#define __ST21NFCA_SE_H
+
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST21NFCA_ESE_MAX_LENGTH			33
+#define ST21NFCA_ESE_HOST_ID			0xc0
+
+struct st21nfca_se_info {
+	u8 atr[ST21NFCA_ESE_MAX_LENGTH];
+	struct completion req_completion;
+
+	struct timer_list bwi_timer;
+	int wt_timeout; /* in msecs */
+	bool bwi_active;
+
+	struct timer_list se_active_timer;
+	bool se_active;
+	int expected_pipes;
+	int count_pipes;
+
+	bool xch_error;
+
+	se_io_cb_t cb;
+	void *cb_context;
+};
+
+int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+					u8 event, struct sk_buff *skb);
+int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+					u8 event, struct sk_buff *skb);
+
+int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
+int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+		u8 *apdu, size_t apdu_length,
+		se_io_cb_t cb, void *cb_context);
+
+void st21nfca_se_init(struct nfc_hci_dev *hdev);
+void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
+#endif /* __ST21NFCA_SE_H */
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h
index 5087fff..cc2bdaf 100644
--- a/include/linux/platform_data/st21nfca.h
+++ b/include/linux/platform_data/st21nfca.h
@@ -26,6 +26,8 @@
 struct st21nfca_nfc_platform_data {
 	unsigned int gpio_ena;
 	unsigned int irq_polarity;
+	bool is_ese_present;
+	bool is_uicc_present;
 };
 
 #endif /* _ST21NFCA_HCI_H_ */
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 16/34] NFC: st21nfca: Remove useless ST21NFCA_SE_HOST_EVT_HOT_PLUG macro
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (14 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 15/34] NFC: st21nfca: Adding support for secure element Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 17/34] NFC: st21nfca: Remove skb_pipe_list and skb_pipe_info useless allocation Christophe Ricard
                     ` (17 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

ST21NFCA_SE_HOST_EVT_HOT_PLUG is never used in the driver.

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 d57e342..e92af42 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -80,7 +80,6 @@
 
 #define ST21NFCA_EVT_HOT_PLUG			0x03
 #define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
-#define ST21NFCA_SE_HOST_EVT_HOT_PLUG	0x01
 
 #define ST21NFCA_SE_TO_PIPES			2000
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 17/34] NFC: st21nfca: Remove skb_pipe_list and skb_pipe_info useless allocation
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (15 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 16/34] NFC: st21nfca: Remove useless ST21NFCA_SE_HOST_EVT_HOT_PLUG macro Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 18/34] NFC: st21nfca: Remove checkpatch.pl warning Possible unnecessary 'out of memory' message Christophe Ricard
                     ` (16 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

skb_pipe_list and skb_pipe_info are allocated in nfc_hci_send_cmd.
alloc_skb on those buffer are then useless.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/st21nfca.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index e92af42..f1aced5 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -127,18 +127,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 		NFC_HCI_TERMINAL_HOST_ID, 0
 	};
 
-	skb_pipe_list = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL);
-	if (!skb_pipe_list) {
-		r = -ENOMEM;
-		goto free_list;
-	}
-
-	skb_pipe_info = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL);
-	if (!skb_pipe_info) {
-		r = -ENOMEM;
-		goto free_info;
-	}
-
 	/* On ST21NFCA device pipes number are dynamics
 	 * A maximum of 16 pipes can be created at the same time
 	 * If pipes are already created, hci_dev_up will fail.
@@ -233,7 +221,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 	memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
 free_info:
 	kfree_skb(skb_pipe_info);
-free_list:
 	kfree_skb(skb_pipe_list);
 	return r;
 }
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 18/34] NFC: st21nfca: Remove checkpatch.pl warning Possible unnecessary 'out of memory' message
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (16 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 17/34] NFC: st21nfca: Remove skb_pipe_list and skb_pipe_info useless allocation Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 19/34] NFC: dts: st21nfca: Document ese-present & uicc-present DTS property Christophe Ricard
                     ` (15 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Remove unnecessary memory allocation message already shown by devm_kzalloc.
This remove a warning when running scripts/checkpatch.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/i2c.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index ea3db65..a321439 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -601,11 +601,8 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
 
 	phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy),
 			   GFP_KERNEL);
-	if (!phy) {
-		nfc_err(&client->dev,
-			"Cannot allocate memory for st21nfca i2c phy.\n");
+	if (!phy)
 		return -ENOMEM;
-	}
 
 	phy->i2c_dev = client;
 	phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 19/34] NFC: dts: st21nfca: Document ese-present & uicc-present DTS property
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (17 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 18/34] NFC: st21nfca: Remove checkpatch.pl warning Possible unnecessary 'out of memory' message Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 20/34] NFC: nci: Add dynamic conn_id NCI concept Christophe Ricard
                     ` (14 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On st21nfca, the mechanism to enable a secure element needs to add 2
properties in order manage the SWP line correctly.

Document ese-present and uicc-present properties.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 Documentation/devicetree/bindings/net/nfc/st21nfca.txt | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt
index db677fe..7bb2e21 100644
--- a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st21nfca.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 ST21NFCA on I2C2):
 
@@ -29,5 +33,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2):
 		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 
 		enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+
+		ese-present;
+		uicc-present;
 	};
 };
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 20/34] NFC: nci: Add dynamic conn_id NCI concept.
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (18 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 19/34] NFC: dts: st21nfca: Document ese-present & uicc-present DTS property Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-21-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 21/34] NFC: nci: Make nci_request available for nfc driver Christophe Ricard
                     ` (13 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The current NCI core only support static conn_id for RF communication.
For other NFC features such as Secure Element communication, we may need
additional conn_id.

In order to address each conn_id dynamically including statics one such as
NCI_STATIC_RF_CONN_ID, we introduce 2 tables referring to conn_id context
by conn_id or by ID (RF Discovery ID or NFCEE ID).

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci_core.h | 29 +++++++++++++++++------
 net/nfc/nci/core.c         | 28 +++++++++++++++++------
 net/nfc/nci/data.c         | 57 ++++++++++++++++++++++++++++++++++------------
 net/nfc/nci/ntf.c          | 34 +++++++++++++++++++--------
 net/nfc/nci/rsp.c          | 16 ++++++++++++-
 5 files changed, 124 insertions(+), 40 deletions(-)

diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 9e51bb4..25c0a70 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -82,6 +82,22 @@ struct nci_ops {
 
 #define NCI_MAX_SUPPORTED_RF_INTERFACES		4
 #define NCI_MAX_DISCOVERED_TARGETS		10
+#define NCI_MAX_NUM_NFCEE   255
+#define NCI_MAX_CONN_ID		7
+
+struct nci_conn_info {
+	__u8	id; /* can be an RF Discovery ID or an NFCEE ID */
+	__u8	conn_id;
+	__u8	max_pkt_payload_len;
+
+	atomic_t credits_cnt;
+	__u8	 initial_num_credits;
+
+	data_exchange_cb_t	data_exchange_cb;
+	void *data_exchange_cb_context;
+
+	struct sk_buff *rx_skb;
+};
 
 /* NCI Core structures */
 struct nci_dev {
@@ -95,7 +111,8 @@ struct nci_dev {
 	unsigned long		flags;
 
 	atomic_t		cmd_cnt;
-	atomic_t		credits_cnt;
+	__u8			cur_conn_id;
+	struct nci_conn_info	*conn_info_by_conn_id[NCI_MAX_CONN_ID];
 
 	struct timer_list	cmd_timer;
 	struct timer_list	data_timer;
@@ -141,13 +158,11 @@ struct nci_dev {
 	__u8			manufact_id;
 	__u32			manufact_specific_info;
 
-	/* received during NCI_OP_RF_INTF_ACTIVATED_NTF */
-	__u8			max_data_pkt_payload_size;
-	__u8			initial_num_credits;
+	/* Save RF Discovery ID or NFCEE ID under conn_create */
+	__u8			cur_id;
+	struct nci_conn_info	*conn_info_by_id[NCI_MAX_NUM_NFCEE];
 
 	/* stored during nci_data_exchange */
-	data_exchange_cb_t	data_exchange_cb;
-	void			*data_exchange_cb_context;
 	struct sk_buff		*rx_data_reassembly;
 
 	/* stored during intf_activated_ntf */
@@ -200,7 +215,7 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
 int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
 int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
 void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
-				int err);
+				__u8 conn_id, int err);
 void nci_clear_target_list(struct nci_dev *ndev);
 
 /* ----- NCI requests ----- */
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 51feb5e..92b42e2 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -712,6 +712,12 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 	int rc;
+	struct nci_conn_info    *conn_info;
+
+	conn_info =
+		(struct nci_conn_info *)ndev->conn_info_by_conn_id[NCI_STATIC_RF_CONN_ID];
+	if (!conn_info)
+		return -EPROTO;
 
 	pr_debug("target_idx %d, len %d\n", target->idx, skb->len);
 
@@ -724,8 +730,8 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
 		return -EBUSY;
 
 	/* store cb and context to be used on receiving data */
-	ndev->data_exchange_cb = cb;
-	ndev->data_exchange_cb_context = cb_context;
+	conn_info->data_exchange_cb = cb;
+	conn_info->data_exchange_cb_context = cb_context;
 
 	rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
 	if (rc)
@@ -1027,20 +1033,26 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload)
 static void nci_tx_work(struct work_struct *work)
 {
 	struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work);
+	struct nci_conn_info    *conn_info;
 	struct sk_buff *skb;
 
-	pr_debug("credits_cnt %d\n", atomic_read(&ndev->credits_cnt));
+	conn_info =
+		(struct nci_conn_info *)ndev->conn_info_by_conn_id[ndev->cur_conn_id];
+	if (!conn_info)
+		return;
+
+	pr_debug("credits_cnt %d\n", atomic_read(&conn_info->credits_cnt));
 
 	/* Send queued tx data */
-	while (atomic_read(&ndev->credits_cnt)) {
+	while (atomic_read(&conn_info->credits_cnt)) {
 		skb = skb_dequeue(&ndev->tx_q);
 		if (!skb)
 			return;
 
 		/* Check if data flow control is used */
-		if (atomic_read(&ndev->credits_cnt) !=
+		if (atomic_read(&conn_info->credits_cnt) !=
 		    NCI_DATA_FLOW_CONTROL_NOT_USED)
-			atomic_dec(&ndev->credits_cnt);
+			atomic_dec(&conn_info->credits_cnt);
 
 		pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
 			 nci_pbf(skb->data),
@@ -1092,7 +1104,9 @@ static void nci_rx_work(struct work_struct *work)
 	if (test_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags)) {
 		/* complete the data exchange transaction, if exists */
 		if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
-			nci_data_exchange_complete(ndev, NULL, -ETIMEDOUT);
+			nci_data_exchange_complete(ndev, NULL,
+						   ndev->cur_conn_id,
+						   -ETIMEDOUT);
 
 		clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
 	}
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index a2de2a8..5485293 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -36,10 +36,21 @@
 
 /* Complete data exchange transaction and forward skb to nfc core */
 void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
-				int err)
+				__u8 conn_id, int err)
 {
-	data_exchange_cb_t cb = ndev->data_exchange_cb;
-	void *cb_context = ndev->data_exchange_cb_context;
+	struct nci_conn_info    *conn_info;
+	data_exchange_cb_t cb;
+	void *cb_context;
+
+	conn_info =
+		(struct nci_conn_info *)ndev->conn_info_by_conn_id[conn_id];
+	if (!conn_info) {
+		kfree_skb(skb);
+		goto exit;
+	}
+
+	cb = conn_info->data_exchange_cb;
+	cb_context = conn_info->data_exchange_cb_context;
 
 	pr_debug("len %d, err %d\n", skb ? skb->len : 0, err);
 
@@ -48,9 +59,6 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
 	clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
 
 	if (cb) {
-		ndev->data_exchange_cb = NULL;
-		ndev->data_exchange_cb_context = NULL;
-
 		/* forward skb to nfc core */
 		cb(cb_context, skb, err);
 	} else if (skb) {
@@ -60,6 +68,7 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
 		kfree_skb(skb);
 	}
 
+exit:
 	clear_bit(NCI_DATA_EXCHANGE, &ndev->flags);
 }
 
@@ -85,6 +94,7 @@ static inline void nci_push_data_hdr(struct nci_dev *ndev,
 static int nci_queue_tx_data_frags(struct nci_dev *ndev,
 				   __u8 conn_id,
 				   struct sk_buff *skb) {
+	struct nci_conn_info    *conn_info;
 	int total_len = skb->len;
 	unsigned char *data = skb->data;
 	unsigned long flags;
@@ -95,11 +105,17 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
 
 	pr_debug("conn_id 0x%x, total_len %d\n", conn_id, total_len);
 
+	conn_info = ndev->conn_info_by_conn_id[conn_id];
+	if (!conn_info) {
+		rc = -EPROTO;
+		goto free_exit;
+	}
+
 	__skb_queue_head_init(&frags_q);
 
 	while (total_len) {
 		frag_len =
-			min_t(int, total_len, ndev->max_data_pkt_payload_size);
+			min_t(int, total_len, conn_info->max_pkt_payload_len);
 
 		skb_frag = nci_skb_alloc(ndev,
 					 (NCI_DATA_HDR_SIZE + frag_len),
@@ -151,12 +167,19 @@ exit:
 /* Send NCI data */
 int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb)
 {
+	struct nci_conn_info    *conn_info;
 	int rc = 0;
 
 	pr_debug("conn_id 0x%x, plen %d\n", conn_id, skb->len);
 
+	conn_info = (struct nci_conn_info *)ndev->conn_info_by_conn_id[conn_id];
+	if (!conn_info) {
+		rc = -EPROTO;
+		goto free_exit;
+	}
+
 	/* check if the packet need to be fragmented */
-	if (skb->len <= ndev->max_data_pkt_payload_size) {
+	if (skb->len <= conn_info->max_pkt_payload_len) {
 		/* no need to fragment packet */
 		nci_push_data_hdr(ndev, conn_id, skb, NCI_PBF_LAST);
 
@@ -170,6 +193,7 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb)
 		}
 	}
 
+	ndev->cur_conn_id = conn_id;
 	queue_work(ndev->tx_wq, &ndev->tx_work);
 
 	goto exit;
@@ -185,7 +209,7 @@ exit:
 
 static void nci_add_rx_data_frag(struct nci_dev *ndev,
 				 struct sk_buff *skb,
-				 __u8 pbf, __u8 status)
+				 __u8 pbf, __u8 conn_id, __u8 status)
 {
 	int reassembly_len;
 	int err = 0;
@@ -229,16 +253,13 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev,
 	}
 
 exit:
-	if (ndev->nfc_dev->rf_mode == NFC_RF_INITIATOR) {
-		nci_data_exchange_complete(ndev, skb, err);
-	} else if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) {
+	if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) {
 		/* Data received in Target mode, forward to nfc core */
 		err = nfc_tm_data_received(ndev->nfc_dev, skb);
 		if (err)
 			pr_err("unable to handle received data\n");
 	} else {
-		pr_err("rf mode unknown\n");
-		kfree_skb(skb);
+		nci_data_exchange_complete(ndev, skb, conn_id, err);
 	}
 }
 
@@ -247,6 +268,8 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u8 pbf = nci_pbf(skb->data);
 	__u8 status = 0;
+	__u8 conn_id = nci_conn_id(skb->data);
+	struct nci_conn_info    *conn_info;
 
 	pr_debug("len %d\n", skb->len);
 
@@ -255,6 +278,10 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		 nci_conn_id(skb->data),
 		 nci_plen(skb->data));
 
+	conn_info = ndev->conn_info_by_conn_id[conn_id];
+	if (!conn_info)
+		return;
+
 	/* strip the nci data header */
 	skb_pull(skb, NCI_DATA_HDR_SIZE);
 
@@ -268,5 +295,5 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		skb_trim(skb, (skb->len - 1));
 	}
 
-	nci_add_rx_data_frag(ndev, skb, pbf, nci_to_errno(status));
+	nci_add_rx_data_frag(ndev, skb, pbf, conn_id, nci_to_errno(status));
 }
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 22e453c..8c73462 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -43,6 +43,7 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
 	struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
+	struct nci_conn_info	*conn_info;
 	int i;
 
 	pr_debug("num_entries %d\n", ntf->num_entries);
@@ -59,11 +60,12 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
 			 i, ntf->conn_entries[i].conn_id,
 			 ntf->conn_entries[i].credits);
 
-		if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) {
-			/* found static rf connection */
-			atomic_add(ntf->conn_entries[i].credits,
-				   &ndev->credits_cnt);
-		}
+		conn_info = ndev->conn_info_by_conn_id[ntf->conn_entries[i].conn_id];
+		if (!conn_info)
+			return;
+
+		atomic_add(ntf->conn_entries[i].credits,
+			   &conn_info->credits_cnt);
 	}
 
 	/* trigger the next tx */
@@ -96,7 +98,7 @@ static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev,
 
 	/* complete the data exchange transaction, if exists */
 	if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
-		nci_data_exchange_complete(ndev, NULL, -EIO);
+		nci_data_exchange_complete(ndev, NULL, ntf->conn_id, -EIO);
 }
 
 static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
@@ -513,6 +515,7 @@ static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev,
 static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
+	struct nci_conn_info    *conn_info;
 	struct nci_rf_intf_activated_ntf ntf;
 	__u8 *data = skb->data;
 	int err = NCI_STATUS_OK;
@@ -614,11 +617,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
 
 exit:
 	if (err == NCI_STATUS_OK) {
-		ndev->max_data_pkt_payload_size = ntf.max_data_pkt_payload_size;
-		ndev->initial_num_credits = ntf.initial_num_credits;
+		conn_info = ndev->conn_info_by_conn_id[NCI_STATIC_RF_CONN_ID];
+		if (!conn_info)
+			return;
+
+		conn_info->max_pkt_payload_len = ntf.max_data_pkt_payload_size;
+		conn_info->initial_num_credits = ntf.initial_num_credits;
 
 		/* set the available credits to initial value */
-		atomic_set(&ndev->credits_cnt, ndev->initial_num_credits);
+		atomic_set(&conn_info->credits_cnt,
+			   conn_info->initial_num_credits);
 
 		/* store general bytes to be reported later in dep_link_up */
 		if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
@@ -661,10 +669,15 @@ exit:
 static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
 					 struct sk_buff *skb)
 {
+	struct nci_conn_info    *conn_info;
 	struct nci_rf_deactivate_ntf *ntf = (void *) skb->data;
 
 	pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason);
 
+	conn_info = ndev->conn_info_by_conn_id[NCI_STATIC_RF_CONN_ID];
+	if (!conn_info)
+		return;
+
 	/* drop tx data queue */
 	skb_queue_purge(&ndev->tx_q);
 
@@ -676,7 +689,8 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
 
 	/* complete the data exchange transaction, if exists */
 	if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
-		nci_data_exchange_complete(ndev, NULL, -EIO);
+		nci_data_exchange_complete(ndev, NULL, NCI_STATIC_RF_CONN_ID,
+					   -EIO);
 
 	switch (ntf->type) {
 	case NCI_DEACTIVATE_TYPE_IDLE_MODE:
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index 041de51..ff8721e 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -140,13 +140,27 @@ static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
 
 static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
+	struct nci_conn_info    *conn_info;
 	__u8 status = skb->data[0];
 
 	pr_debug("status 0x%x\n", status);
 
-	if (status == NCI_STATUS_OK)
+	if (status == NCI_STATUS_OK) {
 		atomic_set(&ndev->state, NCI_DISCOVERY);
+		if (!ndev->conn_info_by_conn_id[NCI_STATIC_RF_CONN_ID]) {
+			conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
+						 sizeof(struct nci_conn_info),
+						 GFP_KERNEL);
+			if (!conn_info) {
+				status = NCI_STATUS_REJECTED;
+				goto exit;
+			}
+			ndev->conn_info_by_conn_id[NCI_STATIC_RF_CONN_ID] =
+								conn_info;
+		}
+	}
 
+exit:
 	nci_req_complete(ndev, status);
 }
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 21/34] NFC: nci: Make nci_request available for nfc driver
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (19 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 20/34] NFC: nci: Add dynamic conn_id NCI concept Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 22/34] NFC: nci: Add NCI NFCEE constant Christophe Ricard
                     ` (12 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

NFC drivers may need to send raw data over NCI. Make this function
available in the NCI core framework.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci_core.h | 3 +++
 net/nfc/nci/core.c         | 8 ++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 25c0a70..395f804 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -217,6 +217,9 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
 void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
 				__u8 conn_id, int err);
 void nci_clear_target_list(struct nci_dev *ndev);
+int nci_request(struct nci_dev *ndev,
+			void (*req)(struct nci_dev *ndev, unsigned long opt),
+			unsigned long opt, __u32 timeout);
 
 /* ----- NCI requests ----- */
 #define NCI_REQ_DONE		0
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 92b42e2..b3ec63e 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -109,10 +109,9 @@ static int __nci_request(struct nci_dev *ndev,
 	return rc;
 }
 
-static inline int nci_request(struct nci_dev *ndev,
-			      void (*req)(struct nci_dev *ndev,
-					  unsigned long opt),
-			      unsigned long opt, __u32 timeout)
+inline int nci_request(struct nci_dev *ndev,
+		void (*req)(struct nci_dev *ndev, unsigned long opt),
+		unsigned long opt, __u32 timeout)
 {
 	int rc;
 
@@ -126,6 +125,7 @@ static inline int nci_request(struct nci_dev *ndev,
 
 	return rc;
 }
+EXPORT_SYMBOL_GPL(nci_request);
 
 static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
 {
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 22/34] NFC: nci: Add NCI NFCEE constant
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (20 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 21/34] NFC: nci: Make nci_request available for nfc driver Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 23/34] NFC: nci: Add nci_nfcee_discover handler command/response/notification Christophe Ricard
                     ` (11 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add NFCEE NCI constant for:
- NFCEE Interface/Protocols
- Destination type
- Destination-specific parameters type
- NFCEE Discovery Action

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index e7257a4..6d99e8f 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -62,6 +62,25 @@
 #define NCI_STATUS_NFCEE_PROTOCOL_ERROR				0xc2
 #define NCI_STATUS_NFCEE_TIMEOUT_ERROR				0xc3
 
+/* NFCEE Interface/Protocols */
+#define NCI_NFCEE_INTERFACE_APDU           0x00
+#define NCI_NFCEE_INTERFACE_HCI_ACCESS     0x01
+#define NCI_NFCEE_INTERFACE_TYPE3_CMD_SET  0x02
+#define NCI_NFCEE_INTERFACE_TRANSPARENT        0x03
+
+/* Destination type */
+#define NCI_DESTINATION_NFCC_LOOPBACK      0x01
+#define NCI_DESTINATION_REMOTE_NFC_ENDPOINT    0x02
+#define NCI_DESTINATION_NFCEE              0x03
+
+/* Destination-specific parameters type */
+#define NCI_DESTINATION_SPECIFIC_PARAM_RF_TYPE     0x00
+#define NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE  0x01
+
+/* NFCEE Discovery Action */
+#define NCI_NFCEE_DISCOVERY_ACTION_DISABLE			0x00
+#define NCI_NFCEE_DISCOVERY_ACTION_ENABLE			0x01
+
 /* NCI RF Technology and Mode */
 #define NCI_NFC_A_PASSIVE_POLL_MODE				0x00
 #define NCI_NFC_B_PASSIVE_POLL_MODE				0x01
@@ -260,6 +279,11 @@ struct nci_rf_deactivate_cmd {
 	__u8	type;
 } __packed;
 
+#define NCI_OP_NFCEE_DISCOVER_CMD nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_discover_cmd {
+	__u8	discovery_action;
+} __packed;
+
 /* ----------------------- */
 /* ---- NCI Responses ---- */
 /* ----------------------- */
@@ -303,6 +327,12 @@ struct nci_core_set_config_rsp {
 
 #define NCI_OP_RF_DEACTIVATE_RSP	nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
 
+#define NCI_OP_NFCEE_DISCOVER_RSP nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_discover_rsp {
+	__u8	status;
+	__u8	num_nfcee;
+} __packed;
+
 /* --------------------------- */
 /* ---- NCI Notifications ---- */
 /* --------------------------- */
@@ -430,4 +460,22 @@ struct nci_rf_deactivate_ntf {
 	__u8	reason;
 } __packed;
 
+#define NCI_OP_NFCEE_DISCOVER_NTF nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
+struct nci_nfcee_supported_protocol {
+	__u8	num_protocol;
+	__u8	supported_protocol[0];
+} __packed;
+
+struct nci_nfcee_information_tlv {
+	__u8	num_tlv;
+	__u8	information_tlv[0];
+} __packed;
+
+struct nci_nfcee_discover_ntf {
+	__u8	nfcee_id;
+	__u8	nfcee_status;
+	struct nci_nfcee_supported_protocol supported_protocols;
+	struct nci_nfcee_information_tlv	information_tlv;
+} __packed;
+
 #endif /* __NCI_H */
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 23/34] NFC: nci: Add nci_nfcee_discover handler command/response/notification
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (21 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 22/34] NFC: nci: Add NCI NFCEE constant Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 24/34] NFC: nci: Add nci_nfcee_mode_set handler command/response Christophe Ricard
                     ` (10 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add nci_nfcee_discover handler according to NFC Forum NCI specification.
It is necessary for example for secure element handling.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci_core.h |  4 ++++
 net/nfc/nci/core.c         | 17 +++++++++++++++++
 net/nfc/nci/ntf.c          | 29 +++++++++++++++++++++++++++++
 net/nfc/nci/rsp.c          | 21 +++++++++++++++++++++
 4 files changed, 71 insertions(+)

diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 395f804..3df7cd6 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -99,6 +99,8 @@ struct nci_conn_info {
 	struct sk_buff *rx_skb;
 };
 
+#define NCI_INVALID_CONN_ID 0x80
+
 /* NCI Core structures */
 struct nci_dev {
 	struct nfc_dev		*nfc_dev;
@@ -181,6 +183,8 @@ void nci_unregister_device(struct nci_dev *ndev);
 int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
 int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val);
 
+int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
+
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
 					    unsigned int len,
 					    gfp_t how)
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index b3ec63e..bd968d5 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -456,6 +456,23 @@ int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val)
 }
 EXPORT_SYMBOL(nci_set_config);
 
+static void nci_nfcee_discover_req(struct nci_dev *ndev, unsigned long opt)
+{
+	struct nci_nfcee_discover_cmd cmd;
+	__u8 action = opt;
+
+	cmd.discovery_action = action;
+
+	nci_send_cmd(ndev, NCI_OP_NFCEE_DISCOVER_CMD, 1, &cmd);
+}
+
+int nci_nfcee_discover(struct nci_dev *ndev, u8 action)
+{
+	return nci_request(ndev, nci_nfcee_discover_req, action,
+				msecs_to_jiffies(NCI_CMD_TIMEOUT));
+}
+EXPORT_SYMBOL(nci_nfcee_discover);
+
 static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 8c73462..5af0564 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -710,6 +710,32 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
 	nci_req_complete(ndev, NCI_STATUS_OK);
 }
 
+static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev,
+					  struct sk_buff *skb)
+{
+	u8 status = NCI_STATUS_OK;
+	struct nci_conn_info    *conn_info;
+	struct nci_nfcee_discover_ntf   *nfcee_ntf =
+				(struct nci_nfcee_discover_ntf *)skb->data;
+
+	pr_debug("\n");
+
+	conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
+				 sizeof(struct nci_conn_info), GFP_KERNEL);
+	if (!conn_info) {
+		status = NCI_STATUS_REJECTED;
+		goto exit;
+	}
+
+	conn_info->id = nfcee_ntf->nfcee_id;
+	conn_info->conn_id = NCI_INVALID_CONN_ID;
+
+	ndev->conn_info_by_id[conn_info->id] = conn_info;
+
+exit:
+	nci_req_complete(ndev, status);
+}
+
 void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 ntf_opcode = nci_opcode(skb->data);
@@ -748,6 +774,9 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		nci_rf_deactivate_ntf_packet(ndev, skb);
 		break;
 
+	case NCI_OP_NFCEE_DISCOVER_NTF:
+		nci_nfcee_discover_ntf_packet(ndev, skb);
+		break;
 	default:
 		pr_err("unknown ntf opcode 0x%x\n", ntf_opcode);
 		break;
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index ff8721e..a93133b 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -192,6 +192,23 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
 	}
 }
 
+static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
+					  struct sk_buff *skb)
+{
+	struct nci_nfcee_discover_rsp *discover_rsp;
+
+	if (skb->len != 2) {
+		nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR);
+		return;
+	}
+
+	discover_rsp = (struct nci_nfcee_discover_rsp *)skb->data;
+
+	if (discover_rsp->status != NCI_STATUS_OK ||
+	    discover_rsp->num_nfcee == 0)
+		nci_req_complete(ndev, discover_rsp->status);
+}
+
 void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 rsp_opcode = nci_opcode(skb->data);
@@ -237,6 +254,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		nci_rf_deactivate_rsp_packet(ndev, skb);
 		break;
 
+	case NCI_OP_NFCEE_DISCOVER_RSP:
+		nci_nfcee_discover_rsp_packet(ndev, skb);
+		break;
+
 	default:
 		pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
 		break;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 24/34] NFC: nci: Add nci_nfcee_mode_set handler command/response
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (22 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 23/34] NFC: nci: Add nci_nfcee_discover handler command/response/notification Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 25/34] NFC: nci: Add nci_core_conn_create " Christophe Ricard
                     ` (9 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add nci_nfcee_mode_set handler according to NFC Forum NCI specification.
It is necessary for example for secure element handling.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci.h      |  9 +++++++++
 include/net/nfc/nci_core.h |  1 +
 net/nfc/nci/core.c         | 21 +++++++++++++++++++++
 net/nfc/nci/rsp.c          | 13 +++++++++++++
 4 files changed, 44 insertions(+)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index 6d99e8f..230f227 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -284,6 +284,14 @@ struct nci_nfcee_discover_cmd {
 	__u8	discovery_action;
 } __packed;
 
+#define NCI_OP_NFCEE_MODE_SET_CMD nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x01)
+#define NCI_NFCEE_DISABLE	0x00
+#define NCI_NFCEE_ENABLE	0x01
+struct nci_nfcee_mode_set_cmd {
+	__u8	nfcee_id;
+	__u8	nfcee_mode;
+} __packed;
+
 /* ----------------------- */
 /* ---- NCI Responses ---- */
 /* ----------------------- */
@@ -333,6 +341,7 @@ struct nci_nfcee_discover_rsp {
 	__u8	num_nfcee;
 } __packed;
 
+#define NCI_OP_NFCEE_MODE_SET_RSP nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x01)
 /* --------------------------- */
 /* ---- NCI Notifications ---- */
 /* --------------------------- */
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 3df7cd6..46bdf86 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -184,6 +184,7 @@ int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
 int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val);
 
 int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
+int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
 
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
 					    unsigned int len,
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index bd968d5..0de7d90 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -473,6 +473,27 @@ int nci_nfcee_discover(struct nci_dev *ndev, u8 action)
 }
 EXPORT_SYMBOL(nci_nfcee_discover);
 
+static void nci_nfcee_mode_set_req(struct nci_dev *ndev, unsigned long opt)
+{
+	struct nci_nfcee_mode_set_cmd *cmd =
+					(struct nci_nfcee_mode_set_cmd *)opt;
+
+	nci_send_cmd(ndev, NCI_OP_NFCEE_MODE_SET_CMD,
+		     sizeof(struct nci_nfcee_mode_set_cmd), cmd);
+}
+
+int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode)
+{
+	struct nci_nfcee_mode_set_cmd cmd;
+
+	cmd.nfcee_id = nfcee_id;
+	cmd.nfcee_mode = nfcee_mode;
+
+	return nci_request(ndev, nci_nfcee_mode_set_req, (unsigned long)&cmd,
+			   msecs_to_jiffies(NCI_CMD_TIMEOUT));
+}
+EXPORT_SYMBOL(nci_nfcee_mode_set);
+
 static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index a93133b..cb358cd 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -209,6 +209,15 @@ static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
 		nci_req_complete(ndev, discover_rsp->status);
 }
 
+static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
+					  struct sk_buff *skb)
+{
+	__u8 status = skb->data[0];
+
+	pr_debug("status 0x%x\n", status);
+	nci_req_complete(ndev, status);
+}
+
 void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 rsp_opcode = nci_opcode(skb->data);
@@ -258,6 +267,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		nci_nfcee_discover_rsp_packet(ndev, skb);
 		break;
 
+	case NCI_OP_NFCEE_MODE_SET_RSP:
+		nci_nfcee_mode_set_rsp_packet(ndev, skb);
+		break;
+
 	default:
 		pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
 		break;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 25/34] NFC: nci: Add nci_core_conn_create handler command/response
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (23 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 24/34] NFC: nci: Add nci_nfcee_mode_set handler command/response Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 26/34] NFC: nci: Add nci_core_conn_close " Christophe Ricard
                     ` (8 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add nci_core_conn_create handler according to NFC Forum NCI specification.
It is necessary for example for secure element handling.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci.h      | 25 +++++++++++++++++++++++++
 include/net/nfc/nci_core.h |  2 ++
 net/nfc/nci/core.c         | 24 ++++++++++++++++++++++++
 net/nfc/nci/rsp.c          | 31 +++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index 230f227..b8ff50c 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -243,6 +243,23 @@ struct nci_core_set_config_cmd {
 	struct	set_config_param param; /* support 1 param per cmd is enough */
 } __packed;
 
+#define NCI_OP_CORE_CONN_CREATE_CMD	nci_opcode_pack(NCI_GID_CORE, 0x04)
+struct dest_spec_params {
+	__u8	id;
+	__u8	protocol;
+} __packed;
+
+struct core_conn_create_dest_spec_params {
+	__u8	type;
+	__u8	length;
+	struct dest_spec_params value;
+} __packed;
+
+struct nci_core_conn_create_cmd {
+	__u8	destination_type;
+	__u8	number_destination_params;
+	struct core_conn_create_dest_spec_params params;
+} __packed;
 #define NCI_OP_RF_DISCOVER_MAP_CMD	nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 struct disc_map_config {
 	__u8	rf_protocol;
@@ -327,6 +344,14 @@ struct nci_core_set_config_rsp {
 	__u8	params_id[0];	/* variable size array */
 } __packed;
 
+#define NCI_OP_CORE_CONN_CREATE_RSP	nci_opcode_pack(NCI_GID_CORE, 0x04)
+struct nci_core_conn_create_rsp {
+	__u8	status;
+	__u8	max_ctrl_pkt_payload_len;
+	__u8    credits;
+	__u8	conn_id;
+} __packed;
+
 #define NCI_OP_RF_DISCOVER_MAP_RSP	nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 
 #define NCI_OP_RF_DISCOVER_RSP		nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 46bdf86..21da170 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -185,6 +185,8 @@ int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val);
 
 int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
 int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
+int nci_core_conn_create(struct nci_dev *ndev,
+			 struct core_conn_create_dest_spec_params *params);
 
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
 					    unsigned int len,
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 0de7d90..cbe6ea3 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -494,6 +494,30 @@ int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode)
 }
 EXPORT_SYMBOL(nci_nfcee_mode_set);
 
+static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt)
+{
+	struct nci_core_conn_create_cmd cmd;
+	struct core_conn_create_dest_spec_params *params =
+				(struct core_conn_create_dest_spec_params *)opt;
+
+	cmd.destination_type = NCI_DESTINATION_NFCEE;
+	cmd.number_destination_params = 1;
+	memcpy(&cmd.params.type, params,
+	       sizeof(struct core_conn_create_dest_spec_params));
+	nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD,
+		     sizeof(struct nci_core_conn_create_cmd), &cmd);
+}
+
+int nci_core_conn_create(struct nci_dev *ndev,
+			 struct core_conn_create_dest_spec_params *params)
+{
+	ndev->cur_id = params->value.id;
+	return nci_request(ndev, nci_core_conn_create_req,
+			(unsigned long)params,
+			msecs_to_jiffies(NCI_CMD_TIMEOUT));
+}
+EXPORT_SYMBOL(nci_core_conn_create);
+
 static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index cb358cd..5b3c66e 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -218,6 +218,33 @@ static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
 	nci_req_complete(ndev, status);
 }
 
+static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
+					    struct sk_buff *skb)
+{
+	__u8 status = skb->data[0];
+	struct nci_conn_info *conn_info;
+	struct nci_core_conn_create_rsp *rsp;
+
+	pr_debug("status 0x%x\n", status);
+
+	if (status == NCI_STATUS_OK) {
+		rsp = (struct nci_core_conn_create_rsp *)skb->data;
+		conn_info = ndev->conn_info_by_id[ndev->cur_id];
+		if (!conn_info) {
+			status = NCI_STATUS_REJECTED;
+			goto exit;
+		}
+
+		conn_info->conn_id = rsp->conn_id;
+		ndev->conn_info_by_conn_id[conn_info->conn_id] = conn_info;
+		conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len;
+		atomic_set(&conn_info->credits_cnt, rsp->credits);
+	}
+
+exit:
+	nci_req_complete(ndev, status);
+}
+
 void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 rsp_opcode = nci_opcode(skb->data);
@@ -247,6 +274,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		nci_core_set_config_rsp_packet(ndev, skb);
 		break;
 
+	case NCI_OP_CORE_CONN_CREATE_RSP:
+		nci_core_conn_create_rsp_packet(ndev, skb);
+		break;
+
 	case NCI_OP_RF_DISCOVER_MAP_RSP:
 		nci_rf_disc_map_rsp_packet(ndev, skb);
 		break;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 26/34] NFC: nci: Add nci_core_conn_close handler command/response
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (24 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 25/34] NFC: nci: Add nci_core_conn_create " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support Christophe Ricard
                     ` (7 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add nci_core_conn_close handler according to NFC Forum NCI specification.
It is necessary for example for secure element handling.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci.h      |  5 +++++
 include/net/nfc/nci_core.h |  1 +
 net/nfc/nci/core.c         | 14 ++++++++++++++
 net/nfc/nci/rsp.c          | 13 +++++++++++++
 4 files changed, 33 insertions(+)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index b8ff50c..deac78b 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -260,6 +260,9 @@ struct nci_core_conn_create_cmd {
 	__u8	number_destination_params;
 	struct core_conn_create_dest_spec_params params;
 } __packed;
+
+#define NCI_OP_CORE_CONN_CLOSE_CMD	nci_opcode_pack(NCI_GID_CORE, 0x05)
+
 #define NCI_OP_RF_DISCOVER_MAP_CMD	nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 struct disc_map_config {
 	__u8	rf_protocol;
@@ -352,6 +355,8 @@ struct nci_core_conn_create_rsp {
 	__u8	conn_id;
 } __packed;
 
+#define NCI_OP_CORE_CONN_CLOSE_RSP	nci_opcode_pack(NCI_GID_CORE, 0x05)
+
 #define NCI_OP_RF_DISCOVER_MAP_RSP	nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 
 #define NCI_OP_RF_DISCOVER_RSP		nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 21da170..4d1a12e 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -187,6 +187,7 @@ int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
 int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
 int nci_core_conn_create(struct nci_dev *ndev,
 			 struct core_conn_create_dest_spec_params *params);
+int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id);
 
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
 					    unsigned int len,
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index cbe6ea3..ed42a71 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -518,6 +518,20 @@ int nci_core_conn_create(struct nci_dev *ndev,
 }
 EXPORT_SYMBOL(nci_core_conn_create);
 
+static void nci_core_conn_close_req(struct nci_dev *ndev, unsigned long opt)
+{
+	__u8 conn_id = opt;
+
+	nci_send_cmd(ndev, NCI_OP_CORE_CONN_CLOSE_CMD, 1, &conn_id);
+}
+
+int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id)
+{
+	return nci_request(ndev, nci_core_conn_close_req, conn_id,
+				msecs_to_jiffies(NCI_CMD_TIMEOUT));
+}
+EXPORT_SYMBOL(nci_core_conn_close);
+
 static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index 5b3c66e..662f021 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -245,6 +245,15 @@ exit:
 	nci_req_complete(ndev, status);
 }
 
+static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
+					   struct sk_buff *skb)
+{
+	__u8 status = skb->data[0];
+
+	pr_debug("status 0x%x\n", status);
+	nci_req_complete(ndev, status);
+}
+
 void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 rsp_opcode = nci_opcode(skb->data);
@@ -278,6 +287,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		nci_core_conn_create_rsp_packet(ndev, skb);
 		break;
 
+	case NCI_OP_CORE_CONN_CLOSE_RSP:
+		nci_core_conn_close_rsp_packet(ndev, skb);
+		break;
+
 	case NCI_OP_RF_DISCOVER_MAP_RSP:
 		nci_rf_disc_map_rsp_packet(ndev, skb);
 		break;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (25 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 26/34] NFC: nci: Add nci_core_conn_close " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
       [not found]     ` <1418072919-10535-28-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2014-12-08 21:08   ` [PATCH v1 28/34] NFC: st21nfcb: Adding support for secure element Christophe Ricard
                     ` (6 subsequent siblings)
  33 siblings, 1 reply; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Some st21nfcb features are only available through HCI commands. Those
HCI commands can be address over NCI by sending data using a dynamic
conn_id. This is useful for example for Secure Element communication.

The HCI core brings the minimal HCI functions required to communicate with
a secure element.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfcb/Makefile            |   2 +-
 drivers/nfc/st21nfcb/st21nfcb_hci_core.c | 783 +++++++++++++++++++++++++++++++
 drivers/nfc/st21nfcb/st21nfcb_hci_core.h | 134 ++++++
 3 files changed, 918 insertions(+), 1 deletion(-)
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.c
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.h

diff --git a/drivers/nfc/st21nfcb/Makefile b/drivers/nfc/st21nfcb/Makefile
index f4d835d..974c2e9 100644
--- a/drivers/nfc/st21nfcb/Makefile
+++ b/drivers/nfc/st21nfcb/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ST21NFCB NCI based NFC driver
 #
 
-st21nfcb_nci-objs = ndlc.o st21nfcb.o
+st21nfcb_nci-objs = ndlc.o st21nfcb.o st21nfcb_hci_core.o
 obj-$(CONFIG_NFC_ST21NFCB)     += st21nfcb_nci.o
 
 st21nfcb_i2c-objs = i2c.o
diff --git a/drivers/nfc/st21nfcb/st21nfcb_hci_core.c b/drivers/nfc/st21nfcb/st21nfcb_hci_core.c
new file mode 100644
index 0000000..f5a8f2e
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb_hci_core.c
@@ -0,0 +1,783 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  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 <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+
+#include "st21nfcb_hci_core.h"
+
+struct nci_data {
+	u8		conn_id;
+	u8		pipe;
+	u8		cmd;
+	const u8	*data;
+	u32		data_len;
+} __packed;
+
+struct st21nfcb_hci_create_pipe_params {
+	u8 src_gate;
+	u8 dest_host;
+	u8 dest_gate;
+} __packed;
+
+struct st21nfcb_hci_create_pipe_resp {
+	u8 src_host;
+	u8 src_gate;
+	u8 dest_host;
+	u8 dest_gate;
+	u8 pipe;
+} __packed;
+
+struct st21nfcb_hci_delete_pipe_noti {
+	u8 pipe;
+} __packed;
+
+struct st21nfcb_hci_all_pipe_cleared_noti {
+	u8 host;
+} __packed;
+
+struct st21nfcb_hcp_message {
+	u8 header;	/* type -cmd,evt,rsp- + instruction */
+	u8 data[];
+} __packed;
+
+struct st21nfcb_hcp_packet {
+	u8 header;	/* cbit+pipe */
+	struct st21nfcb_hcp_message message;
+} __packed;
+
+
+#define ST21NFCB_HCI_ANY_SET_PARAMETER	0x01
+#define ST21NFCB_HCI_ANY_GET_PARAMETER	0x02
+#define ST21NFCB_HCI_ANY_CLOSE_PIPE	0x04
+
+#define ST21NFCB_HFP_NO_CHAINING	0x80
+
+#define NCI_NFCEE_ID_HCI		0x80
+
+#define ST21NFCB_EVT_HOT_PLUG		0x03
+
+#define ST21NFCB_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
+
+/* HCP headers */
+#define ST21NFCB_HCI_HCP_PACKET_HEADER_LEN	1
+#define ST21NFCB_HCI_HCP_MESSAGE_HEADER_LEN	1
+#define ST21NFCB_HCI_HCP_HEADER_LEN		2
+
+/* HCP types */
+#define ST21NFCB_HCI_HCP_COMMAND	0x00
+#define ST21NFCB_HCI_HCP_EVENT		0x01
+#define ST21NFCB_HCI_HCP_RESPONSE	0x02
+
+#define ST21NFCB_HCI_ADM_NOTIFY_PIPE_CREATED     0x12
+#define ST21NFCB_HCI_ADM_NOTIFY_PIPE_DELETED     0x13
+#define ST21NFCB_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
+
+#define ST21NFCB_HCI_FRAGMENT		0x7f
+#define ST21NFCB_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
+					   ((instr) & 0x3f))
+
+#define ST21NFCB_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
+#define ST21NFCB_HCP_MSG_GET_CMD(header)  (header & 0x3f)
+#define ST21NFCB_HCP_MSG_GET_PIPE(header) (header & 0x7f)
+
+#define ST21NFCB_NUM_DEVICES		256
+
+static DECLARE_BITMAP(dev_mask, ST21NFCB_NUM_DEVICES);
+
+static void st21nfcb_hci_data_received_cb(void *context,
+					  struct sk_buff *skb, int err);
+
+static void st21nfcb_hci_reset_pipes(struct st21nfcb_hci_dev *hdev)
+{
+	int i;
+
+	for (i = 0; i < ST21NFCB_HCI_MAX_PIPES; i++) {
+		hdev->pipes[i].gate = ST21NFCB_HCI_INVALID_GATE;
+		hdev->pipes[i].host = ST21NFCB_HCI_INVALID_HOST;
+	}
+	memset(hdev->gate2pipe, ST21NFCB_HCI_INVALID_PIPE,
+	       sizeof(hdev->gate2pipe));
+}
+
+static void st21nfcb_hci_reset_pipes_per_host(struct st21nfcb_hci_dev *hdev, u8 host)
+{
+	int i;
+
+	for (i = 0; i < ST21NFCB_HCI_MAX_PIPES; i++) {
+		if (hdev->pipes[i].host == host) {
+			hdev->pipes[i].gate = ST21NFCB_HCI_INVALID_GATE;
+			hdev->pipes[i].host = ST21NFCB_HCI_INVALID_HOST;
+		}
+	}
+}
+
+/* Fragment HCI data over NCI packet.
+ * NFC Forum NCI 10.2.2 Data Exchange:
+ * The payload of the Data Packets sent on the Logical Connection SHALL be
+ * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
+ * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
+ * applied to Data Messages in either direction. The HCI fragmentation mechanism
+ * is used if required.
+ */
+static int st21nfcb_hci_send_data(struct nci_dev *ndev, u8 conn_id,
+				  u8 pipe, const u8 data_type, const u8 *data,
+				  size_t data_len)
+{
+	struct nci_conn_info    *conn_info;
+	struct sk_buff *skb;
+	int len, i, r;
+	u8 cb = pipe;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	skb = nci_skb_alloc(ndev, 2 + conn_info->max_pkt_payload_len +
+			NCI_DATA_HDR_SIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, 2 + NCI_DATA_HDR_SIZE);
+	*skb_push(skb, 1) = data_type;
+
+	i = 0;
+	len = conn_info->max_pkt_payload_len;
+
+	do {
+		/* If last packet add ST21NFCB_HFP_NO_CHAINING */
+		if (i + conn_info->max_pkt_payload_len -
+		    (skb->len + 1) >= data_len) {
+			cb |= ST21NFCB_HFP_NO_CHAINING;
+			len = data_len - i;
+		} else {
+			len = conn_info->max_pkt_payload_len - skb->len - 1;
+		}
+
+		*skb_push(skb, 1) = cb;
+
+		if (len > 0)
+			memcpy(skb_put(skb, len), data + i, len);
+
+		r = nci_send_data(ndev, conn_info->conn_id, skb);
+		if (r < 0)
+			return r;
+
+		i += len;
+		if (i < data_len) {
+			skb_trim(skb, 0);
+			skb_pull(skb, len);
+		}
+	} while (i < data_len);
+
+	return i;
+}
+
+static void st21nfcb_hci_send_data_req(struct nci_dev *ndev, unsigned long opt)
+{
+	struct nci_data *data = (struct nci_data *) opt;
+
+	st21nfcb_hci_send_data(ndev, data->conn_id, data->pipe, data->cmd,
+			       data->data, data->data_len);
+}
+
+int st21nfcb_hci_send_event(struct st21nfcb_hci_dev *hdev, u8 gate, u8 event,
+				const u8 *param, size_t param_len)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info    *conn_info;
+	u8 pipe = hdev->gate2pipe[gate];
+
+	if (pipe == ST21NFCB_HCI_INVALID_PIPE)
+		return -EADDRNOTAVAIL;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	return st21nfcb_hci_send_data(ndev, conn_info->conn_id, pipe,
+			ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_EVENT, event),
+			param, param_len);
+}
+EXPORT_SYMBOL(st21nfcb_hci_send_event);
+
+int st21nfcb_hci_send_cmd(struct st21nfcb_hci_dev *hdev, u8 gate,
+			u8 cmd, const u8 *param, size_t param_len,
+			struct sk_buff **skb)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info    *conn_info;
+	struct nci_data data;
+	int r;
+	u8 pipe = hdev->gate2pipe[gate];
+
+	if (pipe == ST21NFCB_HCI_INVALID_PIPE)
+		return -EADDRNOTAVAIL;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	data.conn_id = conn_info->conn_id;
+	data.pipe = pipe;
+	data.cmd = ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_COMMAND, cmd);
+	data.data = param;
+	data.data_len = param_len;
+
+	r = nci_request(ndev, st21nfcb_hci_send_data_req, (unsigned long)&data,
+			 msecs_to_jiffies(NCI_DATA_TIMEOUT));
+
+	if (r == NCI_STATUS_OK)
+		*skb = conn_info->rx_skb;
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfcb_hci_send_cmd);
+
+int st21nfcb_hci_send_response(struct st21nfcb_hci_dev *hdev, u8 pipe,
+				u8 cmd, const u8 *param, size_t param_len)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info    *conn_info;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	return st21nfcb_hci_send_data(ndev, conn_info->conn_id, pipe,
+			ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_RESPONSE, cmd),
+			param, param_len);
+}
+EXPORT_SYMBOL(st21nfcb_hci_send_response);
+
+static void st21nfcb_hci_event_received(struct st21nfcb_hci_dev *hdev, u8 pipe,
+					u8 event, struct sk_buff *skb)
+{
+	if (hdev->ops->event_received)
+		hdev->ops->event_received(hdev, pipe, event, skb);
+}
+
+static void st21nfcb_hci_cmd_received(struct st21nfcb_hci_dev *hdev, u8 pipe,
+				      u8 cmd, struct sk_buff *skb)
+{
+	u8 gate = hdev->pipes[pipe].gate;
+	u8 status = ST21NFCB_HCI_ANY_OK;
+	struct st21nfcb_hci_create_pipe_resp *create_info;
+	struct st21nfcb_hci_delete_pipe_noti *delete_info;
+	struct st21nfcb_hci_all_pipe_cleared_noti *cleared_info;
+
+	pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
+
+	switch (cmd) {
+	case ST21NFCB_HCI_ADM_NOTIFY_PIPE_CREATED:
+		if (skb->len != 5) {
+			status = ST21NFCB_HCI_ANY_E_NOK;
+			goto exit;
+		}
+		create_info = (struct st21nfcb_hci_create_pipe_resp *)skb->data;
+
+		/*
+		 * 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[create_info->dest_gate] = create_info->pipe;
+		hdev->pipes[create_info->pipe].gate = create_info->dest_gate;
+		hdev->pipes[create_info->pipe].host = create_info->src_host;
+		break;
+	case ST21NFCB_HCI_ANY_OPEN_PIPE:
+		/* If the pipe is not created report an error */
+		if (gate == ST21NFCB_HCI_INVALID_GATE) {
+			status = ST21NFCB_HCI_ANY_E_NOK;
+			goto exit;
+		}
+		break;
+	case ST21NFCB_HCI_ADM_NOTIFY_PIPE_DELETED:
+		if (skb->len != 1) {
+			status = ST21NFCB_HCI_ANY_E_NOK;
+			goto exit;
+		}
+		delete_info = (struct st21nfcb_hci_delete_pipe_noti *)skb->data;
+
+		hdev->pipes[delete_info->pipe].gate = ST21NFCB_HCI_INVALID_GATE;
+		hdev->pipes[delete_info->pipe].host = ST21NFCB_HCI_INVALID_HOST;
+		break;
+	case ST21NFCB_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
+		if (skb->len != 1) {
+			status = ST21NFCB_HCI_ANY_E_NOK;
+			goto exit;
+		}
+		cleared_info = (struct st21nfcb_hci_all_pipe_cleared_noti *)skb->data;
+		st21nfcb_hci_reset_pipes_per_host(hdev, cleared_info->host);
+		break;
+	default:
+		pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
+		break;
+	}
+
+	if (hdev->ops->cmd_received)
+		hdev->ops->cmd_received(hdev, pipe, cmd, skb);
+
+exit:
+	st21nfcb_hci_send_response(hdev, pipe, status, NULL, 0);
+
+	kfree_skb(skb);
+}
+
+static void st21nfcb_hci_resp_received(struct st21nfcb_hci_dev *hdev, u8 pipe,
+					u8 result, struct sk_buff *skb)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info    *conn_info;
+	u8 status = result;
+
+	if (result != ST21NFCB_HCI_ANY_OK)
+		goto exit;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info) {
+		status = NCI_STATUS_REJECTED;
+		goto exit;
+	}
+
+	conn_info->rx_skb = skb;
+
+exit:
+	nci_req_complete(ndev, status);
+}
+
+/*
+ * Receive hcp message for pipe, with type and cmd.
+ * skb contains optional message data only.
+ */
+static void st21nfcb_hci_hcp_message_rx(struct st21nfcb_hci_dev *hdev, u8 pipe,
+				u8 type, u8 instruction, struct sk_buff *skb)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+
+	switch (type) {
+	case ST21NFCB_HCI_HCP_RESPONSE:
+		st21nfcb_hci_resp_received(hdev, pipe, instruction, skb);
+		break;
+	case ST21NFCB_HCI_HCP_COMMAND:
+		st21nfcb_hci_cmd_received(hdev, pipe, instruction, skb);
+		break;
+	case ST21NFCB_HCI_HCP_EVENT:
+		st21nfcb_hci_event_received(hdev, pipe, instruction, skb);
+		break;
+	default:
+		pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
+			type, instruction);
+		kfree_skb(skb);
+		break;
+	}
+
+	nci_req_complete(ndev, 0);
+}
+
+static void st21nfcb_hci_msg_rx_work(struct work_struct *work)
+{
+	struct st21nfcb_hci_dev *hdev = container_of(work,
+						struct st21nfcb_hci_dev,
+						msg_rx_work);
+	struct sk_buff *skb;
+	struct st21nfcb_hcp_message *message;
+	u8 pipe, type, instruction;
+
+	while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
+		pipe = skb->data[0];
+		skb_pull(skb, ST21NFCB_HCI_HCP_PACKET_HEADER_LEN);
+		message = (struct st21nfcb_hcp_message *)skb->data;
+		type = ST21NFCB_HCP_MSG_GET_TYPE(message->header);
+		instruction = ST21NFCB_HCP_MSG_GET_CMD(message->header);
+		skb_pull(skb, ST21NFCB_HCI_HCP_MESSAGE_HEADER_LEN);
+
+		st21nfcb_hci_hcp_message_rx(hdev, pipe, type, instruction, skb);
+	}
+}
+
+static void st21nfcb_hci_data_received_cb(void *context,
+				struct sk_buff *skb, int err)
+{
+	struct st21nfcb_hci_dev *hdev = (struct st21nfcb_hci_dev *)context;
+	struct st21nfcb_hcp_packet *packet;
+	u8 pipe, type, instruction;
+	struct sk_buff *hcp_skb;
+	struct sk_buff *frag_skb;
+	int msg_len;
+
+	pr_debug("\n");
+
+	if (err) {
+		nci_req_complete(hdev->ndev, err);
+		return;
+	}
+
+	packet = (struct st21nfcb_hcp_packet *)skb->data;
+	if ((packet->header & ~ST21NFCB_HCI_FRAGMENT) == 0) {
+		skb_queue_tail(&hdev->rx_hcp_frags, skb);
+		return;
+	}
+
+	/* it's the last fragment. Does it need re-aggregation? */
+	if (skb_queue_len(&hdev->rx_hcp_frags)) {
+		pipe = packet->header & ST21NFCB_HCI_FRAGMENT;
+		skb_queue_tail(&hdev->rx_hcp_frags, skb);
+
+		msg_len = 0;
+		skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) {
+			msg_len += (frag_skb->len -
+				    ST21NFCB_HCI_HCP_PACKET_HEADER_LEN);
+		}
+
+		hcp_skb = nfc_alloc_recv_skb(ST21NFCB_HCI_HCP_PACKET_HEADER_LEN +
+					     msg_len, GFP_KERNEL);
+		if (hcp_skb == NULL) {
+			nci_req_complete(hdev->ndev, -ENOMEM);
+			return;
+		}
+
+		*skb_put(hcp_skb, ST21NFCB_HCI_HCP_PACKET_HEADER_LEN) = pipe;
+
+		skb_queue_walk(&hdev->rx_hcp_frags, frag_skb) {
+			msg_len = frag_skb->len -
+				  ST21NFCB_HCI_HCP_PACKET_HEADER_LEN;
+			memcpy(skb_put(hcp_skb, msg_len), frag_skb->data +
+			       ST21NFCB_HCI_HCP_PACKET_HEADER_LEN, msg_len);
+		}
+
+		skb_queue_purge(&hdev->rx_hcp_frags);
+	} else {
+		packet->header &= ST21NFCB_HCI_FRAGMENT;
+		hcp_skb = skb;
+	}
+
+	/* if this is a response, dispatch immediately to
+	 * unblock waiting cmd context. Otherwise, enqueue to dispatch
+	 * in separate context where handler can also execute command.
+	 */
+	packet = (struct st21nfcb_hcp_packet *)hcp_skb->data;
+	type = ST21NFCB_HCP_MSG_GET_TYPE(packet->message.header);
+	if (type == ST21NFCB_HCI_HCP_RESPONSE) {
+		pipe = packet->header;
+		instruction = ST21NFCB_HCP_MSG_GET_CMD(packet->message.header);
+		skb_pull(hcp_skb, ST21NFCB_HCI_HCP_PACKET_HEADER_LEN +
+			ST21NFCB_HCI_HCP_MESSAGE_HEADER_LEN);
+		st21nfcb_hci_hcp_message_rx(hdev, pipe, type, instruction,
+					    hcp_skb);
+	} else {
+		skb_queue_tail(&hdev->msg_rx_queue, hcp_skb);
+		schedule_work(&hdev->msg_rx_work);
+	}
+}
+
+int st21nfcb_hci_open_pipe(struct st21nfcb_hci_dev *hdev, u8 pipe)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_data data;
+	struct nci_conn_info    *conn_info;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	data.conn_id = conn_info->conn_id;
+	data.pipe = pipe;
+	data.cmd = ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_COMMAND,
+				       ST21NFCB_HCI_ANY_OPEN_PIPE);
+	data.data = NULL;
+	data.data_len = 0;
+
+	return nci_request(ndev, st21nfcb_hci_send_data_req,
+			(unsigned long)&data,
+			msecs_to_jiffies(NCI_DATA_TIMEOUT));
+}
+EXPORT_SYMBOL(st21nfcb_hci_open_pipe);
+
+int st21nfcb_hci_set_param(struct st21nfcb_hci_dev *hdev, u8 gate, u8 idx,
+			const u8 *param, size_t param_len)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info *conn_info;
+	struct nci_data data;
+	int r;
+	u8 *tmp;
+	u8 pipe = hdev->gate2pipe[gate];
+
+	pr_debug("idx=%d to gate %d\n", idx, gate);
+
+	if (pipe == ST21NFCB_HCI_INVALID_PIPE)
+		return -EADDRNOTAVAIL;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	tmp = kmalloc(1 + param_len, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	*tmp = idx;
+	memcpy(tmp + 1, param, param_len);
+
+	data.conn_id = conn_info->conn_id;
+	data.pipe = pipe;
+	data.cmd = ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_COMMAND,
+				ST21NFCB_HCI_ANY_SET_PARAMETER);
+	data.data = tmp;
+	data.data_len = param_len + 1;
+
+	r = nci_request(ndev, st21nfcb_hci_send_data_req,
+			(unsigned long)&data,
+			msecs_to_jiffies(NCI_DATA_TIMEOUT));
+
+	kfree(tmp);
+	return r;
+}
+EXPORT_SYMBOL(st21nfcb_hci_set_param);
+
+int st21nfcb_hci_get_param(struct st21nfcb_hci_dev *hdev, u8 gate, u8 idx,
+			struct sk_buff **skb)
+{
+	struct nci_dev *ndev = st21nfcb_hci_get_nci(hdev);
+	struct nci_conn_info    *conn_info;
+	struct nci_data data;
+	int r;
+	u8 pipe = hdev->gate2pipe[gate];
+
+	pr_debug("idx=%d to gate %d\n", idx, gate);
+
+	if (pipe == ST21NFCB_HCI_INVALID_PIPE)
+		return -EADDRNOTAVAIL;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return -EPROTO;
+
+	data.conn_id = conn_info->conn_id;
+	data.pipe = pipe;
+	data.cmd = ST21NFCB_HCP_HEADER(ST21NFCB_HCI_HCP_COMMAND,
+				ST21NFCB_HCI_ANY_GET_PARAMETER);
+	data.data = &idx;
+	data.data_len = 1;
+
+	r = nci_request(ndev, st21nfcb_hci_send_data_req, (unsigned long)&data,
+			msecs_to_jiffies(NCI_DATA_TIMEOUT));
+
+	if (r == NCI_STATUS_OK)
+		*skb = conn_info->rx_skb;
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfcb_hci_get_param);
+
+int st21nfcb_hci_connect_gate(struct st21nfcb_hci_dev *hdev,
+				u8 dest_host, u8 dest_gate, u8 pipe)
+{
+	int r;
+
+	if (pipe == ST21NFCB_HCI_DO_NOT_OPEN_PIPE)
+		return 0;
+
+	if (hdev->gate2pipe[dest_gate] != ST21NFCB_HCI_INVALID_PIPE)
+		return -EADDRINUSE;
+
+	if (pipe != ST21NFCB_HCI_INVALID_PIPE)
+		goto open_pipe;
+
+	switch (dest_gate) {
+	case ST21NFCB_HCI_LINK_MGMT_GATE:
+		pipe = ST21NFCB_HCI_LINK_MGMT_PIPE;
+	break;
+	case ST21NFCB_HCI_ADMIN_GATE:
+		pipe = ST21NFCB_HCI_ADMIN_PIPE;
+	break;
+	}
+
+open_pipe:
+	r = st21nfcb_hci_open_pipe(hdev, pipe);
+	if (r < 0)
+		return r;
+
+	hdev->pipes[pipe].gate = dest_gate;
+	hdev->pipes[pipe].host = dest_host;
+	hdev->gate2pipe[dest_gate] = pipe;
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfcb_hci_connect_gate);
+
+static int st21nfcb_hci_dev_connect_gates(struct st21nfcb_hci_dev *hdev,
+					  u8 gate_count,
+					  struct st21nfcb_hci_gate *gates)
+{
+	int r;
+
+	while (gate_count--) {
+		r = st21nfcb_hci_connect_gate(hdev, ST21NFCB_HOST_CONTROLLER_ID,
+					      gates->gate, gates->pipe);
+		if (r < 0)
+			return r;
+		gates++;
+	}
+
+	return 0;
+}
+
+static int st21nfcb_hci_dev_session_init(struct st21nfcb_hci_dev *hdev,
+					 const char *session_id)
+{
+	struct sk_buff *skb;
+	int r, dev_num;
+
+	hdev->count_pipes = 0;
+	hdev->expected_pipes = 0;
+
+	/*
+	 * Session id must include the driver name + i2c bus addr
+	 * persistent info to discriminate 2 identical chips
+	 */
+	dev_num = find_first_zero_bit(dev_mask, ST21NFCB_NUM_DEVICES);
+	if (dev_num >= ST21NFCB_NUM_DEVICES)
+		return -ENODEV;
+
+	scnprintf(hdev->init_data.session_id,
+		  sizeof(hdev->init_data.session_id), "%s%2x", session_id,
+		  dev_num);
+
+	if (hdev->init_data.gates[0].gate != ST21NFCB_HCI_ADMIN_GATE)
+		return -EPROTO;
+
+	r = st21nfcb_hci_connect_gate(hdev, ST21NFCB_HOST_CONTROLLER_ID,
+				hdev->init_data.gates[0].gate,
+				hdev->init_data.gates[0].pipe);
+	if (r < 0)
+		goto exit;
+
+	r = st21nfcb_hci_get_param(hdev, ST21NFCB_HCI_ADMIN_GATE,
+				ST21NFCB_HCI_ADMIN_PARAM_SESSION_IDENTITY,
+				&skb);
+	if (r < 0)
+		goto exit;
+
+	if (skb->len && skb->len == strlen(hdev->init_data.session_id) &&
+	    memcmp(hdev->init_data.session_id, skb->data, skb->len) == 0 &&
+		   hdev->ops->load_session) {
+		/* Restore gate<->pipe table from some proprietary location. */
+		r = hdev->ops->load_session(hdev);
+		if (r < 0)
+			goto exit;
+	} else {
+		r = st21nfcb_hci_dev_connect_gates(hdev,
+					hdev->init_data.gate_count,
+					hdev->init_data.gates);
+		if (r < 0)
+			goto exit;
+
+		r = st21nfcb_hci_set_param(hdev, ST21NFCB_HCI_ADMIN_GATE,
+				ST21NFCB_HCI_ADMIN_PARAM_SESSION_IDENTITY,
+				hdev->init_data.session_id,
+				strlen(hdev->init_data.session_id));
+	}
+	if (r == 0)
+		goto exit;
+
+exit:
+	kfree_skb(skb);
+
+	return r;
+}
+
+struct st21nfcb_hci_dev *st21nfcb_hci_allocate(struct nci_dev *ndev,
+					       struct st21nfcb_hci_ops *ops,
+					       const char *session_id,
+					       struct st21nfcb_hci_gate *gates,
+					       int gates_len)
+{
+	struct st21nfcb_hci_dev  *hdev;
+	struct core_conn_create_dest_spec_params dest_params;
+	struct nci_conn_info    *conn_info;
+	int r;
+
+	hdev = kzalloc(sizeof(struct st21nfcb_hci_dev), GFP_KERNEL);
+	if (!hdev)
+		return NULL;
+
+	r = nci_nfcee_discover(ndev, NCI_NFCEE_DISCOVERY_ACTION_ENABLE);
+	if (r != NCI_STATUS_OK)
+		goto exit;
+
+	dest_params.type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE;
+	dest_params.length = sizeof(struct dest_spec_params);
+	dest_params.value.id = NCI_NFCEE_ID_HCI;
+	dest_params.value.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS;
+	r = nci_core_conn_create(ndev, &dest_params);
+	if (r != NCI_STATUS_OK)
+		goto exit;
+
+	conn_info = ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		goto exit;
+
+	conn_info->data_exchange_cb = st21nfcb_hci_data_received_cb;
+	conn_info->data_exchange_cb_context = hdev;
+
+	hdev->ndev = ndev;
+	hdev->ops = ops;
+
+	skb_queue_head_init(&hdev->rx_hcp_frags);
+	INIT_WORK(&hdev->msg_rx_work, st21nfcb_hci_msg_rx_work);
+	skb_queue_head_init(&hdev->msg_rx_queue);
+
+	memcpy(hdev->init_data.gates, gates, gates_len);
+
+	st21nfcb_hci_reset_pipes(hdev);
+	r = st21nfcb_hci_dev_session_init(hdev, "ST21BH");
+	if (r != ST21NFCB_HCI_ANY_OK)
+		goto exit;
+
+	r = nci_nfcee_mode_set(ndev, NCI_NFCEE_ID_HCI, NCI_NFCEE_ENABLE);
+	if (r != NCI_STATUS_OK)
+		goto exit;
+
+	return hdev;
+
+exit:
+	kfree(hdev);
+	return NULL;
+}
+EXPORT_SYMBOL(st21nfcb_hci_allocate);
+
+void st21nfcb_hci_free(struct st21nfcb_hci_dev *hdev)
+{
+	struct nci_conn_info    *conn_info;
+
+	conn_info = hdev->ndev->conn_info_by_id[NCI_NFCEE_ID_HCI];
+	if (!conn_info)
+		return;
+
+	nci_core_conn_close(hdev->ndev, conn_info->conn_id);
+	kfree(hdev);
+}
+EXPORT_SYMBOL(st21nfcb_hci_free);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/st21nfcb_hci_core.h b/drivers/nfc/st21nfcb/st21nfcb_hci_core.h
new file mode 100644
index 0000000..fa468b4
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb_hci_core.h
@@ -0,0 +1,134 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  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_ST21NFCB_HCI_CORE_H_
+#define __LOCAL_ST21NFCB_HCI_CORE_H_
+
+#define ST21NFCB_HCI_ANY_OPEN_PIPE	0x03
+
+/* Hosts */
+#define ST21NFCB_HOST_CONTROLLER_ID     0x00
+#define ST21NFCB_TERMINAL_HOST_ID       0x01
+#define ST21NFCB_UICC_HOST_ID           0x02
+#define ST21NFCB_ESE_HOST_ID            0xc0
+
+/* Gates */
+#define ST21NFCB_HCI_ADMIN_GATE         0x00
+#define ST21NFCB_DEVICE_MGNT_GATE       0x01
+#define ST21NFCB_HCI_LINK_MGMT_GATE     0x06
+#define ST21NFCB_APDU_READER_GATE       0xf0
+#define ST21NFCB_CONNECTIVITY_GATE      0x41
+
+/* Pipes */
+#define ST21NFCB_HCI_LINK_MGMT_PIPE             0x00
+#define ST21NFCB_HCI_ADMIN_PIPE                 0x01
+#define ST21NFCB_DEVICE_MGNT_PIPE               0x02
+
+/* Generic responses */
+#define ST21NFCB_HCI_ANY_OK                     0x00
+#define ST21NFCB_HCI_ANY_E_NOT_CONNECTED        0x01
+#define ST21NFCB_HCI_ANY_E_CMD_PAR_UNKNOWN      0x02
+#define ST21NFCB_HCI_ANY_E_NOK                  0x03
+#define ST21NFCB_HCI_ANY_E_PIPES_FULL           0x04
+#define ST21NFCB_HCI_ANY_E_REG_PAR_UNKNOWN      0x05
+#define ST21NFCB_HCI_ANY_E_PIPE_NOT_OPENED      0x06
+#define ST21NFCB_HCI_ANY_E_CMD_NOT_SUPPORTED    0x07
+#define ST21NFCB_HCI_ANY_E_INHIBITED            0x08
+#define ST21NFCB_HCI_ANY_E_TIMEOUT              0x09
+#define ST21NFCB_HCI_ANY_E_REG_ACCESS_DENIED    0x0a
+#define ST21NFCB_HCI_ANY_E_PIPE_ACCESS_DENIED   0x0b
+
+#define ST21NFCB_HCI_DO_NOT_OPEN_PIPE		0x81
+#define ST21NFCB_HCI_INVALID_PIPE		0x80
+#define ST21NFCB_HCI_INVALID_GATE		0xFF
+#define ST21NFCB_HCI_INVALID_HOST		0x80
+
+#define ST21NFCB_HCI_MAX_CUSTOM_GATES   50
+#define ST21NFCB_HCI_MAX_PIPES          127
+
+struct st21nfcb_hci_gate {
+	u8 gate;
+	u8 pipe;
+} __packed;
+
+struct st21nfcb_hci_pipe {
+	u8 gate;
+	u8 host;
+} __packed;
+
+struct st21nfcb_hci_init_data {
+	u8 gate_count;
+	struct st21nfcb_hci_gate gates[ST21NFCB_HCI_MAX_CUSTOM_GATES];
+	char session_id[9];
+};
+
+#define ST21NFCB_HCI_MAX_GATES		256
+
+struct st21nfcb_hci_dev {
+	struct nci_dev *ndev;
+
+	struct st21nfcb_hci_init_data init_data;
+	struct st21nfcb_hci_pipe pipes[ST21NFCB_HCI_MAX_PIPES];
+	u8 gate2pipe[ST21NFCB_HCI_MAX_GATES];
+	int expected_pipes;
+	int count_pipes;
+
+	struct sk_buff_head rx_hcp_frags;
+	struct work_struct msg_rx_work;
+	struct sk_buff_head msg_rx_queue;
+
+	struct st21nfcb_hci_ops *ops;
+};
+
+struct st21nfcb_hci_ops {
+	int (*load_session)(struct st21nfcb_hci_dev *hdev);
+	void (*event_received)(struct st21nfcb_hci_dev *hdev, u8 pipe, u8 event,
+			      struct sk_buff *skb);
+	void (*cmd_received)(struct st21nfcb_hci_dev *ndev, u8 pipe, u8 cmd,
+			    struct sk_buff *skb);
+};
+
+static inline struct nci_dev *st21nfcb_hci_get_nci(struct st21nfcb_hci_dev *hdev)
+{
+	return hdev->ndev;
+}
+
+int st21nfcb_hci_send_event(struct st21nfcb_hci_dev *hdev, u8 gate, u8 event,
+			    const u8 *param, size_t param_len);
+int st21nfcb_hci_send_cmd(struct st21nfcb_hci_dev *hdev, u8 gate,
+			  u8 cmd, const u8 *param, size_t param_len,
+			  struct sk_buff **skb);
+int st21nfcb_hci_send_response(struct st21nfcb_hci_dev *hdev, u8 pipe,
+			       u8 cmd, const u8 *param, size_t param_len);
+
+int st21nfcb_hci_open_pipe(struct st21nfcb_hci_dev *hdev, u8 pipe);
+int st21nfcb_hci_connect_gate(struct st21nfcb_hci_dev *hdev,
+			      u8 dest_host, u8 dest_gate, u8 pipe);
+int st21nfcb_hci_set_param(struct st21nfcb_hci_dev *hdev, u8 gate, u8 idx,
+			   const u8 *param, size_t param_len);
+int st21nfcb_hci_get_param(struct st21nfcb_hci_dev *hdev, u8 gate, u8 idx,
+			   struct sk_buff **skb);
+
+struct st21nfcb_hci_dev *st21nfcb_hci_allocate(struct nci_dev *ndev,
+					struct st21nfcb_hci_ops *ops,
+					const char *session_id,
+					struct st21nfcb_hci_gate *gates,
+					int gates_len);
+void st21nfcb_hci_free(struct st21nfcb_hci_dev *hdev);
+
+#endif /* __LOCAL_ST21NFCB_HCI_CORE_H_ */
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 28/34] NFC: st21nfcb: Adding support for secure element
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (26 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 29/34] NFC: Forward NFC_EVT_TRANSACTION up to user space Christophe Ricard
                     ` (5 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

st21nfcb has 3 SWP lines and can support up to 3 secure elements (UICC/eSE and µSD in the future).

Some st21nfcb firmware does not support the nci command nci_nfcee_mode_set(NCI_NFCEE_DISABLE).
For this reason, we assume 2 secures elements are always present (UICC and eSE).
They will be added to the SE list once successfully activated. They will
be available only after running through enable_se handler or when the poll
in listen mode is started.

During initialization, the white_list will be always set assuming both
UICC & eSE are present.

On ese activation, the atr is retrieved to calculate a command exchange
timeout according to the first atr(TB) value.

The se_io will allow to transfer data over SWP. 2 kind of event may appear
after a data is sent over:
- ST21NFCB_EVT_TRANSMIT_DATA when receiving an apdu answer
- ST21NFCB_EVT_WTX_REQUEST when the secure element needs more time than
expected to compute a command. If this timeout expired, a first recovery
tentative consist to send a simple software reset command. If this
tentative still fail, a second recovery tentative consist to send a
hardware reset.
This function is only relevant for eSE like secure element.

Like st21nfca, we do reference pipe with a tuple (gate, host) in order to
keep the host information when receiving secure element event
(ex: EVT_TRANSACTION).

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfcb/Makefile      |   2 +-
 drivers/nfc/st21nfcb/st21nfcb.c    |   8 +-
 drivers/nfc/st21nfcb/st21nfcb.h    |   2 +
 drivers/nfc/st21nfcb/st21nfcb_se.c | 610 +++++++++++++++++++++++++++++++++++++
 drivers/nfc/st21nfcb/st21nfcb_se.h |  59 ++++
 5 files changed, 679 insertions(+), 2 deletions(-)
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_se.c
 create mode 100644 drivers/nfc/st21nfcb/st21nfcb_se.h

diff --git a/drivers/nfc/st21nfcb/Makefile b/drivers/nfc/st21nfcb/Makefile
index 974c2e9..2f452d7 100644
--- a/drivers/nfc/st21nfcb/Makefile
+++ b/drivers/nfc/st21nfcb/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ST21NFCB NCI based NFC driver
 #
 
-st21nfcb_nci-objs = ndlc.o st21nfcb.o st21nfcb_hci_core.o
+st21nfcb_nci-objs = ndlc.o st21nfcb.o st21nfcb_hci_core.o st21nfcb_se.o
 obj-$(CONFIG_NFC_ST21NFCB)     += st21nfcb_nci.o
 
 st21nfcb_i2c-objs = i2c.o
diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c
index ea63d58..d2b60eb 100644
--- a/drivers/nfc/st21nfcb/st21nfcb.c
+++ b/drivers/nfc/st21nfcb/st21nfcb.c
@@ -22,6 +22,7 @@
 #include <net/nfc/nci_core.h>
 
 #include "st21nfcb.h"
+#include "st21nfcb_se.h"
 
 #define DRIVER_DESC "NCI NFC driver for ST21NFCB"
 
@@ -78,6 +79,10 @@ static struct nci_ops st21nfcb_nci_ops = {
 	.close = st21nfcb_nci_close,
 	.send = st21nfcb_nci_send,
 	.get_rfprotocol = st21nfcb_nci_get_rfprotocol,
+	.discover_se = st21nfcb_nci_discover_se,
+	.enable_se = st21nfcb_nci_enable_se,
+	.disable_se = st21nfcb_nci_disable_se,
+	.se_io = st21nfcb_nci_se_io,
 };
 
 int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
@@ -114,9 +119,10 @@ int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
 	if (r) {
 		pr_err("Cannot register nfc device to nci core\n");
 		nci_free_device(ndlc->ndev);
+		return r;
 	}
 
-	return r;
+	return st21nfcb_se_init(ndlc->ndev);
 }
 EXPORT_SYMBOL_GPL(st21nfcb_nci_probe);
 
diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st21nfcb/st21nfcb.h
index ea58a56..5ef8a58 100644
--- a/drivers/nfc/st21nfcb/st21nfcb.h
+++ b/drivers/nfc/st21nfcb/st21nfcb.h
@@ -19,6 +19,7 @@
 #ifndef __LOCAL_ST21NFCB_H_
 #define __LOCAL_ST21NFCB_H_
 
+#include "st21nfcb_se.h"
 #include "ndlc.h"
 
 /* Define private flags: */
@@ -27,6 +28,7 @@
 struct st21nfcb_nci_info {
 	struct llt_ndlc *ndlc;
 	unsigned long flags;
+	struct st21nfcb_se_info se_info;
 };
 
 void st21nfcb_nci_remove(struct nci_dev *ndev);
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.c b/drivers/nfc/st21nfcb/st21nfcb_se.c
new file mode 100644
index 0000000..cf65368
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb_se.c
@@ -0,0 +1,610 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  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 <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+
+#include "st21nfcb.h"
+#include "st21nfcb_se.h"
+#include "st21nfcb_hci_core.h"
+
+struct st21nfcb_pipe_info {
+	u8 pipe_state;
+	u8 src_host_id;
+	u8 src_gate_id;
+	u8 dst_host_id;
+	u8 dst_gate_id;
+} __packed;
+
+/* Connectivity pipe only */
+#define ST21NFCB_SE_COUNT_PIPE_UICC             0x01
+/* Connectivity + APDU Reader pipe */
+#define ST21NFCB_SE_COUNT_PIPE_EMBEDDED         0x02
+
+#define ST21NFCB_SE_TO_HOT_PLUG			1000 /* msecs */
+#define ST21NFCB_SE_TO_PIPES			2000
+
+#define ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(x)   (x->data[0] & 0x80)
+
+#define ST21NFCB_HCI_APDU_PARAM_ATR                     0x01
+#define ST21NFCB_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
+#define ST21NFCB_HCI_ADMIN_PARAM_WHITELIST              0x03
+#define ST21NFCB_HCI_ADMIN_PARAM_HOST_LIST              0x04
+
+#define ST21NFCB_EVT_SE_HARD_RESET		0x20
+#define ST21NFCB_EVT_TRANSMIT_DATA		0x10
+#define ST21NFCB_EVT_WTX_REQUEST		0x11
+#define ST21NFCB_EVT_SE_SOFT_RESET		0x11
+#define ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER	0x21
+#define ST21NFCB_EVT_HOT_PLUG			0x03
+
+#define ST21NFCB_SE_MODE_OFF                    0x00
+#define ST21NFCB_SE_MODE_ON                     0x01
+
+#define ST21NFCB_EVT_CONNECTIVITY       0x10
+#define ST21NFCB_EVT_TRANSACTION        0x12
+
+#define ST21NFCB_DM_GETINFO             0x13
+#define ST21NFCB_DM_GETINFO_PIPE_LIST   0x02
+#define ST21NFCB_DM_GETINFO_PIPE_INFO   0x01
+#define ST21NFCB_DM_PIPE_CREATED        0x02
+#define ST21NFCB_DM_PIPE_OPEN           0x04
+#define ST21NFCB_DM_RF_ACTIVE           0x80
+#define ST21NFCB_DM_DISCONNECT          0x30
+
+#define ST21NFCB_DM_IS_PIPE_OPEN(p) \
+	((p & 0x0f) == (ST21NFCB_DM_PIPE_CREATED | ST21NFCB_DM_PIPE_OPEN))
+
+#define ST21NFCB_ATR_DEFAULT_BWI        0x04
+
+/*
+ * WT = 2^BWI/10[s], convert into msecs and add a secure
+ * room by increasing by 2 this timeout
+ */
+#define ST21NFCB_BWI_TO_TIMEOUT(x)      ((1 << x) * 200)
+#define ST21NFCB_ATR_GET_Y_FROM_TD(x)   (x >> 4)
+
+/* If TA is present bit 0 is set */
+#define ST21NFCB_ATR_TA_PRESENT(x) (x & 0x01)
+/* If TB is present bit 1 is set */
+#define ST21NFCB_ATR_TB_PRESENT(x) (x & 0x02)
+
+/* Here are the mandatory pipe for st21nfcb */
+static struct st21nfcb_hci_gate st21nfcb_gates[] = {
+	{ST21NFCB_HCI_ADMIN_GATE, ST21NFCB_HCI_ADMIN_PIPE},
+	{ST21NFCB_HCI_LINK_MGMT_GATE, ST21NFCB_HCI_LINK_MGMT_PIPE},
+	{ST21NFCB_DEVICE_MGNT_GATE, ST21NFCB_DEVICE_MGNT_PIPE},
+
+	/* Secure element pipes are created by secure element host */
+	{ST21NFCB_CONNECTIVITY_GATE, ST21NFCB_HCI_DO_NOT_OPEN_PIPE},
+	{ST21NFCB_APDU_READER_GATE, ST21NFCB_HCI_DO_NOT_OPEN_PIPE},
+};
+
+static u8 st21nfcb_se_get_bwi(struct nci_dev *ndev)
+{
+	int i;
+	u8 td;
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	/* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
+	for (i = 1; i < ST21NFCB_ESE_MAX_LENGTH; i++) {
+		td = ST21NFCB_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
+		if (ST21NFCB_ATR_TA_PRESENT(td))
+			i++;
+		if (ST21NFCB_ATR_TB_PRESENT(td)) {
+			i++;
+			return info->se_info.atr[i] >> 4;
+		}
+	}
+	return ST21NFCB_ATR_DEFAULT_BWI;
+}
+
+static void st21nfcb_se_get_atr(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+	int r;
+	struct sk_buff *skb;
+
+	r = st21nfcb_hci_get_param(hdev, ST21NFCB_APDU_READER_GATE,
+				ST21NFCB_HCI_APDU_PARAM_ATR, &skb);
+	if (r < 0)
+		return;
+
+	if (skb->len <= ST21NFCB_ESE_MAX_LENGTH) {
+		memcpy(info->se_info.atr, skb->data, skb->len);
+
+		info->se_info.wt_timeout =
+			ST21NFCB_BWI_TO_TIMEOUT(st21nfcb_se_get_bwi(ndev));
+	}
+	kfree_skb(skb);
+}
+
+static int st21nfcb_hci_load_session(struct st21nfcb_hci_dev *hdev)
+{
+	int i, j, r;
+	struct sk_buff *skb_pipe_list, *skb_pipe_info;
+	struct st21nfcb_pipe_info *dm_pipe_info;
+	u8 pipe_list[] = { ST21NFCB_DM_GETINFO_PIPE_LIST,
+			ST21NFCB_TERMINAL_HOST_ID};
+	u8 pipe_info[] = { ST21NFCB_DM_GETINFO_PIPE_INFO,
+			ST21NFCB_TERMINAL_HOST_ID, 0};
+
+	/* On ST21NFCB device pipes number are dynamics
+	 * If pipes are already created, hci_dev_up will fail.
+	 * Doing a clear all pipe is a bad idea because:
+	 * - It does useless EEPROM cycling
+	 * - It might cause issue for secure elements support
+	 * (such as removing connectivity or APDU reader pipe)
+	 * A better approach on ST21NFCB is to:
+	 * - get a pipe list for each host.
+	 * (eg: ST21NFCB_HOST_CONTROLLER_ID for now).
+	 * (TODO Later on UICC HOST and eSE HOST)
+	 * - get pipe information
+	 * - match retrieved pipe list in st21nfcb_gates
+	 * ST21NFCB_DEVICE_MGNT_GATE is a proprietary gate
+	 * with ST21NFCB_DEVICE_MGNT_PIPE.
+	 * Pipe can be closed and need to be open.
+	 */
+	r = st21nfcb_hci_connect_gate(hdev, ST21NFCB_HOST_CONTROLLER_ID,
+				ST21NFCB_DEVICE_MGNT_GATE,
+				ST21NFCB_DEVICE_MGNT_PIPE);
+	if (r < 0)
+		goto free_info;
+
+	/* Get pipe list */
+	r = st21nfcb_hci_send_cmd(hdev, ST21NFCB_DEVICE_MGNT_GATE,
+			ST21NFCB_DM_GETINFO, pipe_list, sizeof(pipe_list),
+			&skb_pipe_list);
+	if (r < 0)
+		goto free_info;
+
+	/* Complete the existing gate_pipe table */
+	for (i = 0; i < skb_pipe_list->len; i++) {
+		pipe_info[2] = skb_pipe_list->data[i];
+		r = st21nfcb_hci_send_cmd(hdev, ST21NFCB_DEVICE_MGNT_GATE,
+					ST21NFCB_DM_GETINFO, pipe_info,
+					sizeof(pipe_info), &skb_pipe_info);
+
+		if (r)
+			continue;
+
+		/*
+		 * Match pipe ID and gate ID
+		 * Output format from ST21NFC_DM_GETINFO is:
+		 * - pipe state (1byte)
+		 * - source hid (1byte)
+		 * - source gid (1byte)
+		 * - destination hid (1byte)
+		 * - destination gid (1byte)
+		 */
+		dm_pipe_info = (struct st21nfcb_pipe_info *)skb_pipe_info->data;
+		if (dm_pipe_info->dst_gate_id == ST21NFCB_APDU_READER_GATE &&
+		    dm_pipe_info->src_host_id != ST21NFCB_ESE_HOST_ID) {
+			pr_err("Unexpected apdu_reader pipe on host %x\n",
+			       dm_pipe_info->src_host_id);
+			continue;
+		}
+
+		for (j = 0; (j < ARRAY_SIZE(st21nfcb_gates)) &&
+		     (st21nfcb_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
+			;
+
+		if (j < ARRAY_SIZE(st21nfcb_gates) &&
+		    st21nfcb_gates[j].gate == dm_pipe_info->dst_gate_id &&
+		    ST21NFCB_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) {
+			st21nfcb_gates[j].pipe = pipe_info[2];
+
+			hdev->gate2pipe[st21nfcb_gates[j].gate] =
+						st21nfcb_gates[j].pipe;
+			hdev->pipes[st21nfcb_gates[j].pipe].gate =
+						st21nfcb_gates[j].gate;
+			hdev->pipes[st21nfcb_gates[j].pipe].host =
+						dm_pipe_info->src_host_id;
+		}
+	}
+
+	memcpy(hdev->init_data.gates, st21nfcb_gates, sizeof(st21nfcb_gates));
+
+free_info:
+	kfree_skb(skb_pipe_info);
+	kfree_skb(skb_pipe_list);
+	return r;
+}
+
+static void st21nfcb_hci_admin_event_received(struct st21nfcb_hci_dev *hdev,
+					      u8 event, struct sk_buff *skb)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(hdev->ndev);
+
+	switch (event) {
+	case ST21NFCB_EVT_HOT_PLUG:
+		if (info->se_info.se_active) {
+			if (!ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
+				del_timer_sync(&info->se_info.se_active_timer);
+				info->se_info.se_active = false;
+				complete(&info->se_info.req_completion);
+			} else {
+				mod_timer(&info->se_info.se_active_timer,
+				      jiffies +
+				      msecs_to_jiffies(ST21NFCB_SE_TO_PIPES));
+			}
+		}
+	break;
+	}
+}
+
+static int st21nfcb_hci_apdu_reader_event_received(struct st21nfcb_hci_dev *hdev,
+						   u8 event,
+						   struct sk_buff *skb)
+{
+	int r = 0;
+	struct st21nfcb_nci_info *info = nci_get_drvdata(hdev->ndev);
+
+	pr_debug("apdu reader gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCB_EVT_TRANSMIT_DATA:
+		del_timer_sync(&info->se_info.bwi_timer);
+		info->se_info.bwi_active = false;
+		info->se_info.cb(info->se_info.cb_context,
+				 skb->data, skb->len, 0);
+	break;
+	case ST21NFCB_EVT_WTX_REQUEST:
+		mod_timer(&info->se_info.bwi_timer, jiffies +
+			  msecs_to_jiffies(info->se_info.wt_timeout));
+	break;
+	}
+
+	kfree_skb(skb);
+	return r;
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+static int st21nfcb_hci_connectivity_event_received(struct st21nfcb_hci_dev *hdev,
+						    u8 host, u8 event,
+						    struct sk_buff *skb)
+{
+	int r = 0;
+
+	pr_debug("connectivity gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCB_EVT_CONNECTIVITY:
+	break;
+	case ST21NFCB_EVT_TRANSACTION:
+	break;
+	default:
+		return 1;
+	}
+	kfree_skb(skb);
+	return r;
+}
+
+static void st21nfcb_hci_event_received(struct st21nfcb_hci_dev *hdev, u8 pipe,
+					u8 event, struct sk_buff *skb)
+{
+	u8 gate = hdev->pipes[pipe].gate;
+	u8 host = hdev->pipes[pipe].host;
+
+	switch (gate) {
+	case ST21NFCB_HCI_ADMIN_GATE:
+		st21nfcb_hci_admin_event_received(hdev, event, skb);
+	break;
+	case ST21NFCB_APDU_READER_GATE:
+		st21nfcb_hci_apdu_reader_event_received(hdev, event, skb);
+	break;
+	case ST21NFCB_CONNECTIVITY_GATE:
+		st21nfcb_hci_connectivity_event_received(hdev, host, event,
+							 skb);
+	break;
+	}
+}
+
+static void st21nfcb_hci_cmd_received(struct st21nfcb_hci_dev *hdev, u8 pipe, u8 cmd,
+				      struct sk_buff *skb)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(hdev->ndev);
+	u8 gate = hdev->pipes[pipe].gate;
+
+	pr_debug("cmd: %x\n", cmd);
+
+	switch (cmd) {
+	case ST21NFCB_HCI_ANY_OPEN_PIPE:
+		if (gate != ST21NFCB_APDU_READER_GATE &&
+		    hdev->pipes[pipe].host != ST21NFCB_UICC_HOST_ID)
+			hdev->count_pipes++;
+
+		if (hdev->count_pipes == hdev->expected_pipes) {
+			del_timer_sync(&info->se_info.se_active_timer);
+			info->se_info.se_active = false;
+			hdev->count_pipes = 0;
+			complete(&info->se_info.req_completion);
+		}
+	break;
+	}
+}
+
+/*
+ * Remarks: On some early st21nfcb firmware, nci_nfcee_mode_set(0)
+ * is rejected
+ */
+static int st21nfcb_nci_control_se(struct nci_dev *ndev, u8 se_idx,
+				   u8 state)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+	int r;
+	struct sk_buff *sk_host_list;
+	u8 host_id;
+
+	switch (se_idx) {
+	case ST21NFCB_UICC_HOST_ID:
+		hdev->count_pipes = 0;
+		hdev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_UICC;
+		break;
+	case ST21NFCB_ESE_HOST_ID:
+		hdev->count_pipes = 0;
+		hdev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_EMBEDDED;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Wait for an EVT_HOT_PLUG in order to
+	 * retrieve a relevant host list.
+	 */
+	reinit_completion(&info->se_info.req_completion);
+	r = nci_nfcee_mode_set(ndev, se_idx, NCI_NFCEE_ENABLE);
+	if (r != NCI_STATUS_OK)
+		return r;
+
+	mod_timer(&info->se_info.se_active_timer, jiffies +
+		msecs_to_jiffies(ST21NFCB_SE_TO_HOT_PLUG));
+	info->se_info.se_active = true;
+
+	/* Ignore return value and check in any case the host_list */
+	wait_for_completion_interruptible(&info->se_info.req_completion);
+
+	r = st21nfcb_hci_get_param(hdev, ST21NFCB_HCI_ADMIN_GATE,
+			ST21NFCB_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
+	if (r != ST21NFCB_HCI_ANY_OK)
+		return r;
+
+	host_id = sk_host_list->data[sk_host_list->len - 1];
+	kfree_skb(sk_host_list);
+	if (state == ST21NFCB_SE_MODE_ON && host_id == se_idx)
+		return se_idx;
+	else if (state == ST21NFCB_SE_MODE_OFF && host_id != se_idx)
+		return se_idx;
+
+	return -1;
+}
+
+int st21nfcb_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+	int r;
+
+	pr_debug("st21nfcb_nci_disable_se\n");
+
+	if (se_idx == NFC_SE_EMBEDDED) {
+		r = st21nfcb_hci_send_event(hdev, ST21NFCB_APDU_READER_GATE,
+				ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
+		if (r < 0)
+			return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_disable_se);
+
+int st21nfcb_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+	int r;
+
+	pr_debug("st21nfcb_nci_enable_se\n");
+
+	if (se_idx == ST21NFCB_HCI_HOST_ID_ESE) {
+		r = st21nfcb_hci_send_event(hdev, ST21NFCB_APDU_READER_GATE,
+				ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0);
+		if (r < 0)
+			return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_enable_se);
+
+static struct st21nfcb_hci_ops hci_ops = {
+	.load_session = st21nfcb_hci_load_session,
+	.event_received = st21nfcb_hci_event_received,
+	.cmd_received = st21nfcb_hci_cmd_received,
+};
+
+int st21nfcb_nci_discover_se(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev;
+	u8 param[2];
+	int r;
+	int se_count = 0;
+
+	pr_debug("st21nfcb_nci_discover_se\n");
+
+	hdev = st21nfcb_hci_allocate(ndev, &hci_ops, "ST21BH",
+				     st21nfcb_gates, sizeof(st21nfcb_gates));
+	if (!hdev)
+		return -ENOMEM;
+
+	info->se_info.hci_dev = hdev;
+
+	r = st21nfcb_hci_open_pipe(hdev, ST21NFCB_HCI_ADMIN_PIPE);
+	if (r != ST21NFCB_HCI_ANY_OK)
+		return r;
+
+	param[0] = ST21NFCB_UICC_HOST_ID;
+	param[1] = ST21NFCB_HCI_HOST_ID_ESE;
+	r = st21nfcb_hci_set_param(hdev, ST21NFCB_HCI_ADMIN_GATE,
+				ST21NFCB_HCI_ADMIN_PARAM_WHITELIST,
+				param, sizeof(param));
+	if (r != ST21NFCB_HCI_ANY_OK)
+		return r;
+
+	r = st21nfcb_nci_control_se(ndev, ST21NFCB_UICC_HOST_ID,
+				ST21NFCB_SE_MODE_ON);
+	if (r == ST21NFCB_UICC_HOST_ID) {
+		nfc_add_se(ndev->nfc_dev, ST21NFCB_UICC_HOST_ID, NFC_SE_UICC);
+		se_count++;
+	}
+
+	/* Try to enable eSE in order to check availability */
+	r = st21nfcb_nci_control_se(ndev, ST21NFCB_HCI_HOST_ID_ESE,
+				ST21NFCB_SE_MODE_ON);
+	if (r == ST21NFCB_HCI_HOST_ID_ESE) {
+		nfc_add_se(ndev->nfc_dev, ST21NFCB_HCI_HOST_ID_ESE,
+			   NFC_SE_EMBEDDED);
+		se_count++;
+		st21nfcb_se_get_atr(ndev);
+	}
+
+	return !se_count;
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_discover_se);
+
+int st21nfcb_nci_se_io(struct nci_dev *ndev, u32 se_idx,
+		       u8 *apdu, size_t apdu_length,
+		       se_io_cb_t cb, void *cb_context)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+
+	pr_debug("\n");
+
+	switch (se_idx) {
+	case ST21NFCB_HCI_HOST_ID_ESE:
+		info->se_info.cb = cb;
+		info->se_info.cb_context = cb_context;
+		mod_timer(&info->se_info.bwi_timer, jiffies +
+			  msecs_to_jiffies(info->se_info.wt_timeout));
+		info->se_info.bwi_active = true;
+		return st21nfcb_hci_send_event(hdev, ST21NFCB_APDU_READER_GATE,
+					ST21NFCB_EVT_TRANSMIT_DATA, apdu,
+					apdu_length);
+	default:
+		return -ENODEV;
+	}
+}
+EXPORT_SYMBOL(st21nfcb_nci_se_io);
+
+static void st21nfcb_se_wt_timeout(unsigned long data)
+{
+	/*
+	 * No answer from the secure element
+	 * within the defined timeout.
+	 * Let's send a reset request as recovery procedure.
+	 * According to the situation, we first try to send a software reset
+	 * to the secure element. If the next command is still not
+	 * answering in time, we send to the CLF a secure element hardware
+	 * reset request.
+	 */
+	/* hardware reset managed through VCC_UICC_OUT power supply */
+	u8 param = 0x01;
+	struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data;
+	struct st21nfcb_hci_dev  *hdev = info->se_info.hci_dev;
+
+	pr_debug("\n");
+
+	info->se_info.bwi_active = false;
+
+	if (!info->se_info.xch_error) {
+		info->se_info.xch_error = true;
+		st21nfcb_hci_send_event(hdev, ST21NFCB_APDU_READER_GATE,
+				ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0);
+	} else {
+		info->se_info.xch_error = false;
+		st21nfcb_hci_send_event(hdev, ST21NFCB_DEVICE_MGNT_GATE,
+				ST21NFCB_EVT_SE_HARD_RESET, &param, 1);
+	}
+	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
+}
+
+static void st21nfcb_se_activation_timeout(unsigned long data)
+{
+	struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data;
+
+	pr_debug("\n");
+
+	info->se_info.se_active = false;
+
+	complete(&info->se_info.req_completion);
+}
+
+int st21nfcb_se_init(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	init_completion(&info->se_info.req_completion);
+	/* initialize timers */
+	init_timer(&info->se_info.bwi_timer);
+	info->se_info.bwi_timer.data = (unsigned long)info;
+	info->se_info.bwi_timer.function = st21nfcb_se_wt_timeout;
+	info->se_info.bwi_active = false;
+
+	init_timer(&info->se_info.se_active_timer);
+	info->se_info.se_active_timer.data = (unsigned long)info;
+	info->se_info.se_active_timer.function =
+			st21nfcb_se_activation_timeout;
+	info->se_info.se_active = false;
+
+	info->se_info.xch_error = false;
+
+	info->se_info.wt_timeout =
+		ST21NFCB_BWI_TO_TIMEOUT(ST21NFCB_ATR_DEFAULT_BWI);
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfcb_se_init);
+
+void st21nfcb_se_deinit(struct nci_dev *ndev)
+{
+	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+	if (info->se_info.bwi_active)
+		del_timer_sync(&info->se_info.bwi_timer);
+	if (info->se_info.se_active)
+		del_timer_sync(&info->se_info.se_active_timer);
+
+	info->se_info.se_active = false;
+	info->se_info.bwi_active = false;
+	st21nfcb_hci_free(info->se_info.hci_dev);
+}
+EXPORT_SYMBOL(st21nfcb_se_deinit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.h b/drivers/nfc/st21nfcb/st21nfcb_se.h
new file mode 100644
index 0000000..979c7dd
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb_se.h
@@ -0,0 +1,59 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014  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_ST21NFCB_SE_H_
+#define __LOCAL_ST21NFCB_SE_H_
+
+#include "st21nfcb_hci_core.h"
+
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST21NFCB_ESE_MAX_LENGTH		33
+#define ST21NFCB_HCI_HOST_ID_ESE	0xc0
+
+struct st21nfcb_se_info {
+	u8 atr[ST21NFCB_ESE_MAX_LENGTH];
+	struct completion req_completion;
+
+	struct timer_list bwi_timer;
+	int wt_timeout; /* in msecs */
+	bool bwi_active;
+
+	struct timer_list se_active_timer;
+	bool se_active;
+
+	struct st21nfcb_hci_dev *hci_dev;
+
+	bool xch_error;
+
+	se_io_cb_t cb;
+	void *cb_context;
+};
+
+int st21nfcb_se_init(struct nci_dev *ndev);
+void st21nfcb_se_deinit(struct nci_dev *ndev);
+
+int st21nfcb_nci_discover_se(struct nci_dev *ndev);
+int st21nfcb_nci_enable_se(struct nci_dev *ndev, u32 se_idx);
+int st21nfcb_nci_disable_se(struct nci_dev *ndev, u32 se_idx);
+int st21nfcb_nci_se_io(struct nci_dev *ndev, u32 se_idx,
+					u8 *apdu, size_t apdu_length,
+					se_io_cb_t cb, void *cb_context);
+
+#endif /* __LOCAL_ST21NFCB_NCI_H_ */
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 29/34] NFC: Forward NFC_EVT_TRANSACTION up to user space
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (27 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 28/34] NFC: st21nfcb: Adding support for secure element Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 30/34] NFC: nci: Add support RF_NFCEE_ACTION_NTF Christophe Ricard
                     ` (4 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

NFC_EVT_TRANSACTION is not managed so far.

Forward event information up to user space in order to tell an application
that some user action(s) are needed.

Forwarded information are:
- SE host generating the event
- Application IDentifier doing the operation
- Applications parameters

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nfc.h    | 27 +++++++++++++++++++++++++++
 include/uapi/linux/nfc.h |  1 +
 net/nfc/core.c           | 21 +++++++++++++++++++++
 net/nfc/netlink.c        | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 net/nfc/nfc.h            |  2 ++
 5 files changed, 98 insertions(+)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 12adb81..73190e6 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -135,6 +135,31 @@ struct nfc_se {
 	u16 state;
 };
 
+/**
+ * nfc_evt_transaction - A struct for NFC secure element event transaction.
+ *
+ * @aid: The application identifier triggering the event
+ *
+ * @aid_len: The application identifier length [5:16]
+ *
+ * @params: The application parameters transmitted during the transaction
+ *
+ * @params_len: The applications parameters length [0:255]
+ *
+ */
+#define NFC_MIN_AID_LENGTH	5
+#define	NFC_MAX_AID_LENGTH	16
+#define NFC_MAX_PARAMS_LENGTH	255
+
+#define NFC_EVT_TRANSACTION_AID_TAG	0x81
+#define NFC_EVT_TRANSACTION_PARAMS_TAG	0x82
+struct nfc_evt_transaction {
+	u32 aid_len;
+	u8 aid[NFC_MAX_AID_LENGTH];
+	u8 params_len;
+	u8 params[NFC_MAX_PARAMS_LENGTH];
+} __packed;
+
 struct nfc_genl_data {
 	u32 poll_req_portid;
 	struct mutex genl_data_mutex;
@@ -262,6 +287,8 @@ int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb);
 
 void nfc_driver_failure(struct nfc_dev *dev, int err);
 
+int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
+		       struct nfc_evt_transaction *evt_transaction);
 int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type);
 int nfc_remove_se(struct nfc_dev *dev, u32 se_idx);
 struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx);
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 8119255..c1e2e63 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -183,6 +183,7 @@ enum nfc_attrs {
 	NFC_ATTR_SE_APDU,
 	NFC_ATTR_TARGET_ISO15693_DSFID,
 	NFC_ATTR_TARGET_ISO15693_UID,
+	NFC_ATTR_SE_PARAMS,
 /* private: internal use only */
 	__NFC_ATTR_AFTER_LAST
 };
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 7f1b635..cff3f16 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -932,6 +932,27 @@ int nfc_remove_se(struct nfc_dev *dev, u32 se_idx)
 }
 EXPORT_SYMBOL(nfc_remove_se);
 
+int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
+		       struct nfc_evt_transaction *evt_transaction)
+{
+	int rc;
+
+	pr_debug("transaction: %x\n", se_idx);
+
+	device_lock(&dev->dev);
+
+	if (!evt_transaction) {
+		rc = -EPROTO;
+		goto out;
+	}
+
+	rc = nfc_genl_se_transaction(dev, se_idx, evt_transaction);
+out:
+	device_unlock(&dev->dev);
+	return rc;
+}
+EXPORT_SYMBOL(nfc_se_transaction);
+
 static void nfc_release(struct device *d)
 {
 	struct nfc_dev *dev = to_nfc_dev(d);
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 44989fc..2fd6777 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -496,6 +496,53 @@ free_msg:
 	return -EMSGSIZE;
 }
 
+int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
+			    struct nfc_evt_transaction *evt_transaction)
+{
+	struct nfc_se *se;
+	struct sk_buff *msg;
+	void *hdr;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+			  NFC_EVENT_SE_TRANSACTION);
+	if (!hdr)
+		goto free_msg;
+
+	se = nfc_find_se(dev, se_idx);
+	if (!se)
+		goto free_msg;
+
+	if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
+	    nla_put_u32(msg, NFC_ATTR_SE_INDEX, se_idx) ||
+	    nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type) ||
+	    nla_put(msg, NFC_ATTR_SE_AID, evt_transaction->aid_len,
+		    evt_transaction->aid) ||
+	    nla_put(msg, NFC_ATTR_SE_PARAMS, evt_transaction->params_len,
+		    evt_transaction->params))
+		goto nla_put_failure;
+
+	/* evt_transaction is no more used */
+	devm_kfree(&dev->dev, evt_transaction);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	/* evt_transaction is no more used */
+	devm_kfree(&dev->dev, evt_transaction);
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
 static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
 				u32 portid, u32 seq,
 				struct netlink_callback *cb,
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 88d6006..a8ce80b 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -100,6 +100,8 @@ int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list);
 
 int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type);
 int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx);
+int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
+			    struct nfc_evt_transaction *evt_transaction);
 
 struct nfc_dev *nfc_get_device(unsigned int idx);
 
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 30/34] NFC: nci: Add support RF_NFCEE_ACTION_NTF
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (28 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 29/34] NFC: Forward NFC_EVT_TRANSACTION up to user space Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 31/34] NFC: nci: Change NCI state machine to LISTEN_ACTIVE and ignore parameters in rf_intf_activated_ntf Christophe Ricard
                     ` (3 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

RF NFCEE Action is the mechanism used to indicate that an action involving one of the NFCEEs
in the device has occurred that may be of interest to the DH.

This may happen for example when doing an RF Transaction with a payment reader.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci.h |  8 ++++++++
 net/nfc/nci/ntf.c     | 11 +++++++++++
 2 files changed, 19 insertions(+)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index deac78b..6c1beb2 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -499,6 +499,14 @@ struct nci_rf_deactivate_ntf {
 	__u8	reason;
 } __packed;
 
+#define NCI_OP_RF_NFCEE_ACTION_NTF	nci_opcode_pack(NCI_GID_RF_MGMT, 0x09)
+struct nci_rf_nfcee_action_ntf {
+	__u8 nfcee_id;
+	__u8 trigger;
+	__u8 supported_data_length;
+	__u8 supported_data[0];
+} __packed;
+
 #define NCI_OP_NFCEE_DISCOVER_NTF nci_opcode_pack(NCI_GID_NFCEE_MGMT, 0x00)
 struct nci_nfcee_supported_protocol {
 	__u8	num_protocol;
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 5af0564..83ba1f8 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -736,6 +736,12 @@ exit:
 	nci_req_complete(ndev, status);
 }
 
+static void nci_nfcee_action_ntf_packet(struct nci_dev *ndev,
+					struct sk_buff *skb)
+{
+	pr_debug("\n");
+}
+
 void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u16 ntf_opcode = nci_opcode(skb->data);
@@ -777,6 +783,11 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	case NCI_OP_NFCEE_DISCOVER_NTF:
 		nci_nfcee_discover_ntf_packet(ndev, skb);
 		break;
+
+	case NCI_OP_RF_NFCEE_ACTION_NTF:
+		nci_nfcee_action_ntf_packet(ndev, skb);
+		break;
+
 	default:
 		pr_err("unknown ntf opcode 0x%x\n", ntf_opcode);
 		break;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 31/34] NFC: nci: Change NCI state machine to LISTEN_ACTIVE and ignore parameters in rf_intf_activated_ntf
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (29 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 30/34] NFC: nci: Add support RF_NFCEE_ACTION_NTF Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 32/34] NFC: st21nfcb: Add support for HCI event transaction Christophe Ricard
                     ` (2 subsequent siblings)
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

When receiving a intf_activated notification, if the rf interface is
NCI_RF_INTERFACE_NFCEE_DIRECT, we need to ignore the next parameters and
change the NCI state machine to NCI_LISTEN_ACTIVE.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/nci/ntf.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 83ba1f8..d2f8512 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -540,6 +540,13 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
 	pr_debug("rf_tech_specific_params_len %d\n",
 		 ntf.rf_tech_specific_params_len);
 
+	/* If this contains a value of 0x00 (NFCEE Direct RF
+	 * Interface) then all following parameters SHALL contain a
+	 * value of 0 and SHALL be ignored.
+	 */
+	if (ntf.rf_interface == NCI_RF_INTERFACE_NFCEE_DIRECT)
+		goto listen;
+
 	if (ntf.rf_tech_specific_params_len > 0) {
 		switch (ntf.activation_rf_tech_and_mode) {
 		case NCI_NFC_A_PASSIVE_POLL_MODE:
@@ -651,6 +658,7 @@ exit:
 			nci_req_complete(ndev, err);
 		}
 	} else {
+listen:
 		/* Listen mode */
 		atomic_set(&ndev->state, NCI_LISTEN_ACTIVE);
 		if (err == NCI_STATUS_OK &&
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 32/34] NFC: st21nfcb: Add support for HCI event transaction
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (30 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 31/34] NFC: nci: Change NCI state machine to LISTEN_ACTIVE and ignore parameters in rf_intf_activated_ntf Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 33/34] NFC: st21nfca: " Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 34/34] NFC: st21nfca: Fix some skb memory leaks Christophe Ricard
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The event transaction notifies the Device Host that an action is required
to manage a specific Secure Element application.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfcb/st21nfcb_se.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.c b/drivers/nfc/st21nfcb/st21nfcb_se.c
index cf65368..6868043 100644
--- a/drivers/nfc/st21nfcb/st21nfcb_se.c
+++ b/drivers/nfc/st21nfcb/st21nfcb_se.c
@@ -287,14 +287,35 @@ static int st21nfcb_hci_connectivity_event_received(struct st21nfcb_hci_dev *hde
 						    struct sk_buff *skb)
 {
 	int r = 0;
+	struct device *dev = &hdev->ndev->nfc_dev->dev;
+	struct nfc_evt_transaction *transaction;
 
 	pr_debug("connectivity gate event: %x\n", event);
 
 	switch (event) {
 	case ST21NFCB_EVT_CONNECTIVITY:
+
 	break;
 	case ST21NFCB_EVT_TRANSACTION:
-	break;
+		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
+		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
+			return -EPROTO;
+
+		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
+					    skb->len - 2, GFP_KERNEL);
+
+		transaction->aid_len = skb->data[1];
+		memcpy(transaction->aid, &skb->data[2], skb->data[1]);
+
+		if (skb->data[transaction->aid_len + 2] !=
+		    NFC_EVT_TRANSACTION_PARAMS_TAG)
+			return -EPROTO;
+
+		transaction->params_len = skb->data[transaction->aid_len + 3];
+		memcpy(transaction->params, skb->data +
+		       transaction->aid_len + 4, transaction->params_len);
+
+		r = nfc_se_transaction(hdev->ndev->nfc_dev, host, transaction);
 	default:
 		return 1;
 	}
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 33/34] NFC: st21nfca: Add support for HCI event transaction
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (31 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 32/34] NFC: st21nfcb: Add support for HCI event transaction Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  2014-12-08 21:08   ` [PATCH v1 34/34] NFC: st21nfca: Fix some skb memory leaks Christophe Ricard
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The event transaction notifies the Device Host that an action is required
to manage a specific Secure Element application.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/st21nfca_se.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/st21nfca_se.c
index 9b93d39..bd13cac 100644
--- a/drivers/nfc/st21nfca/st21nfca_se.c
+++ b/drivers/nfc/st21nfca/st21nfca_se.c
@@ -301,6 +301,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 				u8 event, struct sk_buff *skb)
 {
 	int r = 0;
+	struct device *dev = &hdev->ndev->dev;
+	struct nfc_evt_transaction *transaction;
 
 	pr_debug("connectivity gate event: %x\n", event);
 
@@ -308,6 +310,25 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 	case ST21NFCA_EVT_CONNECTIVITY:
 		break;
 	case ST21NFCA_EVT_TRANSACTION:
+		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
+		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
+			return -EPROTO;
+
+		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
+						   skb->len - 2, GFP_KERNEL);
+
+		transaction->aid_len = skb->data[1];
+		memcpy(transaction->aid, &skb->data[2], skb->data[1]);
+
+		if (skb->data[transaction->aid_len + 2] !=
+		    NFC_EVT_TRANSACTION_PARAMS_TAG)
+			return -EPROTO;
+
+		transaction->params_len = skb->data[transaction->aid_len + 3];
+		memcpy(transaction->params, skb->data +
+		       transaction->aid_len + 4, transaction->params_len);
+
+		r = nfc_se_transaction(hdev->ndev, host, transaction);
 		break;
 	default:
 		return 1;
-- 
2.1.0

--
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] 45+ messages in thread

* [PATCH v1 34/34] NFC: st21nfca: Fix some skb memory leaks
       [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (32 preceding siblings ...)
  2014-12-08 21:08   ` [PATCH v1 33/34] NFC: st21nfca: " Christophe Ricard
@ 2014-12-08 21:08   ` Christophe Ricard
  33 siblings, 0 replies; 45+ messages in thread
From: Christophe Ricard @ 2014-12-08 21:08 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Fix some memory leaks after some nfc_hci_get_param calls.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/st21nfca.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index f1aced5..f6bb9ba 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -299,8 +299,9 @@ static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)
 	if (r < 0)
 		return r;
 
-	if (skb->data[0] == 0) {
-		kfree_skb(skb);
+	param = skb->data[0];
+	kfree_skb(skb);
+	if (param == 0) {
 		param = 1;
 
 		r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
@@ -442,9 +443,12 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
 			r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
 					      ST21NFCA_RF_CARD_F_DATARATE,
 					      param, 1);
-			if (r < 0)
+			if (r < 0) {
+				kfree_skb(datarate_skb);
 				return r;
+			}
 		}
+		kfree_skb(datarate_skb);
 
 		/*
 		 * Configure sens_res
@@ -698,15 +702,15 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
 						struct nfc_target *target)
 {
 	int r;
-	struct sk_buff *nfcid2_skb = NULL, *nfcid1_skb;
+	struct sk_buff *nfcid_skb;
 
 	if (gate == ST21NFCA_RF_READER_F_GATE) {
 		r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
-				ST21NFCA_RF_READER_F_NFCID2, &nfcid2_skb);
+				ST21NFCA_RF_READER_F_NFCID2, &nfcid_skb);
 		if (r < 0)
 			goto exit;
 
-		if (nfcid2_skb->len > NFC_SENSF_RES_MAXSIZE) {
+		if (nfcid_skb->len > NFC_SENSF_RES_MAXSIZE) {
 			r = -EPROTO;
 			goto exit;
 		}
@@ -718,11 +722,11 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
 		 * - After the reception of SEL_RES with NFCIP-1 compliant bit
 		 * set for type A frame NFCID1 will be updated
 		 */
-		if (nfcid2_skb->len > 0) {
+		if (nfcid_skb->len > 0) {
 			/* P2P in type F */
-			memcpy(target->sensf_res, nfcid2_skb->data,
-				nfcid2_skb->len);
-			target->sensf_res_len = nfcid2_skb->len;
+			memcpy(target->sensf_res, nfcid_skb->data,
+				nfcid_skb->len);
+			target->sensf_res_len = nfcid_skb->len;
 			/* NFC Forum Digital Protocol Table 44 */
 			if (target->sensf_res[0] == 0x01 &&
 			    target->sensf_res[1] == 0xfe)
@@ -732,27 +736,28 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
 				target->supported_protocols =
 							NFC_PROTO_FELICA_MASK;
 		} else {
+			kfree_skb(nfcid_skb);
 			/* P2P in type A */
 			r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
 					ST21NFCA_RF_READER_F_NFCID1,
-					&nfcid1_skb);
+					&nfcid_skb);
 			if (r < 0)
 				goto exit;
 
-			if (nfcid1_skb->len > NFC_NFCID1_MAXSIZE) {
+			if (nfcid_skb->len > NFC_NFCID1_MAXSIZE) {
 				r = -EPROTO;
 				goto exit;
 			}
-			memcpy(target->sensf_res, nfcid1_skb->data,
-				nfcid1_skb->len);
-			target->sensf_res_len = nfcid1_skb->len;
+			memcpy(target->sensf_res, nfcid_skb->data,
+				nfcid_skb->len);
+			target->sensf_res_len = nfcid_skb->len;
 			target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
 		}
 		target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE;
 	}
 	r = 1;
 exit:
-	kfree_skb(nfcid2_skb);
+	kfree_skb(nfcid_skb);
 	return r;
 }
 
-- 
2.1.0

--
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] 45+ messages in thread

* Re: [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code
       [not found]     ` <1418072919-10535-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-26  1:10       ` Samuel Ortiz
       [not found]         ` <20150126011001.GB28592-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
  0 siblings, 1 reply; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-26  1:10 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:09PM +0100, Christophe Ricard wrote:
> kfree_skb(skb) in st21nfca_hci_event_received is never reach.
> 
> Reported-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  drivers/nfc/st21nfca/st21nfca.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
> index f2596c8..880193b 100644
> --- a/drivers/nfc/st21nfca/st21nfca.c
> +++ b/drivers/nfc/st21nfca/st21nfca.c
> @@ -845,8 +845,6 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
>  	default:
>  		return 1;
>  	}
> -	kfree_skb(skb);
> -	return 0;
That make sense to me, but while looking at this function, I think your
skb free in st21nfca_dep_event_received() is incorrect.
The HCI core manages the SKBs it sends and frees this skb.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 05/34] NFC: hci: Change event_received handler gate parameter to pipe
       [not found]     ` <1418072919-10535-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-26  1:10       ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-26  1:10 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:10PM +0100, Christophe Ricard wrote:
> We are usually receiving an event from a known pipe.
Please provide a lengthier explanation as to why we are changing this
internal API.
As far as I understand, the main reason here is the fact that we can
have several pipes pointing to the same gate id (from different hosts).
That's something that should be explained in that commit message.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 06/34] NFC: hci: Add pipes table to reference them with a tuple {gate, host}
       [not found]     ` <1418072919-10535-7-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-26  1:11       ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-26  1:11 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:11PM +0100, Christophe Ricard wrote:
>  struct nfc_hci_gate {
>  	u8 gate;
>  	u8 pipe;
> -};
> +} __packed;
Why does this one need to be packed ?


> +struct nfc_hci_pipe {
> +	u8 gate;
> +	u8 dest_host;
> +} __packed;
Ditto.

> +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) {
> +			hdev->pipes[i].gate = NFC_HCI_INVALID_GATE;
> +			hdev->pipes[i].dest_host = NFC_HCI_INVALID_HOST;
> +		}
Nitpick:

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;

is usually preferred.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 07/34] NFC: hci: Change nfc_hci_send_response gate parameter to pipe
       [not found]     ` <1418072919-10535-8-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-26  1:11       ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-26  1:11 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:12PM +0100, Christophe Ricard wrote:
> We are usually sending a response to a command received from a known pipe.
> Keep this information as is.
> 
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  include/net/nfc/hci.h | 2 +-
>  net/nfc/hci/command.c | 7 +------
>  2 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
> index c1c644b..6f11ca2 100644
> --- a/include/net/nfc/hci.h
> +++ b/include/net/nfc/hci.h
> @@ -260,7 +260,7 @@ int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
>  int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
>  			   const u8 *param, size_t param_len,
>  			   data_exchange_cb_t cb, void *cb_context);
> -int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
> +int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 pipe, u8 response,
>  			  const u8 *param, size_t param_len);
This makes this API a bit odd, as all other routines there take a gate
as an input.
Instead of changing the prototype, could you please remove that routine
and have the callers (which is nfc_hci_cmd_received only) call
nfc_hci_hcp_message_tx directly ?

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 08/34] NFC: hci: Reference every pipe information according to notification
       [not found]     ` <1418072919-10535-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-26  1:11       ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-26  1:11 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:13PM +0100, Christophe Ricard wrote:
> Save a relevant pipe status according to received command in pipes table
> with tuple {gate, host}.
>
> Also:
> - If an error is detected it was so far not reported to the CLF.
> - Any HCI command can be received, we need to respond something back to the
> CLF.
I would rephrase this a little bit to explain what you fixed and how you
fixed it. I also usually prefer to have atomic changes (one per fix),
but since this is only impacting one routine, that's ok.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code
       [not found]         ` <20150126011001.GB28592-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
@ 2015-01-26 23:07           ` christophe.ricard
  0 siblings, 0 replies; 45+ messages in thread
From: christophe.ricard @ 2015-01-26 23:07 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Samuel,

Unless i misunderstood the code i thought that skb is freed once used by 
an event_received hook.

For example if skb is relevant for st21nfca event_received hook, it will 
return 0. We then jump to exit_noskb in nfc_hci_event_received.
In st21nfca_dep_event_received, r = 0 is never changed or only for case 
ST21NFCA_EVT_SEND_DATA.

In case skb is not relevant for st21nfca event_received hook, it will 
return a value > 0. I have choosen 1. This way, nfc_hci_event_received
will continue to check for relevant event (aka: 
NFC_HCI_EVT_TARGET_DISCOVERED) and will then free the current skb.

So i am don't think  my there is an error in st21nfca_dep_event_received 
or there is one in nfc_hci_event_received as well ?

What do you think ?

Best Regards
Christophe

On 26/01/2015 02:10, Samuel Ortiz wrote:
> Hi Christophe,
>
> On Mon, Dec 08, 2014 at 10:08:09PM +0100, Christophe Ricard wrote:
>> kfree_skb(skb) in st21nfca_hci_event_received is never reach.
>>
>> Reported-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
>> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
>> ---
>>   drivers/nfc/st21nfca/st21nfca.c | 2 --
>>   1 file changed, 2 deletions(-)
>>
>> diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
>> index f2596c8..880193b 100644
>> --- a/drivers/nfc/st21nfca/st21nfca.c
>> +++ b/drivers/nfc/st21nfca/st21nfca.c
>> @@ -845,8 +845,6 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
>>   	default:
>>   		return 1;
>>   	}
>> -	kfree_skb(skb);
>> -	return 0;
> That make sense to me, but while looking at this function, I think your
> skb free in st21nfca_dep_event_received() is incorrect.
> The HCI core manages the SKBs it sends and frees this skb.
>
> Cheers,
> Samuel.

--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 20/34] NFC: nci: Add dynamic conn_id NCI concept.
       [not found]     ` <1418072919-10535-21-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-27  0:44       ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-27  0:44 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Mon, Dec 08, 2014 at 10:08:25PM +0100, Christophe Ricard wrote:
>  struct nci_dev {
> @@ -95,7 +111,8 @@ struct nci_dev {
>  	unsigned long		flags;
>  
>  	atomic_t		cmd_cnt;
> -	atomic_t		credits_cnt;
> +	__u8			cur_conn_id;
> +	struct nci_conn_info	*conn_info_by_conn_id[NCI_MAX_CONN_ID];
>  
>  	struct timer_list	cmd_timer;
>  	struct timer_list	data_timer;
> @@ -141,13 +158,11 @@ struct nci_dev {
>  	__u8			manufact_id;
>  	__u32			manufact_specific_info;
>  
> -	/* received during NCI_OP_RF_INTF_ACTIVATED_NTF */
> -	__u8			max_data_pkt_payload_size;
> -	__u8			initial_num_credits;
> +	/* Save RF Discovery ID or NFCEE ID under conn_create */
> +	__u8			cur_id;
> +	struct nci_conn_info	*conn_info_by_id[NCI_MAX_NUM_NFCEE];
So we're going to carry 1-2KB of data with each nci_dev for at most 2
NFC EEs (typically, at least). I'd prefer to use a linked list (Or an
hash table, but that'd be overkill as well) for that purpose.
I think it would even make sense to have only one single, ordered linked
list replacing conn_info_by_id and conn_info_by_conn_id. Access time
will be longer, obviously, but we're talking about small lists and the
impact should be minimal.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support
       [not found]     ` <1418072919-10535-28-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-01-27  0:49       ` Samuel Ortiz
       [not found]         ` <20150127004958.GB31396-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
  0 siblings, 1 reply; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-27  0:49 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Christophe,

On Mon, Dec 08, 2014 at 10:08:32PM +0100, Christophe Ricard wrote:
> Some st21nfcb features are only available through HCI commands. Those
> HCI commands can be address over NCI by sending data using a dynamic
> conn_id. This is useful for example for Secure Element communication.
> 
> The HCI core brings the minimal HCI functions required to communicate with
> a secure element.
> 
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  drivers/nfc/st21nfcb/Makefile            |   2 +-
>  drivers/nfc/st21nfcb/st21nfcb_hci_core.c | 783 +++++++++++++++++++++++++++++++
>  drivers/nfc/st21nfcb/st21nfcb_hci_core.h | 134 ++++++
>  3 files changed, 918 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.c
>  create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.h
I may be missing some details, but I believe most of this code could be
made part of the core NCI implementation. I don't mind creating an
hci_dev from there and exporting the relevant API for drivers to send
HCI commands/events through their NCI connections.
You would not need to bring chunks of the HCI core into a driver, and
as a side effect, patch #21 would no longer be needed.

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support
       [not found]         ` <20150127004958.GB31396-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
@ 2015-01-27 22:16           ` christophe.ricard
       [not found]             ` <54C80E40.7020707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 45+ messages in thread
From: christophe.ricard @ 2015-01-27 22:16 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Samuel,

The main reason for making an st21nfcb_hci_core is because the hci 
network initialization procedure is proprietary.
It is almost using only NCI standard commands but some id's and commands 
could be proprietary.

I would ideally rely on the hci core framework but i run out of idea 
when trying this.
However i think "exporting the relevant API for drivers to send HCI 
commands/events through their NCI connections."
is a good idea i need to dig into. It will then needs to hci/nci hook 
for the proprietary stuff.

I have just one worry, when do you think those updates (patch 20 & 27) 
needs to be ready for your 3.20 pull request ?

Best Regards
Christophe
On 27/01/2015 01:49, Samuel Ortiz wrote:
> Christophe,
>
> On Mon, Dec 08, 2014 at 10:08:32PM +0100, Christophe Ricard wrote:
>> Some st21nfcb features are only available through HCI commands. Those
>> HCI commands can be address over NCI by sending data using a dynamic
>> conn_id. This is useful for example for Secure Element communication.
>>
>> The HCI core brings the minimal HCI functions required to communicate with
>> a secure element.
>>
>> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
>> ---
>>   drivers/nfc/st21nfcb/Makefile            |   2 +-
>>   drivers/nfc/st21nfcb/st21nfcb_hci_core.c | 783 +++++++++++++++++++++++++++++++
>>   drivers/nfc/st21nfcb/st21nfcb_hci_core.h | 134 ++++++
>>   3 files changed, 918 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.c
>>   create mode 100644 drivers/nfc/st21nfcb/st21nfcb_hci_core.h
> I may be missing some details, but I believe most of this code could be
> made part of the core NCI implementation. I don't mind creating an
> hci_dev from there and exporting the relevant API for drivers to send
> HCI commands/events through their NCI connections.
> You would not need to bring chunks of the HCI core into a driver, and
> as a side effect, patch #21 would no longer be needed.
>
> Cheers,
> Samuel.

--
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	[flat|nested] 45+ messages in thread

* Re: [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support
       [not found]             ` <54C80E40.7020707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2015-01-28  0:04               ` Samuel Ortiz
  0 siblings, 0 replies; 45+ messages in thread
From: Samuel Ortiz @ 2015-01-28  0:04 UTC (permalink / raw)
  To: christophe.ricard
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Christophe,

On Tue, Jan 27, 2015 at 11:16:32PM +0100, christophe.ricard wrote:
> The main reason for making an st21nfcb_hci_core is because the hci network
> initialization procedure is proprietary.
> It is almost using only NCI standard commands but some id's and commands
> could be proprietary.
That could most likely be fixed with an additional NCI hook.


> I would ideally rely on the hci core framework but i run out of idea when
> trying this.
> However i think "exporting the relevant API for drivers to send HCI
> commands/events through their NCI connections."
Yes, the idea would be for the NCI core to create an hci_dev and
associate it with the right nci_dev (probably when the driver requests
it). Then you should be able to call into the HCI core API, even if it
takes exporting some of it.

> is a good idea i need to dig into. It will then needs to hci/nci hook for
> the proprietary stuff.
> 
> I have just one worry, when do you think those updates (patch 20 & 27) needs
> to be ready for your 3.20 pull request ?
I'm going to send a first pull request tomorrow. And a second one
beginning of next week. I realize it leaves you with very little time,
but I feel patch #27 is quite a bit of potentially duplicated code.
What about you look at patch #20 first and I could then take all your
patchset except for patches #27 and #28 ?

Cheers,
Samuel.
--
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	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2015-01-28  0:04 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-08 21:08 [PATCH v1 00/34] Minor clean & Secure Element support for ST21NFCA/ST21NFCB Christophe Ricard
     [not found] ` <1418072919-10535-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2014-12-08 21:08   ` [PATCH v1 01/34] NFC: dts: st21nfca: Fix compatible string spelling to follow other drivers Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 02/34] NFC: dts: st21nfcb: " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 03/34] NFC: st21nfcb: Fix "WARNING: invalid free of devm_ allocated data" Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 04/34] NFC: st21nfca: Remove unreachable code Christophe Ricard
     [not found]     ` <1418072919-10535-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-26  1:10       ` Samuel Ortiz
     [not found]         ` <20150126011001.GB28592-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
2015-01-26 23:07           ` christophe.ricard
2014-12-08 21:08   ` [PATCH v1 05/34] NFC: hci: Change event_received handler gate parameter to pipe Christophe Ricard
     [not found]     ` <1418072919-10535-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-26  1:10       ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 06/34] NFC: hci: Add pipes table to reference them with a tuple {gate, host} Christophe Ricard
     [not found]     ` <1418072919-10535-7-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-26  1:11       ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 07/34] NFC: hci: Change nfc_hci_send_response gate parameter to pipe Christophe Ricard
     [not found]     ` <1418072919-10535-8-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-26  1:11       ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 08/34] NFC: hci: Reference every pipe information according to notification Christophe Ricard
     [not found]     ` <1418072919-10535-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-26  1:11       ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 09/34] NFC: hci: Add cmd_received handler Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 10/34] NFC: pn544: Change event_received gate parameter to pipe Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 11/34] NFC: microread: " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 12/34] NFC: hci: Remove nfc_hci_pipe2gate function Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 13/34] NFC: nfc_enable_se Remove useless blank line at beginning of function Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 14/34] NFC: nfc_disable_se " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 15/34] NFC: st21nfca: Adding support for secure element Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 16/34] NFC: st21nfca: Remove useless ST21NFCA_SE_HOST_EVT_HOT_PLUG macro Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 17/34] NFC: st21nfca: Remove skb_pipe_list and skb_pipe_info useless allocation Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 18/34] NFC: st21nfca: Remove checkpatch.pl warning Possible unnecessary 'out of memory' message Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 19/34] NFC: dts: st21nfca: Document ese-present & uicc-present DTS property Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 20/34] NFC: nci: Add dynamic conn_id NCI concept Christophe Ricard
     [not found]     ` <1418072919-10535-21-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-27  0:44       ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 21/34] NFC: nci: Make nci_request available for nfc driver Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 22/34] NFC: nci: Add NCI NFCEE constant Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 23/34] NFC: nci: Add nci_nfcee_discover handler command/response/notification Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 24/34] NFC: nci: Add nci_nfcee_mode_set handler command/response Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 25/34] NFC: nci: Add nci_core_conn_create " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 26/34] NFC: nci: Add nci_core_conn_close " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 27/34] NFC: st21nfcb: Add HCI protocol over NCI protocol support Christophe Ricard
     [not found]     ` <1418072919-10535-28-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-01-27  0:49       ` Samuel Ortiz
     [not found]         ` <20150127004958.GB31396-41CF7WKNp/FoDWY/xQGDymt3HXsI98Cx0E9HWUfgJXw@public.gmane.org>
2015-01-27 22:16           ` christophe.ricard
     [not found]             ` <54C80E40.7020707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-01-28  0:04               ` Samuel Ortiz
2014-12-08 21:08   ` [PATCH v1 28/34] NFC: st21nfcb: Adding support for secure element Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 29/34] NFC: Forward NFC_EVT_TRANSACTION up to user space Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 30/34] NFC: nci: Add support RF_NFCEE_ACTION_NTF Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 31/34] NFC: nci: Change NCI state machine to LISTEN_ACTIVE and ignore parameters in rf_intf_activated_ntf Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 32/34] NFC: st21nfcb: Add support for HCI event transaction Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 33/34] NFC: st21nfca: " Christophe Ricard
2014-12-08 21:08   ` [PATCH v1 34/34] NFC: st21nfca: Fix some skb memory leaks Christophe Ricard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.