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