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 Linux too)
19 */
20
21 #include <pthread.h>
22 #include <phNxpLog.h>
23 #include <linux/ipc.h>
24 #include <semaphore.h>
25 #include <errno.h>
26 #include <phDal4Nfc_messageQueueLib.h>
27
28
29 typedef struct phDal4Nfc_message_queue_item
30 {
31 phLibNfc_Message_t nMsg;
32 struct phDal4Nfc_message_queue_item * pPrev;
33 struct phDal4Nfc_message_queue_item * pNext;
34 } phDal4Nfc_message_queue_item_t;
35
36 typedef struct phDal4Nfc_message_queue
37 {
38 phDal4Nfc_message_queue_item_t * pItems;
39 pthread_mutex_t nCriticalSectionMutex;
40 sem_t nProcessSemaphore;
41
42 } phDal4Nfc_message_queue_t;
43
44 /*******************************************************************************
45 **
46 ** Function phDal4Nfc_msgget
47 **
48 ** Description Allocates message queue
49 **
50 ** Parameters Ignored, included only for Linux queue API compatibility
51 **
52 ** Returns (int) value of pQueue if successful
53 ** -1, if failed to allocate memory or to init mutex
54 **
55 *******************************************************************************/
phDal4Nfc_msgget(key_t key,int msgflg)56 intptr_t phDal4Nfc_msgget(key_t key, int msgflg)
57 {
58 phDal4Nfc_message_queue_t * pQueue;
59 UNUSED(key);
60 UNUSED(msgflg);
61 pQueue = (phDal4Nfc_message_queue_t *) malloc(sizeof(phDal4Nfc_message_queue_t));
62 if (pQueue == NULL)
63 return -1;
64 memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
65 if (pthread_mutex_init(&pQueue->nCriticalSectionMutex, NULL) == -1)
66 {
67 free (pQueue);
68 return -1;
69 }
70 if (sem_init(&pQueue->nProcessSemaphore, 0, 0) == -1)
71 {
72 free (pQueue);
73 return -1;
74 }
75
76 return ((intptr_t) pQueue);
77 }
78
79 /*******************************************************************************
80 **
81 ** Function phDal4Nfc_msgrelease
82 **
83 ** Description Releases message queue
84 **
85 ** Parameters msqid - message queue handle
86 **
87 ** Returns None
88 **
89 *******************************************************************************/
phDal4Nfc_msgrelease(intptr_t msqid)90 void phDal4Nfc_msgrelease(intptr_t msqid)
91 {
92 phDal4Nfc_message_queue_t * pQueue = (phDal4Nfc_message_queue_t*)msqid;
93
94 if(pQueue != NULL)
95 {
96 sem_post(&pQueue->nProcessSemaphore);
97 usleep(300000);
98 if (sem_destroy(&pQueue->nProcessSemaphore))
99 {
100 NXPLOG_TML_E("Failed to destroy semaphore (errno=0x%08x)", errno);
101 }
102 pthread_mutex_destroy (&pQueue->nCriticalSectionMutex);
103
104 free(pQueue);
105 }
106
107 return;
108 }
109
110 /*******************************************************************************
111 **
112 ** Function phDal4Nfc_msgctl
113 **
114 ** Description Destroys message queue
115 **
116 ** Parameters msqid - message queue handle
117 ** cmd, buf - ignored, included only for Linux queue API compatibility
118 **
119 ** Returns 0, if successful
120 ** -1, if invalid handle is passed
121 **
122 *******************************************************************************/
phDal4Nfc_msgctl(intptr_t msqid,int cmd,void * buf)123 int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void *buf)
124 {
125 phDal4Nfc_message_queue_t * pQueue;
126 phDal4Nfc_message_queue_item_t * p;
127 UNUSED(cmd);
128 UNUSED(buf);
129 if (msqid == 0)
130 return -1;
131
132 pQueue = (phDal4Nfc_message_queue_t *) msqid;
133 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
134 if (pQueue->pItems != NULL)
135 {
136 p = pQueue->pItems;
137 while (p->pNext != NULL)
138 {
139 p = p->pNext;
140 }
141 while (p->pPrev != NULL)
142 {
143 p = p->pPrev;
144 free(p->pNext);
145 p->pNext = NULL;
146 }
147 free(p);
148 }
149 pQueue->pItems = NULL;
150 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
151 pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
152 free(pQueue);
153
154 return 0;
155 }
156
157 /*******************************************************************************
158 **
159 ** Function phDal4Nfc_msgsnd
160 **
161 ** Description Sends a message to the queue. The message will be added at the end of
162 ** the queue as appropriate for FIFO policy
163 **
164 ** Parameters msqid - message queue handle
165 ** msgp - message to be sent
166 ** msgsz - message size
167 ** msgflg - ignored
168 **
169 ** Returns 0, if successful
170 ** -1, if invalid parameter passed or failed to allocate memory
171 **
172 *******************************************************************************/
phDal4Nfc_msgsnd(intptr_t msqid,phLibNfc_Message_t * msg,int msgflg)173 intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t * msg, int msgflg)
174 {
175 phDal4Nfc_message_queue_t * pQueue;
176 phDal4Nfc_message_queue_item_t * p;
177 phDal4Nfc_message_queue_item_t * pNew;
178 UNUSED(msgflg);
179 if ((msqid == 0) || (msg == NULL) )
180 return -1;
181
182
183 pQueue = (phDal4Nfc_message_queue_t *) msqid;
184 pNew = (phDal4Nfc_message_queue_item_t *) malloc(sizeof(phDal4Nfc_message_queue_item_t));
185 if (pNew == NULL)
186 return -1;
187 memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
188 memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
189 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
190
191 if (pQueue->pItems != NULL)
192 {
193 p = pQueue->pItems;
194 while (p->pNext != NULL)
195 {
196 p = p->pNext;
197 }
198 p->pNext = pNew;
199 pNew->pPrev = p;
200 }
201 else
202 {
203 pQueue->pItems = pNew;
204 }
205 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
206
207 sem_post(&pQueue->nProcessSemaphore);
208
209 return 0;
210 }
211
212 /*******************************************************************************
213 **
214 ** Function phDal4Nfc_msgrcv
215 **
216 ** Description Gets the oldest message from the queue.
217 ** If the queue is empty the function waits (blocks on a mutex)
218 ** until a message is posted to the queue with phDal4Nfc_msgsnd.
219 **
220 ** Parameters msqid - message queue handle
221 ** msgp - message to be received
222 ** msgsz - message size
223 ** msgtyp - ignored
224 ** msgflg - ignored
225 **
226 ** Returns 0, if successful
227 ** -1, if invalid parameter passed
228 **
229 *******************************************************************************/
phDal4Nfc_msgrcv(intptr_t msqid,phLibNfc_Message_t * msg,long msgtyp,int msgflg)230 int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t * msg, long msgtyp, int msgflg)
231 {
232 phDal4Nfc_message_queue_t * pQueue;
233 phDal4Nfc_message_queue_item_t * p;
234 UNUSED(msgflg);
235 UNUSED(msgtyp);
236 if ((msqid == 0) || (msg == NULL))
237 return -1;
238
239 pQueue = (phDal4Nfc_message_queue_t *) msqid;
240
241 sem_wait(&pQueue->nProcessSemaphore);
242
243 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
244
245 if (pQueue->pItems != NULL)
246 {
247 memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
248 p = pQueue->pItems->pNext;
249 free(pQueue->pItems);
250 pQueue->pItems = p;
251 }
252 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
253
254 return 0;
255 }
256