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