1 /*
2  *
3  *  Copyright (C) 2013-2018, 2021-2022 NXP
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 #ifndef _PHNXPNCIHAL_UTILS_H_
20 #define _PHNXPNCIHAL_UTILS_H_
21 
22 #include <assert.h>
23 #include <errno.h>
24 #include <phNfcStatus.h>
25 #include <pthread.h>
26 #include <semaphore.h>
27 
28 /********************* Definitions and structures *****************************/
29 
30 /* List structures */
31 struct listNode {
32   void* pData;
33   struct listNode* pNext;
34 };
35 
36 struct listHead {
37   struct listNode* pFirst;
38   pthread_mutex_t mutex;
39 };
40 
41 /* Semaphore handling structure */
42 typedef struct phNxpNciHal_Sem {
43   /* Semaphore used to wait for callback */
44   sem_t sem;
45 
46   /* Used to store the status sent by the callback */
47   NFCSTATUS status;
48 
49   /* Used to provide a local context to the callback */
50   void* pContext;
51 
52 } phNxpNciHal_Sem_t;
53 
54 typedef enum {
55   PRINT_UNKNOWN = 0x00,
56   PRINT_SEND = 0x01,
57   PRINT_RECV,
58   PRINT_DEBUG
59 } tNFC_printType;
60 
61 /* Semaphore helper macros */
62 #define SEM_WAIT(cb_data)                                         \
63   ((sem_wait(&((cb_data).sem)) == 0) ? 0                          \
64    : (errno == EINTR)                ? sem_wait(&((cb_data).sem)) \
65                                      : -1)
66 
67 #define SEM_POST(p_cb_data) sem_post(&((p_cb_data)->sem))
68 
69 /* Semaphore and mutex monitor */
70 typedef struct phNxpNciHal_Monitor {
71   /* Mutex protecting native library against reentrance */
72   pthread_mutex_t reentrance_mutex;
73 
74   /* Mutex protecting native library against concurrency */
75   pthread_mutex_t concurrency_mutex;
76 
77   /* List used to track pending semaphores waiting for callback */
78   struct listHead sem_list;
79 
80 } phNxpNciHal_Monitor_t;
81 
82 /************************ Exposed functions ***********************************/
83 /* List functions */
84 int listInit(struct listHead* pList);
85 int listDestroy(struct listHead* pList);
86 int listAdd(struct listHead* pList, void* pData);
87 int listRemove(struct listHead* pList, void* pData);
88 int listGetAndRemoveNext(struct listHead* pList, void** ppData);
89 void listDump(struct listHead* pList);
90 
91 /* NXP NCI HAL utility functions */
92 phNxpNciHal_Monitor_t* phNxpNciHal_init_monitor(void);
93 void phNxpNciHal_cleanup_monitor(void);
94 phNxpNciHal_Monitor_t* phNxpNciHal_get_monitor(void);
95 NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t* pCallbackData,
96                                    void* pContext);
97 void phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t* pCallbackData);
98 void phNxpNciHal_releaseall_cb_data(void);
99 void phNxpNciHal_print_packet(const char* pString, const uint8_t* p_data,
100                               uint16_t len);
101 void phNxpNciHal_emergency_recovery(uint8_t status);
102 tNFC_printType getPrintType(const char* pString);
103 
104 /* Lock unlock helper macros */
105 /* Lock unlock helper macros */
106 #define REENTRANCE_LOCK()        \
107   if (phNxpNciHal_get_monitor()) \
108   pthread_mutex_lock(&phNxpNciHal_get_monitor()->reentrance_mutex)
109 #define REENTRANCE_UNLOCK()      \
110   if (phNxpNciHal_get_monitor()) \
111   pthread_mutex_unlock(&phNxpNciHal_get_monitor()->reentrance_mutex)
112 #define CONCURRENCY_LOCK()       \
113   if (phNxpNciHal_get_monitor()) \
114   pthread_mutex_lock(&phNxpNciHal_get_monitor()->concurrency_mutex)
115 #define CONCURRENCY_UNLOCK()     \
116   if (phNxpNciHal_get_monitor()) \
117   pthread_mutex_unlock(&phNxpNciHal_get_monitor()->concurrency_mutex)
118 
119 #endif /* _PHNXPNCIHAL_UTILS_H_ */
120