aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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_ */