1 /******************************************************************************
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 <android-base/properties.h>
24 #include <dlfcn.h>
25 #include <errno.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 #include "st21nfc_dev.h"
33
34 #if defined(ST_LIB_32)
35 #define VENDOR_LIB_PATH "/vendor/lib/"
36 #else
37 #define VENDOR_LIB_PATH "/vendor/lib64/"
38 #endif
39 #define VENDOR_LIB_EXT ".so"
40
41 bool dbg_logging = false;
42
43 extern void HalCoreCallback(void* context, uint32_t event, const void* d,
44 size_t length);
45 extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
46
47 typedef int (*STEseReset)(void);
48
49 const char* halVersion = "ST21NFC AIDL Version 1.0.0";
50
51 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
52 uint8_t hal_is_closed = 1;
53 pthread_mutex_t hal_mtx = PTHREAD_MUTEX_INITIALIZER;
54 st21nfc_dev_t dev;
55 int nfc_mode = 0;
56
57 /*
58 * NCI HAL method implementations. These must be overridden
59 */
60
61 extern bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
62 nfc_stack_data_callback_t* p_data_cback,
63 HALHANDLE* pHandle);
64
65 extern int hal_wrapper_close(int call_cb, int nfc_mode);
66
67 extern void hal_wrapper_send_config();
68 extern void hal_wrapper_factoryReset();
69 extern void hal_wrapper_set_observer_mode(uint8_t enable);
70 extern void hal_wrapper_get_observer_mode();
71
72 /* Make sure to always post nfc_stack_callback_t in a separate thread.
73 This prevents a possible deadlock in upper layer on some sequences.
74 We need to synchronize finely for the callback called for hal close,
75 otherwise the upper layer either does not receive the event, or deadlocks,
76 because the HAL is closing while the callback may be blocked.
77 */
78 static struct async_callback_struct {
79 pthread_mutex_t mutex;
80 pthread_cond_t cond;
81 pthread_t thr;
82 int event_pending;
83 int stop_thread;
84 int thread_running;
85 nfc_event_t event;
86 nfc_status_t event_status;
87 } async_callback_data;
88
async_callback_thread_fct(void * arg)89 static void* async_callback_thread_fct(void* arg) {
90 int ret;
91 struct async_callback_struct* pcb_data = (struct async_callback_struct*)arg;
92
93 ret = pthread_mutex_lock(&pcb_data->mutex);
94 if (ret != 0) {
95 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
96 goto error;
97 }
98
99 do {
100 if (pcb_data->event_pending == 0) {
101 ret = pthread_cond_wait(&pcb_data->cond, &pcb_data->mutex);
102 if (ret != 0) {
103 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
104 break;
105 }
106 }
107
108 if (pcb_data->event_pending) {
109 nfc_event_t event = pcb_data->event;
110 nfc_status_t event_status = pcb_data->event_status;
111 int ending = pcb_data->stop_thread;
112 pcb_data->event_pending = 0;
113 ret = pthread_cond_signal(&pcb_data->cond);
114 if (ret != 0) {
115 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
116 break;
117 }
118 if (ending) {
119 pcb_data->thread_running = 0;
120 }
121 ret = pthread_mutex_unlock(&pcb_data->mutex);
122 if (ret != 0) {
123 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
124 }
125 STLOG_HAL_D("HAL st21nfc: %s event %hhx status %hhx", __func__, event,
126 event_status);
127 dev.p_cback_unwrap(event, event_status);
128 if (ending) {
129 return NULL;
130 }
131 ret = pthread_mutex_lock(&pcb_data->mutex);
132 if (ret != 0) {
133 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
134 goto error;
135 }
136 }
137 } while (pcb_data->stop_thread == 0 || pcb_data->event_pending);
138
139 ret = pthread_mutex_unlock(&pcb_data->mutex);
140 if (ret != 0) {
141 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
142 }
143
144 error:
145 pcb_data->thread_running = 0;
146 return NULL;
147 }
148
async_callback_thread_start()149 static int async_callback_thread_start() {
150 int ret;
151
152 memset(&async_callback_data, 0, sizeof(async_callback_data));
153
154 ret = pthread_mutex_init(&async_callback_data.mutex, NULL);
155 if (ret != 0) {
156 STLOG_HAL_E("HAL: %s pthread_mutex_init failed", __func__);
157 return ret;
158 }
159
160 ret = pthread_cond_init(&async_callback_data.cond, NULL);
161 if (ret != 0) {
162 STLOG_HAL_E("HAL: %s pthread_cond_init failed", __func__);
163 return ret;
164 }
165
166 async_callback_data.thread_running = 1;
167
168 ret = pthread_create(&async_callback_data.thr, NULL,
169 async_callback_thread_fct, &async_callback_data);
170 if (ret != 0) {
171 STLOG_HAL_E("HAL: %s pthread_create failed", __func__);
172 async_callback_data.thread_running = 0;
173 return ret;
174 }
175
176 return 0;
177 }
178
async_callback_thread_end()179 static int async_callback_thread_end() {
180 if (async_callback_data.thread_running != 0) {
181 int ret;
182
183 ret = pthread_mutex_lock(&async_callback_data.mutex);
184 if (ret != 0) {
185 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
186 return ret;
187 }
188
189 async_callback_data.stop_thread = 1;
190
191 // Wait for the thread to have no event pending
192 while (async_callback_data.thread_running &&
193 async_callback_data.event_pending) {
194 ret = pthread_cond_signal(&async_callback_data.cond);
195 if (ret != 0) {
196 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
197 return ret;
198 }
199 ret = pthread_cond_wait(&async_callback_data.cond,
200 &async_callback_data.mutex);
201 if (ret != 0) {
202 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
203 break;
204 }
205 }
206
207 ret = pthread_mutex_unlock(&async_callback_data.mutex);
208 if (ret != 0) {
209 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
210 return ret;
211 }
212
213 ret = pthread_cond_signal(&async_callback_data.cond);
214 if (ret != 0) {
215 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
216 return ret;
217 }
218
219 ret = pthread_join(async_callback_data.thr, (void**)NULL);
220 if (ret != 0) {
221 STLOG_HAL_E("HAL: %s pthread_join failed", __func__);
222 return ret;
223 }
224 }
225 return 0;
226 }
227
async_callback_post(nfc_event_t event,nfc_status_t event_status)228 static void async_callback_post(nfc_event_t event, nfc_status_t event_status) {
229 int ret;
230
231 if (pthread_equal(pthread_self(), async_callback_data.thr)) {
232 dev.p_cback_unwrap(event, event_status);
233 }
234
235 ret = pthread_mutex_lock(&async_callback_data.mutex);
236 if (ret != 0) {
237 STLOG_HAL_E("HAL: %s pthread_mutex_lock failed", __func__);
238 return;
239 }
240
241 if (async_callback_data.thread_running == 0) {
242 (void)pthread_mutex_unlock(&async_callback_data.mutex);
243 STLOG_HAL_E("HAL: %s thread is not running", __func__);
244 dev.p_cback_unwrap(event, event_status);
245 return;
246 }
247
248 while (async_callback_data.event_pending) {
249 ret = pthread_cond_wait(&async_callback_data.cond,
250 &async_callback_data.mutex);
251 if (ret != 0) {
252 STLOG_HAL_E("HAL: %s pthread_cond_wait failed", __func__);
253 return;
254 }
255 }
256
257 async_callback_data.event_pending = 1;
258 async_callback_data.event = event;
259 async_callback_data.event_status = event_status;
260
261 ret = pthread_mutex_unlock(&async_callback_data.mutex);
262 if (ret != 0) {
263 STLOG_HAL_E("HAL: %s pthread_mutex_unlock failed", __func__);
264 return;
265 }
266
267 ret = pthread_cond_signal(&async_callback_data.cond);
268 if (ret != 0) {
269 STLOG_HAL_E("HAL: %s pthread_cond_signal failed", __func__);
270 return;
271 }
272 }
273 /* ------ */
274
StNfc_hal_open(nfc_stack_callback_t * p_cback,nfc_stack_data_callback_t * p_data_cback)275 int StNfc_hal_open(nfc_stack_callback_t* p_cback,
276 nfc_stack_data_callback_t* p_data_cback) {
277 bool result = false;
278
279 STLOG_HAL_D("HAL st21nfc: %s %s", __func__, halVersion);
280
281 (void)pthread_mutex_lock(&hal_mtx);
282
283 if (!hal_is_closed) {
284 hal_wrapper_close(0, nfc_mode);
285 }
286
287 dev.p_cback = p_cback; // will be replaced by wrapper version
288 dev.p_cback_unwrap = p_cback;
289 dev.p_data_cback = p_data_cback;
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
StNfc_hal_write(uint16_t data_len,const uint8_t * p_data)312 int 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
327 uint8_t NCI_ANDROID_PASSIVE_OBSERVER_PREFIX[] = {0x2f, 0x0c, 0x02, 0x02};
328 uint8_t NCI_QUERY_ANDROID_PASSIVE_OBSERVER_PREFIX[] = {0x2f, 0x0c, 0x01, 0x4};
329 if (data_len == 4 && !memcmp(p_data, NCI_QUERY_ANDROID_PASSIVE_OBSERVER_PREFIX,
330 sizeof(NCI_QUERY_ANDROID_PASSIVE_OBSERVER_PREFIX))) {
331 uint8_t CORE_GET_CONFIG_OBSERVER[5] = {0x20, 0x03, 0x02, 0x01, 0xa3};
332 hal_wrapper_get_observer_mode();
333 if (!HalSendDownstream(dev.hHAL, CORE_GET_CONFIG_OBSERVER, 5)) {
334 STLOG_HAL_E("HAL st21nfc %s SendDownstream failed", __func__);
335 (void)pthread_mutex_unlock(&hal_mtx);
336 return 0;
337 }
338 }
339
340 else if (data_len == 5 && !memcmp(p_data, NCI_ANDROID_PASSIVE_OBSERVER_PREFIX,
341 sizeof(NCI_ANDROID_PASSIVE_OBSERVER_PREFIX))) {
342 uint8_t CORE_SET_CONFIG_OBSERVER[7] = {0x20, 0x02, 0x04, 0x01,
343 0xa3, 0x01, p_data[4]};
344
345 hal_wrapper_set_observer_mode(p_data[4]);
346 if (!HalSendDownstream(dev.hHAL, CORE_SET_CONFIG_OBSERVER, 7)) {
347 STLOG_HAL_E("HAL st21nfc %s SendDownstream failed", __func__);
348 (void)pthread_mutex_unlock(&hal_mtx);
349 return 0;
350 }
351 } else if (!HalSendDownstream(dev.hHAL, p_data, data_len)) {
352 STLOG_HAL_E("HAL st21nfc %s SendDownstream failed", __func__);
353 (void)pthread_mutex_unlock(&hal_mtx);
354 return 0;
355 }
356 (void)pthread_mutex_unlock(&hal_mtx);
357
358 return ret;
359 }
360
StNfc_hal_core_initialized()361 int StNfc_hal_core_initialized() {
362 STLOG_HAL_D("HAL st21nfc: %s", __func__);
363
364 (void)pthread_mutex_lock(&hal_mtx);
365 hal_wrapper_send_config();
366 (void)pthread_mutex_unlock(&hal_mtx);
367
368 return 0; // return != 0 to signal ready immediate
369 }
370
StNfc_hal_pre_discover()371 int StNfc_hal_pre_discover() {
372 STLOG_HAL_D("HAL st21nfc: %s", __func__);
373 async_callback_post(HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_OK);
374 // callback directly if no vendor-specific pre-discovery actions are needed
375 return 0;
376 }
377
StNfc_hal_close(int nfc_mode_value)378 int StNfc_hal_close(int nfc_mode_value) {
379 void* stdll = nullptr;
380 STLOG_HAL_D("HAL st21nfc: %s nfc_mode = %d", __func__, nfc_mode_value);
381
382 /* check if HAL is closed */
383 (void)pthread_mutex_lock(&hal_mtx);
384 if (hal_is_closed) {
385 (void)pthread_mutex_unlock(&hal_mtx);
386 return 1;
387 }
388 if (hal_wrapper_close(1, nfc_mode_value) == -1) {
389 hal_is_closed = 1;
390 (void)pthread_mutex_unlock(&hal_mtx);
391 return 1;
392 }
393 hal_is_closed = 1;
394 (void)pthread_mutex_unlock(&hal_mtx);
395
396 deInitializeHalLog();
397
398 if (async_callback_thread_end() != 0) {
399 STLOG_HAL_E("HAL st21nfc: %s async_callback_thread_end failed", __func__);
400 return -1; // We are doomed, stop it here, NOW !
401 }
402
403 std::string valueStr =
404 android::base::GetProperty("persist.vendor.nfc.streset", "");
405 if (valueStr.length() > 0) {
406 stdll = dlopen(valueStr.c_str(), RTLD_NOW);
407 if (!stdll) {
408 valueStr = VENDOR_LIB_PATH + valueStr + VENDOR_LIB_EXT;
409 stdll = dlopen(valueStr.c_str(), RTLD_NOW);
410 }
411 if (stdll) {
412 STLOG_HAL_D("STReset Cold reset");
413 STEseReset fn = (STEseReset)dlsym(stdll, "cold_reset");
414 if (fn) {
415 int ret = fn();
416 STLOG_HAL_D("STReset Result=%d", ret);
417 }
418 } else {
419 STLOG_HAL_D("%s not found, do nothing.", valueStr.c_str());
420 }
421 }
422
423 STLOG_HAL_D("HAL st21nfc: %s close", __func__);
424 return 0;
425 }
426
StNfc_hal_power_cycle()427 int StNfc_hal_power_cycle() {
428 STLOG_HAL_D("HAL st21nfc: %s", __func__);
429
430 /* check if HAL is closed */
431 int ret = HAL_NFC_STATUS_OK;
432 (void)pthread_mutex_lock(&hal_mtx);
433 if (hal_is_closed) {
434 ret = HAL_NFC_STATUS_FAILED;
435 }
436
437 if (ret != HAL_NFC_STATUS_OK) {
438 (void)pthread_mutex_unlock(&hal_mtx);
439 return ret;
440 }
441 async_callback_post(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
442
443 (void)pthread_mutex_unlock(&hal_mtx);
444 return HAL_NFC_STATUS_OK;
445 }
446
StNfc_hal_factoryReset()447 void StNfc_hal_factoryReset() {
448 STLOG_HAL_D("HAL st21nfc: %s", __func__);
449 // hal_wrapper_factoryReset();
450 // Nothing needed for factory reset in st21nfc case.
451 }
452
StNfc_hal_closeForPowerOffCase()453 int StNfc_hal_closeForPowerOffCase() {
454 STLOG_HAL_D("HAL st21nfc: %s", __func__);
455 if (nfc_mode == 1) {
456 return 0;
457 } else {
458 return StNfc_hal_close(nfc_mode);
459 }
460 }
461
StNfc_hal_getConfig(NfcConfig & config)462 void StNfc_hal_getConfig(NfcConfig& config) {
463 STLOG_HAL_D("HAL st21nfc: %s", __func__);
464 unsigned long num = 0;
465 std::array<uint8_t, 10> buffer;
466
467 buffer.fill(0);
468 long retlen = 0;
469
470 memset(&config, 0x00, sizeof(NfcConfig));
471
472 if (GetNumValue(NAME_CE_ON_SWITCH_OFF_STATE, &num, sizeof(num))) {
473 if (num == 0x1) {
474 nfc_mode = 0x1;
475 }
476 }
477
478 if (GetNumValue(NAME_POLL_BAIL_OUT_MODE, &num, sizeof(num))) {
479 config.nfaPollBailOutMode = num;
480 }
481
482 if (GetNumValue(NAME_ISO_DEP_MAX_TRANSCEIVE, &num, sizeof(num))) {
483 config.maxIsoDepTransceiveLength = num;
484 }
485 if (GetNumValue(NAME_DEFAULT_OFFHOST_ROUTE, &num, sizeof(num))) {
486 config.defaultOffHostRoute = num;
487 }
488 if (GetNumValue(NAME_DEFAULT_NFCF_ROUTE, &num, sizeof(num))) {
489 config.defaultOffHostRouteFelica = num;
490 }
491 if (GetNumValue(NAME_DEFAULT_SYS_CODE_ROUTE, &num, sizeof(num))) {
492 config.defaultSystemCodeRoute = num;
493 }
494 if (GetNumValue(NAME_DEFAULT_SYS_CODE_PWR_STATE, &num, sizeof(num))) {
495 config.defaultSystemCodePowerState = num;
496 }
497 if (GetNumValue(NAME_DEFAULT_ROUTE, &num, sizeof(num))) {
498 config.defaultRoute = num;
499 }
500 if (GetByteArrayValue(NAME_DEVICE_HOST_ALLOW_LIST, (char*)buffer.data(),
501 buffer.size(), &retlen)) {
502 config.hostAllowlist.resize(retlen);
503 for (int i = 0; i < retlen; i++) {
504 config.hostAllowlist[i] = buffer[i];
505 }
506 }
507
508 if (GetNumValue(NAME_OFF_HOST_ESE_PIPE_ID, &num, sizeof(num))) {
509 config.offHostESEPipeId = num;
510 }
511 if (GetNumValue(NAME_OFF_HOST_SIM_PIPE_ID, &num, sizeof(num))) {
512 config.offHostSIMPipeId = num;
513 }
514 if ((GetByteArrayValue(NAME_NFA_PROPRIETARY_CFG, (char*)buffer.data(),
515 buffer.size(), &retlen)) &&
516 (retlen == 9)) {
517 config.nfaProprietaryCfg.protocol18092Active = (uint8_t)buffer[0];
518 config.nfaProprietaryCfg.protocolBPrime = (uint8_t)buffer[1];
519 config.nfaProprietaryCfg.protocolDual = (uint8_t)buffer[2];
520 config.nfaProprietaryCfg.protocol15693 = (uint8_t)buffer[3];
521 config.nfaProprietaryCfg.protocolKovio = (uint8_t)buffer[4];
522 config.nfaProprietaryCfg.protocolMifare = (uint8_t)buffer[5];
523 config.nfaProprietaryCfg.discoveryPollKovio = (uint8_t)buffer[6];
524 config.nfaProprietaryCfg.discoveryPollBPrime = (uint8_t)buffer[7];
525 config.nfaProprietaryCfg.discoveryListenBPrime = (uint8_t)buffer[8];
526 } else {
527 memset(&config.nfaProprietaryCfg, 0xFF, sizeof(ProtocolDiscoveryConfig));
528 }
529 if (GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num))) {
530 config.presenceCheckAlgorithm = (PresenceCheckAlgorithm)num;
531 }
532
533 if (GetNumValue(NAME_STNFC_USB_CHARGING_MODE, &num, sizeof(num))) {
534 if ((num == 1) && (nfc_mode == 0x1)) {
535 nfc_mode = 0x2;
536 }
537 }
538
539 if (GetByteArrayValue(NAME_OFFHOST_ROUTE_UICC, (char*)buffer.data(),
540 buffer.size(), &retlen)) {
541 config.offHostRouteUicc.resize(retlen);
542 for (int i = 0; i < retlen; i++) {
543 config.offHostRouteUicc[i] = buffer[i];
544 }
545 }
546
547 if (GetByteArrayValue(NAME_OFFHOST_ROUTE_ESE, (char*)buffer.data(),
548 buffer.size(), &retlen)) {
549 config.offHostRouteEse.resize(retlen);
550 for (int i = 0; i < retlen; i++) {
551 config.offHostRouteEse[i] = buffer[i];
552 }
553 }
554
555 if (GetNumValue(NAME_DEFAULT_ISODEP_ROUTE, &num, sizeof(num))) {
556 config.defaultIsoDepRoute = num;
557 }
558 }
559
StNfc_hal_setLogging(bool enable)560 void StNfc_hal_setLogging(bool enable) {
561 dbg_logging = enable;
562 hal_wrapper_setFwLogging(enable);
563 if (dbg_logging && hal_conf_trace_level < STNFC_TRACE_LEVEL_VERBOSE) {
564 hal_trace_level = STNFC_TRACE_LEVEL_VERBOSE;
565 } else {
566 hal_trace_level = hal_conf_trace_level;
567 }
568 }
569
StNfc_hal_isLoggingEnabled()570 bool StNfc_hal_isLoggingEnabled() { return dbg_logging; }
571