aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2015-01-26 19:18:19 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2015-01-27 18:03:36 -0500
commit2130fb97fecf9a51bb4a21da220cff3f72496a94 (patch)
tree5aca9f7968ac4296321cfb1e1dcb8038fcfe7667
parentec14b6c93c2f804f302b8ea1736539d39b9c544b (diff)
NFC: st21nfca: Adding support for secure element
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@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/st21nfca/Makefile2
-rw-r--r--drivers/nfc/st21nfca/i2c.c17
-rw-r--r--drivers/nfc/st21nfca/st21nfca.c134
-rw-r--r--drivers/nfc/st21nfca/st21nfca.h21
-rw-r--r--drivers/nfc/st21nfca/st21nfca_se.c390
-rw-r--r--drivers/nfc/st21nfca/st21nfca_se.h63
-rw-r--r--include/linux/platform_data/st21nfca.h2
7 files changed, 608 insertions, 21 deletions
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 7d688f97aa27..97edab4bbdf8 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -2,7 +2,7 @@
2# Makefile for ST21NFCA HCI based NFC driver 2# Makefile for ST21NFCA HCI based NFC driver
3# 3#
4 4
5st21nfca_hci-objs = st21nfca.o st21nfca_dep.o 5st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o
6obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o 6obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o
7 7
8st21nfca_i2c-objs = i2c.o 8st21nfca_i2c-objs = i2c.o
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 82b82dbd2997..a32143951616 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -74,6 +74,8 @@ struct st21nfca_i2c_phy {
74 unsigned int gpio_ena; 74 unsigned int gpio_ena;
75 unsigned int irq_polarity; 75 unsigned int irq_polarity;
76 76
77 struct st21nfca_se_status se_status;
78
77 struct sk_buff *pending_skb; 79 struct sk_buff *pending_skb;
78 int current_read_len; 80 int current_read_len;
79 /* 81 /*
@@ -537,6 +539,11 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
537 539
538 phy->irq_polarity = irq_get_trigger_type(client->irq); 540 phy->irq_polarity = irq_get_trigger_type(client->irq);
539 541
542 phy->se_status.is_ese_present =
543 of_property_read_bool(pp, "ese-present");
544 phy->se_status.is_uicc_present =
545 of_property_read_bool(pp, "uicc-present");
546
540 return 0; 547 return 0;
541} 548}
542#else 549#else
@@ -571,6 +578,9 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
571 } 578 }
572 } 579 }
573 580
581 phy->se_status.is_ese_present = pdata->is_ese_present;
582 phy->se_status.is_uicc_present = pdata->is_uicc_present;
583
574 return 0; 584 return 0;
575} 585}
576 586
@@ -638,8 +648,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
638 } 648 }
639 649
640 return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, 650 return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
641 ST21NFCA_FRAME_HEADROOM, ST21NFCA_FRAME_TAILROOM, 651 ST21NFCA_FRAME_HEADROOM,
642 ST21NFCA_HCI_LLC_MAX_PAYLOAD, &phy->hdev); 652 ST21NFCA_FRAME_TAILROOM,
653 ST21NFCA_HCI_LLC_MAX_PAYLOAD,
654 &phy->hdev,
655 &phy->se_status);
643} 656}
644 657
645static int st21nfca_hci_i2c_remove(struct i2c_client *client) 658static int st21nfca_hci_i2c_remove(struct i2c_client *client)
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index 7cb7ce47d2af..24d3d240d5f4 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -23,6 +23,7 @@
23 23
24#include "st21nfca.h" 24#include "st21nfca.h"
25#include "st21nfca_dep.h" 25#include "st21nfca_dep.h"
26#include "st21nfca_se.h"
26 27
27#define DRIVER_DESC "HCI NFC driver for ST21NFCA" 28#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
28 29
@@ -62,7 +63,6 @@
62#define ST21NFCA_RF_CARD_F_DATARATE 0x08 63#define ST21NFCA_RF_CARD_F_DATARATE 0x08
63#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 64#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01
64 65
65#define ST21NFCA_DEVICE_MGNT_GATE 0x01
66#define ST21NFCA_DEVICE_MGNT_PIPE 0x02 66#define ST21NFCA_DEVICE_MGNT_PIPE 0x02
67 67
68#define ST21NFCA_DM_GETINFO 0x13 68#define ST21NFCA_DM_GETINFO 0x13
@@ -78,6 +78,11 @@
78 78
79#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ 79#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/
80 80
81#define ST21NFCA_EVT_HOT_PLUG 0x03
82#define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
83
84#define ST21NFCA_SE_TO_PIPES 2000
85
81static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); 86static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
82 87
83static struct nfc_hci_gate st21nfca_gates[] = { 88static struct nfc_hci_gate st21nfca_gates[] = {
@@ -92,6 +97,10 @@ static struct nfc_hci_gate st21nfca_gates[] = {
92 {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, 97 {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
93 {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, 98 {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
94 {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE}, 99 {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
100
101 /* Secure element pipes are created by secure element host */
102 {ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
103 {ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
95}; 104};
96 105
97struct st21nfca_pipe_info { 106struct st21nfca_pipe_info {
@@ -136,7 +145,8 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
136 * Pipe can be closed and need to be open. 145 * Pipe can be closed and need to be open.
137 */ 146 */
138 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, 147 r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
139 ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE); 148 ST21NFCA_DEVICE_MGNT_GATE,
149 ST21NFCA_DEVICE_MGNT_PIPE);
140 if (r < 0) 150 if (r < 0)
141 goto free_info; 151 goto free_info;
142 152
@@ -167,17 +177,28 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
167 * - destination gid (1byte) 177 * - destination gid (1byte)
168 */ 178 */
169 info = (struct st21nfca_pipe_info *) skb_pipe_info->data; 179 info = (struct st21nfca_pipe_info *) skb_pipe_info->data;
180 if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE &&
181 info->src_host_id != ST21NFCA_ESE_HOST_ID) {
182 pr_err("Unexpected apdu_reader pipe on host %x\n",
183 info->src_host_id);
184 continue;
185 }
186
170 for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) && 187 for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
171 (st21nfca_gates[j].gate != info->dst_gate_id); 188 (st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
172 j++)
173 ; 189 ;
174 190
175 if (j < ARRAY_SIZE(st21nfca_gates) && 191 if (j < ARRAY_SIZE(st21nfca_gates) &&
176 st21nfca_gates[j].gate == info->dst_gate_id && 192 st21nfca_gates[j].gate == info->dst_gate_id &&
177 ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) { 193 ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
178 st21nfca_gates[j].pipe = pipe_info[2]; 194 st21nfca_gates[j].pipe = pipe_info[2];
195
179 hdev->gate2pipe[st21nfca_gates[j].gate] = 196 hdev->gate2pipe[st21nfca_gates[j].gate] =
180 st21nfca_gates[j].pipe; 197 st21nfca_gates[j].pipe;
198 hdev->pipes[st21nfca_gates[j].pipe].gate =
199 st21nfca_gates[j].gate;
200 hdev->pipes[st21nfca_gates[j].pipe].dest_host =
201 info->src_host_id;
181 } 202 }
182 } 203 }
183 204
@@ -187,7 +208,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
187 */ 208 */
188 if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) { 209 if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
189 for (i = skb_pipe_list->len + 3; 210 for (i = skb_pipe_list->len + 3;
190 i < ARRAY_SIZE(st21nfca_gates); i++) { 211 i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
191 r = nfc_hci_connect_gate(hdev, 212 r = nfc_hci_connect_gate(hdev,
192 NFC_HCI_HOST_CONTROLLER_ID, 213 NFC_HCI_HOST_CONTROLLER_ID,
193 st21nfca_gates[i].gate, 214 st21nfca_gates[i].gate,
@@ -244,16 +265,33 @@ out:
244 265
245static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) 266static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)
246{ 267{
268 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
247 struct sk_buff *skb; 269 struct sk_buff *skb;
248 270
249 u8 param; 271 u8 param;
272 u8 white_list[2];
273 int wl_size = 0;
250 int r; 274 int r;
251 275
252 param = NFC_HCI_UICC_HOST_ID; 276 if (info->se_status->is_ese_present &&
253 r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, 277 info->se_status->is_uicc_present) {
254 NFC_HCI_ADMIN_WHITELIST, &param, 1); 278 white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
255 if (r < 0) 279 white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
256 return r; 280 } else if (!info->se_status->is_ese_present &&
281 info->se_status->is_uicc_present) {
282 white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
283 } else if (info->se_status->is_ese_present &&
284 !info->se_status->is_uicc_present) {
285 white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
286 }
287
288 if (wl_size) {
289 r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
290 NFC_HCI_ADMIN_WHITELIST,
291 (u8 *) &white_list, wl_size);
292 if (r < 0)
293 return r;
294 }
257 295
258 /* Set NFC_MODE in device management gate to enable */ 296 /* Set NFC_MODE in device management gate to enable */
259 r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, 297 r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
@@ -821,19 +859,79 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
821 } 859 }
822} 860}
823 861
862static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
863 struct sk_buff *skb)
864{
865 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
866 u8 gate = hdev->pipes[pipe].gate;
867
868 pr_debug("cmd: %x\n", cmd);
869
870 switch (cmd) {
871 case NFC_HCI_ANY_OPEN_PIPE:
872 if (gate != ST21NFCA_APDU_READER_GATE &&
873 hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID)
874 info->se_info.count_pipes++;
875
876 if (info->se_info.count_pipes == info->se_info.expected_pipes) {
877 del_timer_sync(&info->se_info.se_active_timer);
878 info->se_info.se_active = false;
879 info->se_info.count_pipes = 0;
880 complete(&info->se_info.req_completion);
881 }
882 break;
883 }
884}
885
886static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
887 struct sk_buff *skb)
888{
889 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
890
891 pr_debug("admin event: %x\n", event);
892
893 switch (event) {
894 case ST21NFCA_EVT_HOT_PLUG:
895 if (info->se_info.se_active) {
896 if (!ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
897 del_timer_sync(&info->se_info.se_active_timer);
898 info->se_info.se_active = false;
899 complete(&info->se_info.req_completion);
900 } else {
901 mod_timer(&info->se_info.se_active_timer,
902 jiffies +
903 msecs_to_jiffies(ST21NFCA_SE_TO_PIPES));
904 }
905 }
906 break;
907 }
908 kfree_skb(skb);
909 return 0;
910}
911
824/* 912/*
825 * Returns: 913 * Returns:
826 * <= 0: driver handled the event, skb consumed 914 * <= 0: driver handled the event, skb consumed
827 * 1: driver does not handle the event, please do standard processing 915 * 1: driver does not handle the event, please do standard processing
828 */ 916 */
829static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, 917static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
830 u8 event, struct sk_buff *skb) 918 u8 event, struct sk_buff *skb)
831{ 919{
920 u8 gate = hdev->pipes[pipe].gate;
921 u8 host = hdev->pipes[pipe].dest_host;
922
832 pr_debug("hci event: %d gate: %x\n", event, gate); 923 pr_debug("hci event: %d gate: %x\n", event, gate);
833 924
834 switch (gate) { 925 switch (gate) {
926 case NFC_HCI_ADMIN_GATE:
927 return st21nfca_admin_event_received(hdev, event, skb);
835 case ST21NFCA_RF_CARD_F_GATE: 928 case ST21NFCA_RF_CARD_F_GATE:
836 return st21nfca_dep_event_received(hdev, event, skb); 929 return st21nfca_dep_event_received(hdev, event, skb);
930 case ST21NFCA_CONNECTIVITY_GATE:
931 return st21nfca_connectivity_event_received(hdev, host,
932 event, skb);
933 case ST21NFCA_APDU_READER_GATE:
934 return st21nfca_apdu_reader_event_received(hdev, event, skb);
837 default: 935 default:
838 return 1; 936 return 1;
839 } 937 }
@@ -855,11 +953,17 @@ static struct nfc_hci_ops st21nfca_hci_ops = {
855 .tm_send = st21nfca_hci_tm_send, 953 .tm_send = st21nfca_hci_tm_send,
856 .check_presence = st21nfca_hci_check_presence, 954 .check_presence = st21nfca_hci_check_presence,
857 .event_received = st21nfca_hci_event_received, 955 .event_received = st21nfca_hci_event_received,
956 .cmd_received = st21nfca_hci_cmd_received,
957 .discover_se = st21nfca_hci_discover_se,
958 .enable_se = st21nfca_hci_enable_se,
959 .disable_se = st21nfca_hci_disable_se,
960 .se_io = st21nfca_hci_se_io,
858}; 961};
859 962
860int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, 963int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
861 char *llc_name, int phy_headroom, int phy_tailroom, 964 char *llc_name, int phy_headroom, int phy_tailroom,
862 int phy_payload, struct nfc_hci_dev **hdev) 965 int phy_payload, struct nfc_hci_dev **hdev,
966 struct st21nfca_se_status *se_status)
863{ 967{
864 struct st21nfca_hci_info *info; 968 struct st21nfca_hci_info *info;
865 int r = 0; 969 int r = 0;
@@ -919,6 +1023,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
919 goto err_alloc_hdev; 1023 goto err_alloc_hdev;
920 } 1024 }
921 1025
1026 info->se_status = se_status;
1027
922 nfc_hci_set_clientdata(info->hdev, info); 1028 nfc_hci_set_clientdata(info->hdev, info);
923 1029
924 r = nfc_hci_register_device(info->hdev); 1030 r = nfc_hci_register_device(info->hdev);
@@ -927,6 +1033,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
927 1033
928 *hdev = info->hdev; 1034 *hdev = info->hdev;
929 st21nfca_dep_init(info->hdev); 1035 st21nfca_dep_init(info->hdev);
1036 st21nfca_se_init(info->hdev);
930 1037
931 return 0; 1038 return 0;
932 1039
@@ -945,6 +1052,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev)
945 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 1052 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
946 1053
947 st21nfca_dep_deinit(hdev); 1054 st21nfca_dep_deinit(hdev);
1055 st21nfca_se_deinit(hdev);
948 nfc_hci_unregister_device(hdev); 1056 nfc_hci_unregister_device(hdev);
949 nfc_hci_free_device(hdev); 1057 nfc_hci_free_device(hdev);
950 kfree(info); 1058 kfree(info);
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 7c2a85292230..15a78d330a9f 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -20,6 +20,7 @@
20#include <net/nfc/hci.h> 20#include <net/nfc/hci.h>
21 21
22#include "st21nfca_dep.h" 22#include "st21nfca_dep.h"
23#include "st21nfca_se.h"
23 24
24#define HCI_MODE 0 25#define HCI_MODE 0
25 26
@@ -51,9 +52,15 @@
51 52
52#define ST21NFCA_NUM_DEVICES 256 53#define ST21NFCA_NUM_DEVICES 256
53 54
55struct st21nfca_se_status {
56 bool is_ese_present;
57 bool is_uicc_present;
58};
59
54int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, 60int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
55 char *llc_name, int phy_headroom, int phy_tailroom, 61 char *llc_name, int phy_headroom, int phy_tailroom,
56 int phy_payload, struct nfc_hci_dev **hdev); 62 int phy_payload, struct nfc_hci_dev **hdev,
63 struct st21nfca_se_status *se_status);
57void st21nfca_hci_remove(struct nfc_hci_dev *hdev); 64void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
58 65
59enum st21nfca_state { 66enum st21nfca_state {
@@ -66,6 +73,7 @@ struct st21nfca_hci_info {
66 void *phy_id; 73 void *phy_id;
67 74
68 struct nfc_hci_dev *hdev; 75 struct nfc_hci_dev *hdev;
76 struct st21nfca_se_status *se_status;
69 77
70 enum st21nfca_state state; 78 enum st21nfca_state state;
71 79
@@ -76,13 +84,16 @@ struct st21nfca_hci_info {
76 void *async_cb_context; 84 void *async_cb_context;
77 85
78 struct st21nfca_dep_info dep_info; 86 struct st21nfca_dep_info dep_info;
87 struct st21nfca_se_info se_info;
79}; 88};
80 89
81/* Reader RF commands */ 90/* Reader RF commands */
82#define ST21NFCA_WR_XCHG_DATA 0x10 91#define ST21NFCA_WR_XCHG_DATA 0x10
83
84#define ST21NFCA_RF_READER_F_GATE 0x14
85 92
86#define ST21NFCA_RF_CARD_F_GATE 0x24 93#define ST21NFCA_DEVICE_MGNT_GATE 0x01
94#define ST21NFCA_RF_READER_F_GATE 0x14
95#define ST21NFCA_RF_CARD_F_GATE 0x24
96#define ST21NFCA_APDU_READER_GATE 0xf0
97#define ST21NFCA_CONNECTIVITY_GATE 0x41
87 98
88#endif /* __LOCAL_ST21NFCA_H_ */ 99#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 000000000000..9b93d3904ab5
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_se.c
@@ -0,0 +1,390 @@
1/*
2 * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <net/nfc/hci.h>
18
19#include "st21nfca.h"
20#include "st21nfca_se.h"
21
22#define ST21NFCA_EVT_UICC_ACTIVATE 0x10
23#define ST21NFCA_EVT_UICC_DEACTIVATE 0x13
24#define ST21NFCA_EVT_SE_HARD_RESET 0x20
25#define ST21NFCA_EVT_SE_SOFT_RESET 0x11
26#define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER 0x21
27#define ST21NFCA_EVT_SE_ACTIVATE 0x22
28#define ST21NFCA_EVT_SE_DEACTIVATE 0x23
29
30#define ST21NFCA_EVT_TRANSMIT_DATA 0x10
31#define ST21NFCA_EVT_WTX_REQUEST 0x11
32
33#define ST21NFCA_EVT_CONNECTIVITY 0x10
34#define ST21NFCA_EVT_TRANSACTION 0x12
35
36#define ST21NFCA_ESE_HOST_ID 0xc0
37
38#define ST21NFCA_SE_TO_HOT_PLUG 1000
39/* Connectivity pipe only */
40#define ST21NFCA_SE_COUNT_PIPE_UICC 0x01
41/* Connectivity + APDU Reader pipe */
42#define ST21NFCA_SE_COUNT_PIPE_EMBEDDED 0x02
43
44#define ST21NFCA_SE_MODE_OFF 0x00
45#define ST21NFCA_SE_MODE_ON 0x01
46
47#define ST21NFCA_PARAM_ATR 0x01
48#define ST21NFCA_ATR_DEFAULT_BWI 0x04
49
50/*
51 * WT = 2^BWI/10[s], convert into msecs and add a secure
52 * room by increasing by 2 this timeout
53 */
54#define ST21NFCA_BWI_TO_TIMEOUT(x) ((1 << x) * 200)
55#define ST21NFCA_ATR_GET_Y_FROM_TD(x) (x >> 4)
56
57/* If TA is present bit 0 is set */
58#define ST21NFCA_ATR_TA_PRESENT(x) (x & 0x01)
59/* If TB is present bit 1 is set */
60#define ST21NFCA_ATR_TB_PRESENT(x) (x & 0x02)
61
62static u8 st21nfca_se_get_bwi(struct nfc_hci_dev *hdev)
63{
64 int i;
65 u8 td;
66 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
67
68 /* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
69 for (i = 1; i < ST21NFCA_ESE_MAX_LENGTH; i++) {
70 td = ST21NFCA_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
71 if (ST21NFCA_ATR_TA_PRESENT(td))
72 i++;
73 if (ST21NFCA_ATR_TB_PRESENT(td)) {
74 i++;
75 return info->se_info.atr[i] >> 4;
76 }
77 }
78 return ST21NFCA_ATR_DEFAULT_BWI;
79}
80
81static void st21nfca_se_get_atr(struct nfc_hci_dev *hdev)
82{
83 int r;
84 struct sk_buff *skb;
85 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
86
87 r = nfc_hci_get_param(hdev, ST21NFCA_APDU_READER_GATE,
88 ST21NFCA_PARAM_ATR, &skb);
89 if (r < 0)
90 return;
91
92 if (skb->len <= ST21NFCA_ESE_MAX_LENGTH) {
93 memcpy(info->se_info.atr, skb->data, skb->len);
94 info->se_info.wt_timeout =
95 ST21NFCA_BWI_TO_TIMEOUT(st21nfca_se_get_bwi(hdev));
96 }
97 kfree_skb(skb);
98}
99
100static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
101 u8 state)
102{
103 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
104 int r;
105 struct sk_buff *sk_host_list;
106 u8 se_event, host_id;
107
108 switch (se_idx) {
109 case NFC_HCI_UICC_HOST_ID:
110 se_event = (state == ST21NFCA_SE_MODE_ON ?
111 ST21NFCA_EVT_UICC_ACTIVATE :
112 ST21NFCA_EVT_UICC_DEACTIVATE);
113
114 info->se_info.count_pipes = 0;
115 info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_UICC;
116 break;
117 case ST21NFCA_ESE_HOST_ID:
118 se_event = (state == ST21NFCA_SE_MODE_ON ?
119 ST21NFCA_EVT_SE_ACTIVATE :
120 ST21NFCA_EVT_SE_DEACTIVATE);
121
122 info->se_info.count_pipes = 0;
123 info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_EMBEDDED;
124 break;
125 default:
126 return -EINVAL;
127 }
128
129 /*
130 * Wait for an EVT_HOT_PLUG in order to
131 * retrieve a relevant host list.
132 */
133 reinit_completion(&info->se_info.req_completion);
134 r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, se_event,
135 NULL, 0);
136 if (r < 0)
137 return r;
138
139 mod_timer(&info->se_info.se_active_timer, jiffies +
140 msecs_to_jiffies(ST21NFCA_SE_TO_HOT_PLUG));
141 info->se_info.se_active = true;
142
143 /* Ignore return value and check in any case the host_list */
144 wait_for_completion_interruptible(&info->se_info.req_completion);
145
146 r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE,
147 NFC_HCI_ADMIN_HOST_LIST,
148 &sk_host_list);
149 if (r < 0)
150 return r;
151
152 host_id = sk_host_list->data[sk_host_list->len - 1];
153 kfree_skb(sk_host_list);
154
155 if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
156 return se_idx;
157 else if (state == ST21NFCA_SE_MODE_OFF && host_id != se_idx)
158 return se_idx;
159
160 return -1;
161}
162
163int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
164{
165 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
166 int se_count = 0;
167
168 if (info->se_status->is_uicc_present) {
169 nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
170 se_count++;
171 }
172
173 if (info->se_status->is_ese_present) {
174 nfc_add_se(hdev->ndev, ST21NFCA_ESE_HOST_ID, NFC_SE_EMBEDDED);
175 se_count++;
176 }
177
178 return !se_count;
179}
180EXPORT_SYMBOL(st21nfca_hci_discover_se);
181
182int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
183{
184 int r;
185
186 /*
187 * According to upper layer, se_idx == NFC_SE_UICC when
188 * info->se_status->is_uicc_enable is true should never happen.
189 * Same for eSE.
190 */
191 r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
192
193 if (r == ST21NFCA_ESE_HOST_ID) {
194 st21nfca_se_get_atr(hdev);
195 r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
196 ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
197 if (r < 0)
198 return r;
199 } else if (r < 0) {
200 /*
201 * The activation tentative failed, the secure element
202 * is not connected. Remove from the list.
203 */
204 nfc_remove_se(hdev->ndev, se_idx);
205 return r;
206 }
207
208 return 0;
209}
210EXPORT_SYMBOL(st21nfca_hci_enable_se);
211
212int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx)
213{
214 int r;
215
216 /*
217 * According to upper layer, se_idx == NFC_SE_UICC when
218 * info->se_status->is_uicc_enable is true should never happen
219 * Same for eSE.
220 */
221 r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_OFF);
222 if (r < 0)
223 return r;
224
225 return 0;
226}
227EXPORT_SYMBOL(st21nfca_hci_disable_se);
228
229int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
230 u8 *apdu, size_t apdu_length,
231 se_io_cb_t cb, void *cb_context)
232{
233 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
234
235 pr_debug("se_io %x\n", se_idx);
236
237 switch (se_idx) {
238 case ST21NFCA_ESE_HOST_ID:
239 info->se_info.cb = cb;
240 info->se_info.cb_context = cb_context;
241 mod_timer(&info->se_info.bwi_timer, jiffies +
242 msecs_to_jiffies(info->se_info.wt_timeout));
243 info->se_info.bwi_active = true;
244 return nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
245 ST21NFCA_EVT_TRANSMIT_DATA,
246 apdu, apdu_length);
247 default:
248 return -ENODEV;
249 }
250}
251EXPORT_SYMBOL(st21nfca_hci_se_io);
252
253static void st21nfca_se_wt_timeout(unsigned long data)
254{
255 /*
256 * No answer from the secure element
257 * within the defined timeout.
258 * Let's send a reset request as recovery procedure.
259 * According to the situation, we first try to send a software reset
260 * to the secure element. If the next command is still not
261 * answering in time, we send to the CLF a secure element hardware
262 * reset request.
263 */
264 /* hardware reset managed through VCC_UICC_OUT power supply */
265 u8 param = 0x01;
266 struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
267
268 pr_debug("\n");
269
270 info->se_info.bwi_active = false;
271
272 if (!info->se_info.xch_error) {
273 info->se_info.xch_error = true;
274 nfc_hci_send_event(info->hdev, ST21NFCA_APDU_READER_GATE,
275 ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
276 } else {
277 info->se_info.xch_error = false;
278 nfc_hci_send_event(info->hdev, ST21NFCA_DEVICE_MGNT_GATE,
279 ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
280 }
281 info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
282}
283
284static void st21nfca_se_activation_timeout(unsigned long data)
285{
286 struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
287
288 pr_debug("\n");
289
290 info->se_info.se_active = false;
291
292 complete(&info->se_info.req_completion);
293}
294
295/*
296 * Returns:
297 * <= 0: driver handled the event, skb consumed
298 * 1: driver does not handle the event, please do standard processing
299 */
300int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
301 u8 event, struct sk_buff *skb)
302{
303 int r = 0;
304
305 pr_debug("connectivity gate event: %x\n", event);
306
307 switch (event) {
308 case ST21NFCA_EVT_CONNECTIVITY:
309 break;
310 case ST21NFCA_EVT_TRANSACTION:
311 break;
312 default:
313 return 1;
314 }
315 kfree_skb(skb);
316 return r;
317}
318EXPORT_SYMBOL(st21nfca_connectivity_event_received);
319
320int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
321 u8 event, struct sk_buff *skb)
322{
323 int r = 0;
324 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
325
326 pr_debug("apdu reader gate event: %x\n", event);
327
328 switch (event) {
329 case ST21NFCA_EVT_TRANSMIT_DATA:
330 del_timer_sync(&info->se_info.bwi_timer);
331 info->se_info.bwi_active = false;
332 r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
333 ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
334 if (r < 0)
335 goto exit;
336
337 info->se_info.cb(info->se_info.cb_context,
338 skb->data, skb->len, 0);
339 break;
340 case ST21NFCA_EVT_WTX_REQUEST:
341 mod_timer(&info->se_info.bwi_timer, jiffies +
342 msecs_to_jiffies(info->se_info.wt_timeout));
343 break;
344 }
345
346exit:
347 kfree_skb(skb);
348 return r;
349}
350EXPORT_SYMBOL(st21nfca_apdu_reader_event_received);
351
352void st21nfca_se_init(struct nfc_hci_dev *hdev)
353{
354 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
355
356 init_completion(&info->se_info.req_completion);
357 /* initialize timers */
358 init_timer(&info->se_info.bwi_timer);
359 info->se_info.bwi_timer.data = (unsigned long)info;
360 info->se_info.bwi_timer.function = st21nfca_se_wt_timeout;
361 info->se_info.bwi_active = false;
362
363 init_timer(&info->se_info.se_active_timer);
364 info->se_info.se_active_timer.data = (unsigned long)info;
365 info->se_info.se_active_timer.function = st21nfca_se_activation_timeout;
366 info->se_info.se_active = false;
367
368 info->se_info.count_pipes = 0;
369 info->se_info.expected_pipes = 0;
370
371 info->se_info.xch_error = false;
372
373 info->se_info.wt_timeout =
374 ST21NFCA_BWI_TO_TIMEOUT(ST21NFCA_ATR_DEFAULT_BWI);
375}
376EXPORT_SYMBOL(st21nfca_se_init);
377
378void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
379{
380 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
381
382 if (info->se_info.bwi_active)
383 del_timer_sync(&info->se_info.bwi_timer);
384 if (info->se_info.se_active)
385 del_timer_sync(&info->se_info.se_active_timer);
386
387 info->se_info.bwi_active = false;
388 info->se_info.se_active = false;
389}
390EXPORT_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 000000000000..b172cfcaeb90
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_se.h
@@ -0,0 +1,63 @@
1/*
2 * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __ST21NFCA_SE_H
18#define __ST21NFCA_SE_H
19
20#include <linux/skbuff.h>
21#include <linux/workqueue.h>
22
23/*
24 * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
25 * sequence of at most 32 characters.
26 */
27#define ST21NFCA_ESE_MAX_LENGTH 33
28#define ST21NFCA_ESE_HOST_ID 0xc0
29
30struct st21nfca_se_info {
31 u8 atr[ST21NFCA_ESE_MAX_LENGTH];
32 struct completion req_completion;
33
34 struct timer_list bwi_timer;
35 int wt_timeout; /* in msecs */
36 bool bwi_active;
37
38 struct timer_list se_active_timer;
39 bool se_active;
40 int expected_pipes;
41 int count_pipes;
42
43 bool xch_error;
44
45 se_io_cb_t cb;
46 void *cb_context;
47};
48
49int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
50 u8 event, struct sk_buff *skb);
51int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
52 u8 event, struct sk_buff *skb);
53
54int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
55int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
56int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
57int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
58 u8 *apdu, size_t apdu_length,
59 se_io_cb_t cb, void *cb_context);
60
61void st21nfca_se_init(struct nfc_hci_dev *hdev);
62void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
63#endif /* __ST21NFCA_SE_H */
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h
index 5087fff96d86..cc2bdafb0c69 100644
--- a/include/linux/platform_data/st21nfca.h
+++ b/include/linux/platform_data/st21nfca.h
@@ -26,6 +26,8 @@
26struct st21nfca_nfc_platform_data { 26struct st21nfca_nfc_platform_data {
27 unsigned int gpio_ena; 27 unsigned int gpio_ena;
28 unsigned int irq_polarity; 28 unsigned int irq_polarity;
29 bool is_ese_present;
30 bool is_uicc_present;
29}; 31};
30 32
31#endif /* _ST21NFCA_HCI_H_ */ 33#endif /* _ST21NFCA_HCI_H_ */