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