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