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