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