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