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