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