• 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 <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   if (async_callback_thread_end() != 0) {
374     STLOG_HAL_E("HAL st21nfc: %s async_callback_thread_end failed", __func__);
375     return -1;  // We are doomed, stop it here, NOW !
376   }
377 
378   usleep(10000);  // give 10ms for the callback thread to pass the binder
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 
418   return StNfc_hal_close(nfc_mode);
419 }
420 
StNfc_hal_getConfig(NfcConfig & config)421 void StNfc_hal_getConfig(NfcConfig& config) {
422   STLOG_HAL_D("HAL st21nfc: %s", __func__);
423   unsigned long num = 0;
424   std::array<uint8_t, 10> buffer;
425 
426   buffer.fill(0);
427   long retlen = 0;
428 
429   memset(&config, 0x00, sizeof(NfcConfig));
430 
431   if (GetNumValue(NAME_CE_ON_SWITCH_OFF_STATE, &num, sizeof(num))) {
432     if (num == 0x1) {
433       nfc_mode = 0x2;
434     }
435   }
436 
437   if (GetNumValue(NAME_POLL_BAIL_OUT_MODE, &num, sizeof(num))) {
438     config.nfaPollBailOutMode = num;
439   }
440 
441   if (GetNumValue(NAME_ISO_DEP_MAX_TRANSCEIVE, &num, sizeof(num))) {
442     config.maxIsoDepTransceiveLength = num;
443   }
444   if (GetNumValue(NAME_DEFAULT_OFFHOST_ROUTE, &num, sizeof(num))) {
445     config.defaultOffHostRoute = num;
446   }
447   if (GetNumValue(NAME_DEFAULT_NFCF_ROUTE, &num, sizeof(num))) {
448     config.defaultOffHostRouteFelica = num;
449   }
450   if (GetNumValue(NAME_DEFAULT_SYS_CODE_ROUTE, &num, sizeof(num))) {
451     config.defaultSystemCodeRoute = num;
452   }
453   if (GetNumValue(NAME_DEFAULT_SYS_CODE_PWR_STATE, &num, sizeof(num))) {
454     config.defaultSystemCodePowerState = num;
455   }
456   if (GetNumValue(NAME_DEFAULT_ROUTE, &num, sizeof(num))) {
457     config.defaultRoute = num;
458   }
459   if (GetByteArrayValue(NAME_DEVICE_HOST_WHITE_LIST, (char*)buffer.data(),
460                         buffer.size(), &retlen)) {
461     config.hostWhitelist.resize(retlen);
462     for (int i = 0; i < retlen; i++) {
463       config.hostWhitelist[i] = buffer[i];
464     }
465   }
466 
467   if (GetNumValue(NAME_OFF_HOST_ESE_PIPE_ID, &num, sizeof(num))) {
468     config.offHostESEPipeId = num;
469   }
470   if (GetNumValue(NAME_OFF_HOST_SIM_PIPE_ID, &num, sizeof(num))) {
471     config.offHostSIMPipeId = num;
472   }
473   if ((GetByteArrayValue(NAME_NFA_PROPRIETARY_CFG, (char*)buffer.data(),
474                          buffer.size(), &retlen)) &&
475       (retlen == 9)) {
476     config.nfaProprietaryCfg.protocol18092Active = (uint8_t)buffer[0];
477     config.nfaProprietaryCfg.protocolBPrime = (uint8_t)buffer[1];
478     config.nfaProprietaryCfg.protocolDual = (uint8_t)buffer[2];
479     config.nfaProprietaryCfg.protocol15693 = (uint8_t)buffer[3];
480     config.nfaProprietaryCfg.protocolKovio = (uint8_t)buffer[4];
481     config.nfaProprietaryCfg.protocolMifare = (uint8_t)buffer[5];
482     config.nfaProprietaryCfg.discoveryPollKovio = (uint8_t)buffer[6];
483     config.nfaProprietaryCfg.discoveryPollBPrime = (uint8_t)buffer[7];
484     config.nfaProprietaryCfg.discoveryListenBPrime = (uint8_t)buffer[8];
485   } else {
486     memset(&config.nfaProprietaryCfg, 0xFF, sizeof(ProtocolDiscoveryConfig));
487   }
488   if (GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num))) {
489     config.presenceCheckAlgorithm = (PresenceCheckAlgorithm)num;
490   }
491 }
492