1 /*
2 * Copyright (C) 2010 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 * \file phDalNfc_messageQueueLib.c
19 * \brief DAL independant message queue implementation for android (can be used under linux too)
20 *
21 * Project: Trusted NFC Linux Lignt
22 *
23 * $Date: 13 aug 2009
24 * $Author: Jonathan roux
25 * $Revision: 1.0 $
26 *
27 */
28
29 #include <pthread.h>
30 #ifdef ANDROID
31 #include <linux/ipc.h>
32 #else
33 #include <sys/msg.h>
34 #endif
35
36 #include <semaphore.h>
37
38 #include <phDal4Nfc.h>
39 #include <phOsalNfc.h>
40 #include <phDal4Nfc_DeferredCall.h>
41 #include <phDal4Nfc_messageQueueLib.h>
42
43 typedef struct phDal4Nfc_message_queue_item
44 {
45 phLibNfc_Message_t nMsg;
46 struct phDal4Nfc_message_queue_item * pPrev;
47 struct phDal4Nfc_message_queue_item * pNext;
48 } phDal4Nfc_message_queue_item_t;
49
50
51 typedef struct phDal4Nfc_message_queue
52 {
53 phDal4Nfc_message_queue_item_t * pItems;
54 pthread_mutex_t nCriticalSectionMutex;
55 sem_t nProcessSemaphore;
56
57 } phDal4Nfc_message_queue_t;
58
59
60 /**
61 * \ingroup grp_nfc_dal
62 *
63 * \brief DAL message get function
64 * This function allocates the message queue. The parameters are ignored, this is
65 * just to keep the same api as Linux queue.
66 *
67 * \retval -1 Can not allocate memory or can not init mutex.
68 * \retval handle The handle on the message queue.
69 */
phDal4Nfc_msgget(key_t key,int msgflg)70 intptr_t phDal4Nfc_msgget ( key_t key, int msgflg )
71 {
72 phDal4Nfc_message_queue_t * pQueue;
73 pQueue = (phDal4Nfc_message_queue_t *) phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_t));
74 if (pQueue == NULL)
75 return -1;
76 memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
77 if (pthread_mutex_init (&pQueue->nCriticalSectionMutex, NULL) == -1)
78 return -1;
79 if (sem_init (&pQueue->nProcessSemaphore, 0, 0) == -1)
80 return -1;
81 return ((intptr_t)pQueue);
82 }
83
84 /**
85 * \ingroup grp_nfc_dal
86 *
87 * \brief DAL message control function
88 * This function destroys the message queue. The cmd and buf parameters are ignored,
89 * this is just to keep the same api as Linux queue.
90 *
91 * \param[in] msqid The handle of the message queue.
92 *
93 * \retval 0 If success.
94 * \retval -1 Bad passed parameter
95 */
phDal4Nfc_msgctl(intptr_t msqid,int cmd,void * buf)96 int phDal4Nfc_msgctl ( intptr_t msqid, int cmd, void *buf )
97 {
98 phDal4Nfc_message_queue_t * pQueue;
99 phDal4Nfc_message_queue_item_t * p;
100
101 if (msqid == 0)
102 return -1;
103
104 pQueue = (phDal4Nfc_message_queue_t *)msqid;
105 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
106 if (pQueue->pItems != NULL)
107 {
108 p = pQueue->pItems;
109 while(p->pNext != NULL) { p = p->pNext; }
110 while(p->pPrev != NULL)
111 {
112 p = p->pPrev;
113 phOsalNfc_FreeMemory(p->pNext);
114 p->pNext = NULL;
115 }
116 phOsalNfc_FreeMemory(p);
117 }
118 pQueue->pItems = NULL;
119 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
120 pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
121 phOsalNfc_FreeMemory(pQueue);
122 return 0;
123 }
124
125 /**
126 * \ingroup grp_nfc_dal
127 *
128 * \brief DAL message send function
129 * Use this function to send a message to the queue. The message will be added at the end of
130 * the queue with respect to FIFO policy. The msgflg parameter is ignored.
131 *
132 * \param[in] msqid The handle of the message queue.
133 * \param[in] msgp The message to send.
134 * \param[in] msgsz The message size.
135 *
136 * \retval 0 If success.
137 * \retval -1 Bad passed parameter, or can not allocate memory
138 */
phDal4Nfc_msgsnd(intptr_t msqid,void * msgp,size_t msgsz,int msgflg)139 int phDal4Nfc_msgsnd (intptr_t msqid, void * msgp, size_t msgsz, int msgflg)
140 {
141 phDal4Nfc_message_queue_t * pQueue;
142 phDal4Nfc_message_queue_item_t * p;
143 phDal4Nfc_message_queue_item_t * pNew;
144
145 if ((msqid == 0) || (msgp == NULL) || (msgsz == 0))
146 return -1;
147
148 if (msgsz != sizeof(phLibNfc_Message_t))
149 return -1;
150
151 pQueue = (phDal4Nfc_message_queue_t *)msqid;
152 pNew = (phDal4Nfc_message_queue_item_t *)phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_item_t));
153 if (pNew == NULL)
154 return -1;
155 memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
156 memcpy(&pNew->nMsg, &((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, sizeof(phLibNfc_Message_t));
157 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
158 if (pQueue->pItems != NULL)
159 {
160 p = pQueue->pItems;
161 while(p->pNext != NULL) { p = p->pNext; }
162 p->pNext = pNew;
163 pNew->pPrev = p;
164 }
165 else
166 {
167 pQueue->pItems = pNew;
168 }
169 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
170
171 sem_post(&pQueue->nProcessSemaphore);
172 return 0;
173 }
174
175 /**
176 * \ingroup grp_nfc_dal
177 *
178 * \brief DAL message receive function
179 * The call to this function will get the older message from the queue. If the queue is empty the function waits
180 * (blocks on a mutex) until a message is posted to the queue with phDal4Nfc_msgsnd.
181 * The msgtyp and msgflg parameters are ignored.
182 *
183 * \param[in] msqid The handle of the message queue.
184 * \param[out] msgp The received message.
185 * \param[in] msgsz The message size.
186 *
187 * \retval 0 If success.
188 * \retval -1 Bad passed parameter.
189 */
phDal4Nfc_msgrcv(intptr_t msqid,void * msgp,size_t msgsz,long msgtyp,int msgflg)190 int phDal4Nfc_msgrcv (intptr_t msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg)
191 {
192 phDal4Nfc_message_queue_t * pQueue;
193 phDal4Nfc_message_queue_item_t * p;
194
195 if ((msqid == 0) || (msgp == NULL))
196 return -1;
197
198 if (msgsz != sizeof(phLibNfc_Message_t))
199 return -1;
200
201 pQueue = (phDal4Nfc_message_queue_t *)msqid;
202 sem_wait(&pQueue->nProcessSemaphore);
203 pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
204 if (pQueue->pItems != NULL)
205 {
206 memcpy(&((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
207 p = pQueue->pItems->pNext;
208 phOsalNfc_FreeMemory(pQueue->pItems);
209 pQueue->pItems = p;
210 }
211 pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
212 return 0;
213 }
214
215
216
217
218
219