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