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