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