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
43typedef 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
51typedef 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 */
70intptr_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 */
96int 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 */
139int 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 */
190int 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