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