blob: 78c1b2212b1fdf955914abd032edfef3efd13a68 [file] [log] [blame]
Arach MOHAMMED BRAHIMa642ec82019-02-01 11:39:47 +01001/******************************************************************************
2 *
3 * Copyright (C) 1999-2012 Broadcom Corporation
4 * Copyright (C) 2013 ST Microelectronics S.A.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Modified by ST Microelectronics S.A. (adaptation of nfc_nci.c for ST21NFC
19 *NCI version)
20 *
21 ******************************************************************************/
22
23#include <cutils/properties.h>
24#include <errno.h>
25#include <hardware/nfc.h>
26#include <string.h>
27
28#include "StNfc_hal_api.h"
29#include "android_logmsg.h"
30#include "hal_config.h"
31#include "halcore.h"
32
33extern void HalCoreCallback(void* context, uint32_t event, const void* d,
34 size_t length);
35extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
36
37typedef struct {
38 struct nfc_nci_device nci_device; // nci_device must be first struct member
39 // below declarations are private variables within HAL
40 nfc_stack_callback_t* p_cback;
41 nfc_stack_data_callback_t* p_data_cback;
42 HALHANDLE hHAL;
43 nfc_stack_callback_t* p_cback_unwrap;
44} st21nfc_dev_t;
45
Arach MOHAMMED BRAHIMc36c6492019-03-25 15:06:10 +010046const char* halVersion = "ST21NFC HAL1.2 Version 3.2.1";
Arach MOHAMMED BRAHIMa642ec82019-02-01 11:39:47 +010047
48uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
49uint8_t hal_is_closed = 1;
50pthread_mutex_t hal_mtx = PTHREAD_MUTEX_INITIALIZER;
51st21nfc_dev_t dev;
52uint8_t hal_dta_state = 0;
53int nfc_mode = 0;
54
55using namespace android::hardware::nfc::V1_1;
56using namespace android::hardware::nfc::V1_2;
57using android::hardware::nfc::V1_1::NfcEvent;
58
59/*
60 * NCI HAL method implementations. These must be overridden
61 */
62
63extern bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
64 nfc_stack_data_callback_t* p_data_cback,
65 HALHANDLE* pHandle);
66
67extern int hal_wrapper_close(int call_cb, int nfc_mode);
68
69extern void hal_wrapper_send_prop_config();
70
71/* Make sure to always post nfc_stack_callback_t in a separate thread.
72This prevents a possible deadlock in upper layer on some sequences.
73We need to synchronize finely for the callback called for hal close,
74otherwise the upper layer either does not receive the event, or deadlocks,
75because the HAL is closing while the callback may be blocked.
76 */
77static struct async_callback_struct {
78 pthread_mutex_t mutex;
79 pthread_cond_t cond;
80 pthread_t thr;
81 int event_pending;
82 int stop_thread;
83 int thread_running;
84 nfc_event_t event;
85 nfc_status_t event_status;
86} async_callback_data;
87
88static void* async_callback_thread_fct(void* arg) {
89 int ret;
90 struct async_callback_struct* pcb_data = (struct async_callback_struct*)arg;
91
92 ret = pthread_mutex_lock(&pcb_data->mutex);
93 if (ret != 0) {
94 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
95 goto error;
96 }
97
98 do {
99 if (pcb_data->event_pending == 0) {
100 ret = pthread_cond_wait(&pcb_data->cond, &pcb_data->mutex);
101 if (ret != 0) {
102 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
103 break;
104 }
105 }
106
107 if (pcb_data->event_pending) {
108 nfc_event_t event = pcb_data->event;
109 nfc_status_t event_status = pcb_data->event_status;
110 int ending = pcb_data->stop_thread;
111 pcb_data->event_pending = 0;
112 ret = pthread_cond_signal(&pcb_data->cond);
113 if (ret != 0) {
114 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
115 break;
116 }
117 if (ending) {
118 pcb_data->thread_running = 0;
119 }
120 ret = pthread_mutex_unlock(&pcb_data->mutex);
121 if (ret != 0) {
122 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
123 }
124 STLOG_HAL_D("HAL st21nfc: %s event %hhx status %hhx", __func__, event,
125 event_status);
126 dev.p_cback_unwrap(event, event_status);
127 if (ending) {
128 return NULL;
129 }
130 ret = pthread_mutex_lock(&pcb_data->mutex);
131 if (ret != 0) {
132 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
133 goto error;
134 }
135 }
136 } while (pcb_data->stop_thread == 0 || pcb_data->event_pending);
137
138 ret = pthread_mutex_unlock(&pcb_data->mutex);
139 if (ret != 0) {
140 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
141 }
142
143error:
144 pcb_data->thread_running = 0;
145 return NULL;
146}
147
148static int async_callback_thread_start() {
149 int ret;
150
151 memset(&async_callback_data, 0, sizeof(async_callback_data));
152
153 ret = pthread_mutex_init(&async_callback_data.mutex, NULL);
154 if (ret != 0) {
155 STLOG_HAL_E("HAL: %s pthread_mutex_init failed", __func__);
156 return ret;
157 }
158
159 ret = pthread_cond_init(&async_callback_data.cond, NULL);
160 if (ret != 0) {
161 STLOG_HAL_E("HAL: %s pthread_cond_init failed", __func__);
162 return ret;
163 }
164
165 async_callback_data.thread_running = 1;
166
167 ret = pthread_create(&async_callback_data.thr, NULL,
168 async_callback_thread_fct, &async_callback_data);
169 if (ret != 0) {
170 STLOG_HAL_E("HAL: %s pthread_create failed", __func__);
171 async_callback_data.thread_running = 0;
172 return ret;
173 }
174
175 return 0;
176}
177
178static int async_callback_thread_end() {
179 if (async_callback_data.thread_running != 0) {
180 int ret;
181
182 ret = pthread_mutex_lock(&async_callback_data.mutex);
183 if (ret != 0) {
184 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
185 return ret;
186 }
187
188 async_callback_data.stop_thread = 1;
189
190 // Wait for the thread to have no event pending
191 while (async_callback_data.thread_running &&
192 async_callback_data.event_pending) {
193 ret = pthread_cond_signal(&async_callback_data.cond);
194 if (ret != 0) {
195 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
196 return ret;
197 }
198 ret = pthread_cond_wait(&async_callback_data.cond,
199 &async_callback_data.mutex);
200 if (ret != 0) {
201 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
202 break;
203 }
204 }
205
206 ret = pthread_mutex_unlock(&async_callback_data.mutex);
207 if (ret != 0) {
208 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
209 return ret;
210 }
211
212 ret = pthread_cond_signal(&async_callback_data.cond);
213 if (ret != 0) {
214 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
215 return ret;
216 }
217
218 ret = pthread_detach(async_callback_data.thr);
219 if (ret != 0) {
220 STLOG_HAL_E("HAL: %s pthread_detach failed", __func__);
221 return ret;
222 }
223 }
224 return 0;
225}
226
227static void async_callback_post(nfc_event_t event, nfc_status_t event_status) {
228 int ret;
229
230 if (pthread_equal(pthread_self(), async_callback_data.thr)) {
231 dev.p_cback_unwrap(event, event_status);
232 }
233
234 ret = pthread_mutex_lock(&async_callback_data.mutex);
235 if (ret != 0) {
236 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
237 return;
238 }
239
240 if (async_callback_data.thread_running == 0) {
241 (void)pthread_mutex_unlock(&async_callback_data.mutex);
242 STLOG_HAL_E("HAL: %s thread is not running", __func__);
243 dev.p_cback_unwrap(event, event_status);
244 return;
245 }
246
247 while (async_callback_data.event_pending) {
248 ret = pthread_cond_wait(&async_callback_data.cond,
249 &async_callback_data.mutex);
250 if (ret != 0) {
251 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
252 return;
253 }
254 }
255
256 async_callback_data.event_pending = 1;
257 async_callback_data.event = event;
258 async_callback_data.event_status = event_status;
259
260 ret = pthread_mutex_unlock(&async_callback_data.mutex);
261 if (ret != 0) {
262 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
263 return;
264 }
265
266 ret = pthread_cond_signal(&async_callback_data.cond);
267 if (ret != 0) {
268 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
269 return;
270 }
271}
272/* ------ */
273
274int StNfc_hal_open(nfc_stack_callback_t* p_cback,
275 nfc_stack_data_callback_t* p_data_cback) {
276 bool result = false;
277
278 STLOG_HAL_D("HAL st21nfc: %s %s", __func__, halVersion);
279
280 (void)pthread_mutex_lock(&hal_mtx);
281
282 if (!hal_is_closed) {
283 hal_wrapper_close(0, nfc_mode);
284 }
285
286 dev.p_cback = p_cback; // will be replaced by wrapper version
287 dev.p_cback_unwrap = p_cback;
288 dev.p_data_cback = p_data_cback;
289 hal_dta_state = 0;
290 // Initialize and get global logging level
291 InitializeSTLogLevel();
292
293 if ((hal_is_closed || !async_callback_data.thread_running) &&
294 (async_callback_thread_start() != 0)) {
295 dev.p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
296 (void)pthread_mutex_unlock(&hal_mtx);
297 return -1; // We are doomed, stop it here, NOW !
298 }
299 result =
300 hal_wrapper_open(&dev, async_callback_post, p_data_cback, &(dev.hHAL));
301
302 if (!result || !(dev.hHAL)) {
303 async_callback_post(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
304 (void)pthread_mutex_unlock(&hal_mtx);
305 return -1; // We are doomed, stop it here, NOW !
306 }
307 hal_is_closed = 0;
308 (void)pthread_mutex_unlock(&hal_mtx);
309 return 0;
310}
311
312int StNfc_hal_write(uint16_t data_len, const uint8_t* p_data) {
313 STLOG_HAL_D("HAL st21nfc: %s", __func__);
314
315 /* check if HAL is closed */
316 int ret = (int)data_len;
317 (void)pthread_mutex_lock(&hal_mtx);
318 if (hal_is_closed) {
319 ret = 0;
320 }
321
322 if (!ret) {
323 (void)pthread_mutex_unlock(&hal_mtx);
324 return ret;
325 }
326 if (!HalSendDownstream(dev.hHAL, p_data, data_len)) {
327 STLOG_HAL_E("HAL st21nfc %s SendDownstream failed", __func__);
328 (void)pthread_mutex_unlock(&hal_mtx);
329 return 0;
330 }
331 (void)pthread_mutex_unlock(&hal_mtx);
332
333 return ret;
334}
335
336int StNfc_hal_core_initialized(uint8_t* p_core_init_rsp_params) {
337 STLOG_HAL_D("HAL st21nfc: %s", __func__);
338
339 (void)pthread_mutex_lock(&hal_mtx);
340 hal_dta_state = *p_core_init_rsp_params;
341
342 hal_wrapper_send_prop_config();
343 (void)pthread_mutex_unlock(&hal_mtx);
344
345 return 0; // return != 0 to signal ready immediate
346}
347
348int StNfc_hal_pre_discover() {
349 STLOG_HAL_D("HAL st21nfc: %s", __func__);
350
351 return 0; // false if no vendor-specific pre-discovery actions are needed
352}
353
354int StNfc_hal_close(int nfc_mode_value) {
355 STLOG_HAL_D("HAL st21nfc: %s nfc_mode = %d", __func__, nfc_mode_value);
356
357 /* check if HAL is closed */
358 (void)pthread_mutex_lock(&hal_mtx);
359 if (hal_is_closed) {
360 (void)pthread_mutex_unlock(&hal_mtx);
361 return 1;
362 }
363 if (hal_wrapper_close(1, nfc_mode_value) == 0) {
364 hal_is_closed = 1;
365 (void)pthread_mutex_unlock(&hal_mtx);
366 return 1;
367 }
368 hal_is_closed = 1;
369 (void)pthread_mutex_unlock(&hal_mtx);
370
371 hal_dta_state = 0;
372
373 if (async_callback_thread_end() != 0) {
374 STLOG_HAL_E("HAL st21nfc: %s async_callback_thread_end failed", __func__);
375 return -1; // We are doomed, stop it here, NOW !
376 }
377
378 usleep(10000); // give 10ms for the callback thread to pass the binder
379 STLOG_HAL_D("HAL st21nfc: %s close", __func__);
380 return 0;
381}
382
383int StNfc_hal_control_granted() {
384 STLOG_HAL_D("HAL st21nfc: %s", __func__);
385
386 return 0;
387}
388
389int StNfc_hal_power_cycle() {
390 STLOG_HAL_D("HAL st21nfc: %s", __func__);
391
392 /* check if HAL is closed */
393 int ret = HAL_NFC_STATUS_OK;
394 (void)pthread_mutex_lock(&hal_mtx);
395 if (hal_is_closed) {
396 ret = HAL_NFC_STATUS_FAILED;
397 }
398
399 if (ret != HAL_NFC_STATUS_OK) {
400 (void)pthread_mutex_unlock(&hal_mtx);
401 return ret;
402 }
403 async_callback_post(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
404
405 (void)pthread_mutex_unlock(&hal_mtx);
406 return HAL_NFC_STATUS_OK;
407}
408
409void StNfc_hal_factoryReset() {
410 STLOG_HAL_D("HAL st21nfc: %s", __func__);
411 // Nothing needed for factory reset in st21nfc case.
412}
413
414int StNfc_hal_closeForPowerOffCase() {
415 STLOG_HAL_D("HAL st21nfc: %s", __func__);
416
417 return StNfc_hal_close(nfc_mode);
418}
419
420void StNfc_hal_getConfig(android::hardware::nfc::V1_1::NfcConfig& config) {
421 STLOG_HAL_D("HAL st21nfc: %s", __func__);
422 unsigned long num = 0;
423 std::array<uint8_t, 10> buffer;
424
425 buffer.fill(0);
426 long retlen = 0;
427
428 memset(&config, 0x00, sizeof(android::hardware::nfc::V1_1::NfcConfig));
429
430 if (GetNumValue(NAME_CE_ON_SWITCH_OFF_STATE, &num, sizeof(num))) {
431 if (num == 0x1) {
432 nfc_mode = 0x2;
433 }
434 }
435
436 if (GetNumValue(NAME_POLL_BAIL_OUT_MODE, &num, sizeof(num))) {
437 config.nfaPollBailOutMode = num;
438 }
439
440 if (GetNumValue(NAME_ISO_DEP_MAX_TRANSCEIVE, &num, sizeof(num))) {
441 config.maxIsoDepTransceiveLength = num;
442 }
443 if (GetNumValue(NAME_DEFAULT_OFFHOST_ROUTE, &num, sizeof(num))) {
444 config.defaultOffHostRoute = num;
445 }
446 if (GetNumValue(NAME_DEFAULT_NFCF_ROUTE, &num, sizeof(num))) {
447 config.defaultOffHostRouteFelica = num;
448 }
449 if (GetNumValue(NAME_DEFAULT_SYS_CODE_ROUTE, &num, sizeof(num))) {
450 config.defaultSystemCodeRoute = num;
451 }
452 if (GetNumValue(NAME_DEFAULT_SYS_CODE_PWR_STATE, &num, sizeof(num))) {
453 config.defaultSystemCodePowerState = num;
454 }
455 if (GetNumValue(NAME_DEFAULT_ROUTE, &num, sizeof(num))) {
456 config.defaultRoute = num;
457 }
458 if (GetByteArrayValue(NAME_DEVICE_HOST_WHITE_LIST, (char*)buffer.data(),
459 buffer.size(), &retlen)) {
460 config.hostWhitelist.resize(retlen);
461 for (int i = 0; i < retlen; i++) {
462 config.hostWhitelist[i] = buffer[i];
463 }
464 }
465
466 if (GetNumValue(NAME_OFF_HOST_ESE_PIPE_ID, &num, sizeof(num))) {
467 config.offHostESEPipeId = num;
468 }
469 if (GetNumValue(NAME_OFF_HOST_SIM_PIPE_ID, &num, sizeof(num))) {
470 config.offHostSIMPipeId = num;
471 }
472 if ((GetByteArrayValue(NAME_NFA_PROPRIETARY_CFG, (char*)buffer.data(),
473 buffer.size(), &retlen)) &&
474 (retlen == 9)) {
475 config.nfaProprietaryCfg.protocol18092Active = (uint8_t)buffer[0];
476 config.nfaProprietaryCfg.protocolBPrime = (uint8_t)buffer[1];
477 config.nfaProprietaryCfg.protocolDual = (uint8_t)buffer[2];
478 config.nfaProprietaryCfg.protocol15693 = (uint8_t)buffer[3];
479 config.nfaProprietaryCfg.protocolKovio = (uint8_t)buffer[4];
480 config.nfaProprietaryCfg.protocolMifare = (uint8_t)buffer[5];
481 config.nfaProprietaryCfg.discoveryPollKovio = (uint8_t)buffer[6];
482 config.nfaProprietaryCfg.discoveryPollBPrime = (uint8_t)buffer[7];
483 config.nfaProprietaryCfg.discoveryListenBPrime = (uint8_t)buffer[8];
484 } else {
485 memset(&config.nfaProprietaryCfg, 0xFF, sizeof(ProtocolDiscoveryConfig));
486 }
487 if (GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num))) {
488 config.presenceCheckAlgorithm = (PresenceCheckAlgorithm)num;
489 }
490}
491
492void StNfc_hal_getConfig_1_2(android::hardware::nfc::V1_2::NfcConfig& config) {
493 STLOG_HAL_D("HAL st21nfc: %s", __func__);
494 unsigned long num = 0;
495 std::array<uint8_t, 10> buffer;
496
497 buffer.fill(0);
498 long retlen = 0;
499
500 memset(&config, 0x00, sizeof(android::hardware::nfc::V1_2::NfcConfig));
501
502 StNfc_hal_getConfig(config.v1_1);
503
504 if (GetByteArrayValue(NAME_OFFHOST_ROUTE_UICC, (char*)buffer.data(),
505 buffer.size(), &retlen)) {
506 config.offHostRouteUicc.resize(retlen);
507 for (int i = 0; i < retlen; i++) {
508 config.offHostRouteUicc[i] = buffer[i];
509 }
510 }
511
512 if (GetByteArrayValue(NAME_OFFHOST_ROUTE_ESE, (char*)buffer.data(),
513 buffer.size(), &retlen)) {
514 config.offHostRouteEse.resize(retlen);
515 for (int i = 0; i < retlen; i++) {
516 config.offHostRouteEse[i] = buffer[i];
517 }
518 }
519
520 if (GetNumValue(NAME_DEFAULT_ISODEP_ROUTE, &num, sizeof(num))) {
521 config.defaultIsoDepRoute = num;
522 }
523}