1 /*
2 * Copyright (C) 2010-2014 NXP Semiconductors
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(key);
57 UNUSED(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) == -1) {
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_msgctl
105 **
106 ** Description Destroys message queue
107 **
108 ** Parameters msqid - message queue handle
109 ** cmd, buf - ignored, included only for Linux queue API
110 ** compatibility
111 **
112 ** Returns 0, if successful
113 ** -1, if invalid handle is passed
114 **
115 *******************************************************************************/
phDal4Nfc_msgctl(intptr_t msqid,int cmd,void * buf)116 int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void* buf) {
117 phDal4Nfc_message_queue_t* pQueue;
118 phDal4Nfc_message_queue_item_t* p;
119 UNUSED(cmd);
120 UNUSED(buf);
121 if (msqid == 0) return -1;
122
123 pQueue = (phDal4Nfc_message_queue_t*)msqid;
124 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
125 if (pQueue->pItems != NULL) {
126 p = pQueue->pItems;
127 while (p->pNext != NULL) {
128 p = p->pNext;
129 }
130 while (p->pPrev != NULL) {
131 p = p->pPrev;
132 free(p->pNext);
133 p->pNext = NULL;
134 }
135 free(p);
136 }
137 pQueue->pItems = NULL;
138 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
139 pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
140 free(pQueue);
141
142 return 0;
143 }
144
145 /*******************************************************************************
146 **
147 ** Function phDal4Nfc_msgsnd
148 **
149 ** Description Sends a message to the queue. The message will be added at
150 ** the end of the queue as appropriate for FIFO policy
151 **
152 ** Parameters msqid - message queue handle
153 ** msgp - message to be sent
154 ** msgsz - message size
155 ** msgflg - ignored
156 **
157 ** Returns 0, if successful
158 ** -1, if invalid parameter passed or failed to allocate memory
159 **
160 *******************************************************************************/
phDal4Nfc_msgsnd(intptr_t msqid,phLibNfc_Message_t * msg,int msgflg)161 intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t* msg, int msgflg) {
162 phDal4Nfc_message_queue_t* pQueue;
163 phDal4Nfc_message_queue_item_t* p;
164 phDal4Nfc_message_queue_item_t* pNew;
165 UNUSED(msgflg);
166 if ((msqid == 0) || (msg == NULL)) return -1;
167
168 pQueue = (phDal4Nfc_message_queue_t*)msqid;
169 pNew = (phDal4Nfc_message_queue_item_t*)malloc(
170 sizeof(phDal4Nfc_message_queue_item_t));
171 if (pNew == NULL) return -1;
172 memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
173 memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
174 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
175
176 if (pQueue->pItems != NULL) {
177 p = pQueue->pItems;
178 while (p->pNext != NULL) {
179 p = p->pNext;
180 }
181 p->pNext = pNew;
182 pNew->pPrev = p;
183 } else {
184 pQueue->pItems = pNew;
185 }
186 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
187
188 sem_post(&pQueue->nProcessSemaphore);
189
190 return 0;
191 }
192
193 /*******************************************************************************
194 **
195 ** Function phDal4Nfc_msgrcv
196 **
197 ** Description Gets the oldest message from the queue.
198 ** If the queue is empty the function waits (blocks on a mutex)
199 ** until a message is posted to the queue with phDal4Nfc_msgsnd
200 **
201 ** Parameters msqid - message queue handle
202 ** msgp - message to be received
203 ** msgsz - message size
204 ** msgtyp - ignored
205 ** msgflg - ignored
206 **
207 ** Returns 0, if successful
208 ** -1, if invalid parameter passed
209 **
210 *******************************************************************************/
phDal4Nfc_msgrcv(intptr_t msqid,phLibNfc_Message_t * msg,long msgtyp,int msgflg)211 int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t* msg, long msgtyp,
212 int msgflg) {
213 phDal4Nfc_message_queue_t* pQueue;
214 phDal4Nfc_message_queue_item_t* p;
215 UNUSED(msgflg);
216 UNUSED(msgtyp);
217 if ((msqid == 0) || (msg == NULL)) return -1;
218
219 pQueue = (phDal4Nfc_message_queue_t*)msqid;
220
221 sem_wait(&pQueue->nProcessSemaphore);
222
223 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
224
225 if (pQueue->pItems != NULL) {
226 memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
227 p = pQueue->pItems->pNext;
228 free(pQueue->pItems);
229 pQueue->pItems = p;
230 }
231 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
232
233 return 0;
234 }
235