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