1 /*
2 * Copyright 2010-2019, 2023 NXP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * DAL independent message queue implementation for Android (can be used under
19 * Linux too)
20 */
21
22 #include <errno.h>
23 #include <linux/ipc.h>
24 #include <phDal4Nfc_messageQueueLib.h>
25 #include <phNxpLog.h>
26 #include <pthread.h>
27 #include <semaphore.h>
28
29 typedef struct phDal4Nfc_message_queue_item {
30 phLibNfc_Message_t nMsg;
31 struct phDal4Nfc_message_queue_item* pPrev;
32 struct phDal4Nfc_message_queue_item* pNext;
33 } phDal4Nfc_message_queue_item_t;
34
35 typedef struct phDal4Nfc_message_queue {
36 phDal4Nfc_message_queue_item_t* pItems;
37 pthread_mutex_t nCriticalSectionMutex;
38 sem_t nProcessSemaphore;
39
40 } phDal4Nfc_message_queue_t;
41
42 /*******************************************************************************
43 **
44 ** Function phDal4Nfc_msgget
45 **
46 ** Description Allocates message queue
47 **
48 ** Parameters Ignored, included only for Linux queue API compatibility
49 **
50 ** Returns (int) value of pQueue if successful
51 ** -1, if failed to allocate memory or to init mutex
52 **
53 *******************************************************************************/
phDal4Nfc_msgget(key_t key,int msgflg)54 intptr_t phDal4Nfc_msgget(key_t key, int msgflg) {
55 phDal4Nfc_message_queue_t* pQueue;
56 UNUSED_PROP(key);
57 UNUSED_PROP(msgflg);
58 pQueue =
59 (phDal4Nfc_message_queue_t*)malloc(sizeof(phDal4Nfc_message_queue_t));
60 if (pQueue == NULL) return -1;
61 memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
62 if (pthread_mutex_init(&pQueue->nCriticalSectionMutex, NULL) != 0) {
63 free(pQueue);
64 return -1;
65 }
66 if (sem_init(&pQueue->nProcessSemaphore, 0, 0) == -1) {
67 free(pQueue);
68 return -1;
69 }
70
71 return ((intptr_t)pQueue);
72 }
73
74 /*******************************************************************************
75 **
76 ** Function phDal4Nfc_msgrelease
77 **
78 ** Description Releases message queue
79 **
80 ** Parameters msqid - message queue handle
81 **
82 ** Returns None
83 **
84 *******************************************************************************/
phDal4Nfc_msgrelease(intptr_t msqid)85 void phDal4Nfc_msgrelease(intptr_t msqid) {
86 phDal4Nfc_message_queue_t* pQueue = (phDal4Nfc_message_queue_t*)msqid;
87
88 if (pQueue != NULL) {
89 sem_post(&pQueue->nProcessSemaphore);
90 usleep(3000);
91 if (sem_destroy(&pQueue->nProcessSemaphore)) {
92 NXPLOG_TML_E("Failed to destroy semaphore (errno=0x%08x)", errno);
93 }
94 pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
95
96 free(pQueue);
97 }
98
99 return;
100 }
101
102 /*******************************************************************************
103 **
104 ** Function phDal4Nfc_msgsnd
105 **
106 ** Description Sends a message to the queue. The message will be added at
107 ** the end of the queue as appropriate for FIFO policy
108 **
109 ** Parameters msqid - message queue handle
110 ** msgp - message to be sent
111 ** msgsz - message size
112 ** msgflg - ignored
113 **
114 ** Returns 0, if successful
115 ** -1, if invalid parameter passed or failed to allocate memory
116 **
117 *******************************************************************************/
phDal4Nfc_msgsnd(intptr_t msqid,phLibNfc_Message_t * msg,int msgflg)118 intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t* msg, int msgflg) {
119 phDal4Nfc_message_queue_t* pQueue;
120 phDal4Nfc_message_queue_item_t* p;
121 phDal4Nfc_message_queue_item_t* pNew;
122 UNUSED_PROP(msgflg);
123 if ((msqid == 0) || (msg == NULL)) return -1;
124
125 pQueue = (phDal4Nfc_message_queue_t*)msqid;
126 pNew = (phDal4Nfc_message_queue_item_t*)malloc(
127 sizeof(phDal4Nfc_message_queue_item_t));
128 if (pNew == NULL) return -1;
129 memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
130 memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
131 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
132
133 if (pQueue->pItems != NULL) {
134 p = pQueue->pItems;
135 while (p->pNext != NULL) {
136 p = p->pNext;
137 }
138 p->pNext = pNew;
139 pNew->pPrev = p;
140 } else {
141 pQueue->pItems = pNew;
142 }
143 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
144
145 sem_post(&pQueue->nProcessSemaphore);
146
147 return 0;
148 }
149
150 /*******************************************************************************
151 **
152 ** Function phDal4Nfc_msgrcv
153 **
154 ** Description Gets the oldest message from the queue.
155 ** If the queue is empty the function waits (blocks on a mutex)
156 ** until a message is posted to the queue with phDal4Nfc_msgsnd
157 **
158 ** Parameters msqid - message queue handle
159 ** msgp - message to be received
160 ** msgsz - message size
161 ** msgtyp - ignored
162 ** msgflg - ignored
163 **
164 ** Returns 0, if successful
165 ** -1, if invalid parameter passed
166 **
167 *******************************************************************************/
phDal4Nfc_msgrcv(intptr_t msqid,phLibNfc_Message_t * msg,long msgtyp,int msgflg)168 int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t* msg, long msgtyp,
169 int msgflg) {
170 phDal4Nfc_message_queue_t* pQueue;
171 phDal4Nfc_message_queue_item_t* p;
172 UNUSED_PROP(msgflg);
173 UNUSED_PROP(msgtyp);
174 if ((msqid == 0) || (msg == NULL)) return -1;
175
176 pQueue = (phDal4Nfc_message_queue_t*)msqid;
177
178 if (-1 == sem_wait(&pQueue->nProcessSemaphore)) {
179 NXPLOG_TML_E("sem_wait didn't return success\n");
180 }
181
182 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
183
184 if (pQueue->pItems != NULL) {
185 memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
186 p = pQueue->pItems->pNext;
187 free(pQueue->pItems);
188 pQueue->pItems = p;
189 }
190 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
191
192 return 0;
193 }
194