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 <cutils/properties.h>
24 #include <errno.h>
25 #include <hardware/nfc.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 
33 extern void HalCoreCallback(void* context, uint32_t event, const void* d,
34                             size_t length);
35 extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
36 
37 typedef struct {
38   struct nfc_nci_device nci_device;  // nci_device must be first struct member
39   // below declarations are private variables within HAL
40   nfc_stack_callback_t* p_cback;
41   nfc_stack_data_callback_t* p_data_cback;
42   HALHANDLE hHAL;
43   nfc_stack_callback_t* p_cback_unwrap;
44 } st21nfc_dev_t;
45 
46 const char* halVersion = "ST21NFC HAL1.2 Version 3.2.5";
47 
48 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
49 uint8_t hal_is_closed = 1;
50 pthread_mutex_t hal_mtx = PTHREAD_MUTEX_INITIALIZER;
51 st21nfc_dev_t dev;
52 uint8_t hal_dta_state = 0;
53 int nfc_mode = 0;
54 
55 using namespace android::hardware::nfc::V1_1;
56 using namespace android::hardware::nfc::V1_2;
57 using android::hardware::nfc::V1_1::NfcEvent;
58 
59 /*
60  * NCI HAL method implementations. These must be overridden
61  */
62 
63 extern bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
64                              nfc_stack_data_callback_t* p_data_cback,
65                              HALHANDLE* pHandle);
66 
67 extern int hal_wrapper_close(int call_cb, int nfc_mode);
68 
69 extern void hal_wrapper_send_config();
70 extern void hal_wrapper_factoryReset();
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   hal_dta_state = 0;
291   // Initialize and get global logging level
292   InitializeSTLogLevel();
293 
294   if ((hal_is_closed || !async_callback_data.thread_running) &&
295       (async_callback_thread_start() != 0)) {
296     dev.p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
297     (void)pthread_mutex_unlock(&hal_mtx);
298     return -1;  // We are doomed, stop it here, NOW !
299   }
300   result =
301       hal_wrapper_open(&dev, async_callback_post, p_data_cback, &(dev.hHAL));
302 
303   if (!result || !(dev.hHAL)) {
304     async_callback_post(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
305     (void)pthread_mutex_unlock(&hal_mtx);
306     return -1;  // We are doomed, stop it here, NOW !
307   }
308   hal_is_closed = 0;
309   (void)pthread_mutex_unlock(&hal_mtx);
310   return 0;
311 }
312 
StNfc_hal_write(uint16_t data_len,const uint8_t * p_data)313 int StNfc_hal_write(uint16_t data_len, const uint8_t* p_data) {
314   STLOG_HAL_D("HAL st21nfc: %s", __func__);
315 
316   /* check if HAL is closed */
317   int ret = (int)data_len;
318   (void)pthread_mutex_lock(&hal_mtx);
319   if (hal_is_closed) {
320     ret = 0;
321   }
322 
323   if (!ret) {
324     (void)pthread_mutex_unlock(&hal_mtx);
325     return ret;
326   }
327   if (!HalSendDownstream(dev.hHAL, p_data, data_len)) {
328     STLOG_HAL_E("HAL st21nfc %s  SendDownstream failed", __func__);
329     (void)pthread_mutex_unlock(&hal_mtx);
330     return 0;
331   }
332   (void)pthread_mutex_unlock(&hal_mtx);
333 
334   return ret;
335 }
336 
StNfc_hal_core_initialized(uint8_t * p_core_init_rsp_params)337 int StNfc_hal_core_initialized(uint8_t* p_core_init_rsp_params) {
338   STLOG_HAL_D("HAL st21nfc: %s", __func__);
339 
340   (void)pthread_mutex_lock(&hal_mtx);
341   hal_dta_state = *p_core_init_rsp_params;
342 
343   hal_wrapper_send_config();
344   (void)pthread_mutex_unlock(&hal_mtx);
345 
346   return 0;  // return != 0 to signal ready immediate
347 }
348 
StNfc_hal_pre_discover()349 int StNfc_hal_pre_discover() {
350   STLOG_HAL_D("HAL st21nfc: %s", __func__);
351 
352   return 0;  // false if no vendor-specific pre-discovery actions are needed
353 }
354 
StNfc_hal_close(int nfc_mode_value)355 int StNfc_hal_close(int nfc_mode_value) {
356   STLOG_HAL_D("HAL st21nfc: %s nfc_mode = %d", __func__, nfc_mode_value);
357 
358   /* check if HAL is closed */
359   (void)pthread_mutex_lock(&hal_mtx);
360   if (hal_is_closed) {
361     (void)pthread_mutex_unlock(&hal_mtx);
362     return 1;
363   }
364   if (hal_wrapper_close(1, nfc_mode_value) == 0) {
365     hal_is_closed = 1;
366     (void)pthread_mutex_unlock(&hal_mtx);
367     return 1;
368   }
369   hal_is_closed = 1;
370   (void)pthread_mutex_unlock(&hal_mtx);
371 
372   hal_dta_state = 0;
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   STLOG_HAL_D("HAL st21nfc: %s close", __func__);
380   return 0;
381 }
382 
StNfc_hal_control_granted()383 int StNfc_hal_control_granted() {
384   STLOG_HAL_D("HAL st21nfc: %s", __func__);
385 
386   return 0;
387 }
388 
StNfc_hal_power_cycle()389 int StNfc_hal_power_cycle() {
390   STLOG_HAL_D("HAL st21nfc: %s", __func__);
391 
392   /* check if HAL is closed */
393   int ret = HAL_NFC_STATUS_OK;
394   (void)pthread_mutex_lock(&hal_mtx);
395   if (hal_is_closed) {
396     ret = HAL_NFC_STATUS_FAILED;
397   }
398 
399   if (ret != HAL_NFC_STATUS_OK) {
400     (void)pthread_mutex_unlock(&hal_mtx);
401     return ret;
402   }
403   async_callback_post(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
404 
405   (void)pthread_mutex_unlock(&hal_mtx);
406   return HAL_NFC_STATUS_OK;
407 }
408 
StNfc_hal_factoryReset()409 void StNfc_hal_factoryReset() {
410   STLOG_HAL_D("HAL st21nfc: %s", __func__);
411   //hal_wrapper_factoryReset();
412   // Nothing needed for factory reset in st21nfc case.
413 }
414 
StNfc_hal_closeForPowerOffCase()415 int StNfc_hal_closeForPowerOffCase() {
416   STLOG_HAL_D("HAL st21nfc: %s", __func__);
417   if (nfc_mode == 1) {
418     return 0;
419   } else {
420     return StNfc_hal_close(nfc_mode);
421   }
422 }
423 
StNfc_hal_getConfig(android::hardware::nfc::V1_1::NfcConfig & config)424 void StNfc_hal_getConfig(android::hardware::nfc::V1_1::NfcConfig& config) {
425   STLOG_HAL_D("HAL st21nfc: %s", __func__);
426   unsigned long num = 0;
427   std::array<uint8_t, 10> buffer;
428 
429   buffer.fill(0);
430   long retlen = 0;
431 
432   memset(&config, 0x00, sizeof(android::hardware::nfc::V1_1::NfcConfig));
433 
434   if (GetNumValue(NAME_CE_ON_SWITCH_OFF_STATE, &num, sizeof(num))) {
435     if (num == 0x1) {
436       nfc_mode = 0x1;
437     }
438   }
439 
440   if (GetNumValue(NAME_POLL_BAIL_OUT_MODE, &num, sizeof(num))) {
441     config.nfaPollBailOutMode = num;
442   }
443 
444   if (GetNumValue(NAME_ISO_DEP_MAX_TRANSCEIVE, &num, sizeof(num))) {
445     config.maxIsoDepTransceiveLength = num;
446   }
447   if (GetNumValue(NAME_DEFAULT_OFFHOST_ROUTE, &num, sizeof(num))) {
448     config.defaultOffHostRoute = num;
449   }
450   if (GetNumValue(NAME_DEFAULT_NFCF_ROUTE, &num, sizeof(num))) {
451     config.defaultOffHostRouteFelica = num;
452   }
453   if (GetNumValue(NAME_DEFAULT_SYS_CODE_ROUTE, &num, sizeof(num))) {
454     config.defaultSystemCodeRoute = num;
455   }
456   if (GetNumValue(NAME_DEFAULT_SYS_CODE_PWR_STATE, &num, sizeof(num))) {
457     config.defaultSystemCodePowerState = num;
458   }
459   if (GetNumValue(NAME_DEFAULT_ROUTE, &num, sizeof(num))) {
460     config.defaultRoute = num;
461   }
462   if (GetByteArrayValue(NAME_DEVICE_HOST_WHITE_LIST, (char*)buffer.data(),
463                         buffer.size(), &retlen)) {
464     config.hostWhitelist.resize(retlen);
465     for (int i = 0; i < retlen; i++) {
466       config.hostWhitelist[i] = buffer[i];
467     }
468   }
469 
470   if (GetNumValue(NAME_OFF_HOST_ESE_PIPE_ID, &num, sizeof(num))) {
471     config.offHostESEPipeId = num;
472   }
473   if (GetNumValue(NAME_OFF_HOST_SIM_PIPE_ID, &num, sizeof(num))) {
474     config.offHostSIMPipeId = num;
475   }
476   if ((GetByteArrayValue(NAME_NFA_PROPRIETARY_CFG, (char*)buffer.data(),
477                          buffer.size(), &retlen)) &&
478       (retlen == 9)) {
479     config.nfaProprietaryCfg.protocol18092Active = (uint8_t)buffer[0];
480     config.nfaProprietaryCfg.protocolBPrime = (uint8_t)buffer[1];
481     config.nfaProprietaryCfg.protocolDual = (uint8_t)buffer[2];
482     config.nfaProprietaryCfg.protocol15693 = (uint8_t)buffer[3];
483     config.nfaProprietaryCfg.protocolKovio = (uint8_t)buffer[4];
484     config.nfaProprietaryCfg.protocolMifare = (uint8_t)buffer[5];
485     config.nfaProprietaryCfg.discoveryPollKovio = (uint8_t)buffer[6];
486     config.nfaProprietaryCfg.discoveryPollBPrime = (uint8_t)buffer[7];
487     config.nfaProprietaryCfg.discoveryListenBPrime = (uint8_t)buffer[8];
488   } else {
489     memset(&config.nfaProprietaryCfg, 0xFF, sizeof(ProtocolDiscoveryConfig));
490   }
491   if (GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num))) {
492     config.presenceCheckAlgorithm = (PresenceCheckAlgorithm)num;
493   }
494 
495   if (GetNumValue(NAME_STNFC_USB_CHARGING_MODE, &num, sizeof(num))) {
496     if ((num == 1) && (nfc_mode == 0x1)) {
497       nfc_mode = 0x2;
498     }
499   }
500 }
501 
StNfc_hal_getConfig_1_2(android::hardware::nfc::V1_2::NfcConfig & config)502 void StNfc_hal_getConfig_1_2(android::hardware::nfc::V1_2::NfcConfig& config) {
503   STLOG_HAL_D("HAL st21nfc: %s", __func__);
504   unsigned long num = 0;
505   std::array<uint8_t, 10> buffer;
506 
507   buffer.fill(0);
508   long retlen = 0;
509 
510   memset(&config, 0x00, sizeof(android::hardware::nfc::V1_2::NfcConfig));
511 
512   StNfc_hal_getConfig(config.v1_1);
513 
514   if (GetByteArrayValue(NAME_OFFHOST_ROUTE_UICC, (char*)buffer.data(),
515                         buffer.size(), &retlen)) {
516     config.offHostRouteUicc.resize(retlen);
517     for (int i = 0; i < retlen; i++) {
518       config.offHostRouteUicc[i] = buffer[i];
519     }
520   }
521 
522   if (GetByteArrayValue(NAME_OFFHOST_ROUTE_ESE, (char*)buffer.data(),
523                         buffer.size(), &retlen)) {
524     config.offHostRouteEse.resize(retlen);
525     for (int i = 0; i < retlen; i++) {
526       config.offHostRouteEse[i] = buffer[i];
527     }
528   }
529 
530   if (GetNumValue(NAME_DEFAULT_ISODEP_ROUTE, &num, sizeof(num))) {
531     config.defaultIsoDepRoute = num;
532   }
533 }
534