1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Secure Element driver for STMicroelectronics NFC NCI chip |
4 | * |
5 | * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/nfc.h> |
10 | #include <linux/delay.h> |
11 | #include <net/nfc/nci.h> |
12 | #include <net/nfc/nci_core.h> |
13 | |
14 | #include "st-nci.h" |
15 | |
16 | struct st_nci_pipe_info { |
17 | u8 pipe_state; |
18 | u8 src_host_id; |
19 | u8 src_gate_id; |
20 | u8 dst_host_id; |
21 | u8 dst_gate_id; |
22 | } __packed; |
23 | |
24 | /* Hosts */ |
25 | #define ST_NCI_HOST_CONTROLLER_ID 0x00 |
26 | #define ST_NCI_TERMINAL_HOST_ID 0x01 |
27 | #define ST_NCI_UICC_HOST_ID 0x02 |
28 | #define ST_NCI_ESE_HOST_ID 0xc0 |
29 | |
30 | /* Gates */ |
31 | #define ST_NCI_APDU_READER_GATE 0xf0 |
32 | #define ST_NCI_CONNECTIVITY_GATE 0x41 |
33 | |
34 | /* Pipes */ |
35 | #define ST_NCI_DEVICE_MGNT_PIPE 0x02 |
36 | |
37 | /* Connectivity pipe only */ |
38 | #define ST_NCI_SE_COUNT_PIPE_UICC 0x01 |
39 | /* Connectivity + APDU Reader pipe */ |
40 | #define ST_NCI_SE_COUNT_PIPE_EMBEDDED 0x02 |
41 | |
42 | #define ST_NCI_SE_TO_HOT_PLUG 1000 /* msecs */ |
43 | #define ST_NCI_SE_TO_PIPES 2000 |
44 | |
45 | #define ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80) |
46 | |
47 | #define NCI_HCI_APDU_PARAM_ATR 0x01 |
48 | #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01 |
49 | #define NCI_HCI_ADMIN_PARAM_WHITELIST 0x03 |
50 | #define NCI_HCI_ADMIN_PARAM_HOST_LIST 0x04 |
51 | |
52 | #define ST_NCI_EVT_SE_HARD_RESET 0x20 |
53 | #define ST_NCI_EVT_TRANSMIT_DATA 0x10 |
54 | #define ST_NCI_EVT_WTX_REQUEST 0x11 |
55 | #define ST_NCI_EVT_SE_SOFT_RESET 0x11 |
56 | #define ST_NCI_EVT_SE_END_OF_APDU_TRANSFER 0x21 |
57 | #define ST_NCI_EVT_HOT_PLUG 0x03 |
58 | |
59 | #define ST_NCI_SE_MODE_OFF 0x00 |
60 | #define ST_NCI_SE_MODE_ON 0x01 |
61 | |
62 | #define ST_NCI_EVT_CONNECTIVITY 0x10 |
63 | #define ST_NCI_EVT_TRANSACTION 0x12 |
64 | |
65 | #define ST_NCI_DM_GETINFO 0x13 |
66 | #define ST_NCI_DM_GETINFO_PIPE_LIST 0x02 |
67 | #define ST_NCI_DM_GETINFO_PIPE_INFO 0x01 |
68 | #define ST_NCI_DM_PIPE_CREATED 0x02 |
69 | #define ST_NCI_DM_PIPE_OPEN 0x04 |
70 | #define ST_NCI_DM_RF_ACTIVE 0x80 |
71 | #define ST_NCI_DM_DISCONNECT 0x30 |
72 | |
73 | #define ST_NCI_DM_IS_PIPE_OPEN(p) \ |
74 | ((p & 0x0f) == (ST_NCI_DM_PIPE_CREATED | ST_NCI_DM_PIPE_OPEN)) |
75 | |
76 | #define ST_NCI_ATR_DEFAULT_BWI 0x04 |
77 | |
78 | /* |
79 | * WT = 2^BWI/10[s], convert into msecs and add a secure |
80 | * room by increasing by 2 this timeout |
81 | */ |
82 | #define ST_NCI_BWI_TO_TIMEOUT(x) ((1 << x) * 200) |
83 | #define ST_NCI_ATR_GET_Y_FROM_TD(x) (x >> 4) |
84 | |
85 | /* If TA is present bit 0 is set */ |
86 | #define ST_NCI_ATR_TA_PRESENT(x) (x & 0x01) |
87 | /* If TB is present bit 1 is set */ |
88 | #define ST_NCI_ATR_TB_PRESENT(x) (x & 0x02) |
89 | |
90 | #define ST_NCI_NUM_DEVICES 256 |
91 | |
92 | static DECLARE_BITMAP(dev_mask, ST_NCI_NUM_DEVICES); |
93 | |
94 | /* Here are the mandatory pipe for st_nci */ |
95 | static struct nci_hci_gate st_nci_gates[] = { |
96 | {NCI_HCI_ADMIN_GATE, NCI_HCI_ADMIN_PIPE, |
97 | ST_NCI_HOST_CONTROLLER_ID}, |
98 | {NCI_HCI_LINK_MGMT_GATE, NCI_HCI_LINK_MGMT_PIPE, |
99 | ST_NCI_HOST_CONTROLLER_ID}, |
100 | {ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE, |
101 | ST_NCI_HOST_CONTROLLER_ID}, |
102 | |
103 | {NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE, |
104 | ST_NCI_HOST_CONTROLLER_ID}, |
105 | |
106 | /* Secure element pipes are created by secure element host */ |
107 | {ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE, |
108 | ST_NCI_HOST_CONTROLLER_ID}, |
109 | {ST_NCI_APDU_READER_GATE, NCI_HCI_DO_NOT_OPEN_PIPE, |
110 | ST_NCI_HOST_CONTROLLER_ID}, |
111 | }; |
112 | |
113 | static u8 st_nci_se_get_bwi(struct nci_dev *ndev) |
114 | { |
115 | int i; |
116 | u8 td; |
117 | struct st_nci_info *info = nci_get_drvdata(ndev); |
118 | |
119 | /* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */ |
120 | for (i = 1; i < ST_NCI_ESE_MAX_LENGTH; i++) { |
121 | td = ST_NCI_ATR_GET_Y_FROM_TD(info->se_info.atr[i]); |
122 | if (ST_NCI_ATR_TA_PRESENT(td)) |
123 | i++; |
124 | if (ST_NCI_ATR_TB_PRESENT(td)) { |
125 | i++; |
126 | return info->se_info.atr[i] >> 4; |
127 | } |
128 | } |
129 | return ST_NCI_ATR_DEFAULT_BWI; |
130 | } |
131 | |
132 | static void st_nci_se_get_atr(struct nci_dev *ndev) |
133 | { |
134 | struct st_nci_info *info = nci_get_drvdata(ndev); |
135 | int r; |
136 | struct sk_buff *skb; |
137 | |
138 | r = nci_hci_get_param(ndev, ST_NCI_APDU_READER_GATE, |
139 | NCI_HCI_APDU_PARAM_ATR, skb: &skb); |
140 | if (r < 0) |
141 | return; |
142 | |
143 | if (skb->len <= ST_NCI_ESE_MAX_LENGTH) { |
144 | memcpy(info->se_info.atr, skb->data, skb->len); |
145 | |
146 | info->se_info.wt_timeout = |
147 | ST_NCI_BWI_TO_TIMEOUT(st_nci_se_get_bwi(ndev)); |
148 | } |
149 | kfree_skb(skb); |
150 | } |
151 | |
152 | int st_nci_hci_load_session(struct nci_dev *ndev) |
153 | { |
154 | int i, j, r; |
155 | struct sk_buff *skb_pipe_list, *skb_pipe_info; |
156 | struct st_nci_pipe_info *dm_pipe_info; |
157 | u8 pipe_list[] = { ST_NCI_DM_GETINFO_PIPE_LIST, |
158 | ST_NCI_TERMINAL_HOST_ID}; |
159 | u8 pipe_info[] = { ST_NCI_DM_GETINFO_PIPE_INFO, |
160 | ST_NCI_TERMINAL_HOST_ID, 0}; |
161 | |
162 | /* On ST_NCI device pipes number are dynamics |
163 | * If pipes are already created, hci_dev_up will fail. |
164 | * Doing a clear all pipe is a bad idea because: |
165 | * - It does useless EEPROM cycling |
166 | * - It might cause issue for secure elements support |
167 | * (such as removing connectivity or APDU reader pipe) |
168 | * A better approach on ST_NCI is to: |
169 | * - get a pipe list for each host. |
170 | * (eg: ST_NCI_HOST_CONTROLLER_ID for now). |
171 | * (TODO Later on UICC HOST and eSE HOST) |
172 | * - get pipe information |
173 | * - match retrieved pipe list in st_nci_gates |
174 | * ST_NCI_DEVICE_MGNT_GATE is a proprietary gate |
175 | * with ST_NCI_DEVICE_MGNT_PIPE. |
176 | * Pipe can be closed and need to be open. |
177 | */ |
178 | r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID, |
179 | ST_NCI_DEVICE_MGNT_GATE, |
180 | ST_NCI_DEVICE_MGNT_PIPE); |
181 | if (r < 0) |
182 | return r; |
183 | |
184 | /* Get pipe list */ |
185 | r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, |
186 | ST_NCI_DM_GETINFO, param: pipe_list, param_len: sizeof(pipe_list), |
187 | skb: &skb_pipe_list); |
188 | if (r < 0) |
189 | return r; |
190 | |
191 | /* Complete the existing gate_pipe table */ |
192 | for (i = 0; i < skb_pipe_list->len; i++) { |
193 | pipe_info[2] = skb_pipe_list->data[i]; |
194 | r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, |
195 | ST_NCI_DM_GETINFO, param: pipe_info, |
196 | param_len: sizeof(pipe_info), skb: &skb_pipe_info); |
197 | |
198 | if (r) |
199 | continue; |
200 | |
201 | /* |
202 | * Match pipe ID and gate ID |
203 | * Output format from ST21NFC_DM_GETINFO is: |
204 | * - pipe state (1byte) |
205 | * - source hid (1byte) |
206 | * - source gid (1byte) |
207 | * - destination hid (1byte) |
208 | * - destination gid (1byte) |
209 | */ |
210 | dm_pipe_info = (struct st_nci_pipe_info *)skb_pipe_info->data; |
211 | if (dm_pipe_info->dst_gate_id == ST_NCI_APDU_READER_GATE && |
212 | dm_pipe_info->src_host_id == ST_NCI_UICC_HOST_ID) { |
213 | pr_err("Unexpected apdu_reader pipe on host %x\n" , |
214 | dm_pipe_info->src_host_id); |
215 | kfree_skb(skb: skb_pipe_info); |
216 | continue; |
217 | } |
218 | |
219 | for (j = 3; (j < ARRAY_SIZE(st_nci_gates)) && |
220 | (st_nci_gates[j].gate != dm_pipe_info->dst_gate_id); j++) |
221 | ; |
222 | |
223 | if (j < ARRAY_SIZE(st_nci_gates) && |
224 | st_nci_gates[j].gate == dm_pipe_info->dst_gate_id && |
225 | ST_NCI_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) { |
226 | ndev->hci_dev->init_data.gates[j].pipe = pipe_info[2]; |
227 | |
228 | ndev->hci_dev->gate2pipe[st_nci_gates[j].gate] = |
229 | pipe_info[2]; |
230 | ndev->hci_dev->pipes[pipe_info[2]].gate = |
231 | st_nci_gates[j].gate; |
232 | ndev->hci_dev->pipes[pipe_info[2]].host = |
233 | dm_pipe_info->src_host_id; |
234 | } |
235 | kfree_skb(skb: skb_pipe_info); |
236 | } |
237 | |
238 | /* |
239 | * 3 gates have a well known pipe ID. Only NCI_HCI_LINK_MGMT_GATE |
240 | * is not yet open at this stage. |
241 | */ |
242 | r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID, |
243 | NCI_HCI_LINK_MGMT_GATE, |
244 | NCI_HCI_LINK_MGMT_PIPE); |
245 | |
246 | kfree_skb(skb: skb_pipe_list); |
247 | return r; |
248 | } |
249 | EXPORT_SYMBOL_GPL(st_nci_hci_load_session); |
250 | |
251 | static void st_nci_hci_admin_event_received(struct nci_dev *ndev, |
252 | u8 event, struct sk_buff *skb) |
253 | { |
254 | struct st_nci_info *info = nci_get_drvdata(ndev); |
255 | |
256 | switch (event) { |
257 | case ST_NCI_EVT_HOT_PLUG: |
258 | if (info->se_info.se_active) { |
259 | if (!ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(skb)) { |
260 | del_timer_sync(timer: &info->se_info.se_active_timer); |
261 | info->se_info.se_active = false; |
262 | complete(&info->se_info.req_completion); |
263 | } else { |
264 | mod_timer(timer: &info->se_info.se_active_timer, |
265 | expires: jiffies + |
266 | msecs_to_jiffies(ST_NCI_SE_TO_PIPES)); |
267 | } |
268 | } |
269 | break; |
270 | default: |
271 | nfc_err(&ndev->nfc_dev->dev, "Unexpected event on admin gate\n" ); |
272 | } |
273 | } |
274 | |
275 | static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev, |
276 | u8 event, |
277 | struct sk_buff *skb) |
278 | { |
279 | struct st_nci_info *info = nci_get_drvdata(ndev); |
280 | |
281 | pr_debug("apdu reader gate event: %x\n" , event); |
282 | |
283 | switch (event) { |
284 | case ST_NCI_EVT_TRANSMIT_DATA: |
285 | del_timer_sync(timer: &info->se_info.bwi_timer); |
286 | info->se_info.bwi_active = false; |
287 | info->se_info.cb(info->se_info.cb_context, |
288 | skb->data, skb->len, 0); |
289 | break; |
290 | case ST_NCI_EVT_WTX_REQUEST: |
291 | mod_timer(timer: &info->se_info.bwi_timer, expires: jiffies + |
292 | msecs_to_jiffies(m: info->se_info.wt_timeout)); |
293 | break; |
294 | default: |
295 | nfc_err(&ndev->nfc_dev->dev, "Unexpected event on apdu reader gate\n" ); |
296 | return 1; |
297 | } |
298 | |
299 | kfree_skb(skb); |
300 | return 0; |
301 | } |
302 | |
303 | /* |
304 | * Returns: |
305 | * <= 0: driver handled the event, skb consumed |
306 | * 1: driver does not handle the event, please do standard processing |
307 | */ |
308 | static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, |
309 | u8 host, u8 event, |
310 | struct sk_buff *skb) |
311 | { |
312 | int r = 0; |
313 | struct device *dev = &ndev->nfc_dev->dev; |
314 | struct nfc_evt_transaction *transaction; |
315 | u32 aid_len; |
316 | u8 params_len; |
317 | |
318 | pr_debug("connectivity gate event: %x\n" , event); |
319 | |
320 | switch (event) { |
321 | case ST_NCI_EVT_CONNECTIVITY: |
322 | r = nfc_se_connectivity(dev: ndev->nfc_dev, se_idx: host); |
323 | break; |
324 | case ST_NCI_EVT_TRANSACTION: |
325 | /* According to specification etsi 102 622 |
326 | * 11.2.2.4 EVT_TRANSACTION Table 52 |
327 | * Description Tag Length |
328 | * AID 81 5 to 16 |
329 | * PARAMETERS 82 0 to 255 |
330 | * |
331 | * The key differences are aid storage length is variably sized |
332 | * in the packet, but fixed in nfc_evt_transaction, and that |
333 | * the aid_len is u8 in the packet, but u32 in the structure, |
334 | * and the tags in the packet are not included in |
335 | * nfc_evt_transaction. |
336 | * |
337 | * size(b): 1 1 5-16 1 1 0-255 |
338 | * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4 |
339 | * mem name: aid_tag(M) aid_len aid params_tag(M) params_len params |
340 | * example: 0x81 5-16 X 0x82 0-255 X |
341 | */ |
342 | if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) |
343 | return -EPROTO; |
344 | |
345 | aid_len = skb->data[1]; |
346 | |
347 | if (skb->len < aid_len + 4 || |
348 | aid_len > sizeof(transaction->aid)) |
349 | return -EPROTO; |
350 | |
351 | params_len = skb->data[aid_len + 3]; |
352 | |
353 | /* Verify PARAMETERS tag is (82), and final check that there is |
354 | * enough space in the packet to read everything. |
355 | */ |
356 | if (skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG || |
357 | skb->len < aid_len + 4 + params_len) |
358 | return -EPROTO; |
359 | |
360 | transaction = devm_kzalloc(dev, size: sizeof(*transaction) + |
361 | params_len, GFP_KERNEL); |
362 | if (!transaction) |
363 | return -ENOMEM; |
364 | |
365 | transaction->aid_len = aid_len; |
366 | transaction->params_len = params_len; |
367 | |
368 | memcpy(transaction->aid, &skb->data[2], aid_len); |
369 | memcpy(transaction->params, &skb->data[aid_len + 4], |
370 | params_len); |
371 | |
372 | r = nfc_se_transaction(dev: ndev->nfc_dev, se_idx: host, evt_transaction: transaction); |
373 | break; |
374 | default: |
375 | nfc_err(&ndev->nfc_dev->dev, "Unexpected event on connectivity gate\n" ); |
376 | return 1; |
377 | } |
378 | kfree_skb(skb); |
379 | return r; |
380 | } |
381 | |
382 | void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe, |
383 | u8 event, struct sk_buff *skb) |
384 | { |
385 | u8 gate = ndev->hci_dev->pipes[pipe].gate; |
386 | u8 host = ndev->hci_dev->pipes[pipe].host; |
387 | |
388 | switch (gate) { |
389 | case NCI_HCI_ADMIN_GATE: |
390 | st_nci_hci_admin_event_received(ndev, event, skb); |
391 | break; |
392 | case ST_NCI_APDU_READER_GATE: |
393 | st_nci_hci_apdu_reader_event_received(ndev, event, skb); |
394 | break; |
395 | case ST_NCI_CONNECTIVITY_GATE: |
396 | st_nci_hci_connectivity_event_received(ndev, host, event, skb); |
397 | break; |
398 | } |
399 | } |
400 | EXPORT_SYMBOL_GPL(st_nci_hci_event_received); |
401 | |
402 | void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd, |
403 | struct sk_buff *skb) |
404 | { |
405 | struct st_nci_info *info = nci_get_drvdata(ndev); |
406 | u8 gate = ndev->hci_dev->pipes[pipe].gate; |
407 | |
408 | pr_debug("cmd: %x\n" , cmd); |
409 | |
410 | switch (cmd) { |
411 | case NCI_HCI_ANY_OPEN_PIPE: |
412 | if (gate != ST_NCI_APDU_READER_GATE && |
413 | ndev->hci_dev->pipes[pipe].host != ST_NCI_UICC_HOST_ID) |
414 | ndev->hci_dev->count_pipes++; |
415 | |
416 | if (ndev->hci_dev->count_pipes == |
417 | ndev->hci_dev->expected_pipes) { |
418 | del_timer_sync(timer: &info->se_info.se_active_timer); |
419 | info->se_info.se_active = false; |
420 | ndev->hci_dev->count_pipes = 0; |
421 | complete(&info->se_info.req_completion); |
422 | } |
423 | break; |
424 | } |
425 | } |
426 | EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received); |
427 | |
428 | static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx, |
429 | u8 state) |
430 | { |
431 | struct st_nci_info *info = nci_get_drvdata(ndev); |
432 | int r, i; |
433 | struct sk_buff *sk_host_list; |
434 | u8 host_id; |
435 | |
436 | switch (se_idx) { |
437 | case ST_NCI_UICC_HOST_ID: |
438 | ndev->hci_dev->count_pipes = 0; |
439 | ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_UICC; |
440 | break; |
441 | case ST_NCI_ESE_HOST_ID: |
442 | ndev->hci_dev->count_pipes = 0; |
443 | ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_EMBEDDED; |
444 | break; |
445 | default: |
446 | return -EINVAL; |
447 | } |
448 | |
449 | /* |
450 | * Wait for an EVT_HOT_PLUG in order to |
451 | * retrieve a relevant host list. |
452 | */ |
453 | reinit_completion(x: &info->se_info.req_completion); |
454 | r = nci_nfcee_mode_set(ndev, nfcee_id: se_idx, nfcee_mode: state); |
455 | if (r != NCI_STATUS_OK) |
456 | return r; |
457 | |
458 | mod_timer(timer: &info->se_info.se_active_timer, expires: jiffies + |
459 | msecs_to_jiffies(ST_NCI_SE_TO_HOT_PLUG)); |
460 | info->se_info.se_active = true; |
461 | |
462 | /* Ignore return value and check in any case the host_list */ |
463 | wait_for_completion_interruptible(x: &info->se_info.req_completion); |
464 | |
465 | /* There might be some "collision" after receiving a HOT_PLUG event |
466 | * This may cause the CLF to not answer to the next hci command. |
467 | * There is no possible synchronization to prevent this. |
468 | * Adding a small delay is the only way to solve the issue. |
469 | */ |
470 | if (info->se_info.se_status->is_ese_present && |
471 | info->se_info.se_status->is_uicc_present) |
472 | usleep_range(min: 15000, max: 20000); |
473 | |
474 | r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE, |
475 | NCI_HCI_ADMIN_PARAM_HOST_LIST, skb: &sk_host_list); |
476 | if (r != NCI_HCI_ANY_OK) |
477 | return r; |
478 | |
479 | for (i = 0; i < sk_host_list->len && |
480 | sk_host_list->data[i] != se_idx; i++) |
481 | ; |
482 | host_id = sk_host_list->data[i]; |
483 | kfree_skb(skb: sk_host_list); |
484 | if (state == ST_NCI_SE_MODE_ON && host_id == se_idx) |
485 | return se_idx; |
486 | else if (state == ST_NCI_SE_MODE_OFF && host_id != se_idx) |
487 | return se_idx; |
488 | |
489 | return -1; |
490 | } |
491 | |
492 | int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx) |
493 | { |
494 | int r; |
495 | |
496 | /* |
497 | * According to upper layer, se_idx == NFC_SE_UICC when |
498 | * info->se_info.se_status->is_uicc_enable is true should never happen |
499 | * Same for eSE. |
500 | */ |
501 | r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_OFF); |
502 | if (r < 0) { |
503 | /* Do best effort to release SWP */ |
504 | if (se_idx == NFC_SE_EMBEDDED) { |
505 | r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE, |
506 | ST_NCI_EVT_SE_END_OF_APDU_TRANSFER, |
507 | NULL, param_len: 0); |
508 | } |
509 | return r; |
510 | } |
511 | |
512 | return 0; |
513 | } |
514 | EXPORT_SYMBOL_GPL(st_nci_disable_se); |
515 | |
516 | int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx) |
517 | { |
518 | int r; |
519 | |
520 | /* |
521 | * According to upper layer, se_idx == NFC_SE_UICC when |
522 | * info->se_info.se_status->is_uicc_enable is true should never happen. |
523 | * Same for eSE. |
524 | */ |
525 | r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON); |
526 | if (r == ST_NCI_ESE_HOST_ID) { |
527 | st_nci_se_get_atr(ndev); |
528 | r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE, |
529 | ST_NCI_EVT_SE_SOFT_RESET, NULL, param_len: 0); |
530 | } |
531 | |
532 | if (r < 0) { |
533 | /* |
534 | * The activation procedure failed, the secure element |
535 | * is not connected. Remove from the list. |
536 | */ |
537 | nfc_remove_se(dev: ndev->nfc_dev, se_idx); |
538 | return r; |
539 | } |
540 | |
541 | return 0; |
542 | } |
543 | EXPORT_SYMBOL_GPL(st_nci_enable_se); |
544 | |
545 | static int st_nci_hci_network_init(struct nci_dev *ndev) |
546 | { |
547 | struct st_nci_info *info = nci_get_drvdata(ndev); |
548 | struct core_conn_create_dest_spec_params *dest_params; |
549 | struct dest_spec_params spec_params; |
550 | struct nci_conn_info *conn_info; |
551 | int r, dev_num; |
552 | |
553 | dest_params = |
554 | kzalloc(size: sizeof(struct core_conn_create_dest_spec_params) + |
555 | sizeof(struct dest_spec_params), GFP_KERNEL); |
556 | if (dest_params == NULL) |
557 | return -ENOMEM; |
558 | |
559 | dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE; |
560 | dest_params->length = sizeof(struct dest_spec_params); |
561 | spec_params.id = ndev->hci_dev->nfcee_id; |
562 | spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS; |
563 | memcpy(dest_params->value, &spec_params, |
564 | sizeof(struct dest_spec_params)); |
565 | r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, number_destination_params: 1, |
566 | params_len: sizeof(struct core_conn_create_dest_spec_params) + |
567 | sizeof(struct dest_spec_params), |
568 | params: dest_params); |
569 | if (r != NCI_STATUS_OK) |
570 | goto free_dest_params; |
571 | |
572 | conn_info = ndev->hci_dev->conn_info; |
573 | if (!conn_info) |
574 | goto free_dest_params; |
575 | |
576 | ndev->hci_dev->init_data.gate_count = ARRAY_SIZE(st_nci_gates); |
577 | memcpy(ndev->hci_dev->init_data.gates, st_nci_gates, |
578 | sizeof(st_nci_gates)); |
579 | |
580 | /* |
581 | * Session id must include the driver name + i2c bus addr |
582 | * persistent info to discriminate 2 identical chips |
583 | */ |
584 | dev_num = find_first_zero_bit(addr: dev_mask, ST_NCI_NUM_DEVICES); |
585 | if (dev_num >= ST_NCI_NUM_DEVICES) { |
586 | r = -ENODEV; |
587 | goto free_dest_params; |
588 | } |
589 | |
590 | scnprintf(buf: ndev->hci_dev->init_data.session_id, |
591 | size: sizeof(ndev->hci_dev->init_data.session_id), |
592 | fmt: "%s%2x" , "ST21BH" , dev_num); |
593 | |
594 | r = nci_hci_dev_session_init(ndev); |
595 | if (r != NCI_HCI_ANY_OK) |
596 | goto free_dest_params; |
597 | |
598 | /* |
599 | * In factory mode, we prevent secure elements activation |
600 | * by disabling nfcee on the current HCI connection id. |
601 | * HCI will be used here only for proprietary commands. |
602 | */ |
603 | if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) |
604 | r = nci_nfcee_mode_set(ndev, |
605 | nfcee_id: ndev->hci_dev->conn_info->dest_params->id, |
606 | NCI_NFCEE_DISABLE); |
607 | else |
608 | r = nci_nfcee_mode_set(ndev, |
609 | nfcee_id: ndev->hci_dev->conn_info->dest_params->id, |
610 | NCI_NFCEE_ENABLE); |
611 | |
612 | free_dest_params: |
613 | kfree(objp: dest_params); |
614 | return r; |
615 | } |
616 | |
617 | int st_nci_discover_se(struct nci_dev *ndev) |
618 | { |
619 | u8 white_list[2]; |
620 | int r, wl_size = 0; |
621 | int se_count = 0; |
622 | struct st_nci_info *info = nci_get_drvdata(ndev); |
623 | |
624 | r = st_nci_hci_network_init(ndev); |
625 | if (r != 0) |
626 | return r; |
627 | |
628 | if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) |
629 | return 0; |
630 | |
631 | if (info->se_info.se_status->is_uicc_present) |
632 | white_list[wl_size++] = ST_NCI_UICC_HOST_ID; |
633 | if (info->se_info.se_status->is_ese_present) |
634 | white_list[wl_size++] = ST_NCI_ESE_HOST_ID; |
635 | |
636 | if (wl_size) { |
637 | r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE, |
638 | NCI_HCI_ADMIN_PARAM_WHITELIST, |
639 | param: white_list, param_len: wl_size); |
640 | if (r != NCI_HCI_ANY_OK) |
641 | return r; |
642 | } |
643 | |
644 | if (info->se_info.se_status->is_uicc_present) { |
645 | nfc_add_se(dev: ndev->nfc_dev, ST_NCI_UICC_HOST_ID, NFC_SE_UICC); |
646 | se_count++; |
647 | } |
648 | |
649 | if (info->se_info.se_status->is_ese_present) { |
650 | nfc_add_se(dev: ndev->nfc_dev, ST_NCI_ESE_HOST_ID, NFC_SE_EMBEDDED); |
651 | se_count++; |
652 | } |
653 | |
654 | return !se_count; |
655 | } |
656 | EXPORT_SYMBOL_GPL(st_nci_discover_se); |
657 | |
658 | int st_nci_se_io(struct nci_dev *ndev, u32 se_idx, |
659 | u8 *apdu, size_t apdu_length, |
660 | se_io_cb_t cb, void *cb_context) |
661 | { |
662 | struct st_nci_info *info = nci_get_drvdata(ndev); |
663 | |
664 | switch (se_idx) { |
665 | case ST_NCI_ESE_HOST_ID: |
666 | info->se_info.cb = cb; |
667 | info->se_info.cb_context = cb_context; |
668 | mod_timer(timer: &info->se_info.bwi_timer, expires: jiffies + |
669 | msecs_to_jiffies(m: info->se_info.wt_timeout)); |
670 | info->se_info.bwi_active = true; |
671 | return nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE, |
672 | ST_NCI_EVT_TRANSMIT_DATA, param: apdu, |
673 | param_len: apdu_length); |
674 | default: |
675 | /* Need to free cb_context here as at the moment we can't |
676 | * clearly indicate to the caller if the callback function |
677 | * would be called (and free it) or not. In both cases a |
678 | * negative value may be returned to the caller. |
679 | */ |
680 | kfree(objp: cb_context); |
681 | return -ENODEV; |
682 | } |
683 | } |
684 | EXPORT_SYMBOL(st_nci_se_io); |
685 | |
686 | static void st_nci_se_wt_timeout(struct timer_list *t) |
687 | { |
688 | /* |
689 | * No answer from the secure element |
690 | * within the defined timeout. |
691 | * Let's send a reset request as recovery procedure. |
692 | * According to the situation, we first try to send a software reset |
693 | * to the secure element. If the next command is still not |
694 | * answering in time, we send to the CLF a secure element hardware |
695 | * reset request. |
696 | */ |
697 | /* hardware reset managed through VCC_UICC_OUT power supply */ |
698 | u8 param = 0x01; |
699 | struct st_nci_info *info = from_timer(info, t, se_info.bwi_timer); |
700 | |
701 | info->se_info.bwi_active = false; |
702 | |
703 | if (!info->se_info.xch_error) { |
704 | info->se_info.xch_error = true; |
705 | nci_hci_send_event(ndev: info->ndlc->ndev, ST_NCI_APDU_READER_GATE, |
706 | ST_NCI_EVT_SE_SOFT_RESET, NULL, param_len: 0); |
707 | } else { |
708 | info->se_info.xch_error = false; |
709 | nci_hci_send_event(ndev: info->ndlc->ndev, ST_NCI_DEVICE_MGNT_GATE, |
710 | ST_NCI_EVT_SE_HARD_RESET, param: ¶m, param_len: 1); |
711 | } |
712 | info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME); |
713 | } |
714 | |
715 | static void st_nci_se_activation_timeout(struct timer_list *t) |
716 | { |
717 | struct st_nci_info *info = from_timer(info, t, |
718 | se_info.se_active_timer); |
719 | |
720 | info->se_info.se_active = false; |
721 | |
722 | complete(&info->se_info.req_completion); |
723 | } |
724 | |
725 | int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status) |
726 | { |
727 | struct st_nci_info *info = nci_get_drvdata(ndev); |
728 | |
729 | init_completion(x: &info->se_info.req_completion); |
730 | /* initialize timers */ |
731 | timer_setup(&info->se_info.bwi_timer, st_nci_se_wt_timeout, 0); |
732 | info->se_info.bwi_active = false; |
733 | |
734 | timer_setup(&info->se_info.se_active_timer, |
735 | st_nci_se_activation_timeout, 0); |
736 | info->se_info.se_active = false; |
737 | |
738 | info->se_info.xch_error = false; |
739 | |
740 | info->se_info.wt_timeout = |
741 | ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI); |
742 | |
743 | info->se_info.se_status = se_status; |
744 | |
745 | return 0; |
746 | } |
747 | EXPORT_SYMBOL(st_nci_se_init); |
748 | |
749 | void st_nci_se_deinit(struct nci_dev *ndev) |
750 | { |
751 | struct st_nci_info *info = nci_get_drvdata(ndev); |
752 | |
753 | if (info->se_info.bwi_active) |
754 | del_timer_sync(timer: &info->se_info.bwi_timer); |
755 | if (info->se_info.se_active) |
756 | del_timer_sync(timer: &info->se_info.se_active_timer); |
757 | |
758 | info->se_info.se_active = false; |
759 | info->se_info.bwi_active = false; |
760 | } |
761 | EXPORT_SYMBOL(st_nci_se_deinit); |
762 | |
763 | |