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