1 /*
2 *
3 * Copyright (C) 2013-2014 NXP Semiconductors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <phNxpNciHal_utils.h>
20 #include <errno.h>
21 #include <phNxpLog.h>
22
23 /*********************** Link list functions **********************************/
24
25 /*******************************************************************************
26 **
27 ** Function listInit
28 **
29 ** Description List initialization
30 **
31 ** Returns 1, if list initialized, 0 otherwise
32 **
33 *******************************************************************************/
listInit(struct listHead * pList)34 int listInit(struct listHead* pList)
35 {
36 pList->pFirst = NULL;
37 if (pthread_mutex_init(&pList->mutex, NULL) == -1)
38 {
39 NXPLOG_NCIHAL_E("Mutex creation failed (errno=0x%08x)", errno);
40 return 0;
41 }
42
43 return 1;
44 }
45
46 /*******************************************************************************
47 **
48 ** Function listDestroy
49 **
50 ** Description List destruction
51 **
52 ** Returns 1, if list destroyed, 0 if failed
53 **
54 *******************************************************************************/
listDestroy(struct listHead * pList)55 int listDestroy(struct listHead* pList)
56 {
57 int bListNotEmpty = 1;
58 while (bListNotEmpty)
59 {
60 bListNotEmpty = listGetAndRemoveNext(pList, NULL);
61 }
62
63 if (pthread_mutex_destroy(&pList->mutex) == -1)
64 {
65 NXPLOG_NCIHAL_E("Mutex destruction failed (errno=0x%08x)", errno);
66 return 0;
67 }
68
69 return 1;
70 }
71
72 /*******************************************************************************
73 **
74 ** Function listAdd
75 **
76 ** Description Add a node to the list
77 **
78 ** Returns 1, if added, 0 if otherwise
79 **
80 *******************************************************************************/
listAdd(struct listHead * pList,void * pData)81 int listAdd(struct listHead* pList, void* pData)
82 {
83 struct listNode* pNode;
84 struct listNode* pLastNode;
85 int result;
86
87 /* Create node */
88 pNode = (struct listNode*) malloc(sizeof(struct listNode));
89 if (pNode == NULL)
90 {
91 result = 0;
92 NXPLOG_NCIHAL_E("Failed to malloc");
93 goto clean_and_return;
94 }
95 pNode->pData = pData;
96 pNode->pNext = NULL;
97
98 pthread_mutex_lock(&pList->mutex);
99
100 /* Add the node to the list */
101 if (pList->pFirst == NULL)
102 {
103 /* Set the node as the head */
104 pList->pFirst = pNode;
105 }
106 else
107 {
108 /* Seek to the end of the list */
109 pLastNode = pList->pFirst;
110 while (pLastNode->pNext != NULL)
111 {
112 pLastNode = pLastNode->pNext;
113 }
114
115 /* Add the node to the current list */
116 pLastNode->pNext = pNode;
117 }
118
119 result = 1;
120
121 clean_and_return:
122 pthread_mutex_unlock(&pList->mutex);
123 return result;
124 }
125
126 /*******************************************************************************
127 **
128 ** Function listRemove
129 **
130 ** Description Remove node from the list
131 **
132 ** Returns 1, if removed, 0 if otherwise
133 **
134 *******************************************************************************/
listRemove(struct listHead * pList,void * pData)135 int listRemove(struct listHead* pList, void* pData)
136 {
137 struct listNode* pNode;
138 struct listNode* pRemovedNode;
139 int result;
140
141 pthread_mutex_lock(&pList->mutex);
142
143 if (pList->pFirst == NULL)
144 {
145 /* Empty list */
146 NXPLOG_NCIHAL_E("Failed to deallocate (list empty)");
147 result = 0;
148 goto clean_and_return;
149 }
150
151 pNode = pList->pFirst;
152 if (pList->pFirst->pData == pData)
153 {
154 /* Get the removed node */
155 pRemovedNode = pNode;
156
157 /* Remove the first node */
158 pList->pFirst = pList->pFirst->pNext;
159 }
160 else
161 {
162 while (pNode->pNext != NULL)
163 {
164 if (pNode->pNext->pData == pData)
165 {
166 /* Node found ! */
167 break;
168 }
169 pNode = pNode->pNext;
170 }
171
172 if (pNode->pNext == NULL)
173 {
174 /* Node not found */
175 result = 0;
176 NXPLOG_NCIHAL_E("Failed to deallocate (not found %8p)", pData);
177 goto clean_and_return;
178 }
179
180 /* Get the removed node */
181 pRemovedNode = pNode->pNext;
182
183 /* Remove the node from the list */
184 pNode->pNext = pNode->pNext->pNext;
185 }
186
187 /* Deallocate the node */
188 free(pRemovedNode);
189
190 result = 1;
191
192 clean_and_return:
193 pthread_mutex_unlock(&pList->mutex);
194 return result;
195 }
196
197 /*******************************************************************************
198 **
199 ** Function listGetAndRemoveNext
200 **
201 ** Description Get next node on the list and remove it
202 **
203 ** Returns 1, if successful, 0 if otherwise
204 **
205 *******************************************************************************/
listGetAndRemoveNext(struct listHead * pList,void ** ppData)206 int listGetAndRemoveNext(struct listHead* pList, void** ppData)
207 {
208 struct listNode* pNode;
209 int result;
210
211 pthread_mutex_lock(&pList->mutex);
212
213 if (pList->pFirst == NULL)
214 {
215 /* Empty list */
216 NXPLOG_NCIHAL_D("Failed to deallocate (list empty)");
217 result = 0;
218 goto clean_and_return;
219 }
220
221 /* Work on the first node */
222 pNode = pList->pFirst;
223
224 /* Return the data */
225 if (ppData != NULL)
226 {
227 *ppData = pNode->pData;
228 }
229
230 /* Remove and deallocate the node */
231 pList->pFirst = pNode->pNext;
232 free(pNode);
233
234 result = 1;
235
236 clean_and_return:
237 listDump(pList);
238 pthread_mutex_unlock(&pList->mutex);
239 return result;
240 }
241
242 /*******************************************************************************
243 **
244 ** Function listDump
245 **
246 ** Description Dump list information
247 **
248 ** Returns None
249 **
250 *******************************************************************************/
listDump(struct listHead * pList)251 void listDump(struct listHead* pList)
252 {
253 struct listNode* pNode = pList->pFirst;
254
255 NXPLOG_NCIHAL_D("Node dump:");
256 while (pNode != NULL)
257 {
258 NXPLOG_NCIHAL_D("- %8p (%8p)", pNode, pNode->pData);
259 pNode = pNode->pNext;
260 }
261
262 return;
263 }
264
265 /* END Linked list source code */
266
267 /****************** Semaphore and mutex helper functions **********************/
268
269 static phNxpNciHal_Monitor_t *nxpncihal_monitor = NULL;
270
271 /*******************************************************************************
272 **
273 ** Function phNxpNciHal_init_monitor
274 **
275 ** Description Initialize the semaphore monitor
276 **
277 ** Returns Pointer to monitor, otherwise NULL if failed
278 **
279 *******************************************************************************/
280 phNxpNciHal_Monitor_t*
phNxpNciHal_init_monitor(void)281 phNxpNciHal_init_monitor(void)
282 {
283 NXPLOG_NCIHAL_D("Entering phNxpNciHal_init_monitor");
284
285 if (nxpncihal_monitor == NULL)
286 {
287 nxpncihal_monitor = (phNxpNciHal_Monitor_t *) malloc(
288 sizeof(phNxpNciHal_Monitor_t));
289 }
290
291 if (nxpncihal_monitor != NULL)
292 {
293 memset(nxpncihal_monitor, 0x00, sizeof(phNxpNciHal_Monitor_t));
294
295 if (pthread_mutex_init(&nxpncihal_monitor->reentrance_mutex, NULL)
296 == -1)
297 {
298 NXPLOG_NCIHAL_E("reentrance_mutex creation returned 0x%08x", errno);
299 goto clean_and_return;
300 }
301
302 if (pthread_mutex_init(&nxpncihal_monitor->concurrency_mutex, NULL)
303 == -1)
304 {
305 NXPLOG_NCIHAL_E("concurrency_mutex creation returned 0x%08x", errno);
306 pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
307 goto clean_and_return;
308 }
309
310 if (listInit(&nxpncihal_monitor->sem_list) != 1)
311 {
312 NXPLOG_NCIHAL_E("Semaphore List creation failed");
313 pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
314 pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
315 goto clean_and_return;
316 }
317 }
318 else
319 {
320 NXPLOG_NCIHAL_E("nxphal_monitor creation failed");
321 goto clean_and_return;
322 }
323
324 NXPLOG_NCIHAL_D("Returning with SUCCESS");
325
326 return nxpncihal_monitor;
327
328 clean_and_return:
329 NXPLOG_NCIHAL_D("Returning with FAILURE");
330
331 if (nxpncihal_monitor != NULL)
332 {
333 free(nxpncihal_monitor);
334 nxpncihal_monitor = NULL;
335 }
336
337 return NULL;
338 }
339
340 /*******************************************************************************
341 **
342 ** Function phNxpNciHal_cleanup_monitor
343 **
344 ** Description Clean up semaphore monitor
345 **
346 ** Returns None
347 **
348 *******************************************************************************/
phNxpNciHal_cleanup_monitor(void)349 void phNxpNciHal_cleanup_monitor(void)
350 {
351 if (nxpncihal_monitor != NULL)
352 {
353 pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
354 REENTRANCE_UNLOCK();
355 pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
356 phNxpNciHal_releaseall_cb_data();
357 listDestroy(&nxpncihal_monitor->sem_list);
358 }
359
360 free(nxpncihal_monitor);
361 nxpncihal_monitor = NULL;
362
363 return;
364 }
365
366 /*******************************************************************************
367 **
368 ** Function phNxpNciHal_get_monitor
369 **
370 ** Description Get monitor
371 **
372 ** Returns Pointer to monitor
373 **
374 *******************************************************************************/
375 phNxpNciHal_Monitor_t*
phNxpNciHal_get_monitor(void)376 phNxpNciHal_get_monitor(void)
377 {
378 return nxpncihal_monitor;
379 }
380
381 /* Initialize the callback data */
phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t * pCallbackData,void * pContext)382 NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t *pCallbackData,
383 void *pContext)
384 {
385 /* Create semaphore */
386 if (sem_init(&pCallbackData->sem, 0, 0) == -1)
387 {
388 NXPLOG_NCIHAL_E("Semaphore creation failed (errno=0x%08x)", errno);
389 return NFCSTATUS_FAILED;
390 }
391
392 /* Set default status value */
393 pCallbackData->status = NFCSTATUS_FAILED;
394
395 /* Copy the context */
396 pCallbackData->pContext = pContext;
397
398 /* Add to active semaphore list */
399 if (listAdd(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1)
400 {
401 NXPLOG_NCIHAL_E("Failed to add the semaphore to the list");
402 }
403
404 return NFCSTATUS_SUCCESS;
405 }
406
407 /*******************************************************************************
408 **
409 ** Function phNxpNciHal_cleanup_cb_data
410 **
411 ** Description Clean up callback data
412 **
413 ** Returns None
414 **
415 *******************************************************************************/
phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t * pCallbackData)416 void phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t* pCallbackData)
417 {
418 /* Destroy semaphore */
419 if (sem_destroy(&pCallbackData->sem))
420 {
421 NXPLOG_NCIHAL_E("phNxpNciHal_cleanup_cb_data: Failed to destroy semaphore (errno=0x%08x)", errno);
422 }
423
424 /* Remove from active semaphore list */
425 if (listRemove(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1)
426 {
427 NXPLOG_NCIHAL_E("phNxpNciHal_cleanup_cb_data: Failed to remove semaphore from the list");
428 }
429
430 return;
431 }
432
433 /*******************************************************************************
434 **
435 ** Function phNxpNciHal_releaseall_cb_data
436 **
437 ** Description Release all callback data
438 **
439 ** Returns None
440 **
441 *******************************************************************************/
phNxpNciHal_releaseall_cb_data(void)442 void phNxpNciHal_releaseall_cb_data(void)
443 {
444 phNxpNciHal_Sem_t* pCallbackData;
445
446 while (listGetAndRemoveNext(&phNxpNciHal_get_monitor()->sem_list,
447 (void**) &pCallbackData))
448 {
449 pCallbackData->status = NFCSTATUS_FAILED;
450 sem_post(&pCallbackData->sem);
451 }
452
453 return;
454 }
455
456 /* END Semaphore and mutex helper functions */
457
458 /**************************** Other functions *********************************/
459
460 /*******************************************************************************
461 **
462 ** Function phNxpNciHal_print_packet
463 **
464 ** Description Print packet
465 **
466 ** Returns None
467 **
468 *******************************************************************************/
phNxpNciHal_print_packet(const char * pString,const uint8_t * p_data,uint16_t len)469 void phNxpNciHal_print_packet(const char *pString, const uint8_t *p_data,
470 uint16_t len)
471 {
472 uint32_t i, j;
473 char print_buffer[len * 3 + 1];
474
475 memset (print_buffer, 0, sizeof(print_buffer));
476 for (i = 0; i < len; i++) {
477 snprintf(&print_buffer[i * 2], 3, "%02X", p_data[i]);
478 }
479 if( 0 == memcmp(pString,"SEND",0x04))
480 {
481 NXPLOG_NCIX_D("len = %3d > %s", len, print_buffer);
482 }
483 else if( 0 == memcmp(pString,"RECV",0x04))
484 {
485 NXPLOG_NCIR_D("len = %3d > %s", len, print_buffer);
486 }
487
488 return;
489 }
490
491
492 /*******************************************************************************
493 **
494 ** Function phNxpNciHal_emergency_recovery
495 **
496 ** Description Emergency recovery in case of no other way out
497 **
498 ** Returns None
499 **
500 *******************************************************************************/
501
phNxpNciHal_emergency_recovery(void)502 void phNxpNciHal_emergency_recovery(void)
503 {
504 NXPLOG_NCIHAL_E("%s: abort()", __FUNCTION__);
505 // abort();
506 }
507