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